use super::formatter::Formatter;
use super::serializer::Serializer;
use super::wrapper::{DataSerializer, MapKeySerializer, SeqSerializer};
use crate::error::{Error, Result};
use crate::io;
use serde::ser::{
Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
SerializeTupleStruct, SerializeTupleVariant,
};
#[doc(hidden)]
#[derive(Eq, PartialEq)]
pub(crate) enum State {
Empty,
Initial,
First,
Rest,
RestNoClose,
}
#[doc(hidden)]
pub(crate) enum Compound<'a, W: 'a, F: 'a> {
Map {
ser: &'a mut Serializer<W, F>,
state: State,
},
#[cfg(feature = "arbitrary_precision")]
Number { ser: &'a mut Serializer<W, F> },
#[cfg(feature = "raw_value")]
RawValue { ser: &'a mut Serializer<W, F> },
}
impl<'a, W, F> SerializeSeq for Compound<'a, W, F>
where
W: io::Write,
F: Formatter,
{
type Ok = ();
type Error = Error;
#[inline]
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
match self {
Compound::Map { ser, state } => {
match *state {
State::First => *state = State::Rest,
State::Initial => *state = State::RestNoClose,
_ => {
ser.formatter
.begin_array_value(&mut ser.writer)
.map_err(Error::io)?;
}
}
value.serialize(SeqSerializer { ser: *ser })?;
ser.formatter
.end_array_value(&mut ser.writer)
.map_err(Error::io)
}
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
#[cfg(feature = "raw_value")]
Compound::RawValue { .. } => unreachable!(),
}
}
#[inline]
fn end(self) -> Result<()> {
match self {
Compound::Map { ser, state } => match state {
State::Empty => Ok(()),
State::RestNoClose => Ok(()),
_ => ser.formatter.end_array(&mut ser.writer).map_err(Error::io),
},
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
#[cfg(feature = "raw_value")]
Compound::RawValue { .. } => unreachable!(),
}
}
}
impl<'a, W, F> SerializeTuple for Compound<'a, W, F>
where
W: io::Write,
F: Formatter,
{
type Ok = ();
type Error = Error;
#[inline]
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
SerializeSeq::serialize_element(self, value)
}
#[inline]
fn end(self) -> Result<()> {
SerializeSeq::end(self)
}
}
impl<'a, W, F> SerializeTupleStruct for Compound<'a, W, F>
where
W: io::Write,
F: Formatter,
{
type Ok = ();
type Error = Error;
#[inline]
fn serialize_field<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
SerializeSeq::serialize_element(self, value)
}
#[inline]
fn end(self) -> Result<()> {
SerializeSeq::end(self)
}
}
impl<'a, W, F> SerializeTupleVariant for Compound<'a, W, F>
where
W: io::Write,
F: Formatter,
{
type Ok = ();
type Error = Error;
#[inline]
fn serialize_field<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
SerializeSeq::serialize_element(self, value)
}
#[inline]
fn end(self) -> Result<()> {
match self {
Compound::Map { ser, state } => {
match state {
State::Empty => {}
State::RestNoClose => {}
_ => ser
.formatter
.end_array(&mut ser.writer)
.map_err(Error::io)?,
}
ser.formatter.end_data(&mut ser.writer).map_err(Error::io)?;
ser.formatter.end_object(&mut ser.writer).map_err(Error::io)
}
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
#[cfg(feature = "raw_value")]
Compound::RawValue { .. } => unreachable!(),
}
}
}
impl<'a, W, F> SerializeMap for Compound<'a, W, F>
where
W: io::Write,
F: Formatter,
{
type Ok = ();
type Error = Error;
#[inline]
fn serialize_key<T>(&mut self, key: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
match self {
Compound::Map { ser, state } => {
match *state {
State::First => *state = State::Rest,
State::Initial => *state = State::RestNoClose,
_ => {
ser.formatter
.begin_data_key(&mut ser.writer, false)
.map_err(Error::io)?;
}
}
key.serialize(MapKeySerializer { ser: *ser })?;
ser.formatter
.end_data_key(&mut ser.writer)
.map_err(Error::io)
}
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
#[cfg(feature = "raw_value")]
Compound::RawValue { .. } => unreachable!(),
}
}
#[inline]
fn serialize_value<T>(&mut self, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
match self {
Compound::Map { ser, .. } => {
value.serialize(DataSerializer { ser: *ser })?;
ser.formatter.end_data(&mut ser.writer).map_err(Error::io)
}
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
#[cfg(feature = "raw_value")]
Compound::RawValue { .. } => unreachable!(),
}
}
#[inline]
fn end(self) -> Result<()> {
match self {
Compound::Map { ser, state } => match state {
State::Empty => Ok(()),
State::RestNoClose => Ok(()),
_ => ser.formatter.end_object(&mut ser.writer).map_err(Error::io),
},
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
#[cfg(feature = "raw_value")]
Compound::RawValue { .. } => unreachable!(),
}
}
}
impl<'a, W, F> SerializeStruct for Compound<'a, W, F>
where
W: io::Write,
F: Formatter,
{
type Ok = ();
type Error = Error;
#[inline]
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
match self {
Compound::Map { .. } => SerializeMap::serialize_entry(self, key, value),
#[cfg(feature = "arbitrary_precision")]
Compound::Number { ser, .. } => {
if key == crate::number::TOKEN {
value.serialize(NumberStrEmitter(ser))
} else {
Err(invalid_number())
}
}
#[cfg(feature = "raw_value")]
Compound::RawValue { ser, .. } => {
if key == crate::raw::TOKEN {
value.serialize(RawValueStrEmitter(ser))
} else {
Err(invalid_raw_value())
}
}
}
}
#[inline]
fn end(self) -> Result<()> {
match self {
Compound::Map { .. } => SerializeMap::end(self),
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => Ok(()),
#[cfg(feature = "raw_value")]
Compound::RawValue { .. } => Ok(()),
}
}
}
impl<'a, W, F> SerializeStructVariant for Compound<'a, W, F>
where
W: io::Write,
F: Formatter,
{
type Ok = ();
type Error = Error;
#[inline]
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
where
T: ?Sized + Serialize,
{
match *self {
Compound::Map { .. } => SerializeStruct::serialize_field(self, key, value),
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
#[cfg(feature = "raw_value")]
Compound::RawValue { .. } => unreachable!(),
}
}
#[inline]
fn end(self) -> Result<()> {
match self {
Compound::Map { ser, state } => {
match state {
State::Empty => {}
State::RestNoClose => {}
_ => ser
.formatter
.end_object(&mut ser.writer)
.map_err(Error::io)?,
}
ser.formatter.end_data(&mut ser.writer).map_err(Error::io)?;
ser.formatter.end_object(&mut ser.writer).map_err(Error::io)
}
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
#[cfg(feature = "raw_value")]
Compound::RawValue { .. } => unreachable!(),
}
}
}