aboutsummaryrefslogtreecommitdiff
path: root/azalea-nbt/src
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2023-11-19 22:07:38 -0600
committerGitHub <noreply@github.com>2023-11-19 22:07:38 -0600
commit2c610826fc9f8e16897f52313faa8e0602d1dc3d (patch)
tree5aad79ecab3b68511a10ebd7eba07af0bd8a5905 /azalea-nbt/src
parent84e036ce3752ecf57904b0f5aff1f33d43e95a32 (diff)
downloadazalea-drasl-2c610826fc9f8e16897f52313faa8e0602d1dc3d.tar.xz
Replace azalea-nbt with simdnbt (#111)
* delete azalea-nbt and replace with simdnbt * use simdnbt from crates.io * remove serde dependency on azalea-registry
Diffstat (limited to 'azalea-nbt/src')
-rwxr-xr-xazalea-nbt/src/decode.rs314
-rwxr-xr-xazalea-nbt/src/encode.rs296
-rwxr-xr-xazalea-nbt/src/error.rs15
-rwxr-xr-xazalea-nbt/src/lib.rs46
-rwxr-xr-xazalea-nbt/src/tag.rs271
5 files changed, 0 insertions, 942 deletions
diff --git a/azalea-nbt/src/decode.rs b/azalea-nbt/src/decode.rs
deleted file mode 100755
index 23247b74..00000000
--- a/azalea-nbt/src/decode.rs
+++ /dev/null
@@ -1,314 +0,0 @@
-use crate::tag::*;
-use crate::Error;
-use azalea_buf::{BufReadError, McBufReadable};
-use byteorder::{ReadBytesExt, BE};
-use flate2::read::{GzDecoder, ZlibDecoder};
-use std::io::{BufRead, Cursor, Read};
-use tracing::warn;
-
-#[inline]
-fn read_bytes<'a>(buf: &'a mut Cursor<&[u8]>, length: usize) -> Result<&'a [u8], Error> {
- if length > (buf.get_ref().len() - buf.position() as usize) {
- return Err(Error::UnexpectedEof);
- }
- let initial_position = buf.position() as usize;
- buf.set_position(buf.position() + length as u64);
- let data = &buf.get_ref()[initial_position..initial_position + length];
- Ok(data)
-}
-
-#[inline]
-fn read_string(stream: &mut Cursor<&[u8]>) -> Result<NbtString, Error> {
- let length = stream.read_u16::<BE>()? as usize;
-
- let buf = read_bytes(stream, length)?;
-
- Ok(if let Ok(string) = std::str::from_utf8(buf) {
- string.into()
- } else {
- let lossy_string = String::from_utf8_lossy(buf).into_owned();
- warn!("Error decoding utf8 (bytes: {buf:?}, lossy: \"{lossy_string})\"");
- lossy_string.into()
- })
-}
-
-#[inline]
-fn read_byte_array(stream: &mut Cursor<&[u8]>) -> Result<NbtByteArray, Error> {
- let length = stream.read_u32::<BE>()? as usize;
- let bytes = read_bytes(stream, length)?.to_vec();
- Ok(bytes)
-}
-
-// https://stackoverflow.com/a/59707887
-fn vec_u8_into_i8(v: Vec<u8>) -> Vec<i8> {
- // ideally we'd use Vec::into_raw_parts, but it's unstable,
- // so we have to do it manually:
-
- // first, make sure v's destructor doesn't free the data
- // it thinks it owns when it goes out of scope
- let mut v = std::mem::ManuallyDrop::new(v);
-
- // then, pick apart the existing Vec
- let p = v.as_mut_ptr();
- let len = v.len();
- let cap = v.capacity();
-
- // finally, adopt the data into a new Vec
- unsafe { Vec::from_raw_parts(p as *mut i8, len, cap) }
-}
-
-#[inline]
-fn read_list(stream: &mut Cursor<&[u8]>) -> Result<NbtList, Error> {
- let type_id = stream.read_u8()?;
- let length = stream.read_u32::<BE>()?;
- let list = match type_id {
- END_ID => NbtList::Empty,
- BYTE_ID => NbtList::Byte(vec_u8_into_i8(
- read_bytes(stream, length as usize)?.to_vec(),
- )),
- SHORT_ID => NbtList::Short({
- if ((length * 2) as usize) > (stream.get_ref().len() - stream.position() as usize) {
- return Err(Error::UnexpectedEof);
- }
- (0..length)
- .map(|_| stream.read_i16::<BE>())
- .collect::<Result<Vec<_>, _>>()?
- }),
- INT_ID => NbtList::Int({
- if ((length * 4) as usize) > (stream.get_ref().len() - stream.position() as usize) {
- return Err(Error::UnexpectedEof);
- }
- (0..length)
- .map(|_| stream.read_i32::<BE>())
- .collect::<Result<Vec<_>, _>>()?
- }),
- LONG_ID => NbtList::Long({
- if ((length * 8) as usize) > (stream.get_ref().len() - stream.position() as usize) {
- return Err(Error::UnexpectedEof);
- }
- (0..length)
- .map(|_| stream.read_i64::<BE>())
- .collect::<Result<Vec<_>, _>>()?
- }),
- FLOAT_ID => NbtList::Float({
- if ((length * 4) as usize) > (stream.get_ref().len() - stream.position() as usize) {
- return Err(Error::UnexpectedEof);
- }
- (0..length)
- .map(|_| stream.read_f32::<BE>())
- .collect::<Result<Vec<_>, _>>()?
- }),
- DOUBLE_ID => NbtList::Double({
- if ((length * 8) as usize) > (stream.get_ref().len() - stream.position() as usize) {
- return Err(Error::UnexpectedEof);
- }
- (0..length)
- .map(|_| stream.read_f64::<BE>())
- .collect::<Result<Vec<_>, _>>()?
- }),
- BYTE_ARRAY_ID => NbtList::ByteArray({
- if ((length * 4) as usize) > (stream.get_ref().len() - stream.position() as usize) {
- return Err(Error::UnexpectedEof);
- }
- (0..length)
- .map(|_| read_byte_array(stream))
- .collect::<Result<Vec<_>, _>>()?
- }),
- STRING_ID => NbtList::String({
- if ((length * 4) as usize) > (stream.get_ref().len() - stream.position() as usize) {
- return Err(Error::UnexpectedEof);
- }
- (0..length)
- .map(|_| read_string(stream))
- .collect::<Result<Vec<_>, _>>()?
- }),
- LIST_ID => NbtList::List({
- if ((length * 4) as usize) > (stream.get_ref().len() - stream.position() as usize) {
- return Err(Error::UnexpectedEof);
- }
- (0..length)
- .map(|_| read_list(stream))
- .collect::<Result<Vec<_>, _>>()?
- }),
- COMPOUND_ID => NbtList::Compound({
- if ((length * 4) as usize) > (stream.get_ref().len() - stream.position() as usize) {
- return Err(Error::UnexpectedEof);
- }
- (0..length)
- .map(|_| read_compound(stream))
- .collect::<Result<Vec<_>, _>>()?
- }),
- INT_ARRAY_ID => NbtList::IntArray({
- if ((length * 4) as usize) > (stream.get_ref().len() - stream.position() as usize) {
- return Err(Error::UnexpectedEof);
- }
- (0..length)
- .map(|_| read_int_array(stream))
- .collect::<Result<Vec<_>, _>>()?
- }),
- LONG_ARRAY_ID => NbtList::LongArray({
- if ((length * 4) as usize) > (stream.get_ref().len() - stream.position() as usize) {
- return Err(Error::UnexpectedEof);
- }
- (0..length)
- .map(|_| read_long_array(stream))
- .collect::<Result<Vec<_>, _>>()?
- }),
- _ => return Err(Error::InvalidTagType(type_id)),
- };
- Ok(list)
-}
-
-#[inline]
-fn read_compound(stream: &mut Cursor<&[u8]>) -> Result<NbtCompound, Error> {
- // we default to capacity 4 because it'll probably not be empty
- let mut map = NbtCompound::with_capacity(4);
- loop {
- let tag_id = stream.read_u8().unwrap_or(0);
- if tag_id == 0 {
- break;
- }
- let name = read_string(stream)?;
- let tag = Nbt::read_known(stream, tag_id)?;
- map.insert_unsorted(name, tag);
- }
- map.sort();
- Ok(map)
-}
-
-#[inline]
-fn read_int_array(stream: &mut Cursor<&[u8]>) -> Result<NbtIntArray, Error> {
- let length = stream.read_u32::<BE>()? as usize;
- if length * 4 > (stream.get_ref().len() - stream.position() as usize) {
- return Err(Error::UnexpectedEof);
- }
- let mut ints = NbtIntArray::with_capacity(length);
- for _ in 0..length {
- ints.push(stream.read_i32::<BE>()?);
- }
- Ok(ints)
-}
-
-#[inline]
-fn read_long_array(stream: &mut Cursor<&[u8]>) -> Result<NbtLongArray, Error> {
- let length = stream.read_u32::<BE>()? as usize;
- if length * 8 > (stream.get_ref().len() - stream.position() as usize) {
- return Err(Error::UnexpectedEof);
- }
- let mut longs = NbtLongArray::with_capacity(length);
- for _ in 0..length {
- longs.push(stream.read_i64::<BE>()?);
- }
- Ok(longs)
-}
-
-impl Nbt {
- /// Read the NBT data when you already know the ID of the tag. You usually
- /// want [`Nbt::read`] if you're reading an NBT file.
- #[inline]
- fn read_known(stream: &mut Cursor<&[u8]>, id: u8) -> Result<Nbt, Error> {
- Ok(match id {
- // Signifies the end of a TAG_Compound. It is only ever used inside
- // a TAG_Compound, and is not named despite being in a TAG_Compound
- END_ID => Nbt::End,
- // A single signed byte
- BYTE_ID => Nbt::Byte(stream.read_i8()?),
- // A single signed, big endian 16 bit integer
- SHORT_ID => Nbt::Short(stream.read_i16::<BE>()?),
- // A single signed, big endian 32 bit integer
- INT_ID => Nbt::Int(stream.read_i32::<BE>()?),
- // A single signed, big endian 64 bit integer
- LONG_ID => Nbt::Long(stream.read_i64::<BE>()?),
- // A single, big endian IEEE-754 single-precision floating point
- // number (NaN possible)
- FLOAT_ID => Nbt::Float(stream.read_f32::<BE>()?),
- // A single, big endian IEEE-754 double-precision floating point
- // number (NaN possible)
- DOUBLE_ID => Nbt::Double(stream.read_f64::<BE>()?),
- // A length-prefixed array of signed bytes. The prefix is a signed
- // integer (thus 4 bytes)
- BYTE_ARRAY_ID => Nbt::ByteArray(read_byte_array(stream)?),
- // A length-prefixed modified UTF-8 string. The prefix is an
- // unsigned short (thus 2 bytes) signifying the length of the
- // string in bytes
- STRING_ID => Nbt::String(read_string(stream)?),
- // A list of nameless tags, all of the same type. The list is
- // prefixed with the Type ID of the items it contains (thus 1
- // byte), and the length of the list as a signed integer (a further
- // 4 bytes). If the length of the list is 0 or negative, the type
- // may be 0 (TAG_End) but otherwise it must be any other type. (The
- // notchian implementation uses TAG_End in that situation, but
- // another reference implementation by Mojang uses 1 instead;
- // parsers should accept any type if the length is <= 0).
- LIST_ID => Nbt::List(read_list(stream)?),
- // Effectively a list of a named tags. Order is not guaranteed.
- COMPOUND_ID => Nbt::Compound(read_compound(stream)?),
- // A length-prefixed array of signed integers. The prefix is a
- // signed integer (thus 4 bytes) and indicates the number of 4 byte
- // integers.
- INT_ARRAY_ID => Nbt::IntArray(read_int_array(stream)?),
- // A length-prefixed array of signed longs. The prefix is a signed
- // integer (thus 4 bytes) and indicates the number of 8 byte longs.
- LONG_ARRAY_ID => Nbt::LongArray(read_long_array(stream)?),
- _ => return Err(Error::InvalidTagType(id)),
- })
- }
-
- /// Read the NBT data. This will return a compound tag with a single item.
- ///
- /// Minecraft usually uses this function when reading from files.
- /// [`Nbt::read_any_tag`] is used when reading from the network.
- pub fn read(stream: &mut Cursor<&[u8]>) -> Result<Nbt, Error> {
- // default to compound tag
-
- // the parent compound only ever has one item
- let tag_id = stream.read_u8().unwrap_or(0);
- if tag_id == 0 {
- return Ok(Nbt::End);
- }
- let name = read_string(stream)?;
- let tag = Nbt::read_known(stream, tag_id)?;
- let mut map = NbtCompound::with_capacity(1);
- map.insert_unsorted(name, tag);
-
- Ok(Nbt::Compound(map))
- }
-
- /// Read the NBT data. There is no guarantee that the tag will be a compound
- /// with a single item.
- ///
- /// The Minecraft protocol uses this function when reading from the network.
- /// [`Nbt::read`] is usually used when reading from files.
- pub fn read_any_tag(stream: &mut Cursor<&[u8]>) -> Result<Nbt, Error> {
- let tag_id = stream.read_u8().unwrap_or(0);
- let tag = Nbt::read_known(stream, tag_id)?;
- Ok(tag)
- }
-
- /// Read the NBT data compressed wtih zlib.
- pub fn read_zlib(stream: &mut impl BufRead) -> Result<Nbt, Error> {
- let mut gz = ZlibDecoder::new(stream);
- let mut buf = Vec::new();
- gz.read_to_end(&mut buf)?;
- Nbt::read(&mut Cursor::new(&buf))
- }
-
- /// Read the NBT data compressed wtih gzip.
- pub fn read_gzip(stream: &mut Cursor<Vec<u8>>) -> Result<Nbt, Error> {
- let mut gz = GzDecoder::new(stream);
- let mut buf = Vec::new();
- gz.read_to_end(&mut buf)?;
- Nbt::read(&mut Cursor::new(&buf))
- }
-}
-
-impl McBufReadable for Nbt {
- fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
- Ok(Nbt::read_any_tag(buf)?)
- }
-}
-impl From<Error> for BufReadError {
- fn from(e: Error) -> Self {
- BufReadError::Custom(e.to_string())
- }
-}
diff --git a/azalea-nbt/src/encode.rs b/azalea-nbt/src/encode.rs
deleted file mode 100755
index 34c451d2..00000000
--- a/azalea-nbt/src/encode.rs
+++ /dev/null
@@ -1,296 +0,0 @@
-use crate::tag::*;
-use azalea_buf::McBufWritable;
-use byteorder::{WriteBytesExt, BE};
-use flate2::write::{GzEncoder, ZlibEncoder};
-// use packed_simd_2::{i32x16, i32x2, i32x4, i32x8, i64x2, i64x4, i64x8};
-use std::io::Write;
-
-#[inline]
-fn write_string(writer: &mut impl Write, string: &NbtString) {
- writer.write_u16::<BE>(string.len() as u16).unwrap();
- writer.write_all(string.as_bytes()).unwrap();
-}
-
-#[inline]
-fn write_compound(writer: &mut impl Write, value: &NbtCompound, end_tag: bool) {
- for (key, tag) in value.iter() {
- writer.write_u8(tag.id()).unwrap();
- write_string(writer, key);
- write_known(writer, tag);
- }
- if end_tag {
- writer.write_u8(END_ID).unwrap();
- }
-}
-
-fn write_known(writer: &mut impl Write, tag: &Nbt) {
- match tag {
- Nbt::End => {}
- Nbt::Byte(value) => {
- writer.write_i8(*value).unwrap();
- }
- Nbt::Short(value) => {
- writer.write_i16::<BE>(*value).unwrap();
- }
- Nbt::Int(value) => {
- writer.write_i32::<BE>(*value).unwrap();
- }
- Nbt::Long(value) => {
- writer.write_i64::<BE>(*value).unwrap();
- }
- Nbt::Float(value) => {
- writer.write_f32::<BE>(*value).unwrap();
- }
- Nbt::Double(value) => {
- writer.write_f64::<BE>(*value).unwrap();
- }
- Nbt::ByteArray(value) => {
- write_byte_array(writer, value);
- }
- Nbt::String(value) => {
- write_string(writer, value);
- }
- Nbt::List(value) => {
- write_list(writer, value);
- }
- Nbt::Compound(value) => {
- write_compound(writer, value, true);
- }
- Nbt::IntArray(value) => {
- write_int_array(writer, value);
- }
- Nbt::LongArray(value) => {
- write_long_array(writer, value);
- }
- }
-}
-
-#[inline]
-fn write_list(writer: &mut impl Write, value: &NbtList) {
- writer.write_u8(value.id()).unwrap();
- match value {
- NbtList::Empty => writer.write_all(&[0; 4]).unwrap(),
- NbtList::Byte(l) => {
- writer.write_i32::<BE>(l.len() as i32).unwrap();
- let l = l.as_slice();
- writer
- // convert [i8] into [u8]
- .write_all(unsafe { std::slice::from_raw_parts(l.as_ptr() as *const u8, l.len()) })
- .unwrap();
- }
- NbtList::Short(l) => {
- writer.write_i32::<BE>(l.len() as i32).unwrap();
- for &v in l {
- writer.write_i16::<BE>(v).unwrap();
- }
- }
- NbtList::Int(l) => write_int_array(writer, l),
- NbtList::Long(l) => write_long_array(writer, l),
- NbtList::Float(l) => {
- writer.write_i32::<BE>(l.len() as i32).unwrap();
- for &v in l {
- writer.write_f32::<BE>(v).unwrap();
- }
- }
- NbtList::Double(l) => {
- writer.write_i32::<BE>(l.len() as i32).unwrap();
- for &v in l {
- writer.write_f64::<BE>(v).unwrap();
- }
- }
- NbtList::ByteArray(l) => {
- writer.write_i32::<BE>(l.len() as i32).unwrap();
- for v in l {
- write_byte_array(writer, v);
- }
- }
- NbtList::String(l) => {
- writer.write_i32::<BE>(l.len() as i32).unwrap();
- for v in l {
- write_string(writer, v);
- }
- }
- NbtList::List(l) => {
- writer.write_i32::<BE>(l.len() as i32).unwrap();
- for v in l {
- write_list(writer, v);
- }
- }
- NbtList::Compound(l) => {
- writer.write_i32::<BE>(l.len() as i32).unwrap();
- for v in l {
- write_compound(writer, v, true);
- }
- }
- NbtList::IntArray(l) => {
- writer.write_i32::<BE>(l.len() as i32).unwrap();
- for v in l {
- write_int_array(writer, v);
- }
- }
- NbtList::LongArray(l) => {
- writer.write_i32::<BE>(l.len() as i32).unwrap();
- for v in l {
- write_long_array(writer, v);
- }
- }
- }
-}
-
-#[inline]
-fn write_byte_array(writer: &mut impl Write, value: &[u8]) {
- writer.write_u32::<BE>(value.len() as u32).unwrap();
- writer.write_all(value).unwrap();
-}
-
-#[inline]
-fn write_int_array(writer: &mut impl Write, array: &[i32]) {
- writer.write_i32::<BE>(array.len() as i32).unwrap();
-
- for &item in array {
- writer.write_i32::<BE>(item).unwrap();
- }
-
- // (disabled for now since i realized packed_simd to_be does not work as
- // expected) // flip the bits to big endian with simd
- // let mut position = 0;
- // // x16
- // while array.len() - position >= 16 {
- // let l = unsafe {
- // i32x16::from_slice_unaligned_unchecked(&array[position..]) }; let
- // l = l.to_be(); let l = unsafe { std::mem::transmute::<i32x16,
- // [u8; 64]>(l) }; writer.write_all(&l).unwrap();
- // position += 16;
- // }
- // // x8
- // if array.len() - position >= 8 {
- // let l = unsafe {
- // i32x8::from_slice_unaligned_unchecked(&array[position..]) };
- // let l = l.to_be();
- // let l = unsafe { std::mem::transmute::<i32x8, [u8; 32]>(l) };
- // writer.write_all(&l).unwrap();
- // position += 8;
- // }
- // // x4
- // if array.len() - position >= 4 {
- // let l = unsafe {
- // i32x4::from_slice_unaligned_unchecked(&array[position..]) };
- // let l = l.to_be();
- // let l = unsafe { std::mem::transmute::<i32x4, [u8; 16]>(l) };
- // writer.write_all(&l).unwrap();
- // position += 4;
- // }
- // // x2
- // if array.len() - position >= 2 {
- // let l = unsafe {
- // i32x2::from_slice_unaligned_unchecked(&array[position..]) };
- // let l = l.to_be();
- // let l = l.swap_bytes();
- // let l = unsafe { std::mem::transmute::<i32x2, [u8; 8]>(l) };
- // writer.write_all(&l).unwrap();
- // position += 2;
- // }
- // // x1 ... just a normal write_i32
- // if array.len() - position >= 1 {
- // writer.write_i32::<BE>(array[position]).unwrap();
- // }
-}
-
-#[inline]
-fn write_long_array(writer: &mut impl Write, l: &[i64]) {
- writer.write_i32::<BE>(l.len() as i32).unwrap();
-
- for &item in l {
- writer.write_i64::<BE>(item).unwrap();
- }
-
- // (disabled for now since i realized packed_simd to_be does not work as
- // expected)
-
- // // flip the bits to big endian with simd
- // let mut position = 0;
- // // x16
- // while l.len() - position >= 8 {
- // let l = unsafe {
- // i64x8::from_slice_unaligned_unchecked(&l[position..]) };
- // l.to_be();
- // let l = unsafe { std::mem::transmute::<i64x8, [u8; 64]>(l) };
- // writer.write_all(&l).unwrap();
- // position += 8;
- // }
- // // x4
- // if l.len() - position >= 4 {
- // let l = unsafe {
- // i64x4::from_slice_unaligned_unchecked(&l[position..]) };
- // l.to_be();
- // let l = unsafe { std::mem::transmute::<i64x4, [u8; 32]>(l) };
- // writer.write_all(&l).unwrap();
- // position += 4;
- // }
- // // x2
- // if l.len() - position >= 2 {
- // let l = unsafe {
- // i64x2::from_slice_unaligned_unchecked(&l[position..]) };
- // l.to_be();
- // let l = unsafe { std::mem::transmute::<i64x2, [u8; 16]>(l) };
- // writer.write_all(&l).unwrap();
- // position += 2;
- // }
- // // x1 ... just a normal write_i32
- // if l.len() - position >= 1 {
- // writer.write_i64::<BE>(l[position]).unwrap();
- // }
-}
-
-impl Nbt {
- /// Write the compound tag as NBT data.
- ///
- /// # Panics
- ///
- /// Will panic if the tag is not a Compound or End tag.
- pub fn write(&self, writer: &mut impl Write) {
- match self {
- Nbt::Compound(value) => {
- write_compound(writer, value, false);
- }
- Nbt::End => {
- END_ID.write_into(writer).unwrap();
- }
- _ => panic!("Not a compound tag"),
- }
- }
-
- /// Write any tag as NBT data. This is used by Minecraft when writing to the
- /// network, otherwise [`Nbt::write`] is usually used instead.
- pub fn write_any(&self, writer: &mut impl Write) {
- writer.write_u8(self.id()).unwrap();
- write_known(writer, self);
- }
-
- /// Write the compound tag as NBT data compressed wtih zlib.
- ///
- /// # Errors
- ///
- /// Returns an `Err` if it's not a Compound or End tag.
- pub fn write_zlib(&self, writer: &mut impl Write) {
- let mut encoder = ZlibEncoder::new(writer, flate2::Compression::default());
- self.write(&mut encoder)
- }
-
- /// Write the compound tag as NBT data compressed wtih gzip.
- ///
- /// # Errors
- ///
- /// Returns an `Err` if it's not a Compound or End tag.
- pub fn write_gzip(&self, writer: &mut impl Write) {
- let mut encoder = GzEncoder::new(writer, flate2::Compression::default());
- self.write(&mut encoder)
- }
-}
-
-impl McBufWritable for Nbt {
- fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
- self.write_any(buf);
- Ok(())
- }
-}
diff --git a/azalea-nbt/src/error.rs b/azalea-nbt/src/error.rs
deleted file mode 100755
index ace7fcd3..00000000
--- a/azalea-nbt/src/error.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use thiserror::Error;
-
-#[derive(Debug, Error)]
-pub enum Error {
- #[error("Invalid tag type: {0}")]
- InvalidTagType(u8),
- #[error("Invalid tag")]
- InvalidTag,
- #[error("Write error: {0}")]
- WriteError(#[from] std::io::Error),
- #[error("Utf8 error: {0}")]
- Utf8Error(#[from] std::str::Utf8Error),
- #[error("Unexpected EOF")]
- UnexpectedEof,
-}
diff --git a/azalea-nbt/src/lib.rs b/azalea-nbt/src/lib.rs
deleted file mode 100755
index 1a636520..00000000
--- a/azalea-nbt/src/lib.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-#![doc = include_str!("../README.md")]
-
-mod decode;
-mod encode;
-mod error;
-mod tag;
-
-pub use error::Error;
-pub use tag::*;
-
-#[cfg(test)]
-mod tests {
- use std::io::Cursor;
-
- use crate::tag::NbtCompound;
-
- use super::*;
- use azalea_buf::{McBufReadable, McBufWritable};
-
- #[test]
- fn mcbuf_nbt() {
- let mut buf = Vec::new();
- let tag = Nbt::Compound(NbtCompound::from_iter(vec![(
- "hello world".into(),
- Nbt::Compound(NbtCompound::from_iter(vec![(
- "name".into(),
- Nbt::String("Bananrama".into()),
- )])),
- )]));
- tag.write_into(&mut buf).unwrap();
-
- let mut buf = Cursor::new(&buf[..]);
-
- let result = Nbt::read_from(&mut buf).unwrap();
- assert_eq!(
- result,
- Nbt::Compound(NbtCompound::from_iter(vec![(
- "hello world".into(),
- Nbt::Compound(NbtCompound::from_iter(vec![(
- "name".into(),
- Nbt::String("Bananrama".into()),
- )])),
- )]))
- );
- }
-}
diff --git a/azalea-nbt/src/tag.rs b/azalea-nbt/src/tag.rs
deleted file mode 100755
index 224db2d3..00000000
--- a/azalea-nbt/src/tag.rs
+++ /dev/null
@@ -1,271 +0,0 @@
-use compact_str::CompactString;
-use enum_as_inner::EnumAsInner;
-#[cfg(feature = "serde")]
-use serde::{ser::SerializeMap, Deserialize, Serialize};
-
-pub type NbtByte = i8;
-pub type NbtShort = i16;
-pub type NbtInt = i32;
-pub type NbtLong = i64;
-pub type NbtFloat = f32;
-pub type NbtDouble = f64;
-pub type NbtByteArray = Vec<u8>;
-pub type NbtString = CompactString;
-pub type NbtIntArray = Vec<i32>;
-pub type NbtLongArray = Vec<i64>;
-
-pub const END_ID: u8 = 0;
-pub const BYTE_ID: u8 = 1;
-pub const SHORT_ID: u8 = 2;
-pub const INT_ID: u8 = 3;
-pub const LONG_ID: u8 = 4;
-pub const FLOAT_ID: u8 = 5;
-pub const DOUBLE_ID: u8 = 6;
-pub const BYTE_ARRAY_ID: u8 = 7;
-pub const STRING_ID: u8 = 8;
-pub const LIST_ID: u8 = 9;
-pub const COMPOUND_ID: u8 = 10;
-pub const INT_ARRAY_ID: u8 = 11;
-pub const LONG_ARRAY_ID: u8 = 12;
-
-/// An NBT value.
-#[derive(Clone, Debug, PartialEq, Default, EnumAsInner)]
-#[repr(u8)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(untagged))]
-pub enum Nbt {
- #[default]
- End = END_ID,
- Byte(NbtByte) = BYTE_ID,
- Short(NbtShort) = SHORT_ID,
- Int(NbtInt) = INT_ID,
- Long(NbtLong) = LONG_ID,
- Float(NbtFloat) = FLOAT_ID,
- Double(NbtDouble) = DOUBLE_ID,
- ByteArray(NbtByteArray) = BYTE_ARRAY_ID,
- String(NbtString) = STRING_ID,
- List(NbtList) = LIST_ID,
- Compound(NbtCompound) = COMPOUND_ID,
- IntArray(NbtIntArray) = INT_ARRAY_ID,
- LongArray(NbtLongArray) = LONG_ARRAY_ID,
-}
-impl Nbt {
- /// Get the numerical ID of the tag type.
- #[inline]
- pub fn id(&self) -> u8 {
- // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a `repr(C)`
- // `union` between `repr(C)` structs, each of which has the `u8`
- // discriminant as its first field, so we can read the discriminant
- // without offsetting the pointer.
- unsafe { *<*const _>::from(self).cast::<u8>() }
- }
-}
-
-/// An NBT value.
-#[derive(Clone, Debug, PartialEq)]
-#[repr(u8)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(untagged))]
-pub enum NbtList {
- Empty = END_ID,
- Byte(Vec<NbtByte>) = BYTE_ID,
- Short(Vec<NbtShort>) = SHORT_ID,
- Int(Vec<NbtInt>) = INT_ID,
- Long(Vec<NbtLong>) = LONG_ID,
- Float(Vec<NbtFloat>) = FLOAT_ID,
- Double(Vec<NbtDouble>) = DOUBLE_ID,
- ByteArray(Vec<NbtByteArray>) = BYTE_ARRAY_ID,
- String(Vec<NbtString>) = STRING_ID,
- List(Vec<NbtList>) = LIST_ID,
- Compound(Vec<NbtCompound>) = COMPOUND_ID,
- IntArray(Vec<NbtIntArray>) = INT_ARRAY_ID,
- LongArray(Vec<NbtLongArray>) = LONG_ARRAY_ID,
-}
-
-impl NbtList {
- /// Get the numerical ID of the tag type.
- #[inline]
- pub fn id(&self) -> u8 {
- // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a `repr(C)`
- // `union` between `repr(C)` structs, each of which has the `u8`
- // discriminant as its first field, so we can read the discriminant
- // without offsetting the pointer.
- unsafe { *<*const _>::from(self).cast::<u8>() }
- }
-}
-impl From<Vec<NbtByte>> for NbtList {
- fn from(v: Vec<NbtByte>) -> Self {
- Self::Byte(v)
- }
-}
-impl From<Vec<NbtShort>> for NbtList {
- fn from(v: Vec<NbtShort>) -> Self {
- Self::Short(v)
- }
-}
-impl From<Vec<NbtInt>> for NbtList {
- fn from(v: Vec<NbtInt>) -> Self {
- Self::Int(v)
- }
-}
-impl From<Vec<NbtLong>> for NbtList {
- fn from(v: Vec<NbtLong>) -> Self {
- Self::Long(v)
- }
-}
-impl From<Vec<NbtFloat>> for NbtList {
- fn from(v: Vec<NbtFloat>) -> Self {
- Self::Float(v)
- }
-}
-impl From<Vec<NbtDouble>> for NbtList {
- fn from(v: Vec<NbtDouble>) -> Self {
- Self::Double(v)
- }
-}
-impl From<Vec<NbtByteArray>> for NbtList {
- fn from(v: Vec<NbtByteArray>) -> Self {
- Self::ByteArray(v)
- }
-}
-impl From<Vec<NbtString>> for NbtList {
- fn from(v: Vec<NbtString>) -> Self {
- Self::String(v)
- }
-}
-impl From<Vec<NbtList>> for NbtList {
- fn from(v: Vec<NbtList>) -> Self {
- Self::List(v)
- }
-}
-impl From<Vec<NbtCompound>> for NbtList {
- fn from(v: Vec<NbtCompound>) -> Self {
- Self::Compound(v)
- }
-}
-impl From<Vec<NbtIntArray>> for NbtList {
- fn from(v: Vec<NbtIntArray>) -> Self {
- Self::IntArray(v)
- }
-}
-impl From<Vec<NbtLongArray>> for NbtList {
- fn from(v: Vec<NbtLongArray>) -> Self {
- Self::LongArray(v)
- }
-}
-
-// thanks to Moulberry/Graphite for the idea to use a vec and binary search
-#[derive(Debug, Clone, Default, PartialEq)]
-pub struct NbtCompound {
- inner: Vec<(NbtString, Nbt)>,
-}
-impl NbtCompound {
- #[inline]
- pub fn with_capacity(capacity: usize) -> Self {
- Self {
- inner: Vec::with_capacity(capacity),
- }
- }
-
- #[inline]
- fn binary_search(&self, key: &NbtString) -> Result<usize, usize> {
- self.inner.binary_search_by(|(k, _)| k.cmp(key))
- }
-
- /// Get a reference to the value corresponding to the key in this compound.
- ///
- /// If you previously used [`Self::insert_unsorted`] without [`Self::sort`],
- /// this function may return incorrect results.
- #[inline]
- pub fn get(&self, key: &str) -> Option<&Nbt> {
- if self.is_worth_sorting() {
- let key = NbtString::from(key);
- self.binary_search(&key).ok().map(|i| &self.inner[i].1)
- } else {
- for (k, v) in &self.inner {
- if &key == k {
- return Some(v);
- }
- }
- None
- }
- }
-
- #[inline]
- pub fn insert_unsorted(&mut self, key: NbtString, value: Nbt) {
- self.inner.push((key, value));
- }
-
- /// Insert an item into the compound, returning the previous value if it
- /// existed.
- ///
- /// If you're adding many items at once, it's more efficient to use
- /// [`Self::insert_unsorted`] and then [`Self::sort`] after everything is
- /// inserted.
- #[inline]
- pub fn insert(&mut self, key: NbtString, value: Nbt) {
- self.inner.push((key, value));
- self.sort()
- }
-
- #[inline]
- pub fn sort(&mut self) {
- if !self.is_worth_sorting() {
- return;
- }
- self.inner.sort_unstable_by(|(a, _), (b, _)| a.cmp(b));
- }
-
- #[inline]
- pub fn iter(&self) -> std::slice::Iter<'_, (CompactString, Nbt)> {
- self.inner.iter()
- }
-
- #[inline]
- fn is_worth_sorting(&self) -> bool {
- // i don't actually know when binary search starts being better, but it's at
- // least more than 12
- self.inner.len() >= 32
- }
-}
-
-impl IntoIterator for NbtCompound {
- type Item = (NbtString, Nbt);
- type IntoIter = std::vec::IntoIter<Self::Item>;
-
- fn into_iter(self) -> Self::IntoIter {
- self.inner.into_iter()
- }
-}
-
-#[cfg(feature = "serde")]
-impl Serialize for NbtCompound {
- fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
- let mut map = serializer.serialize_map(Some(self.inner.len()))?;
- for (key, value) in &self.inner {
- map.serialize_entry(key, value)?;
- }
- map.end()
- }
-}
-#[cfg(feature = "serde")]
-impl<'de> Deserialize<'de> for NbtCompound {
- fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
- use std::collections::BTreeMap;
- let map = <BTreeMap<NbtString, Nbt> as Deserialize>::deserialize(deserializer)?;
- Ok(Self {
- inner: map.into_iter().collect(),
- })
- }
-}
-
-impl FromIterator<(NbtString, Nbt)> for NbtCompound {
- fn from_iter<T: IntoIterator<Item = (NbtString, Nbt)>>(iter: T) -> Self {
- let inner = iter.into_iter().collect::<Vec<_>>();
- Self { inner }
- }
-}
-
-impl From<Vec<(NbtString, Nbt)>> for NbtCompound {
- fn from(inner: Vec<(NbtString, Nbt)>) -> Self {
- Self { inner }
- }
-}