更新NbtReader的read_f32_unchecked和read_f64_unchecked方法的文档

This commit is contained in:
shenjack 2024-03-08 20:54:21 +08:00
parent 28f76ad4ad
commit be3fbe811a
Signed by: shenjack
GPG Key ID: 7B1134A979775551
2 changed files with 57 additions and 51 deletions

View File

@ -16,36 +16,37 @@ pub struct NbtReader<'data> {
// pub endian: Endian, // pub endian: Endian,
} }
macro_rules! read { macro_rules! read_uncheck {
($name:ident, $ty:ty, $size:literal) => { ($name:ident, $ty:ty, $size:literal) => {
#[doc = concat!("读取 ", stringify!($ty), " 类型 ", $size, " 长度的数据")] #[doc = concat!("读取 ", stringify!($ty), " 类型 ", $size, " 长度的数据")]
/// ///
#[doc = "转换大小端"] #[doc = "转换大小端"]
pub fn $name(&mut self) -> $ty {
unsafe {
// 使用 std::ptr::read_unaligned 解决未对齐地址问题
let value =
std::ptr::read_unaligned(self.data[self.cursor..].as_ptr() as *const $ty);
self.cursor += std::mem::size_of::<$ty>();
value.to_be()
}
}
};
($name:ident, $ty:ty, $size:literal, false) => {
#[doc = concat!("读取 ", stringify!($ty), " 类型 ", $size, " 长度的数据")]
/// ///
#[doc = "不转换大小端"] /// # 安全性
pub fn $name(&mut self) -> $ty { /// 允许未对齐的地址
unsafe { /// 长度溢出会导致 UB
// 使用 std::ptr::read_unaligned 解决未对齐地址问题 pub unsafe fn $name(&mut self) -> $ty {
let value = // 使用 std::ptr::read_unaligned 解决未对齐地址问题
std::ptr::read_unaligned(self.data[self.cursor..].as_ptr() as *const $ty); let value = std::ptr::read_unaligned(self.data[self.cursor..].as_ptr() as *const $ty);
self.cursor += std::mem::size_of::<$ty>(); self.cursor += std::mem::size_of::<$ty>();
value value.to_be()
}
} }
}; };
} }
macro_rules! read {
($name:ident, $ty:ty, $size:literal) => {
#[doc = concat!("读取 ", stringify!($ty), " 类型 ", $size, " 长度的数据")]
pub fn $name(&mut self) -> $ty {
let value = self.data[self.cursor..self.cursor + $size]
.iter()
.fold(0, |acc, &x| (acc << 8) | x as $ty);
self.cursor += $size;
value
}
};
}
impl NbtReader<'_> { impl NbtReader<'_> {
pub fn new(data: &mut [u8]) -> NbtReader { pub fn new(data: &mut [u8]) -> NbtReader {
NbtReader { NbtReader {
@ -64,14 +65,35 @@ impl NbtReader<'_> {
/// 读取一个 i8 类型的数据 /// 读取一个 i8 类型的数据
#[inline] #[inline]
pub fn read_i8(&mut self) -> i8 { self.read_u8() as i8 } pub fn read_i8(&mut self) -> i8 { self.read_u8() as i8 }
read!(read_i16_unchecked, i16, 2); read_uncheck!(read_i16_unchecked, i16, 2);
read!(read_u16_unchecked, u16, 2); read_uncheck!(read_u16_unchecked, u16, 2);
read!(read_i32_unchecked, i32, 4); read_uncheck!(read_i32_unchecked, i32, 4);
read!(read_u32_unchecked, u32, 4); read_uncheck!(read_u32_unchecked, u32, 4);
read!(read_i64_unchecked, i64, 8); read_uncheck!(read_i64_unchecked, i64, 8);
read!(read_u64_unchecked, u64, 8); read_uncheck!(read_u64_unchecked, u64, 8);
read!(read_f32_unchecked, f32, 4, false); /// 读取一个 f32 类型的数据
read!(read_f64_unchecked, f64, 8, false); ///
/// 转换大小端
///
/// # 安全性
/// 允许未对齐的地址
/// 长度溢出会导致 UB
pub unsafe fn read_f32_unchecked(&mut self) -> f32 {
let value = std::ptr::read_unaligned(self.data[self.cursor..].as_ptr() as *const u32);
self.cursor += 4;
f32::from_bits(value.to_be())
}
/// 读取一个 f64 类型的数据
/// 转换大小端
///
/// # 安全性
/// 允许未对齐的地址
/// 长度溢出会导致 UB
pub unsafe fn read_f64_unchecked(&mut self) -> f64 {
let value = std::ptr::read_unaligned(self.data[self.cursor..].as_ptr() as *const u64);
self.cursor += 8;
f64::from_bits(value.to_be())
}
pub fn read_u8_array(&mut self, len: usize) -> &[u8] { pub fn read_u8_array(&mut self, len: usize) -> &[u8] {
let value = &self.data[self.cursor..self.cursor + len]; let value = &self.data[self.cursor..self.cursor + len];

View File

@ -39,32 +39,16 @@ fn read_one_bytes() {
} }
#[test] #[test]
fn read_data_unchecked() { fn read_data_safe() {
let mut datas = gen_datas(100); let mut data = vec![0x01, 0x02, 0x03, 0x04];
let mut reader = NbtReader::new(&mut datas); let mut reader = NbtReader::new(&mut data);
assert_eq!(reader.read_u8(), 0x00); assert_eq!(reader.read_u8(), 0x00);
assert_eq!(reader.cursor, 1); assert_eq!(reader.cursor, 1);
assert_eq!(reader.read_i8(), 0x01); assert_eq!(reader.read_i8(), 0x01);
assert_eq!(reader.cursor, 2); assert_eq!(reader.cursor, 2);
assert_eq!(reader.read_u8(), 0x02); assert_eq!(reader.read_u8(), 0x02);
assert_eq!(reader.cursor, 3); assert_eq!(reader.cursor, 3);
assert_eq!(reader.read_i16_unchecked(), 0x0304);
assert_eq!(reader.cursor, 5);
assert_eq!(reader.read_u16_unchecked(), 0x0506);
assert_eq!(reader.cursor, 7);
assert_eq!(reader.read_i32_unchecked(), 0x0708090A);
assert_eq!(reader.cursor, 11);
assert_eq!(reader.read_u32_unchecked(), 0x0B0C0D0E);
assert_eq!(reader.cursor, 15);
assert_eq!(reader.read_i64_unchecked(), 0x0F10111213141516);
assert_eq!(reader.cursor, 23);
assert_eq!(reader.read_u64_unchecked(), 0x1718191A1B1C1D1E);
assert_eq!(reader.cursor, 31);
assert_eq!(reader.read_f32_unchecked().to_ne_bytes(), [0x1F, 0x20, 0x21, 0x22]);
assert_eq!(
reader.read_f64_unchecked().to_ne_bytes(),
[0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A]
);
} }
#[test] #[test]