From 395a26bd4161e0d886ce1f420a1087717acd78c2 Mon Sep 17 00:00:00 2001 From: shenjack <3695888@qq.com> Date: Sun, 10 Mar 2024 20:52:36 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=9C=AA=E5=AF=B9=E9=BD=90?= =?UTF-8?q?=E9=97=AE=E9=A2=98,=20=E6=B7=BB=E5=8A=A0=E4=B8=80=E4=B8=AA=20re?= =?UTF-8?q?adi16=20be=20api(=E8=99=BD=E8=AF=B4=E7=94=A8=E4=B8=8D=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shen-nbt5/Cargo.toml | 2 +- shen-nbt5/src/lib.rs | 2 +- shen-nbt5/src/reader.rs | 66 +++++++++++++++++++++++++++++------------ shen-nbt5/src/tests.rs | 40 +++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 21 deletions(-) diff --git a/shen-nbt5/Cargo.toml b/shen-nbt5/Cargo.toml index 4b12897..34612a3 100644 --- a/shen-nbt5/Cargo.toml +++ b/shen-nbt5/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shen-nbt5" -version = "0.4.3" +version = "0.4.4" edition = "2021" description = "Just A FASSST NBT parser/writer" homepage = "https://github.com/shenjackyuanjie/nbt-rust" diff --git a/shen-nbt5/src/lib.rs b/shen-nbt5/src/lib.rs index 00fb695..de4fa83 100644 --- a/shen-nbt5/src/lib.rs +++ b/shen-nbt5/src/lib.rs @@ -237,7 +237,7 @@ impl std::fmt::Display for NbtError { } /// 核心 Value -/// +/// /// 暂时不支持 `from_value` 和 `to_value` /// https://github.com/shenjackyuanjie/nbt-rust/issues/1 #[derive(Debug, Clone, PartialEq)] diff --git a/shen-nbt5/src/reader.rs b/shen-nbt5/src/reader.rs index 2418e09..a15f6f4 100644 --- a/shen-nbt5/src/reader.rs +++ b/shen-nbt5/src/reader.rs @@ -721,6 +721,26 @@ impl NbtReader<'_> { self.cursor += len; value } + /// 读取指定长度的 i16 数组 + /// + /// # 安全性 + /// + /// 长度溢出会导致 UB + #[inline] + pub unsafe fn read_be_i16_array_unsafe(&mut self, len: usize) -> Vec { + let mut value: Vec = 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 数组 /// /// # 安全性 @@ -728,15 +748,39 @@ impl NbtReader<'_> { /// 长度溢出会导致 UB #[inline] pub unsafe fn read_be_i32_array_unsafe(&mut self, len: usize) -> Vec { - let value = - std::slice::from_raw_parts(self.data[self.cursor..].as_ptr() as *const i32, len); - let mut value = value.to_vec(); + let mut value: Vec = Vec::with_capacity(len); + std::ptr::copy_nonoverlapping( + 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 { *n = n.to_be(); } self.cursor += len * 4; value } + /// 读取指定长度的 i64 数组 + /// + /// # 安全性 + /// + /// 长度溢出会导致 UB + #[inline] + pub unsafe fn read_be_i64_array_unsafe(&mut self, len: usize) -> Vec { + let mut value: Vec = 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 数组 /// /// # 安全性 @@ -755,22 +799,6 @@ impl NbtReader<'_> { /// /// # 安全性 /// - /// 长度溢出会导致 UB - #[inline] - pub unsafe fn read_be_i64_array_unsafe(&mut self, len: usize) -> Vec { - 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 #[inline] pub fn read_be_i64_array(&mut self, len: usize) -> Vec { diff --git a/shen-nbt5/src/tests.rs b/shen-nbt5/src/tests.rs index 5e07b82..ec0ff31 100644 --- a/shen-nbt5/src/tests.rs +++ b/shen-nbt5/src/tests.rs @@ -280,6 +280,46 @@ mod unsafe_test { 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 {