aboutsummaryrefslogtreecommitdiff
path: root/azalea-nbt/src
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2023-03-24 13:55:11 +0000
committermat <github@matdoes.dev>2023-03-24 13:55:11 +0000
commit4b387c320c126d2db69ec6f2dc1a610a58928a2e (patch)
tree56a22a7872cd1309721c05a770bebac05d0adedb /azalea-nbt/src
parentbdc42557479e6201f88151468ef1331820f62681 (diff)
parent0641dac7f0aa6c055fca8ab633ad85859d0ddd97 (diff)
downloadazalea-drasl-4b387c320c126d2db69ec6f2dc1a610a58928a2e.tar.xz
fix merge conflict
Diffstat (limited to 'azalea-nbt/src')
-rwxr-xr-xazalea-nbt/src/encode.rs73
-rwxr-xr-xazalea-nbt/src/tag.rs90
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 }
+ }
+}