use std::{io::Write, mem};
use byteorder::{BigEndian, WriteBytesExt};
use serde::{
ser::{self, Impossible, SerializeTuple},
Serialize,
};
use crate::{
error::{Error, Result},
Tag, BYTE_ARRAY_TOKEN, INT_ARRAY_TOKEN, LONG_ARRAY_TOKEN,
};
use super::{
array_serializer::ArraySerializer, name_serializer::NameSerializer, write_nbt::WriteNbt,
};
enum DelayedHeader {
List { len: usize }, MapEntry { outer_name: Vec<u8> }, Root { root_name: String }, }
pub struct Serializer<W: Write> {
pub(crate) writer: W,
pub(crate) root_name: String,
}
macro_rules! no_root {
($v:ident, $t:ty) => {
fn $v(self, _: $t) -> Result<()> {
Err(Error::no_root_compound())
}
};
}
impl<'a, W: 'a + Write> serde::ser::Serializer for &'a mut Serializer<W> {
type Ok = ();
type Error = Error;
type SerializeSeq = SerializerTuple<'a, W>;
type SerializeTuple = SerializerTuple<'a, W>;
type SerializeTupleStruct = SerializerTuple<'a, W>;
type SerializeTupleVariant = SerializerTuple<'a, W>;
type SerializeMap = SerializerMap<'a, W>;
type SerializeStruct = SerializerMap<'a, W>;
type SerializeStructVariant = Impossible<(), Error>;
no_root!(serialize_bool, bool);
no_root!(serialize_i8, i8);
no_root!(serialize_i16, i16);
no_root!(serialize_i32, i32);
no_root!(serialize_i64, i64);
no_root!(serialize_i128, i128);
no_root!(serialize_u8, u8);
no_root!(serialize_u16, u16);
no_root!(serialize_u32, u32);
no_root!(serialize_u64, u64);
no_root!(serialize_u128, u128);
no_root!(serialize_f32, f32);
no_root!(serialize_f64, f64);
no_root!(serialize_char, char);
no_root!(serialize_str, &str);
no_root!(serialize_bytes, &[u8]);
no_root!(serialize_unit_struct, &'static str);
fn serialize_none(self) -> Result<()> {
Err(Error::no_root_compound())
}
fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<()>
where
T: Serialize,
{
Err(Error::no_root_compound())
}
fn serialize_unit(self) -> Result<()> {
Err(Error::no_root_compound())
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
) -> Result<()> {
Err(Error::no_root_compound())
}
fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> Result<()>
where
T: Serialize,
{
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &T,
) -> Result<()>
where
T: Serialize,
{
Err(Error::no_root_compound())
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
Err(Error::no_root_compound())
}
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
Err(Error::no_root_compound())
}
fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleStruct> {
Err(Error::no_root_compound())
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant> {
Err(Error::no_root_compound())
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
let root_name = mem::take(&mut self.root_name);
Ok(SerializerMap {
ser: self,
key: None,
header: Some(DelayedHeader::Root { root_name }),
trailer: Some(Tag::End),
})
}
fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
self.serialize_map(Some(len))
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant> {
Err(Error::no_root_compound())
}
}
pub struct SerializerMap<'a, W: Write> {
ser: &'a mut Serializer<W>,
key: Option<Vec<u8>>,
header: Option<DelayedHeader>,
trailer: Option<Tag>,
}
fn write_header(writer: &mut impl Write, header: DelayedHeader, actual_tag: Tag) -> Result<()> {
match header {
DelayedHeader::Root {
root_name: outer_name,
} => {
if actual_tag != Tag::Compound {
return Err(Error::no_root_compound());
}
writer.write_tag(Tag::Compound)?;
writer.write_size_prefixed_str(&outer_name)?;
}
DelayedHeader::MapEntry { ref outer_name } => {
writer.write_tag(actual_tag)?;
writer.write_u16::<BigEndian>(outer_name.len() as u16)?;
writer.write_all(outer_name)?;
}
DelayedHeader::List { len } => {
writer.write_tag(actual_tag)?;
writer.write_len(len)?;
}
};
Ok(())
}
impl<'a, W: Write> serde::ser::SerializeMap for SerializerMap<'a, W> {
type Ok = ();
type Error = Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<()>
where
T: serde::Serialize,
{
let mut name = Vec::new();
key.serialize(&mut NameSerializer { name: &mut name })?;
self.key = Some(name);
Ok(())
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<()>
where
T: serde::Serialize,
{
let name = self.key.take().ok_or_else(|| {
Error::bespoke("serialize_value called before serialize_key".to_string())
})?;
let outer_tag = match std::str::from_utf8(&name) {
Ok(BYTE_ARRAY_TOKEN) => Tag::ByteArray,
Ok(INT_ARRAY_TOKEN) => Tag::IntArray,
Ok(LONG_ARRAY_TOKEN) => Tag::LongArray,
_ => Tag::Compound,
};
if let Some(header) = self.header.take() {
write_header(&mut self.ser.writer, header, outer_tag)?;
}
match std::str::from_utf8(&name) {
Ok(BYTE_ARRAY_TOKEN) => {
self.trailer = None;
value.serialize(ArraySerializer {
ser: self.ser,
tag: Tag::ByteArray,
})
}
Ok(INT_ARRAY_TOKEN) => {
self.trailer = None;
value.serialize(ArraySerializer {
ser: self.ser,
tag: Tag::IntArray,
})
}
Ok(LONG_ARRAY_TOKEN) => {
self.trailer = None;
value.serialize(ArraySerializer {
ser: self.ser,
tag: Tag::LongArray,
})
}
_ => value.serialize(&mut Delayed {
ser: &mut *self.ser,
header: Some(DelayedHeader::MapEntry { outer_name: name }),
is_list: false,
}),
}
}
fn end(mut self) -> Result<()> {
if let Some(tag) = self.trailer {
if let Some(header) = self.header.take() {
write_header(&mut self.ser.writer, header, Tag::Compound)?;
}
self.ser.writer.write_tag(tag)?;
}
Ok(())
}
}
impl<'a, W: Write> serde::ser::SerializeStruct for SerializerMap<'a, W> {
type Ok = ();
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<()>
where
T: serde::Serialize,
{
ser::SerializeMap::serialize_entry(self, key, value)
}
fn end(self) -> Result<()> {
ser::SerializeMap::end(self)
}
}
pub struct SerializerTuple<'a, W: Write> {
pub(crate) ser: &'a mut Serializer<W>,
pub(crate) len: usize,
pub(crate) first: bool,
}
impl<'a, W: 'a + Write> serde::ser::SerializeSeq for SerializerTuple<'a, W> {
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<()>
where
T: Serialize,
{
<Self as serde::ser::SerializeTuple>::serialize_element(self, value)
}
fn end(self) -> Result<()> {
<Self as serde::ser::SerializeTuple>::end(self)
}
}
impl<'a, W: 'a + Write> serde::ser::SerializeTuple for SerializerTuple<'a, W> {
type Ok = ();
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<()>
where
T: Serialize,
{
value.serialize(&mut Delayed {
ser: self.ser,
header: self.first.then_some(DelayedHeader::List { len: self.len }),
is_list: true,
})?;
self.first = false;
Ok(())
}
fn end(self) -> Result<()> {
Ok(())
}
}
impl<'a, W: 'a + Write> serde::ser::SerializeTupleStruct for SerializerTuple<'a, W> {
type Ok = ();
type Error = Error;
fn end(self) -> Result<()> {
Ok(())
}
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<()>
where
T: Serialize,
{
self.serialize_element(value)
}
}
impl<'a, W: 'a + Write> serde::ser::SerializeTupleVariant for SerializerTuple<'a, W> {
type Ok = ();
type Error = Error;
fn end(self) -> Result<()> {
Ok(())
}
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<()>
where
T: Serialize,
{
self.serialize_element(value)
}
}
struct Delayed<'a, W: Write + 'a> {
ser: &'a mut Serializer<W>,
header: Option<DelayedHeader>,
is_list: bool,
}
impl<'a, W: Write + 'a> Delayed<'a, W> {
fn write_header(&mut self, tag: Tag) -> Result<()> {
if let Some(header) = self.header.take() {
write_header(&mut self.ser.writer, header, tag)?;
}
Ok(())
}
}
impl<'a, W: 'a + Write> serde::ser::Serializer for &'a mut Delayed<'a, W> {
type Ok = ();
type Error = Error;
type SerializeSeq = SerializerTuple<'a, W>;
type SerializeTuple = SerializerTuple<'a, W>;
type SerializeTupleStruct = SerializerTuple<'a, W>;
type SerializeTupleVariant = SerializerTuple<'a, W>;
type SerializeMap = SerializerMap<'a, W>;
type SerializeStruct = SerializerMap<'a, W>;
type SerializeStructVariant = Impossible<(), Error>;
fn serialize_bool(self, v: bool) -> Result<()> {
self.write_header(Tag::Byte)?;
self.ser.serialize_bool(v)
}
fn serialize_i8(self, v: i8) -> Result<()> {
self.write_header(Tag::Byte)?;
self.ser.writer.write_i8(v)?;
Ok(())
}
fn serialize_i16(self, v: i16) -> Result<()> {
self.write_header(Tag::Short)?;
self.ser.writer.write_i16::<BigEndian>(v)?;
Ok(())
}
fn serialize_i32(self, v: i32) -> Result<()> {
self.write_header(Tag::Int)?;
self.ser.writer.write_i32::<BigEndian>(v)?;
Ok(())
}
fn serialize_i64(self, v: i64) -> Result<()> {
self.write_header(Tag::Long)?;
self.ser.writer.write_i64::<BigEndian>(v)?;
Ok(())
}
fn serialize_i128(self, v: i128) -> Result<()> {
self.serialize_u128(v as u128)
}
fn serialize_u128(self, v: u128) -> Result<()> {
self.write_header(Tag::IntArray)?;
self.ser.writer.write_len(4)?;
self.ser.writer.write_u32::<BigEndian>((v >> 96) as u32)?;
self.ser.writer.write_u32::<BigEndian>((v >> 64) as u32)?;
self.ser.writer.write_u32::<BigEndian>((v >> 32) as u32)?;
self.ser.writer.write_u32::<BigEndian>(v as u32)?;
Ok(())
}
fn serialize_u8(self, v: u8) -> Result<()> {
self.write_header(Tag::Byte)?;
self.ser.writer.write_u8(v)?;
Ok(())
}
fn serialize_u16(self, v: u16) -> Result<()> {
self.write_header(Tag::Short)?;
self.ser.writer.write_u16::<BigEndian>(v)?;
Ok(())
}
fn serialize_u32(self, v: u32) -> Result<()> {
self.write_header(Tag::Int)?;
self.ser.writer.write_u32::<BigEndian>(v)?;
Ok(())
}
fn serialize_u64(self, v: u64) -> Result<()> {
self.write_header(Tag::Long)?;
self.ser.writer.write_u64::<BigEndian>(v)?;
Ok(())
}
fn serialize_f32(self, v: f32) -> Result<()> {
self.write_header(Tag::Float)?;
self.ser.writer.write_f32::<BigEndian>(v)?;
Ok(())
}
fn serialize_f64(self, v: f64) -> Result<()> {
self.write_header(Tag::Double)?;
self.ser.writer.write_f64::<BigEndian>(v)?;
Ok(())
}
fn serialize_char(self, v: char) -> Result<()> {
self.write_header(Tag::Int)?;
self.ser.writer.write_u32::<BigEndian>(v as u32)?;
Ok(())
}
fn serialize_str(self, v: &str) -> Result<()> {
self.write_header(Tag::String)?;
self.ser.writer.write_size_prefixed_str(v)?;
Ok(())
}
fn serialize_bytes(self, v: &[u8]) -> Result<()> {
self.write_header(Tag::List)?;
self.ser.writer.write_tag(Tag::Byte)?;
self.ser.writer.write_len(v.len())?;
self.ser.writer.write_all(v)?;
Ok(())
}
fn serialize_none(self) -> Result<()> {
if self.is_list {
Err(Error::bespoke("cannot serialize None in list".to_string()))
} else {
Ok(())
}
}
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<()>
where
T: Serialize,
{
value.serialize(self)
}
fn serialize_unit(self) -> Result<()> {
Err(Error::bespoke("cannot serialize unit: ()".to_string()))
}
fn serialize_unit_struct(self, name: &'static str) -> Result<()> {
Err(Error::bespoke(format!(
"cannot serialize unit struct: {name}"
)))
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> Result<()> {
self.write_header(Tag::String)?;
self.ser.writer.write_size_prefixed_str(variant)
}
fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> Result<()>
where
T: Serialize,
{
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &T,
) -> Result<()>
where
T: Serialize,
{
Err(Error::bespoke(
"cannot serialize newtype variant, please open fastnbt issue".to_string(),
))
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
let len =
len.ok_or_else(|| Error::bespoke("sequences must have a known length".to_string()))?;
self.serialize_tuple(len)
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
self.write_header(Tag::List)?;
if len == 0 {
self.ser.writer.write_tag(Tag::End)?;
self.ser.writer.write_u32::<BigEndian>(0)?; }
Ok(SerializerTuple {
ser: self.ser,
first: true,
len,
})
}
fn serialize_tuple_struct(
self,
_name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct> {
self.serialize_tuple(len)
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant> {
self.serialize_seq(Some(len))
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
Ok(SerializerMap {
ser: self.ser,
key: None,
header: self.header.take(),
trailer: Some(Tag::End),
})
}
fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
self.serialize_map(Some(len))
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant> {
Err(Error::bespoke(
"cannot serialize struct variant, please open fastnbt issue".to_string(),
))
}
}