1pub 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
46pub mod nbt_version {
58 use super::{NbtReader, NbtResult, NbtValue};
59
60 pub trait NbtWriteTrait {
61 fn write_i8_array(writer: &mut Vec<u8>, data: &[i8]);
63 fn write_i32_array(writer: &mut Vec<u8>, data: &[i32]);
65 fn write_i64_array(writer: &mut Vec<u8>, data: &[i64]);
67 fn write_nbt_string(writer: &mut Vec<u8>, data: &str);
69 fn write_list(writer: &mut Vec<u8>, data: &[NbtValue]) -> NbtResult<()>;
71 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 fn read_i8_array(reader: &mut NbtReader) -> NbtResult<Vec<i8>>;
93 fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>>;
95 fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>>;
97 fn read_nbt_string(reader: &mut NbtReader) -> NbtResult<String>;
99 fn read_list(reader: &mut NbtReader) -> NbtResult<Vec<NbtValue>>;
101 fn read_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>>;
103
104 fn from_reader(reader: NbtReader) -> NbtResult<NbtValue>;
105 }
106 pub enum Java {}
116 pub enum JavaNetAfter1_20_2 {}
122 pub enum BedrockDisk {}
128 pub enum BedrockNetVarInt {}
136}
137
138pub type NbtTypeId = u8;
139
140pub trait NbtTypeConversion {
142 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#[derive(Debug, Clone, PartialEq)]
173pub enum NbtError {
174 UnknownErr(String),
176 WrongRootType(NbtTypeId),
178 RootWithoutName,
180 UnknownType(NbtTypeId),
182 NameRead(String),
184 CursorOverflow(usize, usize, usize),
192 VarIntTooBig(usize),
194 VarlongTooBig(usize),
196 ListTypeNotSame(Vec<NbtTypeId>),
198 IncorrectType(NbtTypeId, NbtTypeId),
200}
201
202pub 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#[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 Byte(i8),
265 Short(i16),
267 Int(i32),
269 Long(i64),
271 Float(f32),
273 Double(f64),
275 ByteArray(Vec<i8>),
278 String(String),
282 List(Vec<NbtValue>),
285 Compound(Option<String>, Vec<(String, NbtValue)>),
287 IntArray(Vec<i32>),
290 LongArray(Vec<i64>),
293}
294
295impl NbtValue {
296 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}