nbt/
tags.rs

1use std::collections::HashMap;
2use std::fmt;
3
4#[repr(u8)]
5#[derive(Debug, Clone, PartialOrd, PartialEq)]
6#[allow(non_camel_case_types)]
7/// The numerical representation of Tag types.
8///
9/// Used within the internal encode/decode process and hence is returned within errors.
10pub enum TagIdent {
11    /// ## TAG_End (0)
12    /// Signifies the end of a TAG_Compound. It is only ever used inside a TAG_Compound, and is not named despite being in a TAG_Compound
13    TAG_End = 0,
14
15    /// ## TAG_Byte (1)
16    /// A single signed byte
17    TAG_Byte = 1,
18
19    /// ## TAG_Short (2)
20    /// A single signed, big endian 16 bit integer
21    TAG_Short = 2,
22
23    /// ## TAG_Int (3)
24    /// A single signed, big endian 32 bit integer
25    TAG_Int = 3,
26
27    /// ## TAG_Long (4)
28    /// A single signed, big endian 64 bit integer
29    TAG_Long = 4,
30
31    /// ## TAG_Float (5)
32    /// A single, big endian IEEE-754 single-precision floating point number (NaN possible)
33    TAG_Float = 5,
34
35    /// ## TAG_Double (6)
36    /// A single, big endian IEEE-754 double-precision floating point number (NaN possible)
37    TAG_Double = 6,
38
39    /// ## TAG_Byte_Array (7)
40    /// A length-prefixed array of signed bytes. The prefix is a signed integer (thus 4 bytes)
41    TAG_Byte_Array = 7,
42
43    /// ## TAG_String (8)
44    /// A length-prefixed modified UTF-8 string. The prefix is an unsigned short (thus 2 bytes) signifying the length of the string in bytes
45    TAG_String = 8,
46
47    /// ## TAG_List (9)
48    /// A list of nameless tags, all of the same type. The list is prefixed with the Type ID of the items it contains (thus 1 byte), and the length of the list as a signed integer (a further 4 bytes). If the length of the list is 0 or negative, the type may be 0 (TAG_End) but otherwise it must be any other type. (The notchian implementation uses TAG_End in that situation, but another reference implementation by Mojang uses 1 instead; parsers should accept any type if the length is <= 0).
49    TAG_List = 9,
50
51    /// ## TAG_Compound (10)
52    /// Effectively a list of a named tags. Order is not guaranteed.
53    TAG_Compound = 10,
54
55    /// ## TAG_Int_Array (11)
56    /// A length-prefixed array of signed integers. The prefix is a signed integer (thus 4 bytes) and indicates the number of 4 byte integers.
57    TAG_Int_Array = 11,
58
59    /// ## TAG_Long_Array (12)
60    /// A length-prefixed array of signed longs. The prefix is a signed integer (thus 4 bytes) and indicates the number of 8 byte longs.
61    TAG_Long_Array = 12,
62}
63
64impl TagIdent {
65    /// Parse a `u8` into a `TagIdent`
66    pub fn parse(value: &u8) -> Option<TagIdent> {
67        match value {
68            0 => Some(TagIdent::TAG_End),
69            1 => Some(TagIdent::TAG_Byte),
70            2 => Some(TagIdent::TAG_Short),
71            3 => Some(TagIdent::TAG_Int),
72            4 => Some(TagIdent::TAG_Long),
73            5 => Some(TagIdent::TAG_Float),
74            6 => Some(TagIdent::TAG_Double),
75            7 => Some(TagIdent::TAG_Byte_Array),
76            8 => Some(TagIdent::TAG_String),
77            9 => Some(TagIdent::TAG_List),
78            10 => Some(TagIdent::TAG_Compound),
79            11 => Some(TagIdent::TAG_Int_Array),
80            12 => Some(TagIdent::TAG_Long_Array),
81            _ => None
82        }
83    }
84}
85
86impl fmt::Display for TagIdent {
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        match &self {
89            TagIdent::TAG_End => f.write_str("TAG_End"),
90            TagIdent::TAG_Byte => f.write_str("TAG_Byte"),
91            TagIdent::TAG_Short => f.write_str("TAG_Short"),
92            TagIdent::TAG_Int => f.write_str("TAG_Int"),
93            TagIdent::TAG_Long  => f.write_str("TAG_Long"),
94            TagIdent::TAG_Float => f.write_str("TAG_Float"),
95            TagIdent::TAG_Double => f.write_str("TAG_Double"),
96            TagIdent::TAG_Byte_Array => f.write_str("TAG_ByteArray"),
97            TagIdent::TAG_String => f.write_str("TAG_String"),
98            TagIdent::TAG_List => f.write_str("TAG_List"),
99            TagIdent::TAG_Compound => f.write_str("TAG_Compound"),
100            TagIdent::TAG_Int_Array => f.write_str("TAG_IntArray"),
101            TagIdent::TAG_Long_Array => f.write_str("TAG_LongArray"),
102        }
103    }
104}
105
106
107#[derive(Debug, PartialEq)]
108/// A NBT Tag, representing the 13 datatypes supported by the format.
109pub enum Tag {
110    Byte(i8),
111    Short(i16),
112    Int(i32),
113    Long(i64),
114    Float(f32),
115    Double(f64),
116    ByteArray(Vec<i8>),
117    String(String),
118    List(Vec<Tag>),
119    Compound(HashMap<String, Tag>),
120    IntArray(Vec<i32>),
121    LongArray(Vec<i64>)
122}
123
124impl Tag {
125    #[deprecated]
126    pub fn id(&self) -> u8 {
127        match &self {
128            Tag::Byte(_) => 1,
129            Tag::Short(_) => 2,
130            Tag::Int(_) => 3,
131            Tag::Long(_) => 4,
132            Tag::Float(_) => 5,
133            Tag::Double(_) => 6,
134            Tag::ByteArray(_) => 7,
135            Tag::String(_) => 8,
136            Tag::List(_) => 9,
137            Tag::Compound(_) => 10,
138            Tag::IntArray(_) => 11,
139            Tag::LongArray(_) => 12
140        }
141    }
142
143    /// The `TagIdent` representation of a tag.
144    /// Used to identify the prefix of a type.
145    pub fn ident(&self) -> TagIdent {
146        match &self {
147            Tag::Byte(_) => TagIdent::TAG_Byte,
148            Tag::Short(_) => TagIdent::TAG_Short,
149            Tag::Int(_) => TagIdent::TAG_Int,
150            Tag::Long(_) => TagIdent::TAG_Long,
151            Tag::Float(_) => TagIdent::TAG_Float,
152            Tag::Double(_) => TagIdent::TAG_Double,
153            Tag::ByteArray(_) => TagIdent::TAG_Byte_Array,
154            Tag::String(_) => TagIdent::TAG_String,
155            Tag::List(_) => TagIdent::TAG_List,
156            Tag::Compound(_) => TagIdent::TAG_Compound,
157            Tag::IntArray(_) => TagIdent::TAG_Int_Array,
158            Tag::LongArray(_) => TagIdent::TAG_Long_Array,
159        }
160    }
161}