1use std::collections::HashMap;
2use std::fmt;
3use std::io;
4
5use error::{Error, Result};
6use raw::{Endianness, RawWriter, RawReader};
7
8#[derive(Clone, Debug, PartialEq)]
10#[cfg_attr(feature = "serde", derive(Serialize))]
11#[cfg_attr(feature = "serde", derive(Deserialize))]
12#[cfg_attr(feature = "serde", serde(untagged))]
13pub enum Value {
14 Byte(i8),
15 Short(i16),
16 Int(i32),
17 Long(i64),
18 Float(f32),
19 Double(f64),
20 ByteArray(Vec<i8>),
21 String(String),
22 List(Vec<Value>),
23 Compound(HashMap<String, Value>),
24 IntArray(Vec<i32>),
25 LongArray(Vec<i64>),
26}
27
28impl Value {
29 pub fn id(&self) -> i8 {
32 match *self {
33 Value::Byte(_) => 0x01,
34 Value::Short(_) => 0x02,
35 Value::Int(_) => 0x03,
36 Value::Long(_) => 0x04,
37 Value::Float(_) => 0x05,
38 Value::Double(_) => 0x06,
39 Value::ByteArray(_) => 0x07,
40 Value::String(_) => 0x08,
41 Value::List(_) => 0x09,
42 Value::Compound(_) => 0x0a,
43 Value::IntArray(_) => 0x0b,
44 Value::LongArray(_) => 0x0c,
45 }
46 }
47
48 pub fn tag_name(&self) -> &str {
50 match *self {
51 Value::Byte(_) => "TAG_Byte",
52 Value::Short(_) => "TAG_Short",
53 Value::Int(_) => "TAG_Int",
54 Value::Long(_) => "TAG_Long",
55 Value::Float(_) => "TAG_Float",
56 Value::Double(_) => "TAG_Double",
57 Value::ByteArray(_) => "TAG_ByteArray",
58 Value::String(_) => "TAG_String",
59 Value::List(_) => "TAG_List",
60 Value::Compound(_) => "TAG_Compound",
61 Value::IntArray(_) => "TAG_IntArray",
62 Value::LongArray(_) => "TAG_LongArray",
63 }
64 }
65
66 pub(crate) fn to_raw_writer<W>(&self, dst: &mut RawWriter<W>) -> Result<()>
67 where W: io::Write,
68 {
69 match *self {
70 Value::Byte(val) => dst.write_bare_byte(val),
71 Value::Short(val) => dst.write_bare_short(val),
72 Value::Int(val) => dst.write_bare_int(val),
73 Value::Long(val) => dst.write_bare_long(val),
74 Value::Float(val) => dst.write_bare_float(val),
75 Value::Double(val) => dst.write_bare_double(val),
76 Value::ByteArray(ref vals) => dst.write_bare_byte_array(&vals[..]),
77 Value::String(ref val) => dst.write_bare_string(&val),
78 Value::List(ref vals) => {
79 if vals.len() == 0 {
82 dst.write_bare_byte(0)?; dst.write_bare_int(0)?;
84 } else {
85 let first_id = vals[0].id();
87 dst.write_bare_byte(first_id)?;
88 dst.write_bare_int(vals.len() as i32)?;
89 for nbt in vals {
90 if nbt.id() != first_id {
92 return Err(Error::HeterogeneousList);
93 }
94 nbt.to_raw_writer(dst)?;
95 }
96 }
97 Ok(())
98 },
99 Value::Compound(ref vals) => {
100 for (name, ref nbt) in vals {
101 dst.write_bare_byte(nbt.id())?;
103 dst.write_bare_string(name)?;
104 nbt.to_raw_writer(dst)?;
105 }
106 dst.close_nbt()
107 },
108 Value::IntArray(ref vals) => dst.write_bare_int_array(&vals[..]),
109 Value::LongArray(ref vals) => dst.write_bare_long_array(&vals[..]),
110 }
111 }
112
113 pub fn to_writer<W>(&self, dst: &mut W, endian: Endianness) -> Result<()>
115 where W: io::Write
116 {
117 let mut dst = RawWriter::new(dst, endian);
118 self.to_raw_writer(&mut dst)
119 }
120
121 pub(crate) fn from_raw_reader<R>(id: i8, src: &mut RawReader<R>) -> Result<Value>
122 where R: io::Read,
123 {
124 match id {
125 0x01 => Ok(Value::Byte(src.read_bare_byte()?)),
126 0x02 => Ok(Value::Short(src.read_bare_short()?)),
127 0x03 => Ok(Value::Int(src.read_bare_int()?)),
128 0x04 => Ok(Value::Long(src.read_bare_long()?)),
129 0x05 => Ok(Value::Float(src.read_bare_float()?)),
130 0x06 => Ok(Value::Double(src.read_bare_double()?)),
131 0x07 => Ok(Value::ByteArray(src.read_bare_byte_array()?)),
132 0x08 => Ok(Value::String(src.read_bare_string()?)),
133 0x09 => { let id = src.read_bare_byte()?;
135 let len = src.read_bare_int()? as usize;
136 let mut buf = Vec::with_capacity(len);
137 for _ in 0..len {
138 buf.push(Value::from_raw_reader(id, src)?);
139 }
140 Ok(Value::List(buf))
141 },
142 0x0a => { let mut buf = HashMap::new();
144 loop {
145 let (id, name) = src.emit_next_header()?;
146 if id == 0x00 { break; }
147 let tag = Value::from_raw_reader(id, src)?;
148 buf.insert(name, tag);
149 }
150 Ok(Value::Compound(buf))
151 },
152 0x0b => Ok(Value::IntArray(src.read_bare_int_array()?)),
153 0x0c => Ok(Value::LongArray(src.read_bare_long_array()?)),
154 e => Err(Error::InvalidTypeId(e))
155 }
156 }
157
158 pub fn from_reader<R>(id: i8, src: &mut R, endian: Endianness) -> Result<Value>
161 where R: io::Read
162 {
163 let mut src = RawReader::new(src, endian);
164 Value::from_raw_reader(id, &mut src)
165 }
166
167 pub fn print(&self, f: &mut fmt::Formatter, offset: usize) -> fmt::Result {
168 match *self {
169 Value::Byte(v) => write!(f, "{}", v),
170 Value::Short(v) => write!(f, "{}", v),
171 Value::Int(v) => write!(f, "{}", v),
172 Value::Long(v) => write!(f, "{}", v),
173 Value::Float(v) => write!(f, "{}", v),
174 Value::Double(v) => write!(f, "{}", v),
175 Value::ByteArray(ref v) => write!(f, "{:?}", v),
176 Value::String(ref v) => write!(f, "{}", v),
177 Value::IntArray(ref v) => write!(f, "{:?}", v),
178 Value::LongArray(ref v) => write!(f, "{:?}", v),
179 Value::List(ref v) => {
180 if v.len() == 0 {
181 write!(f, "zero entries")
182 } else {
183 write!(f, "{} entries of type {}\n{:>width$}\n", v.len(), v[0].tag_name(), "{", width = offset + 1)?;
184 for tag in v {
185 let new_offset = offset + 2;
186 write!(f, "{:>width$}(None): ", tag.tag_name(), width = new_offset + tag.tag_name().len())?;
187 tag.print(f, new_offset)?;
188 write!(f, "\n")?;
189 }
190 write!(f, "{:>width$}", "}", width = offset + 1)
191 }
192 }
193 Value::Compound(ref v) => {
194 write!(f, "{} entry(ies)\n{:>width$}\n", v.len(), "{", width = offset + 1)?;
195 for (name, tag) in v {
196 let new_offset = offset + 2;
197 write!(f, "{:>width$}({}): ", tag.tag_name(), name, width = new_offset + tag.tag_name().len())?;
198 tag.print(f, new_offset)?;
199 write!(f, "\n")?;
200 }
201 write!(f, "{:>width$}", "}", width = offset + 1)
202 }
203 }
204 }
205}
206
207impl fmt::Display for Value {
208 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
209 self.print(f, 0)
210 }
211}
212
213impl From<i8> for Value {
214 fn from(t: i8) -> Value { Value::Byte(t) }
215}
216
217impl From<i16> for Value {
218 fn from(t: i16) -> Value { Value::Short(t) }
219}
220
221impl From<i32> for Value {
222 fn from(t: i32) -> Value { Value::Int(t) }
223}
224
225impl From<i64> for Value {
226 fn from(t: i64) -> Value { Value::Long(t) }
227}
228
229impl From<f32> for Value {
230 fn from(t: f32) -> Value { Value::Float(t) }
231}
232
233impl From<f64> for Value {
234 fn from(t: f64) -> Value { Value::Double(t) }
235}
236
237impl<'a> From<&'a str> for Value {
238 fn from(t: &'a str) -> Value { Value::String(t.into()) }
239}
240
241impl From<String> for Value {
242 fn from(t: String) -> Value { Value::String(t) }
243}
244
245impl From<Vec<i8>> for Value {
246 fn from(t: Vec<i8>) -> Value { Value::ByteArray(t) }
247}
248
249impl<'a> From<&'a [i8]> for Value {
250 fn from(t: &'a [i8]) -> Value { Value::ByteArray(t.into()) }
251}
252
253impl From<Vec<i32>> for Value {
254 fn from(t: Vec<i32>) -> Value { Value::IntArray(t) }
255}
256
257impl<'a> From<&'a [i32]> for Value {
258 fn from(t: &'a [i32]) -> Value { Value::IntArray(t.into()) }
259}
260
261impl From<Vec<i64>> for Value {
262 fn from(t: Vec<i64>) -> Value { Value::LongArray(t) }
263}
264
265impl<'a> From<&'a [i64]> for Value {
266 fn from(t: &'a [i64]) -> Value { Value::LongArray(t.into()) }
267}