1#![doc(html_root_url = "https://docs.rs/raw-nbt/0.1.1")]
2
3pub mod decode;
4
5use std::borrow::Cow;
6use std::collections::BTreeMap;
7use std::fmt;
8
9#[derive(Debug, Clone, PartialEq)]
11pub enum Value {
12 Byte(i8),
14 Short(i16),
15 Int(i32),
16 Long(i64),
17 Float(f32),
18 Double(f64),
19 ByteArray(Vec<i8>),
20 Str(String),
21 Compound(Compound),
22 IntArray(Vec<i32>),
23 LongArray(Vec<i64>),
24 EndList,
26 EmptyByteList,
30 ByteList(Vec<i8>),
31 ShortList(Vec<i16>),
32 IntList(Vec<i32>),
33 LongList(Vec<i64>),
34 FloatList(Vec<f32>),
35 DoubleList(Vec<f64>),
36 ByteArrayList(Vec<Vec<i8>>),
37 StrList(Vec<String>),
38 ListList(Vec<Value>),
39 CompoundList(Vec<Compound>),
40 IntArrayList(Vec<Vec<i32>>),
41 LongArrayList(Vec<Vec<i64>>),
42}
43
44impl Value {
45 pub fn byte(&self) -> Result<i8> {
46 match self {
47 Value::Byte(x) => Ok(*x),
48 _ => Err(Error::InvalidType("byte", self.val_type())),
49 }
50 }
51
52 pub fn short(&self) -> Result<i16> {
53 match self {
54 Value::Short(x) => Ok(*x),
55 _ => Err(Error::InvalidType("short", self.val_type())),
56 }
57 }
58
59 pub fn int(&self) -> Result<i32> {
60 match self {
61 Value::Int(x) => Ok(*x),
62 _ => Err(Error::InvalidType("int", self.val_type())),
63 }
64 }
65
66 pub fn long(&self) -> Result<i64> {
67 match self {
68 Value::Long(x) => Ok(*x),
69 _ => Err(Error::InvalidType("long", self.val_type())),
70 }
71 }
72
73 pub fn float(&self) -> Result<f32> {
74 match self {
75 Value::Float(x) => Ok(*x),
76 _ => Err(Error::InvalidType("float", self.val_type())),
77 }
78 }
79
80 pub fn double(&self) -> Result<f64> {
81 match self {
82 Value::Double(x) => Ok(*x),
83 _ => Err(Error::InvalidType("double", self.val_type())),
84 }
85 }
86
87 pub fn byte_array(&self) -> Result<&Vec<i8>> {
88 match self {
89 Value::ByteArray(x) => Ok(x),
90 _ => Err(Error::InvalidType("byte array", self.val_type())),
91 }
92 }
93
94 pub fn str(&self) -> Result<&str> {
95 match self {
96 Value::Str(x) => Ok(x),
97 _ => Err(Error::InvalidType("str", self.val_type())),
98 }
99 }
100
101 pub fn compound(&self) -> Result<&Compound> {
102 match self {
103 Value::Compound(x) => Ok(x),
104 _ => Err(Error::InvalidType("compound", self.val_type())),
105 }
106 }
107
108 pub fn get(&self, name: &str) -> Result<&Value> {
110 self.compound()?.get(name).ok_or_else(|| Error::NotFound(name.to_string()))
111 }
112
113 pub fn int_array(&self) -> Result<&Vec<i32>> {
114 match self {
115 Value::IntArray(x) => Ok(x),
116 _ => Err(Error::InvalidType("int array", self.val_type())),
117 }
118 }
119
120 pub fn long_array(&self) -> Result<&Vec<i64>> {
121 match self {
122 Value::LongArray(x) => Ok(x),
123 _ => Err(Error::InvalidType("long array", self.val_type())),
124 }
125 }
126
127 pub fn byte_list(&self) -> Result<Cow<Vec<i8>>> {
128 match self {
129 Value::EndList => Ok(Cow::Owned(Vec::new())),
130 Value::EmptyByteList => Ok(Cow::Owned(Vec::new())),
131 Value::ByteList(x) => Ok(Cow::Borrowed(x)),
132 _ => Err(Error::InvalidType("byte list", self.val_type())),
133 }
134 }
135
136 pub fn short_list(&self) -> Result<Cow<Vec<i16>>> {
137 match self {
138 Value::EndList => Ok(Cow::Owned(Vec::new())),
139 Value::EmptyByteList => Ok(Cow::Owned(Vec::new())),
140 Value::ShortList(x) => Ok(Cow::Borrowed(x)),
141 _ => Err(Error::InvalidType("short list", self.val_type())),
142 }
143 }
144
145 pub fn int_list(&self) -> Result<Cow<Vec<i32>>> {
146 match self {
147 Value::EndList => Ok(Cow::Owned(Vec::new())),
148 Value::EmptyByteList => Ok(Cow::Owned(Vec::new())),
149 Value::IntList(x) => Ok(Cow::Borrowed(x)),
150 _ => Err(Error::InvalidType("short list", self.val_type())),
151 }
152 }
153
154 pub fn long_list(&self) -> Result<Cow<Vec<i64>>> {
155 match self {
156 Value::EndList => Ok(Cow::Owned(Vec::new())),
157 Value::EmptyByteList => Ok(Cow::Owned(Vec::new())),
158 Value::LongList(x) => Ok(Cow::Borrowed(x)),
159 _ => Err(Error::InvalidType("long list", self.val_type())),
160 }
161 }
162
163 pub fn float_list(&self) -> Result<Cow<Vec<f32>>> {
164 match self {
165 Value::EndList => Ok(Cow::Owned(Vec::new())),
166 Value::EmptyByteList => Ok(Cow::Owned(Vec::new())),
167 Value::FloatList(x) => Ok(Cow::Borrowed(x)),
168 _ => Err(Error::InvalidType("float list", self.val_type())),
169 }
170 }
171
172 pub fn double_list(&self) -> Result<Cow<Vec<f64>>> {
173 match self {
174 Value::EndList => Ok(Cow::Owned(Vec::new())),
175 Value::EmptyByteList => Ok(Cow::Owned(Vec::new())),
176 Value::DoubleList(x) => Ok(Cow::Borrowed(x)),
177 _ => Err(Error::InvalidType("double list", self.val_type())),
178 }
179 }
180
181 pub fn byte_array_list(&self) -> Result<Cow<Vec<Vec<i8>>>> {
182 match self {
183 Value::EndList => Ok(Cow::Owned(Vec::new())),
184 Value::EmptyByteList => Ok(Cow::Owned(Vec::new())),
185 Value::ByteArrayList(x) => Ok(Cow::Borrowed(x)),
186 _ => Err(Error::InvalidType("byte array list", self.val_type())),
187 }
188 }
189
190 pub fn str_list(&self) -> Result<Cow<Vec<String>>> {
191 match self {
192 Value::EndList => Ok(Cow::Owned(Vec::new())),
193 Value::EmptyByteList => Ok(Cow::Owned(Vec::new())),
194 Value::StrList(x) => Ok(Cow::Borrowed(x)),
195 _ => Err(Error::InvalidType("str list", self.val_type())),
196 }
197 }
198
199 pub fn list_list(&self) -> Result<Cow<Vec<Value>>> {
200 match self {
201 Value::EndList => Ok(Cow::Owned(Vec::new())),
202 Value::EmptyByteList => Ok(Cow::Owned(Vec::new())),
203 Value::ListList(x) => Ok(Cow::Borrowed(x)),
204 _ => Err(Error::InvalidType("list list", self.val_type())),
205 }
206 }
207
208 pub fn compound_list(&self) -> Result<Cow<Vec<Compound>>> {
209 match self {
210 Value::EndList => Ok(Cow::Owned(Vec::new())),
211 Value::EmptyByteList => Ok(Cow::Owned(Vec::new())),
212 Value::CompoundList(x) => Ok(Cow::Borrowed(x)),
213 _ => Err(Error::InvalidType("compound list", self.val_type())),
214 }
215 }
216
217 pub fn int_array_list(&self) -> Result<Cow<Vec<Vec<i32>>>> {
218 match self {
219 Value::EndList => Ok(Cow::Owned(Vec::new())),
220 Value::EmptyByteList => Ok(Cow::Owned(Vec::new())),
221 Value::IntArrayList(x) => Ok(Cow::Borrowed(x)),
222 _ => Err(Error::InvalidType("int array list", self.val_type())),
223 }
224 }
225
226 pub fn long_array_list(&self) -> Result<Cow<Vec<Vec<i64>>>> {
227 match self {
228 Value::EndList => Ok(Cow::Owned(Vec::new())),
229 Value::EmptyByteList => Ok(Cow::Owned(Vec::new())),
230 Value::LongArrayList(x) => Ok(Cow::Borrowed(x)),
231 _ => Err(Error::InvalidType("long array list", self.val_type())),
232 }
233 }
234
235 fn val_type(&self) -> &'static str {
236 match self {
237 Value::Byte(_) => "byte",
238 Value::Short(_) => "short",
239 Value::Int(_) => "int",
240 Value::Long(_) => "long",
241 Value::Float(_) => "float",
242 Value::Double(_) => "double",
243 Value::ByteArray(_) => "byte array",
244 Value::Str(_) => "str",
245 Value::Compound(_) => "compound",
246 Value::IntArray(_) => "int array",
247 Value::LongArray(_) => "long array",
248 Value::EndList => "end list",
249 Value::EmptyByteList => "byte list (empty)",
250 Value::ByteList(_) => "byte list (non-empty)",
251 Value::ShortList(_) => "short list",
252 Value::IntList(_) => "int list",
253 Value::LongList(_) => "long list",
254 Value::FloatList(_) => "float list",
255 Value::DoubleList(_) => "double list",
256 Value::ByteArrayList(_) => "byte array list",
257 Value::StrList(_) => "str list",
258 Value::ListList(_) => "list list",
259 Value::CompoundList(_) => "compound list",
260 Value::IntArrayList(_) => "int array list",
261 Value::LongArrayList(_) => "long array list",
262 }
263 }
264}
265
266pub type Result<T> = std::result::Result<T, Error>;
267
268pub type Compound = BTreeMap<String, Value>;
269
270#[derive(Debug, Clone)]
271pub enum Error {
272 InvalidType(&'static str, &'static str),
273 NotFound(String),
274}
275
276impl fmt::Display for Error {
277 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
278 match self {
279 Error::InvalidType(to_be, actual) => write!(f, "invalid type: wanted '{}' but actual '{}'", to_be, actual),
280 Error::NotFound(name) => write!(f, "field not found '{}'", name),
281 }
282 }
283}
284
285impl std::error::Error for Error {}