diff --git a/simdnbt/src/borrow/compound.rs b/simdnbt/src/borrow/compound.rs index 3eaa876..9eac7f4 100644 --- a/simdnbt/src/borrow/compound.rs +++ b/simdnbt/src/borrow/compound.rs @@ -211,7 +211,9 @@ impl<'a: 'tape, 'tape> Iterator for NbtCompoundIter<'a, 'tape> { } let name_length_ptr = self.tape[self.current_tape_offset].u64() as *const UnalignedU16; - let name_length = u16::from(unsafe { *name_length_ptr }).swap_bytes(); + let name_length = u16::from(unsafe { *name_length_ptr }); + #[cfg(target_endian = "little")] + let name_length = name_length.swap_bytes(); let name_ptr = unsafe { name_length_ptr.add(1) as *const u8 }; let name_slice = unsafe { std::slice::from_raw_parts(name_ptr, name_length as usize) }; let name = Mutf8Str::from_slice(name_slice); diff --git a/simdnbt/src/borrow/list.rs b/simdnbt/src/borrow/list.rs index b85cd53..04d5373 100644 --- a/simdnbt/src/borrow/list.rs +++ b/simdnbt/src/borrow/list.rs @@ -317,9 +317,11 @@ impl<'a, 'tape> NbtList<'a, 'tape> { return None; } let length_ptr = el.ptr::(); - let length = unsafe { u32::from(*length_ptr).swap_bytes() as usize }; + let length = unsafe { u32::from(*length_ptr) }; + #[cfg(target_endian = "little")] + let length = length.swap_bytes(); let byte_array = - unsafe { std::slice::from_raw_parts(length_ptr.add(1) as *const i8, length) }; + unsafe { std::slice::from_raw_parts(length_ptr.add(1) as *const i8, length as usize) }; Some(byte_array) } pub fn shorts(&self) -> Option> { @@ -830,8 +832,10 @@ where T: Copy + SwappableNumber, { // length is always a u32 - let length = unsafe { u32::from(*ptr).swap_bytes() as usize }; - let length_in_bytes = length * std::mem::size_of::(); + let length = unsafe { u32::from(*ptr) }; + #[cfg(target_endian = "little")] + let length = length.swap_bytes(); + let length_in_bytes = length as usize * std::mem::size_of::(); let array_be = unsafe { std::slice::from_raw_parts(ptr.add(1) as *const u8, length_in_bytes) }; Some(RawList::new(array_be)) } diff --git a/simdnbt/src/lib.rs b/simdnbt/src/lib.rs index b55bfdd..e04900f 100644 --- a/simdnbt/src/lib.rs +++ b/simdnbt/src/lib.rs @@ -22,3 +22,31 @@ pub use mutf8::Mutf8Str; pub use traits::{Deserialize, FromNbtTag, Serialize, ToNbtTag}; pub use simdnbt_derive::*; + +#[cfg(test)] +mod tests { + use std::io::{Cursor, Read}; + + use flate2::bufread::GzDecoder; + + #[test] + fn complex_player_borrow_and_owned() { + let src = include_bytes!("../tests/complex_player.dat").to_vec(); + let mut src_slice = src.as_slice(); + let mut decoded_src_decoder = GzDecoder::new(&mut src_slice); + let mut decoded_src = Vec::new(); + decoded_src_decoder.read_to_end(&mut decoded_src).unwrap(); + let nbt_borrow = crate::borrow::read(&mut Cursor::new(&decoded_src)) + .unwrap() + .unwrap() + .as_compound() + .to_owned(); + let nbt_owned = crate::owned::read(&mut Cursor::new(&decoded_src)) + .unwrap() + .unwrap() + .as_compound(); + + // (there's another test in owned to make sure that PartialEq actually works) + assert_eq!(nbt_borrow, nbt_owned); + } +} diff --git a/simdnbt/src/owned/mod.rs b/simdnbt/src/owned/mod.rs index 423abce..6365ce9 100644 --- a/simdnbt/src/owned/mod.rs +++ b/simdnbt/src/owned/mod.rs @@ -212,7 +212,7 @@ impl BaseNbt { self.tag.write(data); } - pub fn into_inner(self) -> NbtCompound { + pub fn as_compound(self) -> NbtCompound { self.tag } } @@ -785,4 +785,21 @@ mod tests { } assert_eq!(ints.len(), 1023); } + + #[test] + fn equals_can_fail() { + let src = include_bytes!("../../tests/complex_player.dat").to_vec(); + let mut src_slice = src.as_slice(); + let mut decoded_src_decoder = GzDecoder::new(&mut src_slice); + let mut decoded_src = Vec::new(); + decoded_src_decoder.read_to_end(&mut decoded_src).unwrap(); + let nbt = super::read(&mut Cursor::new(&decoded_src)) + .unwrap() + .unwrap() + .as_compound(); + let mut modified_nbt = nbt.clone(); + modified_nbt.insert("foodExhaustionLevel", 2.0f32); + + assert_ne!(nbt, modified_nbt); + } } diff --git a/simdnbt/src/swap_endianness.rs b/simdnbt/src/swap_endianness.rs index 58df950..d5ea4b8 100644 --- a/simdnbt/src/swap_endianness.rs +++ b/simdnbt/src/swap_endianness.rs @@ -1,5 +1,9 @@ use std::{mem, simd::prelude::*}; +// TODO: relying on auto-vectorization for swapping bits is significantly faster +// than this code, we should figure out a way to make that work dynamically and +// then delete all this. + mod private { pub trait Sealed {} @@ -310,6 +314,9 @@ pub fn swap_endianness(data: &[u8]) -> Vec { } #[cfg(test)] +// swap_endianness_as_u8 only does anything on LE systems, so otherwise it'll +// error +#[cfg(target_endian = "little")] mod tests { use super::*;