diff options
| author | mat <github@matdoes.dev> | 2023-03-24 13:55:11 +0000 |
|---|---|---|
| committer | mat <github@matdoes.dev> | 2023-03-24 13:55:11 +0000 |
| commit | 4b387c320c126d2db69ec6f2dc1a610a58928a2e (patch) | |
| tree | 56a22a7872cd1309721c05a770bebac05d0adedb /azalea-nbt/src | |
| parent | bdc42557479e6201f88151468ef1331820f62681 (diff) | |
| parent | 0641dac7f0aa6c055fca8ab633ad85859d0ddd97 (diff) | |
| download | azalea-drasl-4b387c320c126d2db69ec6f2dc1a610a58928a2e.tar.xz | |
fix merge conflict
Diffstat (limited to 'azalea-nbt/src')
| -rwxr-xr-x | azalea-nbt/src/encode.rs | 73 | ||||
| -rwxr-xr-x | azalea-nbt/src/tag.rs | 90 |
2 files changed, 148 insertions, 15 deletions
diff --git a/azalea-nbt/src/encode.rs b/azalea-nbt/src/encode.rs index bf56c223..f5195327 100755 --- a/azalea-nbt/src/encode.rs +++ b/azalea-nbt/src/encode.rs @@ -2,6 +2,7 @@ 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(always)] @@ -81,14 +82,78 @@ fn write_list(writer: &mut impl Write, value: &NbtList) { } NbtList::Int(l) => { writer.write_i32::<BE>(l.len() as i32).unwrap(); - for &v in l { - writer.write_i32::<BE>(v).unwrap(); + // flip the bits to big endian with simd + let l = l.as_slice(); + let mut position = 0; + // x16 + while l.len() - position >= 16 { + let l = unsafe { i32x16::from_slice_unaligned_unchecked(&l[position..]) }; + l.to_be(); + let l = unsafe { std::mem::transmute::<i32x16, [u8; 64]>(l) }; + writer.write_all(&l).unwrap(); + position += 16; + } + // x8 + if l.len() - position >= 8 { + let l = unsafe { i32x8::from_slice_unaligned_unchecked(&l[position..]) }; + l.to_be(); + let l = unsafe { std::mem::transmute::<i32x8, [u8; 32]>(l) }; + writer.write_all(&l).unwrap(); + position += 8; + } + // x4 + if l.len() - position >= 4 { + let l = unsafe { i32x4::from_slice_unaligned_unchecked(&l[position..]) }; + l.to_be(); + let l = unsafe { std::mem::transmute::<i32x4, [u8; 16]>(l) }; + writer.write_all(&l).unwrap(); + position += 4; + } + // x2 + if l.len() - position >= 2 { + let l = unsafe { i32x2::from_slice_unaligned_unchecked(&l[position..]) }; + l.to_be(); + let l = unsafe { std::mem::transmute::<i32x2, [u8; 8]>(l) }; + writer.write_all(&l).unwrap(); + position += 2; + } + // x1 ... just a normal write_i32 + if l.len() - position >= 1 { + writer.write_i32::<BE>(l[position]).unwrap(); } } NbtList::Long(l) => { writer.write_i32::<BE>(l.len() as i32).unwrap(); - for &v in l { - writer.write_i64::<BE>(v).unwrap(); + // flip the bits to big endian with simd + let l = l.as_slice(); + 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(); } } NbtList::Float(l) => { diff --git a/azalea-nbt/src/tag.rs b/azalea-nbt/src/tag.rs index 32d73a7c..efb6bdd2 100755 --- a/azalea-nbt/src/tag.rs +++ b/azalea-nbt/src/tag.rs @@ -48,6 +48,17 @@ pub enum Nbt { 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)] @@ -69,7 +80,7 @@ pub enum NbtList { LongArray(Vec<NbtLongArray>) = LONG_ARRAY_ID, } -impl Nbt { +impl NbtList { /// Get the numerical ID of the tag type. #[inline] pub fn id(&self) -> u8 { @@ -80,15 +91,64 @@ impl Nbt { unsafe { *<*const _>::from(self).cast::<u8>() } } } -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) } } @@ -161,7 +221,9 @@ impl NbtCompound { #[inline] fn is_worth_sorting(&self) -> bool { - self.inner.len() >= 128 + // i don't actually know when binary search starts being better, but it's at + // least more than 12 + self.inner.len() >= 32 } } #[cfg(feature = "serde")] @@ -191,3 +253,9 @@ impl FromIterator<(NbtString, Nbt)> for NbtCompound { Self { inner } } } + +impl From<Vec<(NbtString, Nbt)>> for NbtCompound { + fn from(inner: Vec<(NbtString, Nbt)>) -> Self { + Self { inner } + } +} |
