1use std::error::Error as StdError;
2use std::fmt;
3use std::io;
4use std::io::ErrorKind::InvalidInput;
5use std::result::Result as StdResult;
6
7#[cfg(feature = "serde")]
8use serde;
9
10pub type Result<T> = StdResult<T, Error>;
13
14#[derive(Debug)]
20pub enum Error {
21 IoError(io::Error),
23 #[cfg(feature = "serde")]
25 Serde(String),
26 InvalidTypeId(i8),
29 HeterogeneousList,
31 NoRootCompound,
34 InvalidUtf8,
37 IncompleteNbtValue,
40 TagMismatch(i8, i8),
43 UnexpectedField(String),
46 NonBooleanByte(i8),
48 UnrepresentableType(&'static str),
51 NonStringMapKey,
54}
55
56impl fmt::Display for Error {
57 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58 match self {
59 &Error::IoError(ref e) => e.fmt(f),
60 #[cfg(feature = "serde")]
61 &Error::Serde(ref msg) => write!(f, "{}", msg),
62 &Error::InvalidTypeId(t) => write!(f, "invalid NBT tag byte: '{}'", t),
63 &Error::TagMismatch(a, b) => write!(f, "encountered NBT tag '{}' but expected '{}'", a, b),
64 &Error::NonBooleanByte(b) => write!(f, "encountered a byte value '{}' inside a boolean", b),
65 &Error::UnexpectedField(ref name) => write!(f, "encountered an unexpected field '{}'", name),
66 &Error::UnrepresentableType(ref name) => write!(f, "encountered type '{}', which has no meaningful NBT representation", name),
67 other => write!(f, "{}", other.description()),
69 }
70 }
71}
72
73impl StdError for Error {
74 fn description(&self) -> &str {
75 match *self {
76 Error::IoError(ref e) => e.description(),
77 #[cfg(feature = "serde")]
78 Error::Serde(ref msg) => &msg[..],
79 Error::InvalidTypeId(_) => "invalid NBT tag byte",
80 Error::HeterogeneousList => "values in NBT Lists must be homogeneous",
81 Error::NoRootCompound => "the root value must be Compound-like (tag = 0x0a)",
82 Error::InvalidUtf8 => "a string is not valid UTF-8",
83 Error::IncompleteNbtValue => "data does not represent a complete NbtValue",
84 Error::NonStringMapKey => "encountered a non-string map key",
85 Error::TagMismatch(_, _) => "encountered one NBT tag but expected another",
86 Error::UnexpectedField(_) => "encountered an unexpected field",
87 Error::NonBooleanByte(_) => "encountered a non-boolean byte value inside a boolean",
88 Error::UnrepresentableType(_) => "encountered a type with no meaningful NBT representation",
89 }
90 }
91
92 #[allow(deprecated)]
96 fn cause(&self) -> Option<&dyn StdError> {
97 match *self {
98 Error::IoError(ref e) => e.cause(),
99 _ => None
100 }
101 }
102}
103
104impl PartialEq<Error> for Error {
106 fn eq(&self, other: &Error) -> bool {
107 use Error::{IoError, InvalidTypeId, HeterogeneousList, NoRootCompound,
108 InvalidUtf8, IncompleteNbtValue, TagMismatch, UnexpectedField, NonBooleanByte,
109 UnrepresentableType};
110
111 match (self, other) {
112 (&IoError(_), &IoError(_)) => true,
113 #[cfg(feature = "serde")]
114 (&Error::Serde(_), &Error::Serde(_)) => true,
115 (&InvalidTypeId(a), &InvalidTypeId(b)) => a == b,
116 (&HeterogeneousList, &HeterogeneousList) => true,
117 (&NoRootCompound, &NoRootCompound) => true,
118 (&InvalidUtf8, &InvalidUtf8) => true,
119 (&IncompleteNbtValue, &IncompleteNbtValue) => true,
120 (&TagMismatch(a, b), &TagMismatch(c, d)) => a == c && b == d,
121 (&UnexpectedField(ref a), &UnexpectedField(ref b)) => a == b,
122 (&NonBooleanByte(a), &NonBooleanByte(b)) => a == b,
123 (&UnrepresentableType(ref a), &UnrepresentableType(ref b)) => a == b,
124 _ => false
125 }
126 }
127}
128
129impl From<io::Error> for Error {
130 fn from(e: io::Error) -> Error {
131 use std::io::ErrorKind;
132
133 if e.kind() == ErrorKind::UnexpectedEof {
134 return Error::IncompleteNbtValue;
135 }
136 Error::IoError(e)
137 }
138}
139
140impl From<cesu8::Cesu8DecodingError> for Error {
141 fn from(_: cesu8::Cesu8DecodingError) -> Error {
142 Error::InvalidUtf8
143 }
144}
145
146impl From<Error> for io::Error {
147 fn from(e: Error) -> io::Error {
148 match e {
149 Error::IoError(e) => e,
150 Error::InvalidTypeId(id) =>
151 io::Error::new(InvalidInput, &format!("invalid NBT tag byte: {}", id)[..]),
152 Error::TagMismatch(a, b) =>
153 io::Error::new(InvalidInput, &format!("encountered NBT tag {} \
154 but expected {}", a, b)[..]),
155 Error::UnexpectedField(f) =>
156 io::Error::new(InvalidInput, &format!("encountered unexpected field \
157 with name {}", f)[..]),
158 other => io::Error::new(InvalidInput, other.description()),
159 }
160 }
161}
162
163#[cfg(feature = "serde")]
164impl serde::ser::Error for Error {
165 fn custom<T: fmt::Display>(msg: T) -> Error {
166 Error::Serde(msg.to_string())
167 }
168}
169
170#[cfg(feature = "serde")]
171impl serde::de::Error for Error {
172 fn custom<T: fmt::Display>(msg: T) -> Error {
173 Error::Serde(msg.to_string())
174 }
175}