shen_nbt5/
lib.rs

1//! shen-nbt5
2//!
3//! NBT 格式解析库 v5 by shenjack and InfyniteHeap
4//!
5//! 支持格式
6//!
7//! - Java 版 NBT
8//!
9//! - Java 1.20.2+(协议号 >= 764) 及以后 的网路传输 NBT 格式
10//!
11//! - 基岩版 实际用于存储的 NBT 格式
12//!
13//! - 基岩版 网络 NBT 格式
14//!
15//! 用例:
16//! ```rust
17//! use shen_nbt5::NbtValue;
18//! use shen_nbt5::nbt_version::Java;
19//!
20//! fn main() {
21//!    let mut data = vec![0x0A, 0x00, 0x0B, 0x68, 0x65,
22//!        0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64,
23//!        0x08, 0x00, 0x04, 0x6E, 0x61, 0x6D, 0x65, 0x00, 0x09,
24//!        0x42, 0x61, 0x6E, 0x61, 0x6E, 0x72, 0x61, 0x6D, 0x61, 0x00,
25//!    ];
26//!    let value = NbtValue::from_binary::<Java>(&mut data).unwrap();
27//!    println!("{:?}", value);
28//! }
29//! ```
30
31pub mod reader;
32pub mod writer;
33
34#[cfg(feature = "serde")]
35pub mod ser;
36#[cfg(feature = "serde")]
37use serde;
38#[cfg(feature = "serde")]
39use serde::{Deserialize, Serialize};
40
41use reader::NbtReader;
42
43#[cfg(test)]
44mod tests;
45
46/// 不同版本的 Nbt 数据细节不同
47/// 老要命了
48///
49/// - `Java`
50///   Java 版除了 1.20.2+(协议号) 及以后的网络 NBT 格式
51/// - `JavaNetAfter1_20_2`
52///   1.20.2+(协议号 >= 764) 及以后的网络 NBT 格式
53/// - `BedrockDisk`
54///   基岩版 实际用于存储的 NBT 格式
55/// - `BedrockNetVarInt`
56///   基岩版 网络 NBT 格式
57pub mod nbt_version {
58    use super::{NbtReader, NbtResult, NbtValue};
59
60    pub trait NbtWriteTrait {
61        /// 写入一个 i8(byte) 数组
62        fn write_i8_array(writer: &mut Vec<u8>, data: &[i8]);
63        /// 写入一个 i32(int) 数组
64        fn write_i32_array(writer: &mut Vec<u8>, data: &[i32]);
65        /// 写入一个 i64(long) 数组
66        fn write_i64_array(writer: &mut Vec<u8>, data: &[i64]);
67        /// 写入一个 NBT 字符串
68        fn write_nbt_string(writer: &mut Vec<u8>, data: &str);
69        /// 向 `writer` 写入一个列表类型(List)
70        fn write_list(writer: &mut Vec<u8>, data: &[NbtValue]) -> NbtResult<()>;
71        /// 向 `writer` 写入一个复合标签类型(Compound)
72        ///
73        /// 如果 `name` 为 `None` 则不写入名字
74        fn write_compound(
75            writer: &mut Vec<u8>,
76            name: Option<&String>,
77            data: &[(String, NbtValue)],
78        ) -> NbtResult<()>;
79
80        fn write_to(value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()>;
81        fn write_to_with_name(name: &str, value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()>;
82
83        fn to_bytes(value: &NbtValue) -> NbtResult<Vec<u8>> {
84            let mut buff = Vec::new();
85            Self::write_to(value, &mut buff)?;
86            Ok(buff)
87        }
88    }
89
90    pub trait NbtReadTrait {
91        /// 从 `reader` 读取一个 i8(byte) 数组
92        fn read_i8_array(reader: &mut NbtReader) -> NbtResult<Vec<i8>>;
93        /// 从 `reader` 读取一个 i32(int) 数组
94        fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>>;
95        /// 从 `reader` 读取一个 i64(long) 数组
96        fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>>;
97        /// 从 `reader` 读取一个 NBT 字符串
98        fn read_nbt_string(reader: &mut NbtReader) -> NbtResult<String>;
99        /// 从 `reader` 读取一个列表类型(List)
100        fn read_list(reader: &mut NbtReader) -> NbtResult<Vec<NbtValue>>;
101        /// 从 `reader` 读取一个复合标签类型(Compound)
102        fn read_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>>;
103
104        fn from_reader(reader: NbtReader) -> NbtResult<NbtValue>;
105    }
106    /// Java 版 绝大部分的 NBT 格式
107    ///
108    /// 除了 1.20.2+(协议号 >= 764) 及以后 的网路传输 NBT 格式 都是这个
109    ///
110    /// 上面说的那玩意 请使用 `JavaNetAfter1_20_2`
111    ///
112    /// # 编码特点
113    ///
114    /// 大端, 大端, 还是 xx 的 大端!
115    pub enum Java {}
116    /// 1.20.2+(协议号 >= 764) 及以后 的网路传输 NBT 格式
117    ///
118    /// # 编码特点
119    ///
120    /// 根节点没有名称
121    pub enum JavaNetAfter1_20_2 {}
122    /// 基岩版 实际用于存储的 NBT 格式
123    ///
124    /// # 编码特点
125    ///
126    /// 小端, 小端, 还是 xx 的 小端!
127    pub enum BedrockDisk {}
128    /// 基岩版 网络 NBT 格式
129    /// 最痛苦的一集
130    ///
131    /// # 编码特点
132    ///
133    /// VarInt, VarLong, ZigZagVarInt, ZigZagVarLong
134    /// 全都有
135    pub enum BedrockNetVarInt {}
136}
137
138pub type NbtTypeId = u8;
139
140/// 把 u8 转换成对应的 Nbt 类型名称
141pub trait NbtTypeConversion {
142    /// 把 u8 转换成对应的 Nbt 类型名称
143    fn as_nbt_type_name(&self) -> String;
144}
145
146impl NbtTypeConversion for NbtTypeId {
147    fn as_nbt_type_name(&self) -> String {
148        if *self > 12 {
149            return format!("未知类型({})", *self);
150        }
151        match *self {
152            0 => "NBT_End(0)",
153            1 => "NBT_Byte(1)",
154            2 => "NBT_Short(2)",
155            3 => "NBT_Int(3)",
156            4 => "NBT_Long(4)",
157            5 => "NBT_Float(5)",
158            6 => "NBT_Double(6)",
159            7 => "NBT_ByteArray(7)",
160            8 => "NBT_String(8)",
161            9 => "NBT_List(9)",
162            10 => "NBT_Compound(10)",
163            11 => "NBT_IntArray(11)",
164            12 => "NBT_LongArray(12)",
165            _ => unreachable!(),
166        }
167        .to_string()
168    }
169}
170
171/// Error
172#[derive(Debug, Clone, PartialEq)]
173pub enum NbtError {
174    /// 未知错误
175    UnknownErr(String),
176    /// 根节点类型错误
177    WrongRootType(NbtTypeId),
178    /// 根节点无名称
179    RootWithoutName,
180    /// 未知类型
181    UnknownType(NbtTypeId),
182    /// 名称读取错误
183    NameRead(String),
184    /// 指针超出范围
185    ///
186    /// cursor, len, data.len()
187    /// 三个参数分别表示
188    /// - 当前指针
189    /// - 数据长度
190    /// - 数据总长度
191    CursorOverflow(usize, usize, usize),
192    /// Varint 过大
193    VarIntTooBig(usize),
194    /// Varlong 过大
195    VarlongTooBig(usize),
196    /// NbtList 中类型不同
197    ListTypeNotSame(Vec<NbtTypeId>),
198    /// 错误类型
199    IncorrectType(NbtTypeId, NbtTypeId),
200}
201
202/// 返回类型
203pub type NbtResult<T> = std::result::Result<T, NbtError>;
204
205impl std::error::Error for NbtError {}
206
207impl std::fmt::Display for NbtError {
208    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209        match self {
210            NbtError::UnknownErr(s) => write!(f, "未知错误: {}", s),
211            NbtError::WrongRootType(n) => match n {
212                9 => {
213                    write!(
214                        f,
215                        "根节点为 NbtList(9) 类型, 是否应该使用 BedrockDisk/BedrockNetVarInt?"
216                    )
217                }
218                _ => {
219                    write!(f, "根节点类型错误: {}, 应为 NbtCompound/NbtList(bedrock only)", n)
220                }
221            },
222            NbtError::RootWithoutName => {
223                write!(f, "根节点无名称, 是否应该使用 JavaNetAfter1_20_2 解析?")
224            }
225            NbtError::UnknownType(n) => {
226                if *n == 0 {
227                    write!(f, "未知类型: NBTEnd(0), 请检查数据是否正确")
228                } else {
229                    write!(f, "未知类型: {}", n)
230                }
231            }
232            NbtError::NameRead(s) => write!(f, "名称读取错误: {}", s),
233            NbtError::CursorOverflow(cursor, len, data_len) => write!(
234                f,
235                "指针超出范围: cursor: {}, len: {}, cursor+len: {}, data.len(): {}",
236                cursor,
237                len,
238                cursor + len,
239                data_len
240            ),
241            NbtError::VarIntTooBig(n) => write!(f, "VarInt 过大: {} 最大长度为 5", n),
242            NbtError::VarlongTooBig(n) => write!(f, "VarLong 过大: {} 最大长度为 10", n),
243            NbtError::ListTypeNotSame(types) => {
244                write!(f, "NbtList 中类型不同: {:?} 应相同", types)
245            }
246            NbtError::IncorrectType(expect, got) => {
247                write!(f, "错误类型: 期望: {}, 实际: {}", expect, got)
248            }
249        }
250    }
251}
252
253/// 核心 Value
254///
255/// 暂时不支持 `from_value` 和 `to_value`
256/// https://github.com/shenjackyuanjie/nbt-rust/issues/1
257#[derive(Debug, Clone, PartialEq)]
258#[cfg_attr(feature = "serde", derive(Serialize))]
259#[cfg_attr(feature = "serde", derive(Deserialize))]
260#[cfg_attr(feature = "serde", serde(untagged))]
261pub enum NbtValue {
262    // end: 0
263    /// 1: Byte
264    Byte(i8),
265    /// 2
266    Short(i16),
267    /// 3
268    Int(i32),
269    /// 4
270    Long(i64),
271    /// 5
272    Float(f32),
273    /// 6
274    Double(f64),
275    /// 7
276    /// 长度: i32
277    ByteArray(Vec<i8>),
278    /// 8
279    /// 或者叫 u8 array
280    /// 长度: u16
281    String(String),
282    /// 9
283    /// 长度: i32
284    List(Vec<NbtValue>),
285    /// 10
286    Compound(Option<String>, Vec<(String, NbtValue)>),
287    /// 11
288    /// 长度: i32
289    IntArray(Vec<i32>),
290    /// 12
291    /// 长度: i32
292    LongArray(Vec<i64>),
293}
294
295impl NbtValue {
296    /// 解析 Nbt 数据
297    pub fn from_binary<R>(data: &mut [u8]) -> NbtResult<NbtValue>
298    where
299        R: nbt_version::NbtReadTrait,
300    {
301        let reader = NbtReader::new(data);
302        R::from_reader(reader)
303    }
304
305    pub fn tag(&self) -> NbtTypeId {
306        match self {
307            NbtValue::Byte(_) => 1,
308            NbtValue::Short(_) => 2,
309            NbtValue::Int(_) => 3,
310            NbtValue::Long(_) => 4,
311            NbtValue::Float(_) => 5,
312            NbtValue::Double(_) => 6,
313            NbtValue::ByteArray(_) => 7,
314            NbtValue::String(_) => 8,
315            NbtValue::List(_) => 9,
316            NbtValue::Compound(_, _) => 10,
317            NbtValue::IntArray(_) => 11,
318            NbtValue::LongArray(_) => 12,
319        }
320    }
321
322    pub fn write_to<W>(&self, buff: &mut Vec<u8>) -> NbtResult<()>
323    where
324        W: nbt_version::NbtWriteTrait,
325    {
326        W::write_to(self, buff)
327    }
328
329    pub fn write_to_with_name<W>(&self, name: &str, buff: &mut Vec<u8>) -> NbtResult<()>
330    where
331        W: nbt_version::NbtWriteTrait,
332    {
333        W::write_to_with_name(name, self, buff)
334    }
335
336    pub fn to_binary<W>(&self) -> NbtResult<Vec<u8>>
337    where
338        W: nbt_version::NbtWriteTrait,
339    {
340        W::to_bytes(self)
341    }
342
343    #[inline]
344    pub fn as_i18(&self) -> NbtResult<i8> {
345        match self {
346            NbtValue::Byte(v) => Ok(*v),
347            _ => Err(NbtError::IncorrectType(1_u8, self.tag())),
348        }
349    }
350    #[inline]
351    pub fn as_i16(&self) -> NbtResult<i16> {
352        match self {
353            NbtValue::Short(v) => Ok(*v),
354            _ => Err(NbtError::IncorrectType(2_u8, self.tag())),
355        }
356    }
357    #[inline]
358    pub fn as_i32(&self) -> NbtResult<i32> {
359        match self {
360            NbtValue::Int(v) => Ok(*v),
361            _ => Err(NbtError::IncorrectType(3_u8, self.tag())),
362        }
363    }
364    #[inline]
365    pub fn as_i64(&self) -> NbtResult<i64> {
366        match self {
367            NbtValue::Long(v) => Ok(*v),
368            _ => Err(NbtError::IncorrectType(4_u8, self.tag())),
369        }
370    }
371    #[inline]
372    pub fn as_f32(&self) -> NbtResult<f32> {
373        match self {
374            NbtValue::Float(v) => Ok(*v),
375            _ => Err(NbtError::IncorrectType(5_u8, self.tag())),
376        }
377    }
378    #[inline]
379    pub fn as_f64(&self) -> NbtResult<f64> {
380        match self {
381            NbtValue::Double(v) => Ok(*v),
382            _ => Err(NbtError::IncorrectType(6_u8, self.tag())),
383        }
384    }
385    #[inline]
386    pub fn as_i8_array(&self) -> NbtResult<Vec<i8>> {
387        match self {
388            NbtValue::ByteArray(v) => Ok(v.clone()),
389            _ => Err(NbtError::IncorrectType(7_u8, self.tag())),
390        }
391    }
392    #[inline]
393    pub fn as_i32_array(&self) -> NbtResult<Vec<i32>> {
394        match self {
395            NbtValue::IntArray(v) => Ok(v.clone()),
396            _ => Err(NbtError::IncorrectType(11_u8, self.tag())),
397        }
398    }
399    #[inline]
400    pub fn as_i64_array(&self) -> NbtResult<Vec<i64>> {
401        match self {
402            NbtValue::LongArray(v) => Ok(v.clone()),
403            _ => Err(NbtError::IncorrectType(12_u8, self.tag())),
404        }
405    }
406    #[inline]
407    pub fn as_string(&self) -> NbtResult<String> {
408        match self {
409            NbtValue::String(v) => Ok(v.clone()),
410            _ => Err(NbtError::IncorrectType(8_u8, self.tag())),
411        }
412    }
413    #[inline]
414    pub fn as_list(&self) -> NbtResult<Vec<NbtValue>> {
415        match self {
416            NbtValue::List(v) => Ok(v.clone()),
417            _ => Err(NbtError::IncorrectType(9_u8, self.tag())),
418        }
419    }
420    #[inline]
421    pub fn as_compound(&self) -> NbtResult<(Option<&String>, Vec<(String, NbtValue)>)> {
422        match self {
423            NbtValue::Compound(name, v) => Ok((name.as_ref(), v.clone())),
424            _ => Err(NbtError::IncorrectType(10_u8, self.tag())),
425        }
426    }
427
428    #[inline]
429    pub fn is_i8(&self) -> bool { matches!(self, NbtValue::Byte(_)) }
430    #[inline]
431    pub fn is_i16(&self) -> bool { matches!(self, NbtValue::Short(_)) }
432    #[inline]
433    pub fn is_i32(&self) -> bool { matches!(self, NbtValue::Int(_)) }
434    #[inline]
435    pub fn is_i64(&self) -> bool { matches!(self, NbtValue::Long(_)) }
436    #[inline]
437    pub fn is_f32(&self) -> bool { matches!(self, NbtValue::Float(_)) }
438    #[inline]
439    pub fn is_f64(&self) -> bool { matches!(self, NbtValue::Double(_)) }
440    #[inline]
441    pub fn is_i8_array(&self) -> bool { matches!(self, NbtValue::ByteArray(_)) }
442    #[inline]
443    pub fn is_i32_array(&self) -> bool { matches!(self, NbtValue::IntArray(_)) }
444    #[inline]
445    pub fn is_i64_array(&self) -> bool { matches!(self, NbtValue::LongArray(_)) }
446    #[inline]
447    pub fn is_string(&self) -> bool { matches!(self, NbtValue::String(_)) }
448    #[inline]
449    pub fn is_list(&self) -> bool { matches!(self, NbtValue::List(_)) }
450    #[inline]
451    pub fn is_compound(&self) -> bool { matches!(self, NbtValue::Compound(_, _)) }
452}