Compare commits
2 Commits
6eda5a38fe
...
e3fa34e89c
Author | SHA1 | Date | |
---|---|---|---|
e3fa34e89c | |||
bf6a390eb7 |
22
README.md
22
README.md
@ -2,6 +2,19 @@
|
|||||||
|
|
||||||
一个 "全功能" 的 "快速" NBT 解析器
|
一个 "全功能" 的 "快速" NBT 解析器
|
||||||
|
|
||||||
|
目前进度
|
||||||
|
|
||||||
|
- [ ] 读取
|
||||||
|
- [x] Java
|
||||||
|
- [x] JavaNetAfter1_20_2
|
||||||
|
- [x] BedrockDisk
|
||||||
|
- [ ] BedrockNetVarInt
|
||||||
|
- [ ] 写入
|
||||||
|
- [ ] Java
|
||||||
|
- [ ] JavaNetAfter1_20_2
|
||||||
|
- [ ] BedrockDisk
|
||||||
|
- [ ] BedrockNetVarInt
|
||||||
|
|
||||||
支持
|
支持
|
||||||
|
|
||||||
- `Java`
|
- `Java`
|
||||||
@ -19,6 +32,14 @@
|
|||||||
- 数据都是小端序
|
- 数据都是小端序
|
||||||
- 根节点必须有名称
|
- 根节点必须有名称
|
||||||
- 根节点是 `NbtCompound(10)` 或者 `NbtList(9)` 类型
|
- 根节点是 `NbtCompound(10)` 或者 `NbtList(9)` 类型
|
||||||
|
|
||||||
|
- ```text
|
||||||
|
与Java版本使用的big-endian格式相同,但所有数字都以little-endian编码。
|
||||||
|
这包括标记名称和TAG_String值之前的16位长度前缀,以及TAG_Float和TAG_Double值。
|
||||||
|
|
||||||
|
---- https://wiki.vg/NBT
|
||||||
|
```
|
||||||
|
|
||||||
- `BedrockNetVarInt`
|
- `BedrockNetVarInt`
|
||||||
- 基岩版用于网络传输的 NBT 格式
|
- 基岩版用于网络传输的 NBT 格式
|
||||||
|
|
||||||
@ -33,7 +54,6 @@
|
|||||||
---- https://wiki.vg/NBT
|
---- https://wiki.vg/NBT
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
writen in rust!
|
writen in rust!
|
||||||
|
|
||||||
## 感谢
|
## 感谢
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "shen-nbt5"
|
name = "shen-nbt5"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
@ -28,9 +28,14 @@ pub mod nbt_version {
|
|||||||
use super::{NbtReader, NbtResult, NbtValue};
|
use super::{NbtReader, NbtResult, NbtValue};
|
||||||
|
|
||||||
pub trait NbtReadTrait {
|
pub trait NbtReadTrait {
|
||||||
fn from_reader(reader: NbtReader) -> NbtResult<NbtValue>;
|
fn read_i8_array(reader: &mut NbtReader) -> NbtResult<Vec<i8>>;
|
||||||
|
fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>>;
|
||||||
|
fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>>;
|
||||||
|
fn read_nbt_string(reader: &mut NbtReader) -> NbtResult<String>;
|
||||||
fn read_list(reader: &mut NbtReader) -> NbtResult<Vec<NbtValue>>;
|
fn read_list(reader: &mut NbtReader) -> NbtResult<Vec<NbtValue>>;
|
||||||
fn read_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>>;
|
fn read_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>>;
|
||||||
|
|
||||||
|
fn from_reader(reader: NbtReader) -> NbtResult<NbtValue>;
|
||||||
}
|
}
|
||||||
/// Java 版 绝大部分的 NBT 格式
|
/// Java 版 绝大部分的 NBT 格式
|
||||||
///
|
///
|
||||||
@ -101,6 +106,10 @@ pub enum NbtError {
|
|||||||
/// - 数据长度
|
/// - 数据长度
|
||||||
/// - 数据总长度
|
/// - 数据总长度
|
||||||
CursorOverflow(usize, usize, usize),
|
CursorOverflow(usize, usize, usize),
|
||||||
|
/// Varint 过大
|
||||||
|
VarIntTooBig(usize),
|
||||||
|
/// Varlong 过大
|
||||||
|
VarlongTooBig(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type NbtResult<T> = Result<T, NbtError>;
|
pub type NbtResult<T> = Result<T, NbtError>;
|
||||||
@ -138,6 +147,8 @@ impl std::fmt::Display for NbtError {
|
|||||||
cursor + len,
|
cursor + len,
|
||||||
data_len
|
data_len
|
||||||
),
|
),
|
||||||
|
NbtError::VarIntTooBig(n) => write!(f, "VarInt 过大: {} 最大长度为 5", n),
|
||||||
|
NbtError::VarlongTooBig(n) => write!(f, "VarLong 过大: {} 最大长度为 10", n),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,75 +190,10 @@ pub enum NbtValue {
|
|||||||
|
|
||||||
impl NbtValue {
|
impl NbtValue {
|
||||||
pub fn from_binary<T>(data: &mut [u8]) -> NbtResult<NbtValue>
|
pub fn from_binary<T>(data: &mut [u8]) -> NbtResult<NbtValue>
|
||||||
where T: nbt_version::NbtReadTrait {
|
where
|
||||||
|
T: nbt_version::NbtReadTrait,
|
||||||
|
{
|
||||||
let reader = NbtReader::new(data);
|
let reader = NbtReader::new(data);
|
||||||
T::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_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_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!("根节点类型错误 {}", x.as_nbt_type_name());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::nbt_version;
|
use crate::nbt_version::{BedrockDisk, BedrockNetVarInt, Java, JavaNetAfter1_20_2, NbtReadTrait};
|
||||||
use crate::{NbtError, NbtResult, NbtValue};
|
use crate::{nbt_version, NbtError, NbtResult, NbtValue};
|
||||||
|
|
||||||
/// 用于读取 NBT 数据
|
/// 用于读取 NBT 数据
|
||||||
pub struct NbtReader<'data> {
|
pub struct NbtReader<'data> {
|
||||||
@ -17,9 +17,272 @@ pub struct NbtReader<'data> {
|
|||||||
///
|
///
|
||||||
/// 上面说的那玩意 请使用 `JavaNetAfter1_20_2`
|
/// 上面说的那玩意 请使用 `JavaNetAfter1_20_2`
|
||||||
impl nbt_version::NbtReadTrait for nbt_version::Java {
|
impl nbt_version::NbtReadTrait for nbt_version::Java {
|
||||||
fn from_reader(reader: NbtReader) -> NbtResult<NbtValue> { todo!() }
|
#[inline]
|
||||||
|
fn read_nbt_string(reader: &mut NbtReader) -> NbtResult<String> {
|
||||||
|
let len = reader.read_be_u16() as usize;
|
||||||
|
reader.read_string(len)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_i8_array(reader: &mut NbtReader) -> NbtResult<Vec<i8>> {
|
||||||
|
let len = reader.read_be_i32() as usize;
|
||||||
|
let value = reader.read_i8_array(len);
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>> {
|
||||||
|
let len = reader.read_be_i32() as usize;
|
||||||
|
let value = reader.read_i32_array(len);
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>> {
|
||||||
|
let len = reader.read_be_i32() as usize;
|
||||||
|
let value = reader.read_i64_array(len);
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_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 = Java::read_nbt_string(reader)?;
|
||||||
|
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(Java::read_i8_array(reader)?),
|
||||||
|
8 => NbtValue::String(Java::read_nbt_string(reader)?),
|
||||||
|
9 => NbtValue::List(Java::read_list(reader)?),
|
||||||
|
10 => NbtValue::Compound(None, nbt_version::Java::read_compound(reader)?),
|
||||||
|
11 => NbtValue::IntArray(Java::read_i32_array(reader)?),
|
||||||
|
12 => NbtValue::LongArray(Java::read_i64_array(reader)?),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
compound.push((name, value));
|
||||||
|
}
|
||||||
|
Ok(compound)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_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(Java::read_i8_array(reader)?),
|
||||||
|
8 => NbtValue::String(Java::read_nbt_string(reader)?),
|
||||||
|
9 => NbtValue::List(Java::read_list(reader)?),
|
||||||
|
10 => NbtValue::Compound(None, nbt_version::Java::read_compound(reader)?),
|
||||||
|
11 => NbtValue::IntArray(Java::read_i32_array(reader)?),
|
||||||
|
12 => NbtValue::LongArray(Java::read_i64_array(reader)?),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
list.push(value);
|
||||||
|
}
|
||||||
|
Ok(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_reader(mut reader: NbtReader) -> NbtResult<NbtValue> {
|
||||||
|
// 第一个 tag, 不可能是 0
|
||||||
|
match reader.read_u8() {
|
||||||
|
10 => {
|
||||||
|
let name = Java::read_nbt_string(&mut reader)?;
|
||||||
|
Ok(NbtValue::Compound(Some(name), nbt_version::Java::read_compound(&mut reader)?))
|
||||||
|
}
|
||||||
|
x => Err(NbtError::WrongRootType(x)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 两个最好实现的就在这里了
|
||||||
|
///
|
||||||
|
/// 网络 NBT: 1.20.2+ 的网络 NBT 根节点没有名字
|
||||||
|
impl NbtReadTrait for JavaNetAfter1_20_2 {
|
||||||
|
#[inline]
|
||||||
|
fn read_nbt_string(reader: &mut NbtReader) -> NbtResult<String> {
|
||||||
|
Java::read_nbt_string(reader)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_i8_array(reader: &mut NbtReader) -> NbtResult<Vec<i8>> { Java::read_i8_array(reader) }
|
||||||
|
#[inline]
|
||||||
|
fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>> {
|
||||||
|
Java::read_i32_array(reader)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>> {
|
||||||
|
Java::read_i64_array(reader)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>> {
|
||||||
|
Java::read_compound(reader)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_list(reader: &mut NbtReader) -> NbtResult<Vec<NbtValue>> { Java::read_list(reader) }
|
||||||
|
|
||||||
|
fn from_reader(mut reader: NbtReader) -> NbtResult<NbtValue> {
|
||||||
|
// 第一个 tag, 不可能是 0
|
||||||
|
match reader.read_u8() {
|
||||||
|
10 => {
|
||||||
|
// Java 1.20.2+ 的网络 NBT 没有名字
|
||||||
|
Ok(NbtValue::Compound(None, nbt_version::Java::read_compound(&mut reader)?))
|
||||||
|
}
|
||||||
|
x => Err(NbtError::WrongRootType(x)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 基岩版的其实也还行, 就是有点麻烦
|
||||||
|
///
|
||||||
|
/// 所有都是小端
|
||||||
|
impl NbtReadTrait for BedrockDisk {
|
||||||
|
#[inline]
|
||||||
|
fn read_nbt_string(reader: &mut NbtReader) -> NbtResult<String> {
|
||||||
|
let len = reader.read_le_u16() as usize;
|
||||||
|
reader.read_string(len)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_i8_array(reader: &mut NbtReader) -> NbtResult<Vec<i8>> {
|
||||||
|
let len = reader.read_le_i32() as usize;
|
||||||
|
let value = reader.read_i8_array(len);
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>> {
|
||||||
|
let len = reader.read_le_i32() as usize;
|
||||||
|
let value = reader.read_i32_array(len);
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>> {
|
||||||
|
let len = reader.read_le_i32() as usize;
|
||||||
|
let value = reader.read_i64_array(len);
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_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 = BedrockDisk::read_nbt_string(reader)?;
|
||||||
|
let value = match tag_id {
|
||||||
|
1 => NbtValue::Byte(reader.read_i8()),
|
||||||
|
2 => NbtValue::Short(reader.read_le_i16()),
|
||||||
|
3 => NbtValue::Int(reader.read_le_i32()),
|
||||||
|
4 => NbtValue::Long(reader.read_le_i64()),
|
||||||
|
5 => NbtValue::Float(reader.read_le_f32()),
|
||||||
|
6 => NbtValue::Double(reader.read_le_f64()),
|
||||||
|
7 => NbtValue::ByteArray(BedrockDisk::read_i8_array(reader)?),
|
||||||
|
8 => NbtValue::String(BedrockDisk::read_nbt_string(reader)?),
|
||||||
|
9 => NbtValue::List(BedrockDisk::read_list(reader)?),
|
||||||
|
10 => NbtValue::Compound(None, nbt_version::BedrockDisk::read_compound(reader)?),
|
||||||
|
11 => NbtValue::IntArray(BedrockDisk::read_i32_array(reader)?),
|
||||||
|
12 => NbtValue::LongArray(BedrockDisk::read_i64_array(reader)?),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
compound.push((name, value));
|
||||||
|
}
|
||||||
|
Ok(compound)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn read_list(reader: &mut NbtReader) -> NbtResult<Vec<NbtValue>> {
|
||||||
|
let type_id = reader.read_u8();
|
||||||
|
let len = reader.read_le_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_le_i16()),
|
||||||
|
3 => NbtValue::Int(reader.read_le_i32()),
|
||||||
|
4 => NbtValue::Long(reader.read_le_i64()),
|
||||||
|
5 => NbtValue::Float(reader.read_le_f32()),
|
||||||
|
6 => NbtValue::Double(reader.read_le_f64()),
|
||||||
|
7 => NbtValue::ByteArray(BedrockDisk::read_i8_array(reader)?),
|
||||||
|
8 => NbtValue::String(BedrockDisk::read_nbt_string(reader)?),
|
||||||
|
9 => NbtValue::List(BedrockDisk::read_list(reader)?),
|
||||||
|
10 => NbtValue::Compound(None, nbt_version::BedrockDisk::read_compound(reader)?),
|
||||||
|
11 => NbtValue::IntArray(BedrockDisk::read_i32_array(reader)?),
|
||||||
|
12 => NbtValue::LongArray(BedrockDisk::read_i64_array(reader)?),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
list.push(value);
|
||||||
|
}
|
||||||
|
Ok(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_reader(mut reader: NbtReader) -> NbtResult<NbtValue> {
|
||||||
|
// 第一个 tag, 不可能是 0
|
||||||
|
match reader.read_u8() {
|
||||||
|
9 => {
|
||||||
|
// 基岩版的 NBT 根节点可以是一个 List
|
||||||
|
Ok(NbtValue::List(nbt_version::BedrockDisk::read_list(&mut reader)?))
|
||||||
|
}
|
||||||
|
10 => {
|
||||||
|
// 或者一个有名字的 Compound
|
||||||
|
let name = BedrockDisk::read_nbt_string(&mut reader)?;
|
||||||
|
Ok(NbtValue::Compound(
|
||||||
|
Some(name),
|
||||||
|
nbt_version::BedrockDisk::read_compound(&mut reader)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
// 别的不行
|
||||||
|
x => Err(NbtError::WrongRootType(x)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 最痛苦的来了
|
||||||
|
impl NbtReadTrait for BedrockNetVarInt {
|
||||||
|
fn read_nbt_string(reader: &mut NbtReader) -> NbtResult<String> {
|
||||||
|
let len = reader.read_var_i32()? as usize;
|
||||||
|
reader.read_string(len)
|
||||||
|
}
|
||||||
|
fn read_i8_array(reader: &mut NbtReader) -> NbtResult<Vec<i8>> {
|
||||||
|
let len = reader.read_var_i32()? as usize;
|
||||||
|
let value = reader.read_i8_array(len);
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>> {
|
||||||
|
let len = reader.read_var_i32()? as usize;
|
||||||
|
let value = reader.read_i32_array(len);
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>> {
|
||||||
|
let len = reader.read_var_i32()? as usize;
|
||||||
|
let value = reader.read_i64_array(len);
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
fn read_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>> { todo!() }
|
fn read_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>> { todo!() }
|
||||||
fn read_list(reader: &mut NbtReader) -> NbtResult<Vec<NbtValue>> { todo!() }
|
fn read_list(reader: &mut NbtReader) -> NbtResult<Vec<NbtValue>> { todo!() }
|
||||||
|
fn from_reader(mut reader: NbtReader) -> NbtResult<NbtValue> {
|
||||||
|
match reader.read_u8() {
|
||||||
|
9 => {
|
||||||
|
// 基岩版的 NBT 根节点可以是一个 List
|
||||||
|
Ok(NbtValue::List(BedrockNetVarInt::read_list(&mut reader)?))
|
||||||
|
}
|
||||||
|
10 => {
|
||||||
|
// 或者一个有名字的 Compound
|
||||||
|
let name = BedrockNetVarInt::read_nbt_string(&mut reader)?;
|
||||||
|
Ok(NbtValue::Compound(Some(name), BedrockNetVarInt::read_compound(&mut reader)?))
|
||||||
|
}
|
||||||
|
// 别的不行
|
||||||
|
x => Err(NbtError::WrongRootType(x)),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! read_uncheck {
|
macro_rules! read_uncheck {
|
||||||
@ -134,9 +397,51 @@ impl NbtReader<'_> {
|
|||||||
self.cursor += 4;
|
self.cursor += 4;
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
/// 安全的读取 i32 类型的数据
|
/// 安全的读取一个 Varint 数据
|
||||||
///
|
///
|
||||||
/// 转换大小端(小端)
|
/// 他有大小端区别吗? (其实是小端)
|
||||||
|
///
|
||||||
|
/// 会在超出长度时 panic
|
||||||
|
#[inline]
|
||||||
|
pub fn read_var_i32(&mut self) -> NbtResult<i32> {
|
||||||
|
let mut value = 0;
|
||||||
|
let mut size = 0;
|
||||||
|
loop {
|
||||||
|
let byte = self.read_u8();
|
||||||
|
value |= ((byte & 0b0111_1111) as i32) << (size * 7);
|
||||||
|
size += 1;
|
||||||
|
if size > 5 {
|
||||||
|
return Err(NbtError::VarIntTooBig(value as usize));
|
||||||
|
}
|
||||||
|
if (byte & 0b1000_0000) == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
/// 安全的读取一个 Varlong
|
||||||
|
///
|
||||||
|
/// 他有大小端区别吗? (其实是小端)
|
||||||
|
///
|
||||||
|
/// 会在超出长度时 panic
|
||||||
|
#[inline]
|
||||||
|
pub fn read_var_i64(&mut self) -> NbtResult<i64> {
|
||||||
|
let mut value = 0;
|
||||||
|
let mut size = 0;
|
||||||
|
loop {
|
||||||
|
let byte = self.read_u8();
|
||||||
|
value |= ((byte & 0b0111_1111) as i64) << (size * 7);
|
||||||
|
size += 1;
|
||||||
|
if size > 10 {
|
||||||
|
return Err(NbtError::VarlongTooBig(value as usize));
|
||||||
|
}
|
||||||
|
if (byte & 0b1000_0000) == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
/// 安全的读取一个小端 i32 数据
|
||||||
///
|
///
|
||||||
/// 会在超出长度时 panic
|
/// 会在超出长度时 panic
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{NbtReader, NbtTypeConversion, NbtValue, nbt_version};
|
use crate::{nbt_version, NbtReader, NbtTypeConversion, NbtValue};
|
||||||
|
|
||||||
/// 生成测试数据
|
/// 生成测试数据
|
||||||
pub fn gen_datas(len: usize) -> Vec<u8> {
|
pub fn gen_datas(len: usize) -> Vec<u8> {
|
||||||
@ -303,7 +303,7 @@ mod nbt {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn big_test() {
|
fn big_test() {
|
||||||
let mut data: [u8; 0x608] = [
|
let data: [u8; 0x608] = [
|
||||||
0x0A, 0x00, 0x05, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x04, 0x00, 0x08, 0x6C, 0x6F, 0x6E,
|
0x0A, 0x00, 0x05, 0x4C, 0x65, 0x76, 0x65, 0x6C, 0x04, 0x00, 0x08, 0x6C, 0x6F, 0x6E,
|
||||||
0x67, 0x54, 0x65, 0x73, 0x74, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x02,
|
0x67, 0x54, 0x65, 0x73, 0x74, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x02,
|
||||||
0x00, 0x09, 0x73, 0x68, 0x6F, 0x72, 0x74, 0x54, 0x65, 0x73, 0x74, 0x7F, 0xFF, 0x08,
|
0x00, 0x09, 0x73, 0x68, 0x6F, 0x72, 0x74, 0x54, 0x65, 0x73, 0x74, 0x7F, 0xFF, 0x08,
|
||||||
@ -416,7 +416,8 @@ mod nbt {
|
|||||||
0x6F, 0x75, 0x62, 0x6C, 0x65, 0x54, 0x65, 0x73, 0x74, 0x3F, 0xDF, 0x8F, 0x6B, 0xBB,
|
0x6F, 0x75, 0x62, 0x6C, 0x65, 0x54, 0x65, 0x73, 0x74, 0x3F, 0xDF, 0x8F, 0x6B, 0xBB,
|
||||||
0xFF, 0x6A, 0x5E, 0x00,
|
0xFF, 0x6A, 0x5E, 0x00,
|
||||||
];
|
];
|
||||||
let value = NbtValue::from_binary::<nbt_version::Java>(&mut data);
|
let value = NbtValue::from_binary::<nbt_version::Java>(&mut data.clone());
|
||||||
println!("{:?}", value);
|
println!("{:?}", value);
|
||||||
|
// 其他版本
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user