aboutsummaryrefslogtreecommitdiff
path: root/azalea-nbt/src/encode.rs
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2021-12-18 17:02:23 -0600
committermat <github@matdoes.dev>2021-12-18 17:02:23 -0600
commit76e1985fc4ab21c43e17fef685b17a567b1073a5 (patch)
tree8eb41443888a8d3d5c99e63121ed9189d5f224fe /azalea-nbt/src/encode.rs
parent428d0ee0e643676e47683c7d314cefebd03bf3f1 (diff)
downloadazalea-drasl-76e1985fc4ab21c43e17fef685b17a567b1073a5.tar.xz
reading nbt
Diffstat (limited to 'azalea-nbt/src/encode.rs')
-rw-r--r--azalea-nbt/src/encode.rs117
1 files changed, 117 insertions, 0 deletions
diff --git a/azalea-nbt/src/encode.rs b/azalea-nbt/src/encode.rs
new file mode 100644
index 00000000..86c0d868
--- /dev/null
+++ b/azalea-nbt/src/encode.rs
@@ -0,0 +1,117 @@
+use byteorder::{ReadBytesExt, BE};
+use error::Error;
+use std::{collections::HashMap, io::Read};
+use tag::Tag;
+
+impl Tag {
+ fn write(&self, stream: &mut impl Read) -> Result<(), Error> {
+ println!("read_known: id={}", id);
+ let tag = match id {
+ // Signifies the end of a TAG_Compound. It is only ever used inside
+ // a TAG_Compound, and is not named despite being in a TAG_Compound
+ 0 => Tag::End,
+ // A single signed byte
+ 1 => Tag::Byte(stream.read_i8().map_err(|_| Error::InvalidTag)?),
+ // A single signed, big endian 16 bit integer
+ 2 => Tag::Short(stream.read_i16::<BE>().map_err(|_| Error::InvalidTag)?),
+ // A single signed, big endian 32 bit integer
+ 3 => Tag::Int(stream.read_i32::<BE>().map_err(|_| Error::InvalidTag)?),
+ // A single signed, big endian 64 bit integer
+ 4 => Tag::Long(stream.read_i64::<BE>().map_err(|_| Error::InvalidTag)?),
+ // A single, big endian IEEE-754 single-precision floating point
+ // number (NaN possible)
+ 5 => Tag::Float(stream.read_f32::<BE>().map_err(|_| Error::InvalidTag)?),
+ // A single, big endian IEEE-754 double-precision floating point
+ // number (NaN possible)
+ 6 => Tag::Double(stream.read_f64::<BE>().map_err(|_| Error::InvalidTag)?),
+ // A length-prefixed array of signed bytes. The prefix is a signed
+ // integer (thus 4 bytes)
+ 7 => {
+ let length = stream.read_i32::<BE>().map_err(|_| Error::InvalidTag)?;
+ let mut bytes = Vec::new();
+ for _ in 0..length {
+ bytes.push(stream.read_i8().map_err(|_| Error::InvalidTag)?);
+ }
+ Tag::ByteArray(bytes)
+ }
+ // A length-prefixed modified UTF-8 string. The prefix is an
+ // unsigned short (thus 2 bytes) signifying the length of the
+ // string in bytes
+ 8 => {
+ let length = stream.read_u16::<BE>().map_err(|_| Error::InvalidTag)?;
+ let mut bytes = Vec::new();
+ for _ in 0..length {
+ bytes.push(stream.read_u8().map_err(|_| Error::InvalidTag)?);
+ }
+ Tag::String(String::from_utf8(bytes).map_err(|_| Error::InvalidTag)?)
+ }
+ // A list of nameless tags, all of the same type. The list is
+ // prefixed with the Type ID of the items it contains (thus 1
+ // byte), and the length of the list as a signed integer (a further
+ // 4 bytes). If the length of the list is 0 or negative, the type
+ // may be 0 (TAG_End) but otherwise it must be any other type. (The
+ // notchian implementation uses TAG_End in that situation, but
+ // another reference implementation by Mojang uses 1 instead;
+ // parsers should accept any type if the length is <= 0).
+ 9 => {
+ let type_id = stream.read_u8().map_err(|_| Error::InvalidTag)?;
+ let length = stream.read_i32::<BE>().map_err(|_| Error::InvalidTag)?;
+ let mut list = Vec::new();
+ for _ in 0..length {
+ list.push(Tag::read_known(stream, type_id)?);
+ }
+ Tag::List(list)
+ }
+ // Effectively a list of a named tags. Order is not guaranteed.
+ 10 => {
+ println!("reading compound {{");
+ let mut map = HashMap::new();
+ loop {
+ let tag_id = stream.read_u8().unwrap_or(0);
+ println!("compound tag id: {}", tag_id);
+ if tag_id == 0 {
+ break;
+ }
+ let name = match Tag::read_known(stream, 8)? {
+ Tag::String(name) => name,
+ _ => panic!("Expected a string tag"),
+ };
+ println!("compound name: {}", name);
+ let tag = Tag::read_known(stream, tag_id).map_err(|_| Error::InvalidTag)?;
+ println!("aight read tag: {:?}", tag);
+ map.insert(name, tag);
+ }
+ println!("}} compound map: {:?}", map);
+ Tag::Compound(map)
+ }
+ // A length-prefixed array of signed integers. The prefix is a
+ // signed integer (thus 4 bytes) and indicates the number of 4 byte
+ // integers.
+ 11 => {
+ let length = stream.read_i32::<BE>().map_err(|_| Error::InvalidTag)?;
+ let mut ints = Vec::new();
+ for _ in 0..length {
+ ints.push(stream.read_i32::<BE>().map_err(|_| Error::InvalidTag)?);
+ }
+ Tag::IntArray(ints)
+ }
+ // A length-prefixed array of signed longs. The prefix is a signed
+ // integer (thus 4 bytes) and indicates the number of 8 byte longs.
+ 12 => {
+ let length = stream.read_i32::<BE>().map_err(|_| Error::InvalidTag)?;
+ let mut longs = Vec::new();
+ for _ in 0..length {
+ longs.push(stream.read_i64::<BE>().map_err(|_| Error::InvalidTag)?);
+ }
+ Tag::LongArray(longs)
+ }
+ _ => return Err(Error::InvalidTagType(id)),
+ };
+ Ok(tag)
+ }
+
+ pub fn read(stream: &mut impl Read) -> Result<Tag, Error> {
+ // default to compound tag
+ Tag::read_known(stream, 10)
+ }
+}