修复未对齐问题, 添加一个 readi16 be api(虽说用不上

This commit is contained in:
shenjack 2024-03-10 20:52:36 +08:00
parent 1d8a7400eb
commit 395a26bd41
Signed by: shenjack
GPG Key ID: 7B1134A979775551
4 changed files with 89 additions and 21 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "shen-nbt5" name = "shen-nbt5"
version = "0.4.3" version = "0.4.4"
edition = "2021" edition = "2021"
description = "Just A FASSST NBT parser/writer" description = "Just A FASSST NBT parser/writer"
homepage = "https://github.com/shenjackyuanjie/nbt-rust" homepage = "https://github.com/shenjackyuanjie/nbt-rust"

View File

@ -237,7 +237,7 @@ impl std::fmt::Display for NbtError {
} }
/// 核心 Value /// 核心 Value
/// ///
/// 暂时不支持 `from_value` 和 `to_value` /// 暂时不支持 `from_value` 和 `to_value`
/// https://github.com/shenjackyuanjie/nbt-rust/issues/1 /// https://github.com/shenjackyuanjie/nbt-rust/issues/1
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]

View File

@ -721,6 +721,26 @@ impl NbtReader<'_> {
self.cursor += len; self.cursor += len;
value value
} }
/// 读取指定长度的 i16 数组
///
/// # 安全性
///
/// 长度溢出会导致 UB
#[inline]
pub unsafe fn read_be_i16_array_unsafe(&mut self, len: usize) -> Vec<i16> {
let mut value: Vec<i16> = Vec::with_capacity(len);
std::ptr::copy_nonoverlapping(
self.data[self.cursor..].as_ptr() as *const u8,
value.as_ptr() as *mut u8,
len * 2,
);
value.set_len(len);
for n in &mut value {
*n = n.to_be();
}
self.cursor += len * 2;
value
}
/// 读取指定长度的 i32 数组 /// 读取指定长度的 i32 数组
/// ///
/// # 安全性 /// # 安全性
@ -728,15 +748,39 @@ impl NbtReader<'_> {
/// 长度溢出会导致 UB /// 长度溢出会导致 UB
#[inline] #[inline]
pub unsafe fn read_be_i32_array_unsafe(&mut self, len: usize) -> Vec<i32> { pub unsafe fn read_be_i32_array_unsafe(&mut self, len: usize) -> Vec<i32> {
let value = let mut value: Vec<i32> = Vec::with_capacity(len);
std::slice::from_raw_parts(self.data[self.cursor..].as_ptr() as *const i32, len); std::ptr::copy_nonoverlapping(
let mut value = value.to_vec(); self.data[self.cursor..].as_ptr() as *const u8,
value.as_ptr() as *mut u8,
len * 4,
);
value.set_len(len);
for n in &mut value { for n in &mut value {
*n = n.to_be(); *n = n.to_be();
} }
self.cursor += len * 4; self.cursor += len * 4;
value value
} }
/// 读取指定长度的 i64 数组
///
/// # 安全性
///
/// 长度溢出会导致 UB
#[inline]
pub unsafe fn read_be_i64_array_unsafe(&mut self, len: usize) -> Vec<i64> {
let mut value: Vec<i64> = Vec::with_capacity(len);
std::ptr::copy_nonoverlapping(
self.data[self.cursor..].as_ptr() as *const u8,
value.as_ptr() as *mut u8,
len * 8,
);
value.set_len(len);
for n in &mut value {
*n = n.to_be();
}
self.cursor += len * 8;
value
}
/// 读取指定长度的 i32 数组 /// 读取指定长度的 i32 数组
/// ///
/// # 安全性 /// # 安全性
@ -755,22 +799,6 @@ impl NbtReader<'_> {
/// ///
/// # 安全性 /// # 安全性
/// ///
/// 长度溢出会导致 UB
#[inline]
pub unsafe fn read_be_i64_array_unsafe(&mut self, len: usize) -> Vec<i64> {
let value =
std::slice::from_raw_parts(self.data[self.cursor..].as_ptr() as *const i64, len);
let mut value = value.to_vec();
for n in &mut value {
*n = n.to_be();
}
self.cursor += len * 8;
value
}
/// 读取指定长度的 i64 数组
///
/// # 安全性
///
/// 长度溢出会导致 panic /// 长度溢出会导致 panic
#[inline] #[inline]
pub fn read_be_i64_array(&mut self, len: usize) -> Vec<i64> { pub fn read_be_i64_array(&mut self, len: usize) -> Vec<i64> {

View File

@ -280,6 +280,46 @@ mod unsafe_test {
assert_eq!(reader.cursor, 100 * 8); assert_eq!(reader.cursor, 100 * 8);
} }
} }
/// 未对齐的地址
#[test]
fn unaligned_read_u16_array() {
let mut value = vec![0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04];
let mut reader = NbtReader::new(&mut value);
let value = reader.read_u8();
assert_eq!(value, 0x01);
assert_eq!(reader.cursor, 1);
unsafe {
// 读取 u16 数组
let array = reader.read_be_i16_array_unsafe(3);
assert_eq!(array, vec![0x0203, 0x0401, 0x0203]);
assert_eq!(reader.cursor, 7);
let value = reader.read_u8();
assert_eq!(value, 0x04);
assert_eq!(reader.cursor, 8);
}
}
/// 依然是未对齐
/// 只不过是 u32/i32
#[test]
fn unaligned_read_x32_array() {
let mut value = gen_datas(202);
let mut reader = NbtReader::new(&mut value);
let value = reader.read_u8();
assert_eq!(value, 0x00);
assert_eq!(reader.cursor, 1);
unsafe {
let array = reader.read_be_i32_array_unsafe(50);
reader.roll_back(50 * 4);
let safe_array = reader.read_be_i32_array(50);
assert_eq!(array, safe_array);
assert_eq!(reader.cursor, 201);
}
let value = reader.read_u8();
assert_eq!(value, 201);
assert_eq!(reader.cursor, 202);
}
} }
mod nbt { mod nbt {