Revision control
Copy as Markdown
Other Tools
use crate::errors::serialize::DeError;↩
use serde::ser::{Impossible, Serialize, Serializer};↩
use serde::serde_if_integer128;↩
use std::fmt::Write;↩
↩
/// A serializer, that ensures, that only plain types can be serialized,↩
/// so result can be used as an XML tag or attribute name.↩
///↩
/// This serializer does not check that name does not contain characters that↩
/// [not allowed] in XML names, because in some cases it should pass names↩
/// that would be filtered on higher level.↩
///↩
pub struct QNameSerializer<W: Write> {↩
/// Writer to which this serializer writes content↩
pub writer: W,↩
}↩
↩
impl<W: Write> QNameSerializer<W> {↩
#[inline]↩
fn write_str(&mut self, value: &str) -> Result<(), DeError> {↩
Ok(self.writer.write_str(value)?)↩
}↩
}↩
↩
impl<W: Write> Serializer for QNameSerializer<W> {↩
type Ok = W;↩
type Error = DeError;↩
↩
type SerializeSeq = Impossible<Self::Ok, Self::Error>;↩
type SerializeTuple = Impossible<Self::Ok, Self::Error>;↩
type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;↩
type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;↩
type SerializeMap = Impossible<Self::Ok, Self::Error>;↩
type SerializeStruct = Impossible<Self::Ok, Self::Error>;↩
type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;↩
↩
write_primitive!();↩
↩
fn serialize_str(mut self, value: &str) -> Result<Self::Ok, Self::Error> {↩
self.write_str(value)?;↩
Ok(self.writer)↩
}↩
↩
/// Because unit type can be represented only by empty string which is not↩
/// a valid XML name, serialization of unit returns `Err(Unsupported)`↩
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {↩
Err(DeError::Unsupported(↩
"cannot serialize unit type `()` as an XML tag name".into(),↩
))↩
}↩
↩
/// Because unit struct can be represented only by empty string which is not↩
/// a valid XML name, serialization of unit struct returns `Err(Unsupported)`↩
fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {↩
Err(DeError::Unsupported(↩
format!("cannot serialize unit struct `{}` as an XML tag name", name).into(),↩
))↩
}↩
↩
/// We cannot store both a variant discriminant and a variant value,↩
/// so serialization of enum newtype variant returns `Err(Unsupported)`↩
fn serialize_newtype_variant<T: ?Sized + Serialize>(↩
self,↩
name: &'static str,↩
_variant_index: u32,↩
variant: &'static str,↩
_value: &T,↩
) -> Result<Self::Ok, DeError> {↩
Err(DeError::Unsupported(↩
format!(↩
"cannot serialize enum newtype variant `{}::{}` as an XML tag name",↩
name, variant↩
)↩
.into(),↩
))↩
}↩
↩
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {↩
Err(DeError::Unsupported(↩
"cannot serialize sequence as an XML tag name".into(),↩
))↩
}↩
↩
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {↩
Err(DeError::Unsupported(↩
"cannot serialize tuple as an XML tag name".into(),↩
))↩
}↩
↩
fn serialize_tuple_struct(↩
self,↩
name: &'static str,↩
_len: usize,↩
) -> Result<Self::SerializeTupleStruct, Self::Error> {↩
Err(DeError::Unsupported(↩
format!(↩
"cannot serialize tuple struct `{}` as an XML tag name",↩
name↩
)↩
.into(),↩
))↩
}↩
↩
fn serialize_tuple_variant(↩
self,↩
name: &'static str,↩
_variant_index: u32,↩
variant: &'static str,↩
_len: usize,↩
) -> Result<Self::SerializeTupleVariant, Self::Error> {↩
Err(DeError::Unsupported(↩
format!(↩
"cannot serialize enum tuple variant `{}::{}` as an XML tag name",↩
name, variant↩
)↩
.into(),↩
))↩
}↩
↩
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {↩
Err(DeError::Unsupported(↩
"cannot serialize map as an XML tag name".into(),↩
))↩
}↩
↩
fn serialize_struct(↩
self,↩
name: &'static str,↩
_len: usize,↩
) -> Result<Self::SerializeStruct, Self::Error> {↩
Err(DeError::Unsupported(↩
format!("cannot serialize struct `{}` as an XML tag name", name).into(),↩
))↩
}↩
↩
fn serialize_struct_variant(↩
self,↩
name: &'static str,↩
_variant_index: u32,↩
variant: &'static str,↩
_len: usize,↩
) -> Result<Self::SerializeStructVariant, Self::Error> {↩
Err(DeError::Unsupported(↩
format!(↩
"cannot serialize enum struct variant `{}::{}` as an XML tag name",↩
name, variant↩
)↩
.into(),↩
))↩
}↩
}↩
↩
#[cfg(test)]↩
mod tests {↩
use super::*;↩
use crate::utils::Bytes;↩
use pretty_assertions::assert_eq;↩
use serde::Serialize;↩
use std::collections::BTreeMap;↩
↩
#[derive(Debug, Serialize, PartialEq)]↩
struct Unit;↩
↩
#[derive(Debug, Serialize, PartialEq)]↩
struct Newtype(bool);↩
↩
#[derive(Debug, Serialize, PartialEq)]↩
struct Tuple(&'static str, usize);↩
↩
#[derive(Debug, Serialize, PartialEq)]↩
struct Struct {↩
key: &'static str,↩
val: usize,↩
}↩
↩
#[derive(Debug, Serialize, PartialEq)]↩
enum Enum {↩
Unit,↩
#[serde(rename = "<\"&'>")]↩
UnitEscaped,↩
Newtype(bool),↩
Tuple(&'static str, usize),↩
Struct {↩
key: &'static str,↩
val: usize,↩
},↩
}↩
↩
/// Checks that given `$data` successfully serialized as `$expected`↩
macro_rules! serialize_as {↩
($name:ident: $data:expr => $expected:literal) => {↩
#[test]↩
fn $name() {↩
let ser = QNameSerializer {↩
writer: String::new(),↩
};↩
↩
let buffer = $data.serialize(ser).unwrap();↩
assert_eq!(buffer, $expected);↩
}↩
};↩
}↩
↩
/// Checks that attempt to serialize given `$data` results to a↩
/// serialization error `$kind` with `$reason`↩
macro_rules! err {↩
($name:ident: $data:expr => $kind:ident($reason:literal)) => {↩
#[test]↩
fn $name() {↩
let mut buffer = String::new();↩
let ser = QNameSerializer {↩
writer: &mut buffer,↩
};↩
↩
match $data.serialize(ser).unwrap_err() {↩
DeError::$kind(e) => assert_eq!(e, $reason),↩
e => panic!(↩
"Expected `{}({})`, found `{:?}`",↩
stringify!($kind),↩
$reason,↩
e↩
),↩
}↩
assert_eq!(buffer, "");↩
}↩
};↩
}↩
↩
serialize_as!(false_: false => "false");↩
serialize_as!(true_: true => "true");↩
↩
serialize_as!(i8_: -42i8 => "-42");↩
serialize_as!(i16_: -4200i16 => "-4200");↩
serialize_as!(i32_: -42000000i32 => "-42000000");↩
serialize_as!(i64_: -42000000000000i64 => "-42000000000000");↩
serialize_as!(isize_: -42000000000000isize => "-42000000000000");↩
↩
serialize_as!(u8_: 42u8 => "42");↩
serialize_as!(u16_: 4200u16 => "4200");↩
serialize_as!(u32_: 42000000u32 => "42000000");↩
serialize_as!(u64_: 42000000000000u64 => "42000000000000");↩
serialize_as!(usize_: 42000000000000usize => "42000000000000");↩
↩
serde_if_integer128! {↩
serialize_as!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");↩
serialize_as!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");↩
}↩
↩
serialize_as!(f32_: 4.2f32 => "4.2");↩
serialize_as!(f64_: 4.2f64 => "4.2");↩
↩
serialize_as!(char_non_escaped: 'h' => "h");↩
serialize_as!(char_lt: '<' => "<");↩
serialize_as!(char_gt: '>' => ">");↩
serialize_as!(char_amp: '&' => "&");↩
serialize_as!(char_apos: '\'' => "'");↩
serialize_as!(char_quot: '"' => "\"");↩
↩
serialize_as!(str_valid_name: "valid-name" => "valid-name");↩
serialize_as!(str_space: "string with spaces" => "string with spaces");↩
serialize_as!(str_lt: "string<" => "string<");↩
serialize_as!(str_gt: "string>" => "string>");↩
serialize_as!(str_amp: "string&" => "string&");↩
serialize_as!(str_apos: "string'" => "string'");↩
serialize_as!(str_quot: "string\"" => "string\"");↩
↩
err!(bytes: Bytes(b"<\"escaped & bytes'>")↩
=> Unsupported("`serialize_bytes` not supported yet"));↩
↩
serialize_as!(option_none: Option::<&str>::None => "");↩
serialize_as!(option_some: Some("non-escaped-string") => "non-escaped-string");↩
↩
err!(unit: ()↩
=> Unsupported("cannot serialize unit type `()` as an XML tag name"));↩
err!(unit_struct: Unit↩
=> Unsupported("cannot serialize unit struct `Unit` as an XML tag name"));↩
↩
serialize_as!(enum_unit: Enum::Unit => "Unit");↩
serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<\"&'>");↩
↩
serialize_as!(newtype: Newtype(true) => "true");↩
err!(enum_newtype: Enum::Newtype(false)↩
=> Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as an XML tag name"));↩
↩
err!(seq: vec![1, 2, 3]↩
=> Unsupported("cannot serialize sequence as an XML tag name"));↩
err!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize)↩
=> Unsupported("cannot serialize tuple as an XML tag name"));↩
err!(tuple_struct: Tuple("first", 42)↩
=> Unsupported("cannot serialize tuple struct `Tuple` as an XML tag name"));↩
err!(enum_tuple: Enum::Tuple("first", 42)↩
=> Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as an XML tag name"));↩
↩
err!(map: BTreeMap::from([("_1", 2), ("_3", 4)])↩
=> Unsupported("cannot serialize map as an XML tag name"));↩
err!(struct_: Struct { key: "answer", val: 42 }↩
=> Unsupported("cannot serialize struct `Struct` as an XML tag name"));↩
err!(enum_struct: Enum::Struct { key: "answer", val: 42 }↩
=> Unsupported("cannot serialize enum struct variant `Enum::Struct` as an XML tag name"));↩
}↩