Pumpkin/pumpkin-nbt/src/deserializer.rs
Alexander Medvedev 575f17948f Inline format arguments
Looks much nicer and more readable
2025-05-10 15:22:06 +02:00

448 lines
12 KiB
Rust

use crate::*;
use io::Read;
use serde::de::{self, DeserializeSeed, IntoDeserializer, MapAccess, SeqAccess, Visitor};
use serde::{Deserialize, forward_to_deserialize_any};
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub struct NbtReadHelper<R: Read> {
reader: R,
}
impl<R: Read> NbtReadHelper<R> {
pub fn new(r: R) -> Self {
Self { reader: r }
}
}
impl<R: Read> NbtReadHelper<R> {
pub fn skip_bytes(&mut self, count: u64) -> Result<()> {
let _ = io::copy(&mut self.reader.by_ref().take(count), &mut io::sink())
.map_err(Error::Incomplete)?;
Ok(())
}
//TODO: Macroize this
pub fn get_u8_be(&mut self) -> Result<u8> {
let mut buf = [0u8];
self.reader
.read_exact(&mut buf)
.map_err(Error::Incomplete)?;
Ok(u8::from_be_bytes(buf))
}
pub fn get_i8_be(&mut self) -> Result<i8> {
let mut buf = [0u8];
self.reader
.read_exact(&mut buf)
.map_err(Error::Incomplete)?;
Ok(i8::from_be_bytes(buf))
}
pub fn get_i16_be(&mut self) -> Result<i16> {
let mut buf = [0u8; 2];
self.reader
.read_exact(&mut buf)
.map_err(Error::Incomplete)?;
Ok(i16::from_be_bytes(buf))
}
pub fn get_u16_be(&mut self) -> Result<u16> {
let mut buf = [0u8; 2];
self.reader
.read_exact(&mut buf)
.map_err(Error::Incomplete)?;
Ok(u16::from_be_bytes(buf))
}
pub fn get_i32_be(&mut self) -> Result<i32> {
let mut buf = [0u8; 4];
self.reader
.read_exact(&mut buf)
.map_err(Error::Incomplete)?;
Ok(i32::from_be_bytes(buf))
}
pub fn get_i64_be(&mut self) -> Result<i64> {
let mut buf = [0u8; 8];
self.reader
.read_exact(&mut buf)
.map_err(Error::Incomplete)?;
Ok(i64::from_be_bytes(buf))
}
pub fn get_f32_be(&mut self) -> Result<f32> {
let mut buf = [0u8; 4];
self.reader
.read_exact(&mut buf)
.map_err(Error::Incomplete)?;
Ok(f32::from_be_bytes(buf))
}
pub fn get_f64_be(&mut self) -> Result<f64> {
let mut buf = [0u8; 8];
self.reader
.read_exact(&mut buf)
.map_err(Error::Incomplete)?;
Ok(f64::from_be_bytes(buf))
}
pub fn read_boxed_slice(&mut self, count: usize) -> Result<Box<[u8]>> {
let mut buf = vec![0u8; count];
self.reader
.read_exact(&mut buf)
.map_err(Error::Incomplete)?;
Ok(buf.into())
}
}
#[derive(Debug)]
pub struct Deserializer<R: Read> {
input: NbtReadHelper<R>,
tag_to_deserialize_stack: Vec<u8>,
// Yes, this breaks with recursion. Just an attempt at a sanity check
in_list: bool,
is_named: bool,
// For debugging
key_stack: Vec<String>,
}
impl<R: Read> Deserializer<R> {
pub fn new(input: R, is_named: bool) -> Self {
Deserializer {
input: NbtReadHelper { reader: input },
tag_to_deserialize_stack: Vec::new(),
in_list: false,
is_named,
key_stack: Vec::new(),
}
}
}
/// Deserializes struct using Serde Deserializer from normal NBT
pub fn from_bytes<'a, T>(r: impl Read) -> Result<T>
where
T: Deserialize<'a>,
{
let mut deserializer = Deserializer::new(r, true);
T::deserialize(&mut deserializer)
}
/// Deserializes struct using Serde Deserializer from network NBT
pub fn from_bytes_unnamed<'a, T>(r: impl Read) -> Result<T>
where
T: Deserialize<'a>,
{
let mut deserializer = Deserializer::new(r, false);
T::deserialize(&mut deserializer)
}
impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer<R> {
type Error = Error;
forward_to_deserialize_any! {
i8 i16 i32 i64 f32 f64 char str string unit unit_struct seq tuple tuple_struct
bytes newtype_struct byte_buf
}
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let Some(tag) = self.tag_to_deserialize_stack.pop() else {
return Err(Error::SerdeError("Ignoring nothing!".to_string()));
};
NbtTag::skip_data(&mut self.input, tag)?;
visitor.visit_unit()
}
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let Some(tag_to_deserialize) = self.tag_to_deserialize_stack.pop() else {
return Err(Error::SerdeError(
"The top level must be a component (e.g. a struct)".to_string(),
));
};
match tag_to_deserialize {
END_ID => Err(Error::SerdeError(
"Trying to deserialize an END tag!".to_string(),
)),
LIST_ID | INT_ARRAY_ID | LONG_ARRAY_ID | BYTE_ARRAY_ID => {
let list_type = match tag_to_deserialize {
LIST_ID => self.input.get_u8_be()?,
INT_ARRAY_ID => INT_ID,
LONG_ARRAY_ID => LONG_ID,
BYTE_ARRAY_ID => BYTE_ID,
_ => unreachable!(),
};
let remaining_values = self.input.get_i32_be()?;
if remaining_values < 0 {
return Err(Error::NegativeLength(remaining_values));
}
let result = visitor.visit_seq(ListAccess {
de: self,
list_type,
remaining_values: remaining_values as usize,
})?;
Ok(result)
}
COMPOUND_ID => visitor.visit_map(CompoundAccess { de: self }),
_ => {
let result = match NbtTag::deserialize_data(&mut self.input, tag_to_deserialize)? {
NbtTag::Byte(value) => visitor.visit_i8::<Error>(value)?,
NbtTag::Short(value) => visitor.visit_i16::<Error>(value)?,
NbtTag::Int(value) => visitor.visit_i32::<Error>(value)?,
NbtTag::Long(value) => visitor.visit_i64::<Error>(value)?,
NbtTag::Float(value) => visitor.visit_f32::<Error>(value)?,
NbtTag::Double(value) => visitor.visit_f64::<Error>(value)?,
NbtTag::String(value) => visitor.visit_string::<Error>(value)?,
_ => unreachable!(),
};
Ok(result)
}
}
}
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
if self.in_list {
let value = self.input.get_u8_be()?;
visitor.visit_u8::<Error>(value)
} else {
Err(Error::UnsupportedType(
"u8; NBT only supports signed values".to_string(),
))
}
}
fn deserialize_u16<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
Err(Error::UnsupportedType(
"u16; NBT only supports signed values".to_string(),
))
}
fn deserialize_u32<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
Err(Error::UnsupportedType(
"u32; NBT only supports signed values".to_string(),
))
}
fn deserialize_u64<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
Err(Error::UnsupportedType(
"u64; NBT only supports signed values".to_string(),
))
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
if let Some(tag_id) = self.tag_to_deserialize_stack.last() {
if *tag_id == BYTE_ID {
let value = self.input.get_u8_be()?;
if value != 0 {
visitor.visit_bool(true)
} else {
visitor.visit_bool(false)
}
} else {
Err(Error::UnsupportedType(format!(
"Non-byte bool (found type {tag_id})"
)))
}
} else {
Err(Error::SerdeError(
"Wanted to deserialize a bool, but there was no type hint on the stack!"
.to_string(),
))
}
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
let variant = get_nbt_string(&mut self.input)?;
visitor.visit_enum(variant.into_deserializer())
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
// None is not encoded, so no need for it
visitor.visit_some(self)
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
if let Some(tag_id) = self.tag_to_deserialize_stack.pop() {
if tag_id != COMPOUND_ID {
return Err(Error::SerdeError(format!(
"Trying to deserialize a map without a compound ID ({} with id {})",
self.key_stack
.last()
.cloned()
.unwrap_or_else(|| "compound root".to_string()),
tag_id
)));
}
} else {
let next_byte = self.input.get_u8_be()?;
if next_byte != COMPOUND_ID {
return Err(Error::NoRootCompound(next_byte));
}
if self.is_named {
// Consume struct name
let _ = get_nbt_string(&mut self.input)?;
}
}
let value = visitor.visit_map(CompoundAccess { de: self })?;
Ok(value)
}
fn deserialize_struct<V>(
self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_map(visitor)
}
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let str = get_nbt_string(&mut self.input)?;
visitor.visit_string(str)
}
fn is_human_readable(&self) -> bool {
false
}
}
struct CompoundAccess<'a, R: Read> {
de: &'a mut Deserializer<R>,
}
impl<'de, R: Read> MapAccess<'de> for CompoundAccess<'_, R> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
where
K: DeserializeSeed<'de>,
{
let tag = self.de.input.get_u8_be()?;
self.de.tag_to_deserialize_stack.push(tag);
if tag == END_ID {
return Ok(None);
}
seed.deserialize(MapKey { de: self.de }).map(Some)
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where
V: DeserializeSeed<'de>,
{
let result = seed.deserialize(&mut *self.de);
self.de.key_stack.pop();
result
}
}
struct MapKey<'a, R: Read> {
de: &'a mut Deserializer<R>,
}
impl<'de, R: Read> de::Deserializer<'de> for MapKey<'_, R> {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
where
V: de::Visitor<'de>,
{
let key = get_nbt_string(&mut self.de.input)?;
self.de.key_stack.push(key.clone());
visitor.visit_string(key)
}
forward_to_deserialize_any! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit unit_struct seq tuple tuple_struct map
struct identifier ignored_any bytes enum newtype_struct byte_buf option
}
}
struct ListAccess<'a, R: Read> {
de: &'a mut Deserializer<R>,
remaining_values: usize,
list_type: u8,
}
impl<'de, R: Read> SeqAccess<'de> for ListAccess<'_, R> {
type Error = Error;
fn size_hint(&self) -> Option<usize> {
Some(self.remaining_values)
}
fn next_element_seed<E>(&mut self, seed: E) -> Result<Option<E::Value>>
where
E: DeserializeSeed<'de>,
{
if self.remaining_values == 0 {
return Ok(None);
}
self.remaining_values -= 1;
self.de.tag_to_deserialize_stack.push(self.list_type);
self.de.in_list = true;
let result = seed.deserialize(&mut *self.de).map(Some);
self.de.in_list = false;
result
}
}