1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//! This module contains all error related datatypes and their implementations
use crate::NbtTypeId;
/// Error enum to describe an error that occurs while reading/writing NBT data
#[derive(Debug, PartialEq, Eq)]
pub enum NbtError {
    /// Variant for unknown errors
    UnknownErr(String),
    /// This error occures if the root of the nbt data is not a `Compound`
    WrongRootType(u8),
    /// This error occures if the root of the nbt data has no name but the name is required
    RootWithoutName,
    /// This error occures if the parsing reads and unknown type id
    UnknownType(u8),
    /// This error occurs, if the parsing fails to read a name
    NameRead(String),
    /// This error occurs, if the parsing tries to read more data than supplied
    Overflow(usize, usize, usize),
    /// This error occurs, if a value is too large to be a `VarInt`, but a `VarInt` is expected
    VarIntTooBig(usize),
    /// This error occurs, if a value is too large to be a `VarLong`, but a `VarLong` is expected
    VarLongTooBig(usize),
    /// This error occurs, if elements in a list are not the same type
    ListTypeNotSame(Vec<NbtTypeId>),
    /// This error occurs, if a specific type is expected, but an other one is found
    IncorrectType(NbtTypeId, NbtTypeId),
}
/// A type declaration to store data `T` or return an error of [`NbtError`]
pub type NbtResult<T> = std::result::Result<T, NbtError>;
impl std::error::Error for NbtError {}
impl std::fmt::Display for NbtError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            NbtError::IncorrectType(t0, t1) => write!(f, "Expected type {t0} but got type {t1}"),
            NbtError::NameRead(name) => write!(f, "Could not read name '{name}'"),
            NbtError::Overflow(c, l, d) => write!(f, "Can't move cursor ({c}) by {l}, because the data length is only {d}"),
            NbtError::UnknownErr(err) => write!(f, "Unknown error occured: {err}"),
            NbtError::RootWithoutName => todo!(),
            NbtError::UnknownType(t0) => write!(f, "The type id {t0} does not corrospond to a valid type"),
            NbtError::VarIntTooBig(byte_length) => write!(f, "Could not construct VarInt, because the data would take {byte_length} bytes"),
            NbtError::VarLongTooBig(byte_length) => write!(f, "Could not construct VarLong, because the data would take {byte_length} bytes"),
            NbtError::ListTypeNotSame(types) => write!(f, "Could not create list, because following list types are not the same: {:?}", types),
            NbtError::WrongRootType(type_id) => write!(f, "The Root has to be an type id 0x0A, but is an {:02x}", type_id),
        }
    }
}

/// An error enum for nbt serialization
#[derive(Debug)]
#[allow(missing_docs)]
pub enum Error {
    Message(String),
    Eof,
    Syntax,
    ExpectedBoolean,
    ExpectedByte,
    ExpectedShort,
    ExpectedInteger,
    ExpectedLong,
    ExpectedFloat,
    ExpectedDouble,
    ExpectedByteArray,
    ExpectedIntArray,
    ExpectedLongArray,
    ExpectedString,
    ExpectedList,
    ExpectedMap,
    TrailingCharacters,
}
impl Error {
    /// Generate a [`Message`] with no root comound message
    ///
    /// [`Message`]: `Error::Message`
    pub fn no_root_compound() -> Self {
        Self::Message("The found element should have been an root compound, but it wasn't".to_string())
    }
    /// Generate a [`Message`] with array as other message
    ///
    /// [`Message`]: `Error::Message`
    pub fn array_as_other() -> Self {
        Self::Message("The found element should have been an array, but it wasn't".to_string())
    }
}
impl From<std::io::Error> for Error {
    fn from(e: std::io::Error) -> Self {
        Error::Message(format!("io error: {}", e))
    }
}
/// A Result type for nbt serialization with error type [`Error`]
///
/// [`Error`]: Error
pub type Result<T> = std::result::Result<T, Error>;
impl std::fmt::Display for Error {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            Error::Message(msg) => formatter.write_str(msg),
            Error::Eof => formatter.write_str("unexpected end of input"),
            Error::Syntax => formatter.write_str("unexpected syntax"),
            Error::ExpectedBoolean => formatter.write_str("expected boolean"),
            Error::ExpectedByte => formatter.write_str("expected byte"),
            Error::ExpectedShort => formatter.write_str("expected short"),
            Error::ExpectedInteger => formatter.write_str("expected integer"),
            Error::ExpectedLong => formatter.write_str("expected long"),
            Error::ExpectedFloat => formatter.write_str("expected float"),
            Error::ExpectedDouble => formatter.write_str("expected double"),
            Error::ExpectedString => formatter.write_str("expected string"),
            Error::ExpectedList => formatter.write_str("expected list"),
            Error::ExpectedMap => formatter.write_str("expected map"),
            Error::ExpectedByteArray => formatter.write_str("expected byte array"),
            Error::ExpectedIntArray => formatter.write_str("expected int array"),
            Error::ExpectedLongArray => formatter.write_str("expected long array"),
            Error::TrailingCharacters => formatter.write_str("found training characters")
            /* and so forth */
        }
    }
}
impl std::error::Error for Error {}
impl serde::de::Error for Error {
    fn custom<T>(msg:T) -> Self where T:std::fmt::Display {
        Error::Message(msg.to_string())
    }
}
impl serde::ser::Error for Error {
    fn custom<T>(msg:T) -> Self where T:std::fmt::Display {
        Error::Message(msg.to_string())
    }
}