use super::*;
use serde::{ser, Serialize};
use std::{error, fmt};
type Res = Result<Kserd<'static>, Error>;
pub struct Encoder;
impl ser::Serializer for Encoder {
type Ok = Kserd<'static>;
type Error = Error;
type SerializeSeq = SeqLike;
type SerializeTuple = TupleLike;
type SerializeTupleStruct = TupleLike;
type SerializeTupleVariant = TupleLike;
type SerializeMap = MapLike;
type SerializeStruct = CntrLike;
type SerializeStructVariant = CntrLike;
fn serialize_bool(self, v: bool) -> Res {
Ok(Kserd::new_bool(v))
}
fn serialize_i8(self, v: i8) -> Res {
Ok(Kserd::new_num(v))
}
fn serialize_i16(self, v: i16) -> Res {
Ok(Kserd::new_num(v))
}
fn serialize_i32(self, v: i32) -> Res {
Ok(Kserd::new_num(v))
}
fn serialize_i64(self, v: i64) -> Res {
Ok(Kserd::new_num(v))
}
fn serialize_i128(self, v: i128) -> Res {
Ok(Kserd::new_num(v))
}
fn serialize_u8(self, v: u8) -> Res {
Ok(Kserd::new_num(v))
}
fn serialize_u16(self, v: u16) -> Res {
Ok(Kserd::new_num(v))
}
fn serialize_u32(self, v: u32) -> Res {
Ok(Kserd::new_num(v))
}
fn serialize_u64(self, v: u64) -> Res {
Ok(Kserd::new_num(v))
}
fn serialize_u128(self, v: u128) -> Res {
Ok(Kserd::new_num(v))
}
fn serialize_f32(self, v: f32) -> Res {
Ok(Kserd::new_num(v))
}
fn serialize_f64(self, v: f64) -> Res {
Ok(Kserd::new_num(v))
}
fn serialize_char(self, v: char) -> Res {
Ok(Kserd::with_id_unchk(
"char",
Value::Str(Kstr::owned(v.to_string())),
))
}
fn serialize_str(self, v: &str) -> Res {
Ok(Kserd::new_str(v).into_owned())
}
fn serialize_bytes(self, v: &[u8]) -> Res {
Ok(Kserd::new_barr(v).into_owned())
}
fn serialize_none(self) -> Res {
Ok(Kserd::with_id_unchk("None", Value::Tuple(vec![])))
}
fn serialize_some<T: ?Sized + Serialize>(self, v: &T) -> Res {
Ok(Kserd::with_id_unchk(
"Some",
Value::Tuple(vec![v.serialize(self)?]),
))
}
fn serialize_unit(self) -> Res {
Ok(Kserd::new_unit())
}
fn serialize_unit_struct(self, name: &'static str) -> Res {
Kserd::with_id(name, Value::Tuple(vec![])).map_err(Error::InvalidId)
}
fn serialize_unit_variant(self, _: &'static str, _: u32, variant: &'static str) -> Res {
Kserd::with_id(variant, Value::Tuple(vec![])).map_err(Error::InvalidId)
}
fn serialize_newtype_struct<T: ?Sized + Serialize>(self, name: &'static str, value: &T) -> Res {
Kserd::with_id(name, Value::Tuple(vec![value.serialize(self)?])).map_err(Error::InvalidId)
}
fn serialize_newtype_variant<T: ?Sized + Serialize>(
self,
_: &'static str,
_: u32,
variant: &'static str,
value: &T,
) -> Res {
Kserd::with_id(variant, Value::Tuple(vec![value.serialize(self)?]))
.map_err(Error::InvalidId)
}
fn serialize_seq(self, len: Option<usize>) -> Result<SeqLike, Error> {
Ok(SeqLike {
kserd: Kserd::new(Value::Seq(Vec::with_capacity(len.unwrap_or_default()))),
})
}
fn serialize_tuple(self, len: usize) -> Result<TupleLike, Error> {
Ok(TupleLike {
kserd: Kserd::new(Value::Tuple(Vec::with_capacity(len))),
})
}
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<TupleLike, Error> {
Ok(TupleLike {
kserd: Kserd::with_id(name, Value::Tuple(Vec::with_capacity(len)))
.map_err(Error::InvalidId)?,
})
}
fn serialize_tuple_variant(
self,
_: &'static str,
_: u32,
variant: &'static str,
len: usize,
) -> Result<TupleLike, Error> {
Ok(TupleLike {
kserd: Kserd::with_id(variant, Value::Tuple(Vec::with_capacity(len)))
.map_err(Error::InvalidId)?,
})
}
fn serialize_map(self, _len: Option<usize>) -> Result<MapLike, Error> {
Ok(MapLike {
key: None,
kserd: Kserd::new(Value::Map(BTreeMap::new())),
})
}
fn serialize_struct(self, name: &'static str, _len: usize) -> Result<CntrLike, Error> {
Ok(CntrLike {
kserd: Kserd::with_id(name, Value::Cntr(Fields::new())).map_err(Error::InvalidId)?,
})
}
fn serialize_struct_variant(
self,
_: &'static str,
_: u32,
variant: &'static str,
_: usize,
) -> Result<CntrLike, Error> {
Ok(CntrLike {
kserd: Kserd::with_id(variant, Value::Cntr(Fields::new())).map_err(Error::InvalidId)?,
})
}
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: std::fmt::Display,
{
self.serialize_str(&value.to_string())
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum Error {
NoKeyAvailable,
InvalidId(crate::ds::InvalidId),
Message(String),
}
impl ser::Error for Error {
fn custom<T: fmt::Display>(msg: T) -> Self {
Error::Message(msg.to_string())
}
}
impl error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::NoKeyAvailable => {
write!(f, "no key was available when trying to serialize map value")
}
Error::InvalidId(s) => write!(f, "{}", s),
Error::Message(s) => write!(f, "custom error: {}", s),
}
}
}
pub struct SeqLike {
kserd: Kserd<'static>,
}
impl ser::SerializeSeq for SeqLike {
type Ok = Kserd<'static>;
type Error = Error;
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
match &mut self.kserd.val {
Value::Seq(v) => v.push(value.serialize(Encoder)?),
_ => unreachable!(),
}
Ok(())
}
fn end(self) -> Res {
Ok(self.kserd)
}
}
pub struct TupleLike {
kserd: Kserd<'static>,
}
impl ser::SerializeTuple for TupleLike {
type Ok = Kserd<'static>;
type Error = Error;
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
match &mut self.kserd.val {
Value::Tuple(v) => v.push(value.serialize(Encoder)?),
_ => unreachable!(),
}
Ok(())
}
fn end(self) -> Res {
Ok(self.kserd)
}
}
impl ser::SerializeTupleStruct for TupleLike {
type Ok = Kserd<'static>;
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
match &mut self.kserd.val {
Value::Tuple(v) => v.push(value.serialize(Encoder)?),
_ => unreachable!(),
}
Ok(())
}
fn end(self) -> Res {
Ok(self.kserd)
}
}
impl ser::SerializeTupleVariant for TupleLike {
type Ok = Kserd<'static>;
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
match &mut self.kserd.val {
Value::Tuple(v) => v.push(value.serialize(Encoder)?),
_ => unreachable!(),
}
Ok(())
}
fn end(self) -> Res {
Ok(self.kserd)
}
}
pub struct MapLike {
key: Option<Kserd<'static>>,
kserd: Kserd<'static>,
}
impl ser::SerializeMap for MapLike {
type Ok = Kserd<'static>;
type Error = Error;
fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<(), Error> {
self.key = Some(key.serialize(Encoder)?);
Ok(())
}
fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Error> {
let key = self.key.take().ok_or(Error::NoKeyAvailable)?;
match &mut self.kserd.val {
Value::Map(v) => {
v.insert(key, value.serialize(Encoder)?);
}
_ => unreachable!(),
}
Ok(())
}
fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Error>
where
K: ?Sized + Serialize,
V: ?Sized + Serialize,
{
match &mut self.kserd.val {
Value::Map(v) => {
v.insert(key.serialize(Encoder)?, value.serialize(Encoder)?);
}
_ => unreachable!(),
}
Ok(())
}
fn end(self) -> Res {
Ok(self.kserd)
}
}
pub struct CntrLike {
kserd: Kserd<'static>,
}
impl ser::SerializeStruct for CntrLike {
type Ok = Kserd<'static>;
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Error> {
match &mut self.kserd.val {
Value::Cntr(cntr) => {
cntr.insert(key.into(), value.serialize(Encoder)?);
}
_ => unreachable!(),
}
Ok(())
}
fn end(self) -> Res {
Ok(self.kserd)
}
}
impl ser::SerializeStructVariant for CntrLike {
type Ok = Kserd<'static>;
type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(
&mut self,
key: &'static str,
value: &T,
) -> Result<(), Error> {
match &mut self.kserd.val {
Value::Cntr(cntr) => {
cntr.insert(key.into(), value.serialize(Encoder)?);
}
_ => unreachable!(),
}
Ok(())
}
fn end(self) -> Res {
Ok(self.kserd)
}
}
#[cfg(test)]
mod tests {
use super::*;
use ser::Error as _;
use ser::{SerializeMap, Serializer};
#[test]
fn other_tests() {
let kserd = Encoder.serialize_newtype_struct("Test", &());
assert_eq!(kserd, Ok(Kserd::new(Value::Tuple(vec![Kserd::new_unit()]))));
let kserd = kserd.unwrap();
assert_eq!(kserd.id(), Some("Test"));
let kserd = Encoder
.serialize_newtype_struct("\\Test", &())
.map_err(|e| e.to_string());
assert_eq!(kserd, Err(r#"identity '\Test' contains invalid characters. Invalid characters: '(){}[]<> ,./\='"#.into()));
let kserd = Encoder
.serialize_newtype_variant("\\Test", 0, "\\Test", &())
.map_err(|e| e.to_string());
assert_eq!(kserd, Err(r#"identity '\Test' contains invalid characters. Invalid characters: '(){}[]<> ,./\='"#.into()));
let kserd = Encoder.collect_str("Hello, world!");
assert_eq!(kserd, Ok(Kserd::new_str("Hello, world!")));
let err = Error::custom("Hello");
assert_eq!(&err.to_string(), "custom error: Hello");
}
#[test]
fn map_tests() {
let map: std::collections::HashMap<u64, String> =
vec![(100, "Hello".into())].into_iter().collect();
let kserd = Kserd::enc(&map);
assert_eq!(
kserd,
Ok(Kserd::new_map(vec![(
100.into_kserd().unwrap(),
"Hello".into_kserd().unwrap()
)]))
);
let mut map = MapLike {
key: None,
kserd: Kserd::new_map(vec![]),
};
let r = map.serialize_key(&100);
assert_eq!(r, Ok(()));
assert_eq!(map.key, Some(Kserd::new_num(100)));
let r = map.serialize_value("Hello");
assert_eq!(r, Ok(()));
assert_eq!(
map.kserd,
Kserd::new_map(vec![(
100.into_kserd().unwrap(),
"Hello".into_kserd().unwrap()
)])
);
}
}