Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix our NBT serde #549

Merged
merged 12 commits into from
Feb 16, 2025
102 changes: 71 additions & 31 deletions pumpkin-nbt/src/compound.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::deserializer::ReadAdaptor;
use crate::serializer::WriteAdaptor;
use crate::tag::NbtTag;
use crate::{get_nbt_string, Error, Nbt, END_ID};
use bytes::{Buf, BufMut, Bytes, BytesMut};
use std::io::{Cursor, Write};
use std::io::{ErrorKind, Read, Write};
use std::vec::IntoIter;

#[derive(Clone, Debug, Default, PartialEq, PartialOrd)]
Expand All @@ -16,46 +17,85 @@ impl NbtCompound {
}
}

pub fn deserialize_content(bytes: &mut impl Buf) -> Result<NbtCompound, Error> {
let mut compound = NbtCompound::new();

while bytes.has_remaining() {
let tag_id = bytes.get_u8();
pub fn skip_content<R>(reader: &mut ReadAdaptor<R>) -> Result<(), Error>
where
R: Read,
{
loop {
let tag_id = match reader.get_u8_be() {
Ok(id) => id,
Err(err) => match err {
Error::Incomplete(err) => match err.kind() {
ErrorKind::UnexpectedEof => {
break;
}
_ => {
return Err(Error::Incomplete(err));
}
},
_ => {
return Err(err);
}
},
};
if tag_id == END_ID {
break;
}

let name = get_nbt_string(bytes).map_err(|_| Error::Cesu8DecodingError)?;
let len = reader.get_u16_be()?;
reader.skip_bytes(len as u64)?;

NbtTag::skip_data(reader, tag_id)?;
}

Ok(())
}

if let Ok(tag) = NbtTag::deserialize_data(bytes, tag_id) {
compound.put(&name, tag);
} else {
pub fn deserialize_content<R>(reader: &mut ReadAdaptor<R>) -> Result<NbtCompound, Error>
where
R: Read,
{
let mut compound = NbtCompound::new();

loop {
let tag_id = match reader.get_u8_be() {
Ok(id) => id,
Err(err) => match err {
Error::Incomplete(err) => match err.kind() {
ErrorKind::UnexpectedEof => {
break;
}
_ => {
return Err(Error::Incomplete(err));
}
},
_ => {
return Err(err);
}
},
};
if tag_id == END_ID {
break;
}

let name = get_nbt_string(reader)?;
let tag = NbtTag::deserialize_data(reader, tag_id)?;
compound.put(&name, tag);
}

Ok(compound)
}

pub fn deserialize_content_from_cursor(
cursor: &mut Cursor<&[u8]>,
) -> Result<NbtCompound, Error> {
Self::deserialize_content(cursor)
}

pub fn serialize_content(&self) -> Bytes {
let mut bytes = BytesMut::new();
pub fn serialize_content<W>(&self, w: &mut WriteAdaptor<W>) -> Result<(), Error>
where
W: Write,
{
for (name, tag) in &self.child_tags {
bytes.put_u8(tag.get_type_id());
bytes.put(NbtTag::String(name.clone()).serialize_data());
bytes.put(tag.serialize_data());
w.write_u8_be(tag.get_type_id())?;
NbtTag::String(name.clone()).serialize_data(w)?;
tag.serialize_data(w)?;
}
bytes.put_u8(END_ID);
bytes.freeze()
}

pub fn serialize_content_to_writer<W: Write>(&self, mut writer: W) -> std::io::Result<()> {
writer.write_all(&self.serialize_content())?;
w.write_u8_be(END_ID)?;
Ok(())
}

Expand Down Expand Up @@ -139,19 +179,19 @@ impl NbtCompound {
self.get(name).and_then(|tag| tag.extract_string())
}

pub fn get_list(&self, name: &str) -> Option<&Vec<NbtTag>> {
pub fn get_list(&self, name: &str) -> Option<&[NbtTag]> {
self.get(name).and_then(|tag| tag.extract_list())
}

pub fn get_compound(&self, name: &str) -> Option<&NbtCompound> {
self.get(name).and_then(|tag| tag.extract_compound())
}

pub fn get_int_array(&self, name: &str) -> Option<&Vec<i32>> {
pub fn get_int_array(&self, name: &str) -> Option<&[i32]> {
self.get(name).and_then(|tag| tag.extract_int_array())
}

pub fn get_long_array(&self, name: &str) -> Option<&Vec<i64>> {
pub fn get_long_array(&self, name: &str) -> Option<&[i64]> {
self.get(name).and_then(|tag| tag.extract_long_array())
}
}
Expand Down
Loading