1
0
Fork 0
mirror of https://github.com/azalea-rs/simdnbt.git synced 2025-08-02 07:26:04 +00:00

fix errors on big-endian systems

This commit is contained in:
mat 2024-10-18 06:58:40 +00:00
parent 969fd38fa6
commit 6c54c4c240
5 changed files with 64 additions and 6 deletions

View file

@ -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);

View file

@ -317,9 +317,11 @@ impl<'a, 'tape> NbtList<'a, 'tape> {
return None;
}
let length_ptr = el.ptr::<UnalignedU32>();
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<Vec<i16>> {
@ -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::<T>();
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::<T>();
let array_be = unsafe { std::slice::from_raw_parts(ptr.add(1) as *const u8, length_in_bytes) };
Some(RawList::new(array_be))
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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<T: SwappableNumber>(data: &[u8]) -> Vec<T> {
}
#[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::*;