aboutsummaryrefslogtreecommitdiff
path: root/src/nbt.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/nbt.rs')
-rw-r--r--src/nbt.rs172
1 files changed, 124 insertions, 48 deletions
diff --git a/src/nbt.rs b/src/nbt.rs
index f784454..27eb051 100644
--- a/src/nbt.rs
+++ b/src/nbt.rs
@@ -1,7 +1,9 @@
-use std::fmt;
-use crate::{DeserializeResult, DeserializeErr, Deserialized};
-use crate::utils::{read_short, take, read_int, read_long, read_one_byte, write_long, write_int, write_short};
use crate::protocol::TestRandom;
+use crate::utils::{
+ read_int, read_long, read_one_byte, read_short, take, write_int, write_long, write_short,
+};
+use crate::{DeserializeErr, DeserializeResult, Deserialized};
+use std::fmt;
#[derive(Clone, Debug, PartialEq)]
pub struct NamedTag {
@@ -34,12 +36,15 @@ impl TestRandom for NamedTag {
impl fmt::Display for NamedTag {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_fmt(format_args!("TAG_{}('{}'): ", self.payload.tag_type_name(), self.name))?;
+ f.write_fmt(format_args!(
+ "TAG_{}('{}'): ",
+ self.payload.tag_type_name(),
+ self.name
+ ))?;
self.payload.write_contents(f)
}
}
-
#[derive(Clone, Debug, PartialEq)]
pub enum Tag {
Byte(i8),
@@ -140,7 +145,7 @@ impl TestRandom for Tag {
4 => Tag::Float(f32::test_gen_random()),
5 => Tag::Double(f64::test_gen_random()),
6 => Tag::String(String::test_gen_random()),
- other => panic!("impossible {}", other)
+ other => panic!("impossible {}", other),
});
}
@@ -160,19 +165,34 @@ impl TestRandom for Tag {
}
#[inline]
-fn write_contents<F>(contents: &Vec<F>) -> String where F: fmt::Display {
- format!("{} entries\n{{\n{}\n}}", contents.len(), contents.iter()
- .flat_map(move |elem| elem.to_string().split("\n").map(String::from).collect::<Vec<String>>())
- .map(move |line| " ".to_owned() + line.as_str())
- .collect::<Vec<String>>()
- .join("\n"))
+fn write_contents<F>(contents: &Vec<F>) -> String
+where
+ F: fmt::Display,
+{
+ format!(
+ "{} entries\n{{\n{}\n}}",
+ contents.len(),
+ contents
+ .iter()
+ .flat_map(move |elem| elem
+ .to_string()
+ .split("\n")
+ .map(String::from)
+ .collect::<Vec<String>>())
+ .map(move |line| " ".to_owned() + line.as_str())
+ .collect::<Vec<String>>()
+ .join("\n")
+ )
}
// deserialization first
// reads from the root level
fn read_nbt_data(data: &[u8]) -> DeserializeResult<NamedTag> {
- let Deserialized { value: tag_type_id, data: _ } = read_one_byte(data)?;
+ let Deserialized {
+ value: tag_type_id,
+ data: _,
+ } = read_one_byte(data)?;
match tag_type_id {
0x0A => read_named_tag(data),
other => Err(DeserializeErr::NbtInvalidStartTag(other)),
@@ -182,8 +202,12 @@ fn read_nbt_data(data: &[u8]) -> DeserializeResult<NamedTag> {
// reads any named tag: read id -> read name -> read tag with id -> name tag with name
#[inline]
pub fn read_named_tag(data: &[u8]) -> DeserializeResult<NamedTag> {
- let Deserialized { value: tag_type_id, data } = read_one_byte(data)?;
- if tag_type_id == 0x00 { // tag end
+ let Deserialized {
+ value: tag_type_id,
+ data,
+ } = read_one_byte(data)?;
+ if tag_type_id == 0x00 {
+ // tag end
Deserialized::ok(Tag::End.with_name(""), data)
} else {
let Deserialized { value: name, data } = read_string(data)?;
@@ -244,7 +268,8 @@ fn read_tag_double(data: &[u8]) -> DeserializeResult<Tag> {
#[inline]
fn read_tag_byte_array(data: &[u8]) -> DeserializeResult<Tag> {
- Ok(read_int(data)?.and_then(move |size, rest| take(size as usize)(rest))?
+ Ok(read_int(data)?
+ .and_then(move |size, rest| take(size as usize)(rest))?
.map(move |arr| Tag::ByteArray(Vec::from(arr))))
}
@@ -254,19 +279,28 @@ fn read_tag_string(data: &[u8]) -> DeserializeResult<Tag> {
}
fn read_tag_list(data: &[u8]) -> DeserializeResult<Tag> {
- let Deserialized { value: contents_tag_type_id, data } = read_one_byte(data)?;
- let Deserialized { value: list_length, data } = read_int(data)?;
+ let Deserialized {
+ value: contents_tag_type_id,
+ data,
+ } = read_one_byte(data)?;
+ let Deserialized {
+ value: list_length,
+ data,
+ } = read_int(data)?;
if list_length <= 0 {
if contents_tag_type_id != 0x00 {
Err(DeserializeErr::NbtBadLength(list_length as isize))
} else {
- Deserialized::ok(Tag::List(vec!()), data)
+ Deserialized::ok(Tag::List(vec![]), data)
}
} else {
let mut out_vec = Vec::with_capacity(list_length as usize);
let mut remaining_data = data;
for _ in 0..list_length {
- let Deserialized { value: element, data: rest } = read_tag(contents_tag_type_id, &remaining_data)?;
+ let Deserialized {
+ value: element,
+ data: rest,
+ } = read_tag(contents_tag_type_id, &remaining_data)?;
out_vec.push(element);
remaining_data = rest;
}
@@ -279,7 +313,10 @@ fn read_tag_compound(data: &[u8]) -> DeserializeResult<Tag> {
let mut out = Vec::new();
let mut remaining_data = data;
loop {
- let Deserialized { value: elem, data: rest } = read_named_tag(remaining_data)?;
+ let Deserialized {
+ value: elem,
+ data: rest,
+ } = read_named_tag(remaining_data)?;
remaining_data = rest;
if elem.is_end() {
break;
@@ -295,7 +332,8 @@ fn read_tag_int_array(data: &[u8]) -> DeserializeResult<Tag> {
read_array_tag(
data,
move |data| Ok(read_int(data)?.map(move |r| r as i32)),
- Tag::IntArray)
+ Tag::IntArray,
+ )
}
#[inline]
@@ -303,13 +341,19 @@ fn read_tag_long_array(data: &[u8]) -> DeserializeResult<Tag> {
read_array_tag(
data,
move |data| Ok(read_long(data)?.map(move |r| r as i64)),
- Tag::LongArray)
+ Tag::LongArray,
+ )
}
#[inline]
-fn read_array_tag<'a, R, F, M>(data: &'a [u8], parser: F, finalizer: M) -> DeserializeResult<'a, Tag> where
+fn read_array_tag<'a, R, F, M>(
+ data: &'a [u8],
+ parser: F,
+ finalizer: M,
+) -> DeserializeResult<'a, Tag>
+where
F: Fn(&'a [u8]) -> DeserializeResult<'a, R>,
- M: Fn(Vec<R>) -> Tag
+ M: Fn(Vec<R>) -> Tag,
{
let Deserialized { value: count, data } = read_int(data)?.map(move |v| v as i32);
if count < 0 {
@@ -318,7 +362,10 @@ fn read_array_tag<'a, R, F, M>(data: &'a [u8], parser: F, finalizer: M) -> Deser
let mut out = Vec::with_capacity(count as usize);
let mut data_remaining = data;
for _ in 0..count {
- let Deserialized { value: elem, data: rest } = parser(data_remaining)?;
+ let Deserialized {
+ value: elem,
+ data: rest,
+ } = parser(data_remaining)?;
data_remaining = rest;
out.push(elem);
}
@@ -330,12 +377,11 @@ fn read_array_tag<'a, R, F, M>(data: &'a [u8], parser: F, finalizer: M) -> Deser
#[inline]
fn read_string(data: &[u8]) -> DeserializeResult<String> {
read_short(data)?
- .and_then(move |length, data|
- take(length as usize)(data))?
- .try_map(move |bytes|
- String::from_utf8(Vec::from(bytes)).map_err(move |err| {
- DeserializeErr::BadStringEncoding(err)
- }))
+ .and_then(move |length, data| take(length as usize)(data))?
+ .try_map(move |bytes| {
+ String::from_utf8(Vec::from(bytes))
+ .map_err(move |err| DeserializeErr::BadStringEncoding(err))
+ })
}
// serialize
@@ -343,12 +389,13 @@ impl NamedTag {
pub fn bytes(&self) -> Vec<u8> {
let type_id = self.payload.id();
if type_id == 0x00 {
- vec!(0x00)
+ vec![0x00]
} else {
let payload_bytes = self.payload.bytes();
let name_len = self.name.len();
let name_len_bytes = write_short(name_len as u16);
- let mut out = Vec::with_capacity(1 + name_len_bytes.len() + name_len + payload_bytes.len());
+ let mut out =
+ Vec::with_capacity(1 + name_len_bytes.len() + name_len + payload_bytes.len());
out.push(type_id);
out.extend_from_slice(&name_len_bytes);
out.extend(self.name.bytes());
@@ -379,7 +426,7 @@ impl Tag {
pub fn bytes(&self) -> Vec<u8> {
match self {
- Tag::Byte(b) => vec!(*b as u8),
+ Tag::Byte(b) => vec![*b as u8],
Tag::Short(v) => Vec::from(write_short(*v as u16)),
Tag::Int(v) => Vec::from(write_int(*v as u32)),
Tag::Long(v) => Vec::from(write_long(*v as u64)),
@@ -412,7 +459,9 @@ impl Tag {
let elem_id = elem.id();
if let Some(old_id) = id.replace(elem_id) {
if old_id != elem_id {
- panic!("list contains tags of different types, cannot serialize");
+ panic!(
+ "list contains tags of different types, cannot serialize"
+ );
}
}
}
@@ -467,9 +516,9 @@ impl Tag {
#[cfg(test)]
mod tests {
use super::*;
- use std::io::Read;
use flate2::read::GzDecoder;
use std::fs::File;
+ use std::io::Read;
#[test]
fn test_read_bignbt_example() {
@@ -521,29 +570,53 @@ mod tests {
let (unzipped, result) = read_bigtest_with_bytes();
let serialized = result.bytes();
assert_eq!(unzipped, serialized);
- let Deserialized { value: unserialized, data: _ } = NamedTag::root_compound_tag_from_bytes(serialized.as_slice()).expect("deserialize serialized nbt");
+ let Deserialized {
+ value: unserialized,
+ data: _,
+ } = NamedTag::root_compound_tag_from_bytes(serialized.as_slice())
+ .expect("deserialize serialized nbt");
assert_eq!(unserialized, result);
}
#[test]
fn test_int_array() {
- let original = Tag::Compound(vec!(
- Tag::IntArray(vec!(1, 2, -5, 123127, -12373, 0, 0, 4, 2)).with_name("test ints")
- )).with_name("test");
+ let original = Tag::Compound(vec![Tag::IntArray(vec![
+ 1, 2, -5, 123127, -12373, 0, 0, 4, 2,
+ ])
+ .with_name("test ints")])
+ .with_name("test");
let bytes = original.bytes();
- let Deserialized { value: unserialized, data: _ } = NamedTag::root_compound_tag_from_bytes(bytes.as_slice()).expect("deserialize int array");
+ let Deserialized {
+ value: unserialized,
+ data: _,
+ } = NamedTag::root_compound_tag_from_bytes(bytes.as_slice())
+ .expect("deserialize int array");
assert_eq!(original, unserialized);
}
#[test]
fn test_long_array() {
- let original = Tag::Compound(vec!(
- Tag::LongArray(vec!(1, 2, -5, 123127999999, -1237399999, 0, 0, 4, 2)).with_name("test ints")
- )).with_name("test");
+ let original = Tag::Compound(vec![Tag::LongArray(vec![
+ 1,
+ 2,
+ -5,
+ 123127999999,
+ -1237399999,
+ 0,
+ 0,
+ 4,
+ 2,
+ ])
+ .with_name("test ints")])
+ .with_name("test");
let bytes = original.bytes();
- let Deserialized { value: unserialized, data: _ } = NamedTag::root_compound_tag_from_bytes(bytes.as_slice()).expect("deserialize int array");
+ let Deserialized {
+ value: unserialized,
+ data: _,
+ } = NamedTag::root_compound_tag_from_bytes(bytes.as_slice())
+ .expect("deserialize int array");
assert_eq!(original, unserialized);
}
@@ -559,7 +632,10 @@ mod tests {
fn read_bigtest_with_bytes() -> (Vec<u8>, NamedTag) {
let unzipped = read_compressed_file("src/testdata/bigtest.nbt").expect("read nbt data");
- let Deserialized { value: result, data: rest } = NamedTag::root_compound_tag_from_bytes(unzipped.as_slice()).expect("deserialize nbt");
+ let Deserialized {
+ value: result,
+ data: rest,
+ } = NamedTag::root_compound_tag_from_bytes(unzipped.as_slice()).expect("deserialize nbt");
assert_eq!(rest.len(), 0);
(unzipped, result)
@@ -586,4 +662,4 @@ mod tests {
gz.read_to_end(&mut out)?;
Ok(out)
}
-} \ No newline at end of file
+}