2024-03-09 17:31:32 +08:00
|
|
|
pub enum Endian {
|
|
|
|
Big,
|
|
|
|
Little,
|
|
|
|
}
|
2024-03-06 22:24:14 +08:00
|
|
|
|
2024-03-09 18:02:26 +08:00
|
|
|
/// 后面也许会实现的
|
2024-03-09 18:49:07 +08:00
|
|
|
///
|
2024-03-09 18:02:26 +08:00
|
|
|
/// 不同版本的 Nbt 数据细节不同
|
|
|
|
/// 老要命了
|
2024-03-09 18:49:07 +08:00
|
|
|
///
|
2024-03-09 18:02:26 +08:00
|
|
|
/// - `Java`
|
|
|
|
/// Java 版除了 1.20.2+(协议号) 及以后的网络 NBT 格式
|
|
|
|
/// - `JavaNetAfter1_20_2`
|
|
|
|
/// 1.20.2+(协议号 >= 764) 及以后的网络 NBT 格式
|
|
|
|
/// - `BedrockDisk`
|
|
|
|
/// 基岩版 实际用于存储的 NBT 格式
|
|
|
|
/// - `BedrockNetVarInt`
|
|
|
|
/// 基岩版 网络 NBT 格式
|
|
|
|
pub enum NbtVersion {
|
|
|
|
Java,
|
|
|
|
JavaNetAfter1_20_2,
|
|
|
|
BedrockDisk,
|
|
|
|
BedrockNetVarInt,
|
|
|
|
}
|
|
|
|
|
2024-03-10 00:02:04 +08:00
|
|
|
// pub trait Nbt {
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
2024-03-09 23:30:25 +08:00
|
|
|
/// Error
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub enum NbtError {
|
|
|
|
/// 未知错误
|
|
|
|
UnknownErr(String),
|
|
|
|
/// 根节点类型错误
|
|
|
|
WrongRootType(u8),
|
|
|
|
/// 根节点无名称
|
|
|
|
RootWithoutName,
|
|
|
|
/// 未知类型
|
2024-03-09 23:53:01 +08:00
|
|
|
UnknownType(u8),
|
2024-03-09 23:30:25 +08:00
|
|
|
/// 名称读取错误
|
2024-03-09 23:53:01 +08:00
|
|
|
NameRead(String),
|
2024-03-09 23:30:25 +08:00
|
|
|
/// 指针超出范围
|
|
|
|
///
|
|
|
|
/// cursor, len, data.len()
|
|
|
|
/// 三个参数分别表示
|
|
|
|
/// - 当前指针
|
|
|
|
/// - 数据长度
|
|
|
|
/// - 数据总长度
|
2024-03-09 23:53:01 +08:00
|
|
|
CursorOverflow(usize, usize, usize),
|
2024-03-09 23:30:25 +08:00
|
|
|
}
|
|
|
|
|
2024-03-09 23:53:01 +08:00
|
|
|
pub type NbtResult<T> = Result<T, NbtError>;
|
|
|
|
|
2024-03-09 23:30:25 +08:00
|
|
|
impl std::fmt::Display for NbtError {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
match self {
|
|
|
|
NbtError::UnknownErr(s) => write!(f, "未知错误: {}", s),
|
|
|
|
NbtError::WrongRootType(n) => {
|
|
|
|
match n {
|
|
|
|
9 => {
|
|
|
|
write!(f, "根节点为 NbtList(9) 类型, 是否应该使用 BedrockDisk/BedrockNetVarInt 解析?")
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
write!(f, "根节点类型错误: {}, 应为 NbtCompound/NbtList(bedrock only)", n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NbtError::RootWithoutName => {
|
|
|
|
write!(f, "根节点无名称, 是否应该使用 JavaNetAfter1_20_2 解析?")
|
|
|
|
}
|
2024-03-09 23:53:01 +08:00
|
|
|
NbtError::UnknownType(n) => {
|
2024-03-09 23:30:25 +08:00
|
|
|
if *n == 0 {
|
|
|
|
write!(f, "未知类型: NBTEnd(0), 请检查数据是否正确")
|
|
|
|
} else {
|
|
|
|
write!(f, "未知类型: {}", n)
|
|
|
|
}
|
|
|
|
}
|
2024-03-09 23:53:01 +08:00
|
|
|
NbtError::NameRead(s) => write!(f, "名称读取错误: {}", s),
|
|
|
|
NbtError::CursorOverflow(cursor, len, data_len) => write!(
|
2024-03-09 23:30:25 +08:00
|
|
|
f,
|
|
|
|
"指针超出范围: cursor: {}, len: {}, cursor+len: {}, data.len(): {}",
|
|
|
|
cursor,
|
|
|
|
len,
|
|
|
|
cursor + len,
|
|
|
|
data_len
|
|
|
|
),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-06 23:39:15 +08:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests;
|
|
|
|
|
2024-03-06 22:33:46 +08:00
|
|
|
/// 用于读取 NBT 数据
|
|
|
|
pub struct NbtReader<'data> {
|
2024-03-06 23:06:42 +08:00
|
|
|
/// NBT 数据
|
2024-03-07 22:34:51 +08:00
|
|
|
pub data: &'data mut [u8],
|
2024-03-06 23:06:42 +08:00
|
|
|
/// 当前读取的位置
|
|
|
|
pub cursor: usize,
|
|
|
|
// be/le
|
|
|
|
// pub endian: Endian,
|
2024-03-06 22:33:46 +08:00
|
|
|
}
|
|
|
|
|
2024-03-08 20:54:21 +08:00
|
|
|
macro_rules! read_uncheck {
|
2024-03-06 23:06:42 +08:00
|
|
|
($name:ident, $ty:ty, $size:literal) => {
|
|
|
|
#[doc = concat!("读取 ", stringify!($ty), " 类型 ", $size, " 长度的数据")]
|
2024-03-08 06:13:05 +08:00
|
|
|
///
|
|
|
|
#[doc = "转换大小端"]
|
2024-03-09 13:21:25 +08:00
|
|
|
///
|
2024-03-08 20:54:21 +08:00
|
|
|
/// # 安全性
|
|
|
|
/// 允许未对齐的地址
|
|
|
|
/// 长度溢出会导致 UB
|
2024-03-09 14:00:53 +08:00
|
|
|
#[inline]
|
2024-03-08 20:54:21 +08:00
|
|
|
pub unsafe fn $name(&mut self) -> $ty {
|
|
|
|
// 使用 std::ptr::read_unaligned 解决未对齐地址问题
|
2024-03-09 17:12:43 +08:00
|
|
|
let ptr = self.data.as_ptr().add(self.cursor) as *const $ty;
|
|
|
|
let value = std::ptr::read_unaligned(ptr);
|
2024-03-08 20:54:21 +08:00
|
|
|
self.cursor += std::mem::size_of::<$ty>();
|
|
|
|
value.to_be()
|
2024-03-06 23:06:42 +08:00
|
|
|
}
|
|
|
|
};
|
2024-03-08 20:54:21 +08:00
|
|
|
}
|
|
|
|
|
2024-03-06 22:33:46 +08:00
|
|
|
impl NbtReader<'_> {
|
2024-03-09 18:49:07 +08:00
|
|
|
pub fn new(data: &mut [u8]) -> NbtReader { NbtReader { data, cursor: 0 } }
|
2024-03-09 17:12:43 +08:00
|
|
|
/// 向后滚动
|
|
|
|
#[inline]
|
|
|
|
pub fn roll_back(&mut self, len: usize) { self.cursor -= len; }
|
|
|
|
/// 向前滚动
|
|
|
|
#[inline]
|
|
|
|
pub fn roll_down(&mut self, len: usize) { self.cursor += len; }
|
2024-03-08 06:13:05 +08:00
|
|
|
/// 读取一个 u8 类型的数据
|
|
|
|
#[inline]
|
2024-03-06 23:06:42 +08:00
|
|
|
pub fn read_u8(&mut self) -> u8 {
|
|
|
|
let value = self.data[self.cursor];
|
|
|
|
self.cursor += 1;
|
|
|
|
value
|
2024-03-06 22:33:46 +08:00
|
|
|
}
|
2024-03-08 06:13:05 +08:00
|
|
|
/// 读取一个 i8 类型的数据
|
|
|
|
#[inline]
|
|
|
|
pub fn read_i8(&mut self) -> i8 { self.read_u8() as i8 }
|
2024-03-08 20:54:21 +08:00
|
|
|
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);
|
2024-03-09 13:21:25 +08:00
|
|
|
/// 安全的读取 i16 类型的数据
|
|
|
|
///
|
|
|
|
/// 转换大小端(大端)
|
|
|
|
///
|
|
|
|
/// 会在超出长度时 panic
|
2024-03-09 13:55:20 +08:00
|
|
|
#[inline]
|
2024-03-09 13:21:25 +08:00
|
|
|
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
|
2024-03-09 13:55:20 +08:00
|
|
|
#[inline]
|
2024-03-09 13:21:25 +08:00
|
|
|
pub fn read_u16(&mut self) -> u16 { self.read_i16() as u16 }
|
|
|
|
/// 安全的读取 i32 类型的数据
|
|
|
|
///
|
|
|
|
/// 转换大小端(大端)
|
|
|
|
///
|
|
|
|
/// 会在超出长度时 panic
|
2024-03-09 13:55:20 +08:00
|
|
|
#[inline]
|
2024-03-09 13:21:25 +08:00
|
|
|
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
|
2024-03-09 13:55:20 +08:00
|
|
|
#[inline]
|
2024-03-09 17:12:43 +08:00
|
|
|
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
|
|
|
|
}
|
2024-03-09 13:21:25 +08:00
|
|
|
/// 安全的读取 i64 类型的数据
|
|
|
|
///
|
|
|
|
/// 转换大小端(大端)
|
|
|
|
///
|
|
|
|
/// 会在超出长度时 panic
|
2024-03-09 13:55:20 +08:00
|
|
|
#[inline]
|
2024-03-09 13:21:25 +08:00
|
|
|
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
|
2024-03-09 13:55:20 +08:00
|
|
|
#[inline]
|
2024-03-09 17:12:43 +08:00
|
|
|
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
|
|
|
|
}
|
2024-03-08 20:54:21 +08:00
|
|
|
/// 读取一个 f32 类型的数据
|
2024-03-09 13:21:25 +08:00
|
|
|
///
|
2024-03-08 20:54:21 +08:00
|
|
|
/// 转换大小端
|
2024-03-09 13:21:25 +08:00
|
|
|
///
|
2024-03-09 13:38:38 +08:00
|
|
|
/// 会在超出长度时 panic
|
2024-03-09 13:55:20 +08:00
|
|
|
#[inline]
|
|
|
|
pub fn read_f32(&mut self) -> f32 { f32::from_bits(self.read_u32()) }
|
2024-03-09 13:38:38 +08:00
|
|
|
/// 读取一个 f64 类型的数据
|
|
|
|
///
|
|
|
|
/// 转换大小端
|
|
|
|
///
|
|
|
|
/// 会在超出长度时 panic
|
2024-03-09 13:55:20 +08:00
|
|
|
#[inline]
|
|
|
|
pub fn read_f64(&mut self) -> f64 { f64::from_bits(self.read_u64()) }
|
2024-03-09 13:38:38 +08:00
|
|
|
/// 读取一个 f32 类型的数据
|
|
|
|
///
|
|
|
|
/// 转换大小端
|
|
|
|
///
|
2024-03-08 20:54:21 +08:00
|
|
|
/// # 安全性
|
|
|
|
/// 允许未对齐的地址
|
|
|
|
/// 长度溢出会导致 UB
|
2024-03-09 17:12:43 +08:00
|
|
|
#[inline]
|
2024-03-08 20:54:21 +08:00
|
|
|
pub unsafe fn read_f32_unchecked(&mut self) -> f32 {
|
2024-03-09 17:12:43 +08:00
|
|
|
let value = self.read_u32_unchecked();
|
|
|
|
std::mem::transmute::<u32, f32>(value)
|
2024-03-08 20:54:21 +08:00
|
|
|
}
|
|
|
|
/// 读取一个 f64 类型的数据
|
|
|
|
/// 转换大小端
|
2024-03-09 13:21:25 +08:00
|
|
|
///
|
2024-03-08 20:54:21 +08:00
|
|
|
/// # 安全性
|
|
|
|
/// 允许未对齐的地址
|
|
|
|
/// 长度溢出会导致 UB
|
2024-03-09 17:12:43 +08:00
|
|
|
#[inline]
|
2024-03-08 20:54:21 +08:00
|
|
|
pub unsafe fn read_f64_unchecked(&mut self) -> f64 {
|
2024-03-09 17:12:43 +08:00
|
|
|
let value = self.read_u64_unchecked();
|
|
|
|
std::mem::transmute::<u64, f64>(value)
|
2024-03-08 20:54:21 +08:00
|
|
|
}
|
2024-03-09 13:21:25 +08:00
|
|
|
/// 读取指定长度的 u8 数组
|
|
|
|
///
|
|
|
|
/// # 安全性
|
|
|
|
///
|
|
|
|
/// 长度溢出会导致 panic
|
2024-03-09 13:55:20 +08:00
|
|
|
#[inline]
|
2024-03-06 23:31:51 +08:00
|
|
|
pub fn read_u8_array(&mut self, len: usize) -> &[u8] {
|
2024-03-06 23:06:42 +08:00
|
|
|
let value = &self.data[self.cursor..self.cursor + len];
|
|
|
|
self.cursor += len;
|
|
|
|
value
|
2024-03-06 22:33:46 +08:00
|
|
|
}
|
2024-03-09 13:21:25 +08:00
|
|
|
/// 读取指定长度的 i8 数组
|
|
|
|
///
|
|
|
|
/// # 安全性
|
|
|
|
///
|
|
|
|
/// 长度溢出会导致 UB
|
2024-03-09 17:12:43 +08:00
|
|
|
#[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();
|
2024-03-06 23:31:51 +08:00
|
|
|
self.cursor += len;
|
|
|
|
value
|
|
|
|
}
|
2024-03-09 13:21:25 +08:00
|
|
|
/// 读取指定长度的 utf-8 字符串
|
|
|
|
///
|
|
|
|
/// # 安全性
|
|
|
|
///
|
|
|
|
/// 长度溢出会导致 panic
|
2024-03-09 13:55:20 +08:00
|
|
|
#[inline]
|
2024-03-09 23:30:25 +08:00
|
|
|
pub fn read_string(&mut self, len: usize) -> Result<String, NbtError> {
|
|
|
|
if len + self.cursor > self.data.len() {
|
2024-03-09 23:53:01 +08:00
|
|
|
return Err(NbtError::CursorOverflow(self.cursor, len, self.data.len()));
|
2024-03-09 23:30:25 +08:00
|
|
|
}
|
2024-03-06 23:31:51 +08:00
|
|
|
let value = String::from_utf8_lossy(&self.data[self.cursor..self.cursor + len]);
|
|
|
|
self.cursor += len;
|
2024-03-09 23:30:25 +08:00
|
|
|
Ok(value.into_owned())
|
2024-03-06 23:31:51 +08:00
|
|
|
}
|
2024-03-09 14:00:53 +08:00
|
|
|
/// 读取指定长度的 i32 数组
|
|
|
|
///
|
|
|
|
/// # 安全性
|
|
|
|
///
|
|
|
|
/// 长度溢出会导致 UB
|
2024-03-09 17:12:43 +08:00
|
|
|
#[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();
|
2024-03-06 23:33:14 +08:00
|
|
|
}
|
2024-03-09 17:12:43 +08:00
|
|
|
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
|
2024-03-06 23:31:51 +08:00
|
|
|
}
|
2024-03-09 14:00:53 +08:00
|
|
|
/// 读取指定长度的 i64 数组
|
|
|
|
///
|
|
|
|
/// # 安全性
|
|
|
|
///
|
|
|
|
/// 长度溢出会导致 UB
|
2024-03-09 17:12:43 +08:00
|
|
|
#[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();
|
2024-03-06 23:33:14 +08:00
|
|
|
}
|
2024-03-09 17:12:43 +08:00
|
|
|
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
|
2024-03-06 23:31:51 +08:00
|
|
|
}
|
2024-03-09 17:31:32 +08:00
|
|
|
|
|
|
|
/// 读取一个 NBT byte array
|
|
|
|
pub fn read_nbt_i8_array(&mut self) -> Vec<i8> {
|
|
|
|
let len = self.read_i32() as usize;
|
2024-03-09 18:02:26 +08:00
|
|
|
let value = unsafe { self.read_i8_array_unchecked(len) };
|
2024-03-09 17:31:32 +08:00
|
|
|
value
|
|
|
|
}
|
2024-03-09 18:02:26 +08:00
|
|
|
|
2024-03-09 17:31:32 +08:00
|
|
|
/// 读取一个 NBT int array
|
|
|
|
pub fn read_nbt_i32_array(&mut self) -> Vec<i32> {
|
|
|
|
let len = self.read_i32() as usize;
|
2024-03-09 18:02:26 +08:00
|
|
|
let value = unsafe { self.read_i32_array_unchecked(len) };
|
2024-03-09 17:31:32 +08:00
|
|
|
value
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 读取一个 NBT long array
|
|
|
|
pub fn read_nbt_i64_array(&mut self) -> Vec<i64> {
|
|
|
|
let len = self.read_i32() as usize;
|
2024-03-09 18:02:26 +08:00
|
|
|
let value = unsafe { self.read_i64_array_unchecked(len) };
|
2024-03-09 17:31:32 +08:00
|
|
|
value
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 读取一个 NBT string
|
2024-03-09 23:53:01 +08:00
|
|
|
pub fn read_nbt_string(&mut self) -> NbtResult<String> {
|
2024-03-09 17:31:32 +08:00
|
|
|
let len = self.read_u16() as usize;
|
2024-03-09 23:30:25 +08:00
|
|
|
self.read_string(len)
|
2024-03-09 17:31:32 +08:00
|
|
|
}
|
2024-03-06 22:33:46 +08:00
|
|
|
}
|
|
|
|
|
2024-03-09 18:49:07 +08:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
2024-03-06 23:31:51 +08:00
|
|
|
pub enum NbtValue {
|
2024-03-06 22:24:14 +08:00
|
|
|
// end: 0
|
|
|
|
/// 1: Byte
|
|
|
|
Byte(i8),
|
|
|
|
/// 2
|
|
|
|
Short(i16),
|
|
|
|
/// 3
|
|
|
|
Int(i32),
|
|
|
|
/// 4
|
|
|
|
Long(i64),
|
|
|
|
/// 5
|
|
|
|
Float(f32),
|
|
|
|
/// 6
|
|
|
|
Double(f64),
|
|
|
|
/// 7
|
2024-03-09 17:31:32 +08:00
|
|
|
/// 长度: i32
|
2024-03-06 22:24:14 +08:00
|
|
|
ByteArray(Vec<i8>),
|
2024-03-06 22:33:46 +08:00
|
|
|
/// 8
|
|
|
|
/// 或者叫 u8 array
|
2024-03-09 17:31:32 +08:00
|
|
|
/// 长度: u16
|
2024-03-06 23:31:51 +08:00
|
|
|
String(String),
|
2024-03-06 22:24:14 +08:00
|
|
|
/// 9
|
2024-03-09 17:31:32 +08:00
|
|
|
/// 长度: i32
|
2024-03-06 23:31:51 +08:00
|
|
|
List(Vec<NbtValue>),
|
2024-03-06 22:24:14 +08:00
|
|
|
/// 10
|
2024-03-09 17:31:32 +08:00
|
|
|
Compound(Option<String>, Vec<(String, NbtValue)>),
|
2024-03-06 22:33:46 +08:00
|
|
|
/// 11
|
2024-03-09 17:31:32 +08:00
|
|
|
/// 长度: i32
|
2024-03-06 22:33:46 +08:00
|
|
|
IntArray(Vec<i32>),
|
|
|
|
/// 12
|
2024-03-09 17:31:32 +08:00
|
|
|
/// 长度: i32
|
2024-03-06 22:33:46 +08:00
|
|
|
LongArray(Vec<i64>),
|
2024-03-06 22:24:14 +08:00
|
|
|
}
|
2024-03-09 17:12:43 +08:00
|
|
|
|
|
|
|
impl NbtValue {
|
2024-03-09 23:30:25 +08:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
2024-03-09 23:53:01 +08:00
|
|
|
pub fn from_binary(data: &mut [u8]) -> NbtResult<NbtValue> {
|
2024-03-09 17:12:43 +08:00
|
|
|
let reader = NbtReader::new(data);
|
2024-03-09 23:53:01 +08:00
|
|
|
Ok(NbtValue::from_reader(reader))
|
2024-03-09 17:12:43 +08:00
|
|
|
}
|
|
|
|
|
2024-03-09 23:53:01 +08:00
|
|
|
fn read_nbt_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>> {
|
2024-03-09 18:49:07 +08:00
|
|
|
let mut compound = Vec::with_capacity(10);
|
|
|
|
loop {
|
|
|
|
let tag_id = reader.read_u8();
|
|
|
|
if tag_id == 0 {
|
|
|
|
break;
|
|
|
|
}
|
2024-03-09 23:53:01 +08:00
|
|
|
let name = reader.read_nbt_string()?;
|
2024-03-09 18:49:07 +08:00
|
|
|
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()),
|
2024-03-09 23:53:01 +08:00
|
|
|
8 => NbtValue::String(reader.read_nbt_string()?),
|
|
|
|
9 => NbtValue::List(NbtValue::read_nbt_list(reader)?),
|
|
|
|
10 => NbtValue::Compound(None, NbtValue::read_nbt_compound(reader)?),
|
2024-03-09 18:49:07 +08:00
|
|
|
11 => NbtValue::IntArray(reader.read_nbt_i32_array()),
|
|
|
|
12 => NbtValue::LongArray(reader.read_nbt_i64_array()),
|
|
|
|
_ => unimplemented!(),
|
|
|
|
};
|
|
|
|
compound.push((name, value));
|
|
|
|
}
|
2024-03-09 23:53:01 +08:00
|
|
|
Ok(compound)
|
2024-03-09 18:49:07 +08:00
|
|
|
}
|
|
|
|
|
2024-03-09 23:53:01 +08:00
|
|
|
fn read_nbt_list(reader: &mut NbtReader) -> NbtResult<Vec<NbtValue>> {
|
2024-03-09 18:49:07 +08:00
|
|
|
let type_id = reader.read_u8();
|
|
|
|
let len = reader.read_i32() as usize;
|
|
|
|
let mut list = Vec::with_capacity(len);
|
2024-03-09 23:53:01 +08:00
|
|
|
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);
|
2024-03-09 18:49:07 +08:00
|
|
|
}
|
2024-03-09 23:53:01 +08:00
|
|
|
Ok(list)
|
2024-03-09 18:49:07 +08:00
|
|
|
}
|
2024-03-09 17:31:32 +08:00
|
|
|
|
2024-03-09 23:53:01 +08:00
|
|
|
pub fn from_reader(mut reader: NbtReader) -> NbtValue {
|
2024-03-09 17:31:32 +08:00
|
|
|
// 第一个 tag, 不可能是 0
|
|
|
|
match reader.read_u8() {
|
2024-03-09 23:53:01 +08:00
|
|
|
9 => NbtValue::List(NbtValue::read_nbt_list(&mut reader).unwrap()),
|
2024-03-09 18:49:07 +08:00
|
|
|
10 => {
|
2024-03-09 23:30:25 +08:00
|
|
|
let name = reader.read_nbt_string().unwrap();
|
2024-03-09 23:53:01 +08:00
|
|
|
NbtValue::Compound(Some(name), NbtValue::read_nbt_compound(&mut reader).unwrap())
|
2024-03-09 18:49:07 +08:00
|
|
|
}
|
2024-03-09 23:30:25 +08:00
|
|
|
x => {
|
|
|
|
panic!("根节点类型错误 {}", Self::type_id_as_name(x));
|
|
|
|
}
|
2024-03-09 17:31:32 +08:00
|
|
|
}
|
|
|
|
}
|
2024-03-09 17:12:43 +08:00
|
|
|
}
|