use crate::*; use bytes::Buf; use serde::de::{self, DeserializeSeed, MapAccess, SeqAccess, Visitor}; use serde::{forward_to_deserialize_any, Deserialize}; use std::io::Cursor; pub type Result = std::result::Result; #[derive(Debug)] pub struct Deserializer<'de, T> { input: &'de mut T, tag_to_deserialize: Option, is_named: bool, } impl<'de, T: Buf> Deserializer<'de, T> { pub fn new(input: &'de mut T, is_named: bool) -> Self { Deserializer { input, tag_to_deserialize: None, is_named, } } } /// Deserializes struct using Serde Deserializer from normal NBT pub fn from_bytes<'a, T>(s: &'a mut impl Buf) -> Result where T: Deserialize<'a>, { let mut deserializer = Deserializer::new(s, true); T::deserialize(&mut deserializer) } /// Deserializes struct using Serde Deserializer from normal NBT pub fn from_bytes_unnamed<'a, T>(s: &'a mut impl Buf) -> Result where T: Deserialize<'a>, { let mut deserializer = Deserializer::new(s, false); T::deserialize(&mut deserializer) } pub fn from_cursor<'a, T>(cursor: &'a mut Cursor<&[u8]>) -> Result where T: Deserialize<'a>, { let mut deserializer = Deserializer::new(cursor, true); T::deserialize(&mut deserializer) } pub fn from_cursor_unnamed<'a, T>(cursor: &'a mut Cursor<&[u8]>) -> Result where T: Deserialize<'a>, { let mut deserializer = Deserializer::new(cursor, false); T::deserialize(&mut deserializer) } impl<'de, T: Buf> de::Deserializer<'de> for &mut Deserializer<'de, T> { type Error = Error; forward_to_deserialize_any!(i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 seq char str string bytes byte_buf tuple tuple_struct enum ignored_any unit unit_struct option newtype_struct); fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { let tag_to_deserialize = self.tag_to_deserialize.unwrap(); let list_type = match tag_to_deserialize { LIST_ID => Some(self.input.get_u8()), INT_ARRAY_ID => Some(INT_ID), LONG_ARRAY_ID => Some(LONG_ID), BYTE_ARRAY_ID => Some(BYTE_ID), _ => None, }; if let Some(list_type) = list_type { let remaining_values = self.input.get_u32(); return visitor.visit_seq(ListAccess { de: self, list_type, remaining_values, }); } let result: Result = Ok( match NbtTag::deserialize_data(self.input, tag_to_deserialize)? { NbtTag::Byte(value) => visitor.visit_i8::(value)?, NbtTag::Short(value) => visitor.visit_i16::(value)?, NbtTag::Int(value) => visitor.visit_i32::(value)?, NbtTag::Long(value) => visitor.visit_i64::(value)?, NbtTag::Float(value) => visitor.visit_f32::(value)?, NbtTag::Double(value) => visitor.visit_f64::(value)?, NbtTag::String(value) => visitor.visit_string::(value)?, _ => unreachable!(), }, ); self.tag_to_deserialize = None; result } fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>, { if self.tag_to_deserialize.unwrap() == BYTE_ID { let value = self.input.get_u8(); if value != 0 { return visitor.visit_bool(true); } } visitor.visit_bool(false) } fn deserialize_map(self, visitor: V) -> Result where V: Visitor<'de>, { if self.tag_to_deserialize.is_none() { let next_byte = self.input.get_u8(); if next_byte != COMPOUND_ID { return Err(Error::NoRootCompound(next_byte)); } if self.is_named { // Consume struct name NbtTag::deserialize(self.input)?; } } let value = visitor.visit_map(CompoundAccess { de: self })?; Ok(value) } fn deserialize_struct( self, _name: &'static str, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.deserialize_map(visitor) } fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { let str = get_nbt_string(&mut self.input).map_err(|_| Error::Cesu8DecodingError)?; visitor.visit_string(str) } fn is_human_readable(&self) -> bool { false } } struct CompoundAccess<'a, 'de: 'a, T: Buf> { de: &'a mut Deserializer<'de, T>, } impl<'de, T: Buf> MapAccess<'de> for CompoundAccess<'_, 'de, T> { type Error = Error; fn next_key_seed(&mut self, seed: K) -> Result> where K: DeserializeSeed<'de>, { let tag = self.de.input.get_u8(); self.de.tag_to_deserialize = Some(tag); if tag == END_ID { return Ok(None); } seed.deserialize(&mut *self.de).map(Some) } fn next_value_seed(&mut self, seed: V) -> Result where V: DeserializeSeed<'de>, { seed.deserialize(&mut *self.de) } } struct ListAccess<'a, 'de: 'a, T: Buf> { de: &'a mut Deserializer<'de, T>, remaining_values: u32, list_type: u8, } impl<'de, T: Buf> SeqAccess<'de> for ListAccess<'_, 'de, T> { type Error = Error; fn next_element_seed(&mut self, seed: E) -> Result> where E: DeserializeSeed<'de>, { if self.remaining_values == 0 { return Ok(None); } self.remaining_values -= 1; self.de.tag_to_deserialize = Some(self.list_type); seed.deserialize(&mut *self.de).map(Some) } }