diff options
Diffstat (limited to 'src/nbt.rs')
-rw-r--r-- | src/nbt.rs | 172 |
1 files changed, 124 insertions, 48 deletions
@@ -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 +} |