bookshelf/nbt/
tag.rs

1use serde::{
2    de::{Error, VariantAccess, Visitor, EnumAccess, IgnoredAny},
3    Deserialize, Deserializer, Serialize, Serializer
4};
5use std::{
6    collections::HashMap,
7    fmt::{self, Display, Formatter},
8    marker::PhantomData
9};
10
11use super::TagType;
12
13/// Represents a NBT Compound,
14/// implements [`serde::Serialize`] and [`serde::Deserialize`]
15pub type Compound = HashMap<String, Tag>;
16
17/// Represents any NBT Tag,
18/// implements [`serde::Serialize`] and [`serde::Deserialize`]
19#[derive(Clone, PartialEq, Debug)]
20pub enum Tag {
21    ///A 8-bit signed integer
22    Byte(i8),
23    ///A 16-bit signed integer
24    Short(i16),
25    ///A 32-bit signed integer
26    Int(i32),
27    ///A 64-bit signed integer
28    Long(i64),
29    ///A 32-bit floating point encoded as "binary32" as defined in IEEE 754-2008
30    Float(f32),
31    ///A 64-bit floating point encoded as "binary64" as defined in IEEE 754-2008
32    Double(f64),
33    ///An array of 8-bit signed integers
34    ByteArray(Vec<i8>),
35    ///A String
36    String(String),
37    ///A list of nameless tags of the same type
38    List(List),
39    ///A list of named tags of different types
40    Compound(Compound),
41    ///An array of 32-bit signed integers
42    IntArray(Vec<i32>),
43    ///An array of 64-bit signed integers
44    LongArray(Vec<i64>),
45}
46
47impl Serialize for Tag {
48    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
49        match self {
50            Tag::Byte(v) => v.serialize(serializer),
51            Tag::Short(v) => v.serialize(serializer),
52            Tag::Int(v) => v.serialize(serializer),
53            Tag::Long(v) => v.serialize(serializer),
54            Tag::Float(v) => v.serialize(serializer),
55            Tag::Double(v) => v.serialize(serializer),
56            Tag::ByteArray(v) => byte_array::serialize(v, serializer),
57            Tag::String(v) => v.serialize(serializer),
58            Tag::List(v) => v.serialize(serializer),
59            Tag::Compound(v) => v.serialize(serializer),
60            Tag::IntArray(v) => int_array::serialize(v, serializer),
61            Tag::LongArray(v) => long_array::serialize(v, serializer),
62        }
63    }
64}
65
66impl<'de> Deserialize<'de> for Tag {
67    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
68        deserializer.deserialize_any(TagVisitor)
69    }
70}
71
72struct TagVisitor;
73
74impl<'de> Visitor<'de> for TagVisitor {
75    type Value = Tag;
76
77    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
78        write!(formatter, "a NBT value")
79    }
80
81    fn visit_i8<E: Error>(self, v: i8) -> Result<Self::Value, E> {
82        Ok(Tag::Byte(v))
83    }
84
85    fn visit_i16<E: Error>(self, v: i16) -> Result<Self::Value, E> {
86        Ok(Tag::Short(v))
87    }
88
89    fn visit_i32<E: Error>(self, v: i32) -> Result<Self::Value, E> {
90        Ok(Tag::Int(v))
91    }
92
93    fn visit_i64<E: Error>(self, v: i64) -> Result<Self::Value, E> {
94        Ok(Tag::Long(v))
95    }
96
97    fn visit_f32<E: Error>(self, v: f32) -> Result<Self::Value, E> {
98        Ok(Tag::Float(v))
99    }
100
101    fn visit_f64<E: Error>(self, v: f64) -> Result<Self::Value, E> {
102        Ok(Tag::Double(v))
103    }
104
105    fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
106        Ok(Tag::String(v.to_owned()))
107    }
108
109    fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
110        Ok(Tag::String(v))
111    }
112
113    fn visit_map<A: serde::de::MapAccess<'de>>(self, map: A) -> Result<Self::Value, A::Error> {
114        visit_map(map).map(Tag::Compound)
115    }
116
117    fn visit_enum<A: serde::de::EnumAccess<'de>>(self, data: A) -> Result<Self::Value, A::Error> {
118        let (array_type, variant) = data.variant()?;
119        match array_type {
120            ArrayType::Byte => Ok(Tag::ByteArray(variant.newtype_variant()?)),
121            ArrayType::Int => Ok(Tag::IntArray(variant.newtype_variant()?)),
122            ArrayType::Long => Ok(Tag::LongArray(variant.newtype_variant()?)),
123        }
124    }
125
126    fn visit_seq<A: serde::de::SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
127        ListVisitor.visit_seq(seq).map(Tag::List)
128    }
129}
130
131fn visit_map<'de, A: serde::de::MapAccess<'de>>(mut map: A) -> Result<Compound, A::Error> {
132    let mut compound = Compound::new();
133
134    while let Some((k, v)) = map.next_entry()? {
135        compound.insert(k, v);
136    }
137
138    Ok(compound)
139}
140
141/// Represents any NBT List,
142/// implements [`serde::Serialize`] and [`serde::Deserialize`]
143#[derive(Clone, PartialEq, Debug)]
144pub enum List {
145    ///A generic length zero list, isn't bounded by any type
146    Empty,
147    ///A list of nameless byte tags
148    Byte(Vec<i8>),
149    ///A list of nameless short tags
150    Short(Vec<i16>),
151    ///A list of nameless int tags
152    Int(Vec<i32>),
153    ///A list of nameless long tags
154    Long(Vec<i64>),
155    ///A list of nameless float tags
156    Float(Vec<f32>),
157    ///A list of nameless double tags
158    Double(Vec<f64>),
159    ///A list of nameless byte array tags
160    ByteArray(Vec<Vec<i8>>),
161    ///A list of nameless string tags
162    String(Vec<String>),
163    ///A list of nameless list tags, each list can hold a different type of tag
164    List(Vec<List>),
165    ///A list of nameless compound tags
166    Compound(Vec<Compound>),
167    ///A list of nameless int array tags
168    IntArray(Vec<Vec<i32>>),
169    ///A list of nameless long array tags
170    LongArray(Vec<Vec<i64>>),
171}
172
173impl Serialize for List {
174    fn serialize<S: ::serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
175        match self {
176            List::Empty => [(); 0].serialize(serializer),
177            List::Byte(l) => l.serialize(serializer),
178            List::Short(l) => l.serialize(serializer),
179            List::Int(l) => l.serialize(serializer),
180            List::Long(l) => l.serialize(serializer),
181            List::Float(l) => l.serialize(serializer),
182            List::Double(l) => l.serialize(serializer),
183            List::ByteArray(l) => l.serialize(serializer),
184            List::String(l) => l.serialize(serializer),
185            List::List(l) => l.serialize(serializer),
186            List::Compound(l) => l.serialize(serializer),
187            List::IntArray(l) => l.serialize(serializer),
188            List::LongArray(l) => l.serialize(serializer),
189        }
190    }
191}
192
193struct ListVisitor;
194
195impl<'de> Visitor<'de> for ListVisitor {
196    type Value = List;
197
198    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
199        write!(formatter, "an NBT list")
200    }
201
202    fn visit_seq<A: serde::de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
203        let mut list = List::Empty;
204
205        while seq.next_element_seed(ListElement(&mut list))?.is_some() {}
206
207        Ok(list)
208    }
209}
210
211struct ListElement<'a>(&'a mut List);
212
213impl<'de, 'a> serde::de::DeserializeSeed<'de> for ListElement<'a> {
214    type Value = ();
215
216    fn deserialize<D: serde::Deserializer<'de>>(
217        self,
218        deserializer: D,
219    ) -> Result<Self::Value, D::Error> {
220        deserializer.deserialize_any(self)
221    }
222}
223
224macro_rules! visit {
225    ($self:expr, $variant:ident, $value:expr, $error:ty) => {
226        match $self.0 {
227            List::Empty => {
228                *$self.0 = List::$variant(vec![$value]);
229                Ok(())
230            }
231            List::$variant(l) => {
232                l.push($value);
233                Ok(())
234            }
235            _ => Err(<$error>::custom("NBT lists must be homogenous")),
236        }
237    };
238}
239
240impl<'de, 'a> Visitor<'de> for ListElement<'a> {
241    type Value = ();
242
243    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
244        write!(formatter, "a valid NBT list element")
245    }
246
247    fn visit_i8<E: Error>(self, v: i8) -> Result<Self::Value, E> {
248        visit!(self, Byte, v, E)
249    }
250
251    fn visit_i16<E: Error>(self, v: i16) -> Result<Self::Value, E> {
252        visit!(self, Short, v, E)
253    }
254
255    fn visit_i32<E: Error>(self, v: i32) -> Result<Self::Value, E> {
256        visit!(self, Int, v, E)
257    }
258
259    fn visit_i64<E: Error>(self, v: i64) -> Result<Self::Value, E> {
260        visit!(self, Long, v, E)
261    }
262
263    fn visit_f32<E: Error>(self, v: f32) -> Result<Self::Value, E> {
264        visit!(self, Float, v, E)
265    }
266
267    fn visit_f64<E: Error>(self, v: f64) -> Result<Self::Value, E> {
268        visit!(self, Double, v, E)
269    }
270
271    fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
272        visit!(self, String, v.to_owned(), E)
273    }
274
275    fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
276        visit!(self, String, v, E)
277    }
278
279    fn visit_seq<A: serde::de::SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
280        visit!(self, List, ListVisitor.visit_seq(seq)?, A::Error)
281    }
282
283    fn visit_map<A: serde::de::MapAccess<'de>>(self, map: A) -> Result<Self::Value, A::Error> {
284        visit!(self, Compound, visit_map(map)?, A::Error)
285    }
286
287    fn visit_enum<A: serde::de::EnumAccess<'de>>(self, data: A) -> Result<Self::Value, A::Error> {
288        let (array_type, variant) = data.variant()?;
289        match array_type {
290            ArrayType::Byte => visit!(self, ByteArray, variant.newtype_variant()?, A::Error),
291            ArrayType::Int => visit!(self, IntArray, variant.newtype_variant()?, A::Error),
292            ArrayType::Long => visit!(self, LongArray, variant.newtype_variant()?, A::Error),
293        }
294    }
295}
296
297// internal names used to deserialize and serialize
298// arrays using enum handlers
299pub(crate) const BYTE_ARRAY_NAME: &str = "__byte_array__";
300pub(crate) const INT_ARRAY_NAME: &str = "__int_array__";
301pub(crate) const LONG_ARRAY_NAME: &str = "__long_array__";
302
303pub(crate) const ARRAY_ENUM_NAME: &str = "__array__";
304pub(crate) const ARRAY_VARIANTS: &[&str] = &[BYTE_ARRAY_NAME, INT_ARRAY_NAME, LONG_ARRAY_NAME];
305
306macro_rules! array {
307    ($mod:ident, $tag:literal, $index:literal, $variant:tt) => {
308        pub mod $mod {
309            use super::*;
310
311            pub fn serialize<T, S>(array: &T, serializer: S) -> core::result::Result<S::Ok, S::Error>
312            where
313                T: Serialize,
314                S: Serializer,
315            {
316                serializer.serialize_newtype_variant(ARRAY_ENUM_NAME, $index, $variant, array)
317            }
318
319            pub fn deserialize<'de, T, D>(deserializer: D) -> core::result::Result<T, D::Error>
320            where
321                T: Deserialize<'de>,
322                D: Deserializer<'de>,
323            {
324                struct ArrayVisitor<T>(PhantomData<T>);
325
326                impl<'de, T: Deserialize<'de>> Visitor<'de> for ArrayVisitor<T> {
327                    type Value = T;
328
329                    fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
330                        write!(formatter, $tag)
331                    }
332
333                    fn visit_enum<A>(self, data: A) -> core::result::Result<Self::Value, A::Error>
334                    where
335                        A: EnumAccess<'de>,
336                    {
337                        // Ignore the variant name.
338                        let (_, variant) = data.variant::<IgnoredAny>()?;
339
340                        variant.newtype_variant()
341                    }
342                }
343
344                deserializer.deserialize_enum(
345                    ARRAY_ENUM_NAME,
346                    ARRAY_VARIANTS,
347                    ArrayVisitor(PhantomData),
348                )
349            }
350        }
351    };
352}
353
354array!(byte_array, "Tag_BYTE_ARRAY", 0, BYTE_ARRAY_NAME);
355array!(int_array, "Tag_INT_ARRAY", 1, INT_ARRAY_NAME);
356array!(long_array, "Tag_LONG_ARRAY", 2, LONG_ARRAY_NAME);
357
358enum ArrayType {
359    Byte,
360    Int,
361    Long,
362}
363
364impl<'de> Deserialize<'de> for ArrayType {
365    fn deserialize<D: ::serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
366        struct ArrayVisitor;
367
368        impl<'de> Visitor<'de> for ArrayVisitor {
369            type Value = ArrayType;
370
371            fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
372                write!(formatter, "a u8 or string encoding an NBT array type")
373            }
374
375            fn visit_u8<E: Error>(self, v: u8) -> Result<Self::Value, E> {
376                match v {
377                    0 => Ok(ArrayType::Byte),
378                    1 => Ok(ArrayType::Int),
379                    2 => Ok(ArrayType::Long),
380                    i => Err(E::custom(format!("invalid array type index `{i}`"))),
381                }
382            }
383
384            fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
385                match v {
386                    BYTE_ARRAY_NAME => Ok(ArrayType::Byte),
387                    INT_ARRAY_NAME => Ok(ArrayType::Int),
388                    LONG_ARRAY_NAME => Ok(ArrayType::Long),
389                    s => Err(E::custom(format!("invalid array type `{s}`"))),
390                }
391            }
392        }
393
394        deserializer.deserialize_u8(ArrayVisitor)
395    }
396}
397
398
399#[derive(Debug)]
400pub enum TagConversionError<'a> {
401    Tag(TagType, &'a str),
402    List(TagType, &'a str)
403}
404
405impl<'a> std::error::Error for TagConversionError<'a> {
406    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
407        None
408    }
409}
410
411impl<'a> Display for TagConversionError<'a> {
412    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
413        match self {
414            TagConversionError::Tag(x, y) => write!(f, "couldn't convert {x:?} to {y}"),
415            TagConversionError::List(x, y) => write!(f, "couldn't convert {x:?} to Vec<{y}>")
416        }
417    }
418}
419
420pub trait CompoundTryGetInto<T> where Self: Sized {
421    type Error;
422    fn try_get_into(self, key: &str) -> Result<Option<T>, Self::Error>;
423}
424
425macro_rules! tag_conversion {
426    ($tag:ident, &$ty:ty, $str:expr) => {
427        impl<'a> TryInto<&'a $ty> for &'a Tag {
428            type Error = TagConversionError<'a>;
429            fn try_into(self) -> Result<&'a $ty, TagConversionError<'a>> {
430                match self {
431                    Tag::$tag(x) => Ok(x),
432                    _ => Err(TagConversionError::Tag(self.tag_type(), $str))
433                }
434            }
435        }
436
437        impl<'a> TryInto<&'a mut $ty> for &'a mut Tag {
438            type Error = TagConversionError<'a>;
439            fn try_into(self) -> Result<&'a mut $ty, TagConversionError<'a>> {
440                match self {
441                    Tag::$tag(x) => Ok(x),
442                    _ => Err(TagConversionError::Tag(self.tag_type(), $str))
443                }
444            }
445        }
446
447        impl<'a> CompoundTryGetInto<&'a $ty> for &'a Compound {
448            type Error = TagConversionError<'a>;
449            fn try_get_into(self, key: &str) -> Result<Option<&'a $ty>, TagConversionError<'a>> {
450                match self.get(key) {
451                    Some(x) => match x {
452                        Tag::$tag(y) => Ok(Some(y)),
453                        _ => Err(TagConversionError::Tag(x.tag_type(), $str))
454                    },
455                    None => Ok(None)
456                }
457            }
458        }
459
460        impl<'a> CompoundTryGetInto<&'a mut $ty> for &'a mut Compound {
461            type Error = TagConversionError<'a>;
462            fn try_get_into(self, key: &str) -> Result<Option<&'a mut $ty>, TagConversionError<'a>> {
463                match self.get_mut(key) {
464                    Some(x) => match x {
465                        Tag::$tag(y) => Ok(Some(y)),
466                        _ => Err(TagConversionError::Tag(x.tag_type(), $str))
467                    },
468                    None => Ok(None)
469                }
470            }
471        }
472        
473        impl<'a> TryInto<&'a [$ty]> for &'a Tag {
474            type Error = TagConversionError<'a>;
475            fn try_into(self) -> Result<&'a [$ty], TagConversionError<'a>> {
476                match self {
477                    Tag::List(List::$tag(x)) => Ok(x),
478                    _ => Err(TagConversionError::Tag(self.tag_type(), "{&[$str]}"))
479                }
480            }
481        }
482
483        impl<'a> TryInto<&'a mut [$ty]> for &'a mut Tag {
484            type Error = TagConversionError<'a>;
485            fn try_into(self) -> Result<&'a mut [$ty], TagConversionError<'a>> {
486                match self {
487                    Tag::List(List::$tag(x)) => Ok(x),
488                    _ => Err(TagConversionError::Tag(self.tag_type(), "{&[$str]}"))
489                }
490            }
491        }
492
493        impl<'a> CompoundTryGetInto<&'a [$ty]> for &'a Compound {
494            type Error = TagConversionError<'a>;
495            fn try_get_into(self, key: &str) -> Result<Option<&'a [$ty]>, TagConversionError<'a>> {
496                match self.get(key) {
497                    Some(x) => match x {
498                        Tag::List(List::$tag(y)) => Ok(Some(y)),
499                        _ => Err(TagConversionError::Tag(x.tag_type(), $str))
500                    },
501                    None => Ok(None)
502                }
503            }
504        }
505
506        impl<'a> CompoundTryGetInto<&'a mut [$ty]> for &'a mut Compound {
507            type Error = TagConversionError<'a>;
508            fn try_get_into(self, key: &str) -> Result<Option<&'a mut [$ty]>, TagConversionError<'a>> {
509                match self.get_mut(key) {
510                    Some(x) => match x {
511                        Tag::List(List::$tag(y)) => Ok(Some(y)),
512                        _ => Err(TagConversionError::Tag(x.tag_type(), $str))
513                    },
514                    None => Ok(None)
515                }
516            }
517        }
518
519        impl<'a> TryInto<&'a [$ty]> for &'a List {
520            type Error = TagConversionError<'a>;
521            fn try_into(self) -> Result<&'a [$ty], TagConversionError<'a>> {
522                match self {
523                    List::$tag(x) => Ok(x),
524                    _ => Err(TagConversionError::List(self.tag_type(), $str))
525                }
526            }
527        }
528
529        impl<'a> TryInto<&'a mut [$ty]> for &'a mut List {
530            type Error = TagConversionError<'a>;
531            fn try_into(self) -> Result<&'a mut [$ty], TagConversionError<'a>> {
532                match self {
533                    List::$tag(x) => Ok(x),
534                    _ => Err(TagConversionError::List(self.tag_type(), $str))
535                }
536            }
537        }
538    };
539    ($tag:ident, $ty:ty, $str:expr) => {
540        impl<'a> TryInto<$ty> for &'a Tag {
541            type Error = TagConversionError<'a>;
542            fn try_into(self) -> Result<$ty, TagConversionError<'a>> {
543                match self {
544                    Tag::$tag(x) => Ok(*x),
545                    _ => Err(TagConversionError::Tag(self.tag_type(), $str))
546                }
547            }
548        }
549
550        impl<'a> CompoundTryGetInto<$ty> for &'a Compound {
551            type Error = TagConversionError<'a>;
552            fn try_get_into(self, key: &str) -> Result<Option<$ty>, TagConversionError<'a>> {
553                match self.get(key) {
554                    Some(x) => match x {
555                        Tag::$tag(y) => Ok(Some(*y)),
556                        _ => Err(TagConversionError::Tag(x.tag_type(), $str))
557                    },
558                    None => Ok(None)
559                }
560            }
561        }
562        tag_conversion!($tag, &$ty, $str);
563    }
564}
565
566tag_conversion!(Byte, i8, "i8");
567tag_conversion!(Short, i16, "i16");
568tag_conversion!(Int, i32, "i32");
569tag_conversion!(Long, i64, "i64");
570tag_conversion!(Float, f32, "f32");
571tag_conversion!(Double, f64, "f64");
572tag_conversion!(List, &List, "List");
573tag_conversion!(Compound, &Compound, "Compound");
574
575impl<'a> TryInto<&'a str> for &'a Tag {
576    type Error = TagConversionError<'a>;
577    fn try_into(self) -> Result<&'a str, TagConversionError<'a>> {
578        match self {
579            Tag::String(x) => Ok(x),
580            _ => Err(TagConversionError::Tag(self.tag_type(), "str"))
581        }
582    }
583}
584
585impl<'a> TryInto<&'a mut String> for &'a mut Tag {
586    type Error = TagConversionError<'a>;
587    fn try_into(self) -> Result<&'a mut String, TagConversionError<'a>> {
588        match self {
589            Tag::String(x) => Ok(x),
590            _ => Err(TagConversionError::Tag(self.tag_type(), "str"))
591        }
592    }
593}
594
595impl<'a> TryInto<&'a [String]> for &'a List {
596    type Error = TagConversionError<'a>;
597    fn try_into(self) -> Result<&'a [String], TagConversionError<'a>> {
598        match self {
599            List::String(x) => Ok(x),
600            _ => Err(TagConversionError::List(self.tag_type(), "str"))
601        }
602    }
603}
604
605impl<'a> TryInto<&'a mut [String]> for &'a mut List {
606    type Error = TagConversionError<'a>;
607    fn try_into(self) -> Result<&'a mut [String], TagConversionError<'a>> {
608        match self {
609            List::String(x) => Ok(x),
610            _ => Err(TagConversionError::List(self.tag_type(), "str"))
611        }
612    }
613}
614
615impl<'a> CompoundTryGetInto<&'a str> for &'a Compound {
616    type Error = TagConversionError<'a>;
617    fn try_get_into(self, key: &str) -> Result<Option<&'a str>, TagConversionError<'a>> {
618        match self.get(key) {
619            Some(x) => match x {
620                Tag::String(y) => Ok(Some(y)),
621                _ => Err(TagConversionError::Tag(x.tag_type(), "str"))
622            },
623            None => Ok(None)
624        }
625    }
626}
627
628impl<'a> CompoundTryGetInto<&'a mut String> for &'a mut Compound {
629    type Error = TagConversionError<'a>;
630    fn try_get_into(self, key: &str) -> Result<Option<&'a mut String>, TagConversionError<'a>> {
631        match self.get_mut(key) {
632            Some(x) => match x {
633                Tag::String(y) => Ok(Some(y)),
634                _ => Err(TagConversionError::Tag(x.tag_type(), "str"))
635            },
636            None => Ok(None)
637        }
638    }
639}
640
641impl Tag {
642    pub fn try_get(&self, key: &String) -> Result<Option<&Tag>, TagConversionError> {
643        let compound: &Compound = self.try_into()?;
644        Ok(compound.get(key))
645    }
646
647    pub fn tag_type(&self) -> TagType {
648        match self {
649            Tag::Byte(_) => TagType::Byte,
650            Tag::Short(_) => TagType::Short,
651            Tag::Int(_) => TagType::Int,
652            Tag::Long(_) => TagType::Long,
653            Tag::Float(_) => TagType::Float,
654            Tag::Double(_) => TagType::Double,
655            Tag::ByteArray(_) => TagType::ByteArray,
656            Tag::String(_) => TagType::String,
657            Tag::List(_) => TagType::List,
658            Tag::Compound(_) => TagType::Compound,
659            Tag::IntArray(_) => TagType::IntArray,
660            Tag::LongArray(_) => TagType::LongArray
661        }
662    }
663}
664
665impl List {
666    pub fn tag_type(&self) -> TagType {
667        match self {
668            List::Empty => TagType::End,
669            List::Byte(_) => TagType::Byte,
670            List::Short(_) => TagType::Short,
671            List::Int(_) => TagType::Int,
672            List::Long(_) => TagType::Long,
673            List::Float(_) => TagType::Float,
674            List::Double(_) => TagType::Double,
675            List::ByteArray(_) => TagType::ByteArray,
676            List::String(_) => TagType::String,
677            List::List(_) => TagType::List,
678            List::Compound(_) => TagType::Compound,
679            List::IntArray(_) => TagType::IntArray,
680            List::LongArray(_) => TagType::LongArray
681        }
682    }
683}