raw_nbt/
lib.rs

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/// An NBT Value.
10#[derive(Debug, Clone, PartialEq)]
11pub enum Value {
12    // basic types
13    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    // list
25    EndList,
26    /// Empty byte list.
27    ///
28    /// EmptyByteList variant is distinguished from ByteList because it is often used as empty other types.
29    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    /// Get value of compound.
109    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 {}