use crate::{
de::{INNER_VALUE, UNFLATTEN_PREFIX},
errors::{serialize::DeError, Error},
events::{BytesEnd, BytesStart, Event},
se::key::XmlNameSerializer,
se::Serializer,
writer::Writer,
};
use serde::ser::{self, Serialize};
use serde::Serializer as _;
use std::io::Write;
pub struct Map<'r, 'w, W>
where
W: 'w + Write,
{
parent: &'w mut Serializer<'r, W>,
}
impl<'r, 'w, W> Map<'r, 'w, W>
where
W: 'w + Write,
{
pub fn new(parent: &'w mut Serializer<'r, W>) -> Self {
Map { parent }
}
}
impl<'r, 'w, W> ser::SerializeMap for Map<'r, 'w, W>
where
W: 'w + Write,
{
type Ok = ();
type Error = DeError;
fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<(), DeError> {
write!(self.parent.writer.inner(), "<enum key=\"").map_err(Error::Io)?;
key.serialize(&mut *self.parent)?;
write!(self.parent.writer.inner(), "\"/>").map_err(Error::Io)?;
Ok(())
}
fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), DeError> {
value.serialize(&mut *self.parent)
}
fn end(self) -> Result<Self::Ok, DeError> {
if let Some(tag) = self.parent.root_tag {
self.parent
.writer
.write_event(Event::End(BytesEnd::new(tag)))?;
}
Ok(())
}
fn serialize_entry<K: ?Sized + Serialize, V: ?Sized + Serialize>(
&mut self,
key: &K,
value: &V,
) -> Result<(), DeError> {
let key = key.serialize(XmlNameSerializer {
writer: String::new(),
})?;
let writer = self.parent.writer.inner();
writer.write_all(b"<").map_err(Error::Io)?;
writer.write_all(key.as_bytes()).map_err(Error::Io)?;
writer.write_all(b">").map_err(Error::Io)?;
value.serialize(&mut *self.parent)?;
let writer = self.parent.writer.inner();
writer.write_all(b"</").map_err(Error::Io)?;
writer.write_all(key.as_bytes()).map_err(Error::Io)?;
writer.write_all(b">").map_err(Error::Io)?;
Ok(())
}
}
pub struct Struct<'r, 'w, W>
where
W: 'w + Write,
{
parent: &'w mut Serializer<'r, W>,
attrs: BytesStart<'w>,
children: Vec<u8>,
buffer: Vec<u8>,
}
impl<'r, 'w, W> Struct<'r, 'w, W>
where
W: 'w + Write,
{
pub fn new(parent: &'w mut Serializer<'r, W>, name: &'r str) -> Self {
Struct {
parent,
attrs: BytesStart::new(name),
children: Vec::new(),
buffer: Vec::new(),
}
}
}
impl<'r, 'w, W> ser::SerializeStruct for Struct<'r, 'w, W>
where
W: 'w + Write,
{
type Ok = ();
type Error = DeError;
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), DeError> {
let writer = Writer::new(&mut self.buffer);
if key.starts_with(UNFLATTEN_PREFIX) {
let key = &key[UNFLATTEN_PREFIX.len()..];
let mut serializer = Serializer::with_root(writer, Some(key));
serializer.serialize_newtype_struct(key, value)?;
self.children.append(&mut self.buffer);
} else {
let mut serializer = Serializer::with_root(writer, Some(key));
value.serialize(&mut serializer)?;
if !self.buffer.is_empty() {
if self.buffer[0] == b'<' || key == INNER_VALUE {
self.children.append(&mut self.buffer);
} else {
self.attrs
.push_attribute((key.as_bytes(), self.buffer.as_ref()));
self.buffer.clear();
}
}
}
Ok(())
}
fn end(self) -> Result<Self::Ok, DeError> {
if self.children.is_empty() {
self.parent.writer.write_event(Event::Empty(self.attrs))?;
} else {
self.parent
.writer
.write_event(Event::Start(self.attrs.borrow()))?;
self.parent.writer.write(&self.children)?;
self.parent
.writer
.write_event(Event::End(self.attrs.to_end()))?;
}
Ok(())
}
}
impl<'r, 'w, W> ser::SerializeStructVariant for Struct<'r, 'w, W>
where
W: 'w + Write,
{
type Ok = ();
type Error = DeError;
#[inline]
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Self::Error> {
<Self as ser::SerializeStruct>::serialize_field(self, key, value)
}
#[inline]
fn end(self) -> Result<Self::Ok, Self::Error> {
<Self as ser::SerializeStruct>::end(self)
}
}
pub struct Seq<'r, 'w, W>
where
W: 'w + Write,
{
parent: &'w mut Serializer<'r, W>,
}
impl<'r, 'w, W> Seq<'r, 'w, W>
where
W: 'w + Write,
{
pub fn new(parent: &'w mut Serializer<'r, W>) -> Self {
Seq { parent }
}
}
impl<'r, 'w, W> ser::SerializeSeq for Seq<'r, 'w, W>
where
W: 'w + Write,
{
type Ok = ();
type Error = DeError;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
value.serialize(&mut *self.parent)?;
Ok(())
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(())
}
}
pub struct Tuple<'r, 'w, W>
where
W: 'w + Write,
{
parent: &'w mut Serializer<'r, W>,
name: &'r str,
}
impl<'r, 'w, W> Tuple<'r, 'w, W>
where
W: 'w + Write,
{
pub fn new(parent: &'w mut Serializer<'r, W>, name: &'r str) -> Self {
Tuple { parent, name }
}
}
impl<'r, 'w, W> ser::SerializeTuple for Tuple<'r, 'w, W>
where
W: 'w + Write,
{
type Ok = ();
type Error = DeError;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
write!(self.parent.writer.inner(), "<{}>", self.name).map_err(Error::Io)?;
value.serialize(&mut *self.parent)?;
write!(self.parent.writer.inner(), "</{}>", self.name).map_err(Error::Io)?;
Ok(())
}
#[inline]
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(())
}
}
impl<'r, 'w, W> ser::SerializeTupleStruct for Tuple<'r, 'w, W>
where
W: 'w + Write,
{
type Ok = ();
type Error = DeError;
#[inline]
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
<Self as ser::SerializeTuple>::serialize_element(self, value)
}
#[inline]
fn end(self) -> Result<Self::Ok, Self::Error> {
<Self as ser::SerializeTuple>::end(self)
}
}
impl<'r, 'w, W> ser::SerializeTupleVariant for Tuple<'r, 'w, W>
where
W: 'w + Write,
{
type Ok = ();
type Error = DeError;
#[inline]
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
<Self as ser::SerializeTuple>::serialize_element(self, value)
}
#[inline]
fn end(self) -> Result<Self::Ok, Self::Error> {
<Self as ser::SerializeTuple>::end(self)
}
}
#[test]
fn test_serialize_map_entries() {
use serde::ser::SerializeMap;
let mut buffer = Vec::new();
{
let mut ser = Serializer::new(&mut buffer);
let mut map = Map::new(&mut ser);
map.serialize_entry("name", "Bob").unwrap();
map.serialize_entry("age", "5").unwrap();
}
assert_eq!(
String::from_utf8(buffer).unwrap(),
"<name>Bob</name><age>5</age>"
);
}