添加了trait-test项目和相关依赖
This commit is contained in:
parent
cec3b191b9
commit
6eda5a38fe
@ -5,7 +5,7 @@ members = [
|
||||
"shen-nbt2",
|
||||
"shen-nbt3",
|
||||
"shen-nbt4",
|
||||
"shen-nbt5",
|
||||
"shen-nbt5", "trait-test",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
|
39
README.md
39
README.md
@ -1,13 +1,48 @@
|
||||
# nbt-rust
|
||||
|
||||
nbt解析器 by shenjack
|
||||
一个 "全功能" 的 "快速" NBT 解析器
|
||||
|
||||
支持
|
||||
|
||||
- `Java`
|
||||
- 也就是除了 1.20.2+ (协议号 >= 764) 之后的 网络传输用 NBT 格式
|
||||
- 数据都是大端序
|
||||
- 根节点必须有名称
|
||||
- 根节点必须是一个 `NbtCompound(10)` 类型
|
||||
- `JavaNetAfter1_20_2`
|
||||
- Java 版在 1.20.2 之后的网络传输用 NBT 格式
|
||||
- 数据都是大端序
|
||||
- 根节点没有名称
|
||||
- 根节点必须是一个 `NbtCompound(10)` 类型
|
||||
- `BedrockDisk`
|
||||
- 基岩版存在硬盘里的 NBT 格式
|
||||
- 数据都是小端序
|
||||
- 根节点必须有名称
|
||||
- 根节点是 `NbtCompound(10)` 或者 `NbtList(9)` 类型
|
||||
- `BedrockNetVarInt`
|
||||
- 基岩版用于网络传输的 NBT 格式
|
||||
|
||||
- ```text
|
||||
这种格式比其他格式稍微复杂一些。与Java版本的big-endian格式的区别如下:
|
||||
|
||||
TAG_Short、TAG_Float和TAG_Double值被编码为其小端对应值
|
||||
TAG_Int值以及TAG_List、TAG_Byte_Array、TAG_Int_Array和TAG_Long_Array的长度前缀均编码为使用ZigZag编码的VarInt
|
||||
TAG_Long值使用ZigZag编码被编码为VarLong
|
||||
所有字符串(标记名称和TAG_String值)都以普通的VarInt作为长度前缀
|
||||
|
||||
---- https://wiki.vg/NBT
|
||||
```
|
||||
|
||||
|
||||
writen in rust!
|
||||
|
||||
感谢 @神楽坂柚咲/伊欧/langyo
|
||||
## 感谢
|
||||
|
||||
感谢 @langyo 和 @InfyniteHeap
|
||||
在编写过程中的帮助(
|
||||
|
||||
感谢 [wiki.vg](https://wiki.vg/NBT) 存储的 NBT 格式的详细信息
|
||||
|
||||
## 概况
|
||||
|
||||
- `shen-nbt1`
|
||||
|
@ -1,7 +1,9 @@
|
||||
pub enum Endian {
|
||||
Big,
|
||||
Little,
|
||||
}
|
||||
pub mod reader;
|
||||
|
||||
use reader::NbtReader;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// 后面也许会实现的
|
||||
///
|
||||
@ -16,16 +18,67 @@ pub enum Endian {
|
||||
/// 基岩版 实际用于存储的 NBT 格式
|
||||
/// - `BedrockNetVarInt`
|
||||
/// 基岩版 网络 NBT 格式
|
||||
pub enum NbtVersion {
|
||||
Java,
|
||||
JavaNetAfter1_20_2,
|
||||
BedrockDisk,
|
||||
BedrockNetVarInt,
|
||||
// pub enum NbtVersion {
|
||||
// Java,
|
||||
// JavaNetAfter1_20_2,
|
||||
// BedrockDisk,
|
||||
// BedrockNetVarInt,
|
||||
// }
|
||||
pub mod nbt_version {
|
||||
use super::{NbtReader, NbtResult, NbtValue};
|
||||
|
||||
pub trait NbtReadTrait {
|
||||
fn from_reader(reader: NbtReader) -> NbtResult<NbtValue>;
|
||||
fn read_list(reader: &mut NbtReader) -> NbtResult<Vec<NbtValue>>;
|
||||
fn read_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>>;
|
||||
}
|
||||
/// Java 版 绝大部分的 NBT 格式
|
||||
///
|
||||
/// 除了 1.20.2+(协议号 >= 764) 及以后 的网路传输 NBT 格式 都是这个
|
||||
///
|
||||
/// 上面说的那玩意 请使用 `JavaNetAfter1_20_2`
|
||||
///
|
||||
/// # 编码特点
|
||||
///
|
||||
/// 大端, 大端, 还是 xx 的 大端!
|
||||
pub enum Java {}
|
||||
pub enum JavaNetAfter1_20_2 {}
|
||||
pub enum BedrockDisk {}
|
||||
pub enum BedrockNetVarInt {}
|
||||
}
|
||||
|
||||
// pub trait Nbt {
|
||||
pub type NbtTypeId = u8;
|
||||
|
||||
// }
|
||||
/// 把 u8 转换成对应的 Nbt 类型名称
|
||||
pub trait NbtTypeConversion {
|
||||
/// 把 u8 转换成对应的 Nbt 类型名称
|
||||
fn as_nbt_type_name(&self) -> String;
|
||||
}
|
||||
|
||||
impl NbtTypeConversion for NbtTypeId {
|
||||
fn as_nbt_type_name(&self) -> String {
|
||||
if *self > 12 {
|
||||
return format!("未知类型({})", *self);
|
||||
}
|
||||
match *self {
|
||||
0 => "NBT_End(0)",
|
||||
1 => "NBT_Byte(1)",
|
||||
2 => "NBT_Short(2)",
|
||||
3 => "NBT_Int(3)",
|
||||
4 => "NBT_Long(4)",
|
||||
5 => "NBT_Float(5)",
|
||||
6 => "NBT_Double(6)",
|
||||
7 => "NBT_ByteArray(7)",
|
||||
8 => "NBT_String(8)",
|
||||
9 => "NBT_List(9)",
|
||||
10 => "NBT_Compound(10)",
|
||||
11 => "NBT_IntArray(11)",
|
||||
12 => "NBT_LongArray(12)",
|
||||
_ => unreachable!(),
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// Error
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@ -89,326 +142,6 @@ impl std::fmt::Display for NbtError {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// 用于读取 NBT 数据
|
||||
pub struct NbtReader<'data> {
|
||||
/// NBT 数据
|
||||
pub data: &'data mut [u8],
|
||||
/// 当前读取的位置
|
||||
pub cursor: usize,
|
||||
// be/le
|
||||
// pub endian: Endian,
|
||||
}
|
||||
|
||||
macro_rules! read_uncheck {
|
||||
($name:ident, $ty:ty, $size:literal) => {
|
||||
#[doc = concat!("读取 ", stringify!($ty), " 类型 ", $size, " 长度的数据")]
|
||||
///
|
||||
#[doc = "转换大小端"]
|
||||
///
|
||||
/// # 安全性
|
||||
/// 允许未对齐的地址
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn $name(&mut self) -> $ty {
|
||||
// 使用 std::ptr::read_unaligned 解决未对齐地址问题
|
||||
let ptr = self.data.as_ptr().add(self.cursor) as *const $ty;
|
||||
let value = std::ptr::read_unaligned(ptr);
|
||||
self.cursor += std::mem::size_of::<$ty>();
|
||||
value.to_be()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl NbtReader<'_> {
|
||||
pub fn new(data: &mut [u8]) -> NbtReader { NbtReader { data, cursor: 0 } }
|
||||
/// 向后滚动
|
||||
#[inline]
|
||||
pub fn roll_back(&mut self, len: usize) { self.cursor -= len; }
|
||||
/// 向前滚动
|
||||
#[inline]
|
||||
pub fn roll_down(&mut self, len: usize) { self.cursor += len; }
|
||||
/// 读取一个 u8 类型的数据
|
||||
#[inline]
|
||||
pub fn read_u8(&mut self) -> u8 {
|
||||
let value = self.data[self.cursor];
|
||||
self.cursor += 1;
|
||||
value
|
||||
}
|
||||
/// 读取一个 i8 类型的数据
|
||||
#[inline]
|
||||
pub fn read_i8(&mut self) -> i8 { self.read_u8() as i8 }
|
||||
read_uncheck!(read_i16_unchecked, i16, 2);
|
||||
read_uncheck!(read_u16_unchecked, u16, 2);
|
||||
read_uncheck!(read_i32_unchecked, i32, 4);
|
||||
read_uncheck!(read_u32_unchecked, u32, 4);
|
||||
read_uncheck!(read_i64_unchecked, i64, 8);
|
||||
read_uncheck!(read_u64_unchecked, u64, 8);
|
||||
/// 安全的读取 i16 类型的数据
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_i16(&mut self) -> i16 {
|
||||
let value = i16::from_be_bytes([self.data[self.cursor], self.data[self.cursor + 1]]);
|
||||
self.cursor += 2;
|
||||
value
|
||||
}
|
||||
/// 安全的读取 u16 类型的数据
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_u16(&mut self) -> u16 { self.read_i16() as u16 }
|
||||
/// 安全的读取 i32 类型的数据
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_i32(&mut self) -> i32 {
|
||||
let value = i32::from_be_bytes([
|
||||
self.data[self.cursor],
|
||||
self.data[self.cursor + 1],
|
||||
self.data[self.cursor + 2],
|
||||
self.data[self.cursor + 3],
|
||||
]);
|
||||
self.cursor += 4;
|
||||
value
|
||||
}
|
||||
/// 安全的读取 u32 类型的数据
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_u32(&mut self) -> u32 {
|
||||
let value = u32::from_be_bytes([
|
||||
self.data[self.cursor],
|
||||
self.data[self.cursor + 1],
|
||||
self.data[self.cursor + 2],
|
||||
self.data[self.cursor + 3],
|
||||
]);
|
||||
self.cursor += 4;
|
||||
value
|
||||
}
|
||||
/// 安全的读取 i64 类型的数据
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_i64(&mut self) -> i64 {
|
||||
let value = i64::from_be_bytes([
|
||||
self.data[self.cursor],
|
||||
self.data[self.cursor + 1],
|
||||
self.data[self.cursor + 2],
|
||||
self.data[self.cursor + 3],
|
||||
self.data[self.cursor + 4],
|
||||
self.data[self.cursor + 5],
|
||||
self.data[self.cursor + 6],
|
||||
self.data[self.cursor + 7],
|
||||
]);
|
||||
self.cursor += 8;
|
||||
value
|
||||
}
|
||||
/// 安全的读取 u64 类型的数据
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_u64(&mut self) -> u64 {
|
||||
let value = u64::from_be_bytes([
|
||||
self.data[self.cursor],
|
||||
self.data[self.cursor + 1],
|
||||
self.data[self.cursor + 2],
|
||||
self.data[self.cursor + 3],
|
||||
self.data[self.cursor + 4],
|
||||
self.data[self.cursor + 5],
|
||||
self.data[self.cursor + 6],
|
||||
self.data[self.cursor + 7],
|
||||
]);
|
||||
self.cursor += 8;
|
||||
value
|
||||
}
|
||||
/// 读取一个 f32 类型的数据
|
||||
///
|
||||
/// 转换大小端
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_f32(&mut self) -> f32 { f32::from_bits(self.read_u32()) }
|
||||
/// 读取一个 f64 类型的数据
|
||||
///
|
||||
/// 转换大小端
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_f64(&mut self) -> f64 { f64::from_bits(self.read_u64()) }
|
||||
/// 读取一个 f32 类型的数据
|
||||
///
|
||||
/// 转换大小端
|
||||
///
|
||||
/// # 安全性
|
||||
/// 允许未对齐的地址
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn read_f32_unchecked(&mut self) -> f32 {
|
||||
let value = self.read_u32_unchecked();
|
||||
std::mem::transmute::<u32, f32>(value)
|
||||
}
|
||||
/// 读取一个 f64 类型的数据
|
||||
/// 转换大小端
|
||||
///
|
||||
/// # 安全性
|
||||
/// 允许未对齐的地址
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn read_f64_unchecked(&mut self) -> f64 {
|
||||
let value = self.read_u64_unchecked();
|
||||
std::mem::transmute::<u64, f64>(value)
|
||||
}
|
||||
/// 读取指定长度的 u8 数组
|
||||
///
|
||||
/// # 安全性
|
||||
///
|
||||
/// 长度溢出会导致 panic
|
||||
#[inline]
|
||||
pub fn read_u8_array(&mut self, len: usize) -> &[u8] {
|
||||
let value = &self.data[self.cursor..self.cursor + len];
|
||||
self.cursor += len;
|
||||
value
|
||||
}
|
||||
/// 读取指定长度的 i8 数组
|
||||
///
|
||||
/// # 安全性
|
||||
///
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn read_i8_array_unchecked(&mut self, len: usize) -> Vec<i8> {
|
||||
let value = std::slice::from_raw_parts(self.data[self.cursor..].as_ptr() as *const i8, len);
|
||||
self.cursor += len;
|
||||
value.to_vec()
|
||||
}
|
||||
/// 读取指定长度的 i8 数组
|
||||
///
|
||||
/// # 安全性
|
||||
///
|
||||
/// 长度溢出会导致 panic
|
||||
#[inline]
|
||||
pub fn read_i8_array(&mut self, len: usize) -> Vec<i8> {
|
||||
let value = self.data[self.cursor..self.cursor + len].iter().map(|&n| n as i8).collect();
|
||||
self.cursor += len;
|
||||
value
|
||||
}
|
||||
/// 读取指定长度的 utf-8 字符串
|
||||
///
|
||||
/// # 安全性
|
||||
///
|
||||
/// 长度溢出会导致 panic
|
||||
#[inline]
|
||||
pub fn read_string(&mut self, len: usize) -> Result<String, NbtError> {
|
||||
if len + self.cursor > self.data.len() {
|
||||
return Err(NbtError::CursorOverflow(self.cursor, len, self.data.len()));
|
||||
}
|
||||
let value = String::from_utf8_lossy(&self.data[self.cursor..self.cursor + len]);
|
||||
self.cursor += len;
|
||||
Ok(value.into_owned())
|
||||
}
|
||||
/// 读取指定长度的 i32 数组
|
||||
///
|
||||
/// # 安全性
|
||||
///
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn read_i32_array_unchecked(&mut self, len: usize) -> Vec<i32> {
|
||||
let value =
|
||||
std::slice::from_raw_parts(self.data[self.cursor..].as_ptr() as *const i32, len);
|
||||
let mut value = value.to_vec();
|
||||
for n in &mut value {
|
||||
*n = n.to_be();
|
||||
}
|
||||
self.cursor += len * 4;
|
||||
value
|
||||
}
|
||||
/// 读取指定长度的 i32 数组
|
||||
///
|
||||
/// # 安全性
|
||||
///
|
||||
/// 长度溢出会导致 panic
|
||||
#[inline]
|
||||
pub fn read_i32_array(&mut self, len: usize) -> Vec<i32> {
|
||||
let value = self.data[self.cursor..self.cursor + len * 4]
|
||||
.chunks_exact(4)
|
||||
.map(|n| i32::from_be_bytes(n[0..4].try_into().unwrap()))
|
||||
.collect();
|
||||
self.cursor += len * 4;
|
||||
value
|
||||
}
|
||||
/// 读取指定长度的 i64 数组
|
||||
///
|
||||
/// # 安全性
|
||||
///
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn read_i64_array_unchecked(&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
|
||||
#[inline]
|
||||
pub fn read_i64_array(&mut self, len: usize) -> Vec<i64> {
|
||||
let value = self.data[self.cursor..self.cursor + len * 8]
|
||||
.chunks_exact(8)
|
||||
.map(|n| i64::from_be_bytes(n[0..8].try_into().unwrap()))
|
||||
.collect();
|
||||
self.cursor += len * 8;
|
||||
value
|
||||
}
|
||||
|
||||
/// 读取一个 NBT byte array
|
||||
pub fn read_nbt_i8_array(&mut self) -> Vec<i8> {
|
||||
let len = self.read_i32() as usize;
|
||||
let value = unsafe { self.read_i8_array_unchecked(len) };
|
||||
value
|
||||
}
|
||||
|
||||
/// 读取一个 NBT int array
|
||||
pub fn read_nbt_i32_array(&mut self) -> Vec<i32> {
|
||||
let len = self.read_i32() as usize;
|
||||
let value = unsafe { self.read_i32_array_unchecked(len) };
|
||||
value
|
||||
}
|
||||
|
||||
/// 读取一个 NBT long array
|
||||
pub fn read_nbt_i64_array(&mut self) -> Vec<i64> {
|
||||
let len = self.read_i32() as usize;
|
||||
let value = unsafe { self.read_i64_array_unchecked(len) };
|
||||
value
|
||||
}
|
||||
|
||||
/// 读取一个 NBT string
|
||||
pub fn read_nbt_string(&mut self) -> NbtResult<String> {
|
||||
let len = self.read_u16() as usize;
|
||||
self.read_string(len)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum NbtValue {
|
||||
// end: 0
|
||||
@ -445,98 +178,76 @@ pub enum NbtValue {
|
||||
}
|
||||
|
||||
impl NbtValue {
|
||||
pub fn type_id_as_name(type_id: u8) -> String {
|
||||
if type_id > 12 {
|
||||
return format!("未知类型({})", type_id);
|
||||
}
|
||||
match type_id {
|
||||
0 => "NBT_End(0)",
|
||||
1 => "NBT_Byte(1)",
|
||||
2 => "NBT_Short(2)",
|
||||
3 => "NBT_Int(3)",
|
||||
4 => "NBT_Long(4)",
|
||||
5 => "NBT_Float(5)",
|
||||
6 => "NBT_Double(6)",
|
||||
7 => "NBT_ByteArray(7)",
|
||||
8 => "NBT_String(8)",
|
||||
9 => "NBT_List(9)",
|
||||
10 => "NBT_Compound(10)",
|
||||
11 => "NBT_IntArray(11)",
|
||||
12 => "NBT_LongArray(12)",
|
||||
_ => unreachable!(),
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub fn from_binary(data: &mut [u8]) -> NbtResult<NbtValue> {
|
||||
pub fn from_binary<T>(data: &mut [u8]) -> NbtResult<NbtValue>
|
||||
where T: nbt_version::NbtReadTrait {
|
||||
let reader = NbtReader::new(data);
|
||||
Ok(NbtValue::from_reader(reader))
|
||||
T::from_reader(reader)
|
||||
}
|
||||
|
||||
fn read_nbt_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>> {
|
||||
let mut compound = Vec::with_capacity(10);
|
||||
loop {
|
||||
let tag_id = reader.read_u8();
|
||||
if tag_id == 0 {
|
||||
break;
|
||||
}
|
||||
let name = reader.read_nbt_string()?;
|
||||
let value = match tag_id {
|
||||
1 => NbtValue::Byte(reader.read_i8()),
|
||||
2 => NbtValue::Short(reader.read_i16()),
|
||||
3 => NbtValue::Int(reader.read_i32()),
|
||||
4 => NbtValue::Long(reader.read_i64()),
|
||||
5 => NbtValue::Float(reader.read_f32()),
|
||||
6 => NbtValue::Double(reader.read_f64()),
|
||||
7 => NbtValue::ByteArray(reader.read_nbt_i8_array()),
|
||||
8 => NbtValue::String(reader.read_nbt_string()?),
|
||||
9 => NbtValue::List(NbtValue::read_nbt_list(reader)?),
|
||||
10 => NbtValue::Compound(None, NbtValue::read_nbt_compound(reader)?),
|
||||
11 => NbtValue::IntArray(reader.read_nbt_i32_array()),
|
||||
12 => NbtValue::LongArray(reader.read_nbt_i64_array()),
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
compound.push((name, value));
|
||||
}
|
||||
Ok(compound)
|
||||
}
|
||||
// fn read_nbt_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>> {
|
||||
// let mut compound = Vec::with_capacity(10);
|
||||
// loop {
|
||||
// let tag_id = reader.read_u8();
|
||||
// if tag_id == 0 {
|
||||
// break;
|
||||
// }
|
||||
// let name = reader.read_nbt_string()?;
|
||||
// let value = match tag_id {
|
||||
// 1 => NbtValue::Byte(reader.read_i8()),
|
||||
// 2 => NbtValue::Short(reader.read_be_i16()),
|
||||
// 3 => NbtValue::Int(reader.read_be_i32()),
|
||||
// 4 => NbtValue::Long(reader.read_be_i64()),
|
||||
// 5 => NbtValue::Float(reader.read_be_f32()),
|
||||
// 6 => NbtValue::Double(reader.read_be_f64()),
|
||||
// 7 => NbtValue::ByteArray(reader.read_nbt_i8_array()),
|
||||
// 8 => NbtValue::String(reader.read_nbt_string()?),
|
||||
// 9 => NbtValue::List(NbtValue::read_nbt_list(reader)?),
|
||||
// 10 => NbtValue::Compound(None, NbtValue::read_nbt_compound(reader)?),
|
||||
// 11 => NbtValue::IntArray(reader.read_nbt_i32_array()),
|
||||
// 12 => NbtValue::LongArray(reader.read_nbt_i64_array()),
|
||||
// _ => unimplemented!(),
|
||||
// };
|
||||
// compound.push((name, value));
|
||||
// }
|
||||
// Ok(compound)
|
||||
// }
|
||||
|
||||
fn read_nbt_list(reader: &mut NbtReader) -> NbtResult<Vec<NbtValue>> {
|
||||
let type_id = reader.read_u8();
|
||||
let len = reader.read_i32() as usize;
|
||||
let mut list = Vec::with_capacity(len);
|
||||
for _ in 0..len {
|
||||
let value = match type_id {
|
||||
1 => NbtValue::Byte(reader.read_i8()),
|
||||
2 => NbtValue::Short(reader.read_i16()),
|
||||
3 => NbtValue::Int(reader.read_i32()),
|
||||
4 => NbtValue::Long(reader.read_i64()),
|
||||
5 => NbtValue::Float(reader.read_f32()),
|
||||
6 => NbtValue::Double(reader.read_f64()),
|
||||
7 => NbtValue::ByteArray(reader.read_nbt_i8_array()),
|
||||
8 => NbtValue::String(reader.read_nbt_string()?),
|
||||
9 => NbtValue::List(NbtValue::read_nbt_list(reader)?),
|
||||
10 => NbtValue::Compound(None, NbtValue::read_nbt_compound(reader)?),
|
||||
11 => NbtValue::IntArray(reader.read_nbt_i32_array()),
|
||||
12 => NbtValue::LongArray(reader.read_nbt_i64_array()),
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
list.push(value);
|
||||
}
|
||||
Ok(list)
|
||||
}
|
||||
// fn read_nbt_list(reader: &mut NbtReader) -> NbtResult<Vec<NbtValue>> {
|
||||
// let type_id = reader.read_u8();
|
||||
// let len = reader.read_be_i32() as usize;
|
||||
// let mut list = Vec::with_capacity(len);
|
||||
// for _ in 0..len {
|
||||
// let value = match type_id {
|
||||
// 1 => NbtValue::Byte(reader.read_i8()),
|
||||
// 2 => NbtValue::Short(reader.read_be_i16()),
|
||||
// 3 => NbtValue::Int(reader.read_be_i32()),
|
||||
// 4 => NbtValue::Long(reader.read_be_i64()),
|
||||
// 5 => NbtValue::Float(reader.read_be_f32()),
|
||||
// 6 => NbtValue::Double(reader.read_be_f64()),
|
||||
// 7 => NbtValue::ByteArray(reader.read_nbt_i8_array()),
|
||||
// 8 => NbtValue::String(reader.read_nbt_string()?),
|
||||
// 9 => NbtValue::List(NbtValue::read_nbt_list(reader)?),
|
||||
// 10 => NbtValue::Compound(None, NbtValue::read_nbt_compound(reader)?),
|
||||
// 11 => NbtValue::IntArray(reader.read_nbt_i32_array()),
|
||||
// 12 => NbtValue::LongArray(reader.read_nbt_i64_array()),
|
||||
// _ => unimplemented!(),
|
||||
// };
|
||||
// list.push(value);
|
||||
// }
|
||||
// Ok(list)
|
||||
// }
|
||||
|
||||
pub fn from_reader(mut reader: NbtReader) -> NbtValue {
|
||||
// 第一个 tag, 不可能是 0
|
||||
match reader.read_u8() {
|
||||
9 => NbtValue::List(NbtValue::read_nbt_list(&mut reader).unwrap()),
|
||||
10 => {
|
||||
let name = reader.read_nbt_string().unwrap();
|
||||
NbtValue::Compound(Some(name), NbtValue::read_nbt_compound(&mut reader).unwrap())
|
||||
}
|
||||
x => {
|
||||
panic!("根节点类型错误 {}", Self::type_id_as_name(x));
|
||||
}
|
||||
}
|
||||
}
|
||||
// pub fn from_reader(mut reader: NbtReader) -> NbtValue {
|
||||
// // 第一个 tag, 不可能是 0
|
||||
// match reader.read_u8() {
|
||||
// 9 => NbtValue::List(NbtValue::read_nbt_list(&mut reader).unwrap()),
|
||||
// 10 => {
|
||||
// let name = reader.read_nbt_string().unwrap();
|
||||
// NbtValue::Compound(Some(name), NbtValue::read_nbt_compound(&mut reader).unwrap())
|
||||
// }
|
||||
// x => {
|
||||
// panic!("根节点类型错误 {}", x.as_nbt_type_name());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
459
shen-nbt5/src/reader.rs
Normal file
459
shen-nbt5/src/reader.rs
Normal file
@ -0,0 +1,459 @@
|
||||
use crate::nbt_version;
|
||||
use crate::{NbtError, NbtResult, NbtValue};
|
||||
|
||||
/// 用于读取 NBT 数据
|
||||
pub struct NbtReader<'data> {
|
||||
/// NBT 数据
|
||||
pub data: &'data mut [u8],
|
||||
/// 当前读取的位置
|
||||
pub cursor: usize,
|
||||
// be/le
|
||||
// pub endian: Endian,
|
||||
}
|
||||
|
||||
/// Java 版 绝大部分的 NBT 格式
|
||||
///
|
||||
/// 除了 1.20.2+(协议号 >= 764) 及以后 的网路传输 NBT 格式 都是这个
|
||||
///
|
||||
/// 上面说的那玩意 请使用 `JavaNetAfter1_20_2`
|
||||
impl nbt_version::NbtReadTrait for nbt_version::Java {
|
||||
fn from_reader(reader: NbtReader) -> NbtResult<NbtValue> { todo!() }
|
||||
fn read_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>> { todo!() }
|
||||
fn read_list(reader: &mut NbtReader) -> NbtResult<Vec<NbtValue>> { todo!() }
|
||||
}
|
||||
|
||||
macro_rules! read_uncheck {
|
||||
($be_name:ident, $le_name:ident, $ty:ty, $size:literal) => {
|
||||
#[doc = concat!("读取 ", stringify!($ty), " 类型 ", $size, " 长度的数据")]
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// # 安全性
|
||||
/// 允许未对齐的地址
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn $be_name(&mut self) -> $ty {
|
||||
// 使用 std::ptr::read_unaligned 解决未对齐地址问题
|
||||
let ptr = self.data.as_ptr().add(self.cursor) as *const $ty;
|
||||
let value = std::ptr::read_unaligned(ptr);
|
||||
self.cursor += std::mem::size_of::<$ty>();
|
||||
value.to_be()
|
||||
}
|
||||
|
||||
#[doc = concat!("读取 ", stringify!($ty), " 类型 ", $size, " 长度的数据")]
|
||||
///
|
||||
/// 转换大小端(小端)
|
||||
///
|
||||
/// # 安全性
|
||||
/// 允许未对齐的地址
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn $le_name(&mut self) -> $ty {
|
||||
// 使用 std::ptr::read_unaligned 解决未对齐地址问题
|
||||
let ptr = self.data.as_ptr().add(self.cursor) as *const $ty;
|
||||
let value = std::ptr::read_unaligned(ptr);
|
||||
self.cursor += std::mem::size_of::<$ty>();
|
||||
value.to_le()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl NbtReader<'_> {
|
||||
pub fn new(data: &mut [u8]) -> NbtReader { NbtReader { data, cursor: 0 } }
|
||||
/// 向后滚动
|
||||
#[inline]
|
||||
pub fn roll_back(&mut self, len: usize) { self.cursor -= len; }
|
||||
/// 向前滚动
|
||||
#[inline]
|
||||
pub fn roll_down(&mut self, len: usize) { self.cursor += len; }
|
||||
/// 读取一个 u8 类型的数据
|
||||
#[inline]
|
||||
pub fn read_u8(&mut self) -> u8 {
|
||||
let value = self.data[self.cursor];
|
||||
self.cursor += 1;
|
||||
value
|
||||
}
|
||||
/// 读取一个 i8 类型的数据
|
||||
#[inline]
|
||||
pub fn read_i8(&mut self) -> i8 { self.read_u8() as i8 }
|
||||
read_uncheck!(read_be_i16_unsafe, read_le_i16_unsafe, i16, 2);
|
||||
read_uncheck!(read_be_u16_unsafe, read_le_u16_unsafe, u16, 2);
|
||||
read_uncheck!(read_be_i32_unsafe, read_le_i32_unsafe, i32, 4);
|
||||
read_uncheck!(read_be_u32_unsafe, read_le_u32_unsafe, u32, 4);
|
||||
read_uncheck!(read_be_i64_unsafe, read_le_i64_unsafe, i64, 8);
|
||||
read_uncheck!(read_be_u64_unsafe, read_le_u64_unsafe, u64, 8);
|
||||
/// 安全的读取 i16 类型的数据
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_be_i16(&mut self) -> i16 {
|
||||
let value = i16::from_be_bytes([self.data[self.cursor], self.data[self.cursor + 1]]);
|
||||
self.cursor += 2;
|
||||
value
|
||||
}
|
||||
/// 安全的读取 i16 类型的数据
|
||||
///
|
||||
/// 转换大小端(小端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_le_i16(&mut self) -> i16 {
|
||||
let value = i16::from_le_bytes([self.data[self.cursor], self.data[self.cursor + 1]]);
|
||||
self.cursor += 2;
|
||||
value
|
||||
}
|
||||
/// 安全的读取 u16 类型的数据
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_be_u16(&mut self) -> u16 { self.read_be_i16() as u16 }
|
||||
/// 安全的读取 u16 类型的数据
|
||||
///
|
||||
/// 转换大小端(小端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_le_u16(&mut self) -> u16 { self.read_le_i16() as u16 }
|
||||
/// 安全的读取 i32 类型的数据
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_be_i32(&mut self) -> i32 {
|
||||
let value = i32::from_be_bytes([
|
||||
self.data[self.cursor],
|
||||
self.data[self.cursor + 1],
|
||||
self.data[self.cursor + 2],
|
||||
self.data[self.cursor + 3],
|
||||
]);
|
||||
self.cursor += 4;
|
||||
value
|
||||
}
|
||||
/// 安全的读取 i32 类型的数据
|
||||
///
|
||||
/// 转换大小端(小端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_le_i32(&mut self) -> i32 {
|
||||
let value = i32::from_le_bytes([
|
||||
self.data[self.cursor],
|
||||
self.data[self.cursor + 1],
|
||||
self.data[self.cursor + 2],
|
||||
self.data[self.cursor + 3],
|
||||
]);
|
||||
self.cursor += 4;
|
||||
value
|
||||
}
|
||||
/// 安全的读取 u32 类型的数据
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_be_u32(&mut self) -> u32 {
|
||||
let value = u32::from_be_bytes([
|
||||
self.data[self.cursor],
|
||||
self.data[self.cursor + 1],
|
||||
self.data[self.cursor + 2],
|
||||
self.data[self.cursor + 3],
|
||||
]);
|
||||
self.cursor += 4;
|
||||
value
|
||||
}
|
||||
/// 安全的读取 u32 类型的数据
|
||||
///
|
||||
/// 转换大小端(小端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_le_u32(&mut self) -> u32 {
|
||||
let value = u32::from_le_bytes([
|
||||
self.data[self.cursor],
|
||||
self.data[self.cursor + 1],
|
||||
self.data[self.cursor + 2],
|
||||
self.data[self.cursor + 3],
|
||||
]);
|
||||
self.cursor += 4;
|
||||
value
|
||||
}
|
||||
/// 安全的读取 i64 类型的数据
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_be_i64(&mut self) -> i64 {
|
||||
let value = i64::from_be_bytes([
|
||||
self.data[self.cursor],
|
||||
self.data[self.cursor + 1],
|
||||
self.data[self.cursor + 2],
|
||||
self.data[self.cursor + 3],
|
||||
self.data[self.cursor + 4],
|
||||
self.data[self.cursor + 5],
|
||||
self.data[self.cursor + 6],
|
||||
self.data[self.cursor + 7],
|
||||
]);
|
||||
self.cursor += 8;
|
||||
value
|
||||
}
|
||||
/// 安全的读取 i64 类型的数据
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_le_i64(&mut self) -> i64 {
|
||||
let value = i64::from_le_bytes([
|
||||
self.data[self.cursor],
|
||||
self.data[self.cursor + 1],
|
||||
self.data[self.cursor + 2],
|
||||
self.data[self.cursor + 3],
|
||||
self.data[self.cursor + 4],
|
||||
self.data[self.cursor + 5],
|
||||
self.data[self.cursor + 6],
|
||||
self.data[self.cursor + 7],
|
||||
]);
|
||||
self.cursor += 8;
|
||||
value
|
||||
}
|
||||
/// 安全的读取 u64 类型的数据
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_be_u64(&mut self) -> u64 {
|
||||
let value = u64::from_be_bytes([
|
||||
self.data[self.cursor],
|
||||
self.data[self.cursor + 1],
|
||||
self.data[self.cursor + 2],
|
||||
self.data[self.cursor + 3],
|
||||
self.data[self.cursor + 4],
|
||||
self.data[self.cursor + 5],
|
||||
self.data[self.cursor + 6],
|
||||
self.data[self.cursor + 7],
|
||||
]);
|
||||
self.cursor += 8;
|
||||
value
|
||||
}
|
||||
/// 安全的读取 u64 类型的数据
|
||||
///
|
||||
/// 转换大小端(大端)
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_le_u64(&mut self) -> u64 {
|
||||
let value = u64::from_le_bytes([
|
||||
self.data[self.cursor],
|
||||
self.data[self.cursor + 1],
|
||||
self.data[self.cursor + 2],
|
||||
self.data[self.cursor + 3],
|
||||
self.data[self.cursor + 4],
|
||||
self.data[self.cursor + 5],
|
||||
self.data[self.cursor + 6],
|
||||
self.data[self.cursor + 7],
|
||||
]);
|
||||
self.cursor += 8;
|
||||
value
|
||||
}
|
||||
/// 读取一个大端 f32 数据
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_be_f32(&mut self) -> f32 { f32::from_bits(self.read_be_u32()) }
|
||||
/// 读取一个小端 f32 数据
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_le_f32(&mut self) -> f32 { f32::from_bits(self.read_le_u32()) }
|
||||
/// 读取一个大端 f64 数据
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_be_f64(&mut self) -> f64 { f64::from_bits(self.read_be_u64()) }
|
||||
/// 读取一个小端 f64 数据
|
||||
///
|
||||
/// 会在超出长度时 panic
|
||||
#[inline]
|
||||
pub fn read_le_f64(&mut self) -> f64 { f64::from_bits(self.read_le_u64()) }
|
||||
/// 读取一个大端 f32 数据
|
||||
///
|
||||
/// # 安全性
|
||||
/// 允许未对齐的地址
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn read_be_f32_unsafe(&mut self) -> f32 {
|
||||
let value = self.read_be_u32_unsafe();
|
||||
std::mem::transmute::<u32, f32>(value)
|
||||
}
|
||||
/// 读取一个小端 f32 数据
|
||||
///
|
||||
/// # 安全性
|
||||
/// 允许未对齐的地址
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn read_le_f32_unsafe(&mut self) -> f32 {
|
||||
let value = self.read_le_u32_unsafe();
|
||||
std::mem::transmute::<u32, f32>(value)
|
||||
}
|
||||
/// 读取一个大端 f64 数据
|
||||
///
|
||||
/// # 安全性
|
||||
/// 允许未对齐的地址
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn read_be_f64_unsafe(&mut self) -> f64 {
|
||||
let value = self.read_be_u64_unsafe();
|
||||
std::mem::transmute::<u64, f64>(value)
|
||||
}
|
||||
/// 读取一个小端 f64 数据
|
||||
///
|
||||
/// # 安全性
|
||||
/// 允许未对齐的地址
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn read_le_f64_unsafe(&mut self) -> f64 {
|
||||
let value = self.read_le_u64_unsafe();
|
||||
std::mem::transmute::<u64, f64>(value)
|
||||
}
|
||||
/// 读取指定长度的 u8 数组
|
||||
///
|
||||
/// # 安全性
|
||||
///
|
||||
/// 长度溢出会导致 panic
|
||||
#[inline]
|
||||
pub fn read_u8_array(&mut self, len: usize) -> &[u8] {
|
||||
let value = &self.data[self.cursor..self.cursor + len];
|
||||
self.cursor += len;
|
||||
value
|
||||
}
|
||||
/// 读取指定长度的 i8 数组
|
||||
///
|
||||
/// # 安全性
|
||||
///
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn read_i8_array_unsafe(&mut self, len: usize) -> Vec<i8> {
|
||||
let value = std::slice::from_raw_parts(self.data[self.cursor..].as_ptr() as *const i8, len);
|
||||
self.cursor += len;
|
||||
value.to_vec()
|
||||
}
|
||||
/// 读取指定长度的 i8 数组
|
||||
///
|
||||
/// # 安全性
|
||||
///
|
||||
/// 长度溢出会导致 panic
|
||||
#[inline]
|
||||
pub fn read_i8_array(&mut self, len: usize) -> Vec<i8> {
|
||||
let value = self.data[self.cursor..self.cursor + len].iter().map(|&n| n as i8).collect();
|
||||
self.cursor += len;
|
||||
value
|
||||
}
|
||||
/// 读取指定长度的 i32 数组
|
||||
///
|
||||
/// # 安全性
|
||||
///
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn read_i32_array_unsafe(&mut self, len: usize) -> Vec<i32> {
|
||||
let value =
|
||||
std::slice::from_raw_parts(self.data[self.cursor..].as_ptr() as *const i32, len);
|
||||
let mut value = value.to_vec();
|
||||
for n in &mut value {
|
||||
*n = n.to_be();
|
||||
}
|
||||
self.cursor += len * 4;
|
||||
value
|
||||
}
|
||||
/// 读取指定长度的 i32 数组
|
||||
///
|
||||
/// # 安全性
|
||||
///
|
||||
/// 长度溢出会导致 panic
|
||||
#[inline]
|
||||
pub fn read_i32_array(&mut self, len: usize) -> Vec<i32> {
|
||||
let value = self.data[self.cursor..self.cursor + len * 4]
|
||||
.chunks_exact(4)
|
||||
.map(|n| i32::from_be_bytes(n[0..4].try_into().unwrap()))
|
||||
.collect();
|
||||
self.cursor += len * 4;
|
||||
value
|
||||
}
|
||||
/// 读取指定长度的 i64 数组
|
||||
///
|
||||
/// # 安全性
|
||||
///
|
||||
/// 长度溢出会导致 UB
|
||||
#[inline]
|
||||
pub unsafe fn read_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
|
||||
#[inline]
|
||||
pub fn read_i64_array(&mut self, len: usize) -> Vec<i64> {
|
||||
let value = self.data[self.cursor..self.cursor + len * 8]
|
||||
.chunks_exact(8)
|
||||
.map(|n| i64::from_be_bytes(n[0..8].try_into().unwrap()))
|
||||
.collect();
|
||||
self.cursor += len * 8;
|
||||
value
|
||||
}
|
||||
/// 读取指定长度的 utf-8 字符串
|
||||
///
|
||||
/// # 安全性
|
||||
///
|
||||
/// 长度溢出会导致 panic
|
||||
#[inline]
|
||||
pub fn read_string(&mut self, len: usize) -> Result<String, NbtError> {
|
||||
if len + self.cursor > self.data.len() {
|
||||
return Err(NbtError::CursorOverflow(self.cursor, len, self.data.len()));
|
||||
}
|
||||
let value = String::from_utf8_lossy(&self.data[self.cursor..self.cursor + len]);
|
||||
self.cursor += len;
|
||||
Ok(value.into_owned())
|
||||
}
|
||||
|
||||
// /// 读取一个 NBT byte array
|
||||
// pub fn read_nbt_i8_array(&mut self) -> Vec<i8> {
|
||||
// let len = self.read_be_i32() as usize;
|
||||
// let value = unsafe { self.read_i8_array_unsafe(len) };
|
||||
// value
|
||||
// }
|
||||
|
||||
// /// 读取一个 NBT int array
|
||||
// pub fn read_nbt_i32_array(&mut self) -> Vec<i32> {
|
||||
// let len = self.read_be_i32() as usize;
|
||||
// let value = unsafe { self.read_i32_array_unsafe(len) };
|
||||
// value
|
||||
// }
|
||||
|
||||
// /// 读取一个 NBT long array
|
||||
// pub fn read_nbt_i64_array(&mut self) -> Vec<i64> {
|
||||
// let len = self.read_be_i32() as usize;
|
||||
// let value = unsafe { self.read_i64_array_unsafe(len) };
|
||||
// value
|
||||
// }
|
||||
|
||||
// /// 读取一个 NBT string
|
||||
// pub fn read_nbt_string(&mut self) -> NbtResult<String> {
|
||||
// let len = self.read_be_u16() as usize;
|
||||
// self.read_string(len)
|
||||
// }
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use crate::{NbtReader, NbtValue};
|
||||
use crate::{NbtReader, NbtTypeConversion, NbtValue, nbt_version};
|
||||
|
||||
/// 生成测试数据
|
||||
pub fn gen_datas(len: usize) -> Vec<u8> {
|
||||
@ -36,41 +36,57 @@ mod safe_test {
|
||||
|
||||
#[test]
|
||||
fn read_x16() {
|
||||
let mut data = vec![0x01, 0x02, 0x03, 0x04];
|
||||
let mut data = vec![0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04];
|
||||
data.extend(i16::MIN.to_be_bytes());
|
||||
data.extend(i16::MAX.to_be_bytes());
|
||||
let mut reader = NbtReader::new(&mut data);
|
||||
assert_eq!(reader.read_i16(), 0x0102);
|
||||
assert_eq!(reader.read_be_i16(), 0x0102);
|
||||
assert_eq!(reader.cursor, 2);
|
||||
assert_eq!(reader.read_u16(), 0x0304);
|
||||
assert_eq!(reader.read_be_u16(), 0x0304);
|
||||
assert_eq!(reader.cursor, 4);
|
||||
assert_eq!(reader.read_i16(), i16::MIN);
|
||||
assert_eq!(reader.read_le_i16(), 0x0201);
|
||||
assert_eq!(reader.cursor, 6);
|
||||
assert_eq!(reader.read_i16(), i16::MAX);
|
||||
assert_eq!(reader.read_le_u16(), 0x0403);
|
||||
assert_eq!(reader.cursor, 8);
|
||||
assert_eq!(reader.read_be_i16(), i16::MIN);
|
||||
assert_eq!(reader.cursor, 10);
|
||||
assert_eq!(reader.read_be_i16(), i16::MAX);
|
||||
assert_eq!(reader.cursor, 12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_x32() {
|
||||
let mut data = vec![0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04];
|
||||
let mut data = vec![
|
||||
0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02,
|
||||
0x03, 0x04,
|
||||
];
|
||||
let mut reader = NbtReader::new(&mut data);
|
||||
assert_eq!(reader.read_i32(), 0x01020304);
|
||||
assert_eq!(reader.read_be_i32(), 0x01020304);
|
||||
assert_eq!(reader.cursor, 4);
|
||||
assert_eq!(reader.read_u32(), 0x01020304);
|
||||
assert_eq!(reader.read_be_u32(), 0x01020304);
|
||||
assert_eq!(reader.cursor, 8);
|
||||
assert_eq!(reader.read_le_i32(), 0x04030201);
|
||||
assert_eq!(reader.cursor, 12);
|
||||
assert_eq!(reader.read_le_u32(), 0x04030201);
|
||||
assert_eq!(reader.cursor, 16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_x64() {
|
||||
let mut data = vec![
|
||||
0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02,
|
||||
0x03, 0x04,
|
||||
0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
|
||||
0x01, 0x02, 0x03, 0x04,
|
||||
];
|
||||
let mut reader = NbtReader::new(&mut data);
|
||||
assert_eq!(reader.read_i64(), 0x0102030401020304);
|
||||
assert_eq!(reader.read_be_i64(), 0x0102030401020304);
|
||||
assert_eq!(reader.cursor, 8);
|
||||
assert_eq!(reader.read_u64(), 0x0102030401020304);
|
||||
assert_eq!(reader.read_be_u64(), 0x0102030401020304);
|
||||
assert_eq!(reader.cursor, 16);
|
||||
assert_eq!(reader.read_le_i64(), 0x0403020104030201);
|
||||
assert_eq!(reader.cursor, 24);
|
||||
assert_eq!(reader.read_le_u64(), 0x0403020104030201);
|
||||
assert_eq!(reader.cursor, 32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -78,12 +94,18 @@ mod safe_test {
|
||||
let mut data = Vec::with_capacity(12);
|
||||
data.extend_from_slice(&std::f32::consts::PI.to_be_bytes());
|
||||
data.extend_from_slice(&std::f64::consts::PI.to_be_bytes());
|
||||
data.extend_from_slice(&std::f32::consts::PI.to_le_bytes());
|
||||
data.extend_from_slice(&std::f64::consts::PI.to_le_bytes());
|
||||
println!("{:?}", data);
|
||||
let mut reader = NbtReader::new(&mut data);
|
||||
assert_eq!(reader.read_f32(), std::f32::consts::PI);
|
||||
assert_eq!(reader.read_be_f32(), std::f32::consts::PI);
|
||||
assert_eq!(reader.cursor, 4);
|
||||
assert_eq!(reader.read_f64(), std::f64::consts::PI);
|
||||
assert_eq!(reader.read_be_f64(), std::f64::consts::PI);
|
||||
assert_eq!(reader.cursor, 12);
|
||||
assert_eq!(reader.read_le_f32(), std::f32::consts::PI);
|
||||
assert_eq!(reader.cursor, 16);
|
||||
assert_eq!(reader.read_le_f64(), std::f64::consts::PI);
|
||||
assert_eq!(reader.cursor, 24);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -100,7 +122,7 @@ mod safe_test {
|
||||
|
||||
#[test]
|
||||
fn just_format() {
|
||||
assert_eq!(NbtValue::type_id_as_name(15), "未知类型(15)");
|
||||
assert_eq!(15_u8.as_nbt_type_name(), "未知类型(15)");
|
||||
}
|
||||
|
||||
/// unsafe 测试
|
||||
@ -118,14 +140,14 @@ mod unsafe_test {
|
||||
let mut data = vec![0x01, 0x02, 0x03, 0x04];
|
||||
let mut reader = NbtReader::new(&mut data);
|
||||
unsafe {
|
||||
let value = reader.read_i16_unchecked();
|
||||
let value = reader.read_be_i16_unsafe();
|
||||
reader.roll_back(2);
|
||||
let safe_value = reader.read_i16();
|
||||
let safe_value = reader.read_be_i16();
|
||||
assert_eq!(value, safe_value);
|
||||
assert_eq!(reader.cursor, 2);
|
||||
let value = reader.read_u16_unchecked();
|
||||
let value = reader.read_be_u16_unsafe();
|
||||
reader.roll_back(2);
|
||||
let safe_value = reader.read_u16();
|
||||
let safe_value = reader.read_be_u16();
|
||||
assert_eq!(value, safe_value);
|
||||
assert_eq!(reader.cursor, 4);
|
||||
}
|
||||
@ -136,14 +158,14 @@ mod unsafe_test {
|
||||
let mut data = vec![0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04];
|
||||
let mut reader = NbtReader::new(&mut data);
|
||||
unsafe {
|
||||
let value = reader.read_i32_unchecked();
|
||||
let value = reader.read_be_i32_unsafe();
|
||||
reader.roll_back(4);
|
||||
let safe_value = reader.read_i32();
|
||||
let safe_value = reader.read_be_i32();
|
||||
assert_eq!(value, safe_value);
|
||||
assert_eq!(reader.cursor, 4);
|
||||
let value = reader.read_u32_unchecked();
|
||||
let value = reader.read_be_u32_unsafe();
|
||||
reader.roll_back(4);
|
||||
let safe_value = reader.read_u32();
|
||||
let safe_value = reader.read_be_u32();
|
||||
assert_eq!(value, safe_value);
|
||||
assert_eq!(reader.cursor, 8);
|
||||
}
|
||||
@ -153,20 +175,34 @@ mod unsafe_test {
|
||||
fn read_x64() {
|
||||
let mut data = vec![
|
||||
0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02,
|
||||
0x03, 0x04,
|
||||
0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
|
||||
0x01, 0x02, 0x03, 0x04,
|
||||
];
|
||||
let mut reader = NbtReader::new(&mut data);
|
||||
unsafe {
|
||||
let value = reader.read_i64_unchecked();
|
||||
let value = reader.read_be_i64_unsafe();
|
||||
reader.roll_back(8);
|
||||
let safe_value = reader.read_i64();
|
||||
let safe_value = reader.read_be_i64();
|
||||
assert_eq!(value, safe_value);
|
||||
assert_eq!(reader.cursor, 8);
|
||||
let value = reader.read_u64_unchecked();
|
||||
|
||||
let value = reader.read_be_u64_unsafe();
|
||||
reader.roll_back(8);
|
||||
let safe_value = reader.read_u64();
|
||||
let safe_value = reader.read_be_u64();
|
||||
assert_eq!(value, safe_value);
|
||||
assert_eq!(reader.cursor, 16);
|
||||
|
||||
let value = reader.read_le_i64_unsafe();
|
||||
reader.roll_back(8);
|
||||
let safe_value = reader.read_le_i64();
|
||||
assert_eq!(value, safe_value);
|
||||
assert_eq!(reader.cursor, 24);
|
||||
|
||||
let value = reader.read_le_u64_unsafe();
|
||||
reader.roll_back(8);
|
||||
let safe_value = reader.read_le_u64();
|
||||
assert_eq!(value, safe_value);
|
||||
assert_eq!(reader.cursor, 32);
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,19 +211,34 @@ mod unsafe_test {
|
||||
let mut data = Vec::with_capacity(12);
|
||||
data.extend_from_slice(&std::f32::consts::PI.to_be_bytes());
|
||||
data.extend_from_slice(&std::f64::consts::PI.to_be_bytes());
|
||||
data.extend_from_slice(&std::f32::consts::PI.to_le_bytes());
|
||||
data.extend_from_slice(&std::f64::consts::PI.to_le_bytes());
|
||||
println!("{:?}", data);
|
||||
let mut reader = NbtReader::new(&mut data);
|
||||
unsafe {
|
||||
let value = reader.read_f32_unchecked();
|
||||
let value = reader.read_be_f32_unsafe();
|
||||
reader.roll_back(4);
|
||||
let safe_value = reader.read_f32();
|
||||
let safe_value = reader.read_be_f32();
|
||||
assert_eq!(value, safe_value);
|
||||
assert_eq!(reader.cursor, 4);
|
||||
let value = reader.read_f64_unchecked();
|
||||
|
||||
let value = reader.read_be_f64_unsafe();
|
||||
reader.roll_back(8);
|
||||
let safe_value = reader.read_f64();
|
||||
let safe_value = reader.read_be_f64();
|
||||
assert_eq!(value, safe_value);
|
||||
assert_eq!(reader.cursor, 12);
|
||||
|
||||
let value = reader.read_le_f32_unsafe();
|
||||
reader.roll_back(4);
|
||||
let safe_value = reader.read_le_f32();
|
||||
assert_eq!(value, safe_value);
|
||||
assert_eq!(reader.cursor, 16);
|
||||
|
||||
let value = reader.read_le_f64_unsafe();
|
||||
reader.roll_back(8);
|
||||
let safe_value = reader.read_le_f64();
|
||||
assert_eq!(value, safe_value);
|
||||
assert_eq!(reader.cursor, 24);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +247,7 @@ mod unsafe_test {
|
||||
let mut data = gen_datas(100);
|
||||
let mut reader = NbtReader::new(&mut data);
|
||||
unsafe {
|
||||
let value = reader.read_i8_array_unchecked(100);
|
||||
let value = reader.read_i8_array_unsafe(100);
|
||||
reader.roll_back(100);
|
||||
let safe_value = reader.read_i8_array(100);
|
||||
assert_eq!(value, safe_value);
|
||||
@ -209,7 +260,7 @@ mod unsafe_test {
|
||||
let mut value = gen_datas(4 * 100);
|
||||
let mut reader = NbtReader::new(&mut value);
|
||||
unsafe {
|
||||
let value = reader.read_i32_array_unchecked(100);
|
||||
let value = reader.read_i32_array_unsafe(100);
|
||||
reader.roll_back(100 * 4);
|
||||
let safe_value = reader.read_i32_array(100);
|
||||
assert_eq!(value, safe_value);
|
||||
@ -222,7 +273,7 @@ mod unsafe_test {
|
||||
let mut value = gen_datas(8 * 100);
|
||||
let mut reader = NbtReader::new(&mut value);
|
||||
unsafe {
|
||||
let value = reader.read_i64_array_unchecked(100);
|
||||
let value = reader.read_i64_array_unsafe(100);
|
||||
reader.roll_back(100 * 8);
|
||||
let safe_value = reader.read_i64_array(100);
|
||||
assert_eq!(value, safe_value);
|
||||
@ -241,7 +292,7 @@ mod nbt {
|
||||
0x08, 0x00, 0x04, 0x6E, 0x61, 0x6D, 0x65, 0x00, 0x09, 0x42, 0x61, 0x6E, 0x61, 0x6E,
|
||||
0x72, 0x61, 0x6D, 0x61, 0x00,
|
||||
];
|
||||
let data = NbtValue::from_binary(&mut data);
|
||||
let data = NbtValue::from_binary::<nbt_version::Java>(&mut data);
|
||||
println!("{:?}", data);
|
||||
let correct_data = NbtValue::Compound(
|
||||
Some("hello world".to_string()),
|
||||
@ -365,7 +416,7 @@ mod nbt {
|
||||
0x6F, 0x75, 0x62, 0x6C, 0x65, 0x54, 0x65, 0x73, 0x74, 0x3F, 0xDF, 0x8F, 0x6B, 0xBB,
|
||||
0xFF, 0x6A, 0x5E, 0x00,
|
||||
];
|
||||
let value = NbtValue::from_binary(&mut data);
|
||||
let value = NbtValue::from_binary::<nbt_version::Java>(&mut data);
|
||||
println!("{:?}", value);
|
||||
}
|
||||
}
|
||||
|
8
trait-test/Cargo.toml
Normal file
8
trait-test/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "trait-test"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
byteorder = "1.5.0"
|
||||
varint-rs = "2.2.0"
|
5
trait-test/src/main.rs
Normal file
5
trait-test/src/main.rs
Normal file
@ -0,0 +1,5 @@
|
||||
use byteorder::{BigEndian, ReadBytesExt};
|
||||
use varint_rs::*;
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
Loading…
Reference in New Issue
Block a user