Move user-facing serialization interface out of trait
This commit is contained in:
parent
2827bd404e
commit
9577aace57
|
@ -49,7 +49,10 @@ pub fn to_xml(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|||
|
||||
proc_macro::TokenStream::from(quote!(
|
||||
impl #generics ToXml for #ident #generics {
|
||||
fn serialize<W: std::fmt::Write>(&self, serializer: &mut instant_xml::Serializer<W>) -> Result<(), instant_xml::Error> {
|
||||
fn serialize<W: ::core::fmt::Write + ?::core::marker::Sized>(
|
||||
&self,
|
||||
serializer: &mut instant_xml::Serializer<W>,
|
||||
) -> Result<(), instant_xml::Error> {
|
||||
let _ = serializer.consume_field_context();
|
||||
let mut field_context = instant_xml::ser::FieldContext {
|
||||
name: #root_name,
|
||||
|
|
|
@ -54,10 +54,10 @@ impl<'a, T> ToXml for DisplayToXml<'a, T>
|
|||
where
|
||||
T: fmt::Display,
|
||||
{
|
||||
fn serialize<W>(&self, serializer: &mut Serializer<W>) -> Result<(), Error>
|
||||
where
|
||||
W: fmt::Write,
|
||||
{
|
||||
fn serialize<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
serializer: &mut Serializer<W>,
|
||||
) -> Result<(), Error> {
|
||||
let field_context = match serializer.consume_field_context() {
|
||||
Some(field_context) => field_context,
|
||||
None => return Err(Error::UnexpectedValue),
|
||||
|
@ -80,7 +80,7 @@ where
|
|||
macro_rules! to_xml_for_number {
|
||||
($typ:ty) => {
|
||||
impl ToXml for $typ {
|
||||
fn serialize<W: fmt::Write>(
|
||||
fn serialize<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
serializer: &mut Serializer<W>,
|
||||
) -> Result<(), Error> {
|
||||
|
@ -321,7 +321,10 @@ to_xml_for_number!(f32);
|
|||
to_xml_for_number!(f64);
|
||||
|
||||
impl ToXml for bool {
|
||||
fn serialize<W: fmt::Write>(&self, serializer: &mut Serializer<W>) -> Result<(), Error> {
|
||||
fn serialize<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
serializer: &mut Serializer<W>,
|
||||
) -> Result<(), Error> {
|
||||
let value = match self {
|
||||
true => "true",
|
||||
false => "false",
|
||||
|
@ -332,32 +335,47 @@ impl ToXml for bool {
|
|||
}
|
||||
|
||||
impl ToXml for String {
|
||||
fn serialize<W: fmt::Write>(&self, serializer: &mut Serializer<W>) -> Result<(), Error> {
|
||||
fn serialize<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
serializer: &mut Serializer<W>,
|
||||
) -> Result<(), Error> {
|
||||
DisplayToXml(&escape(self)?).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToXml for char {
|
||||
fn serialize<W: fmt::Write>(&self, serializer: &mut Serializer<W>) -> Result<(), Error> {
|
||||
fn serialize<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
serializer: &mut Serializer<W>,
|
||||
) -> Result<(), Error> {
|
||||
let mut tmp = [0u8; 4];
|
||||
DisplayToXml(&escape(&*self.encode_utf8(&mut tmp))?).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToXml for &str {
|
||||
fn serialize<W: fmt::Write>(&self, serializer: &mut Serializer<W>) -> Result<(), Error> {
|
||||
fn serialize<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
serializer: &mut Serializer<W>,
|
||||
) -> Result<(), Error> {
|
||||
DisplayToXml(&escape(self)?).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToXml for Cow<'_, str> {
|
||||
fn serialize<W: fmt::Write>(&self, serializer: &mut Serializer<W>) -> Result<(), Error> {
|
||||
fn serialize<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
serializer: &mut Serializer<W>,
|
||||
) -> Result<(), Error> {
|
||||
DisplayToXml(&escape(self)?).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ToXml> ToXml for Option<T> {
|
||||
fn serialize<W: fmt::Write>(&self, serializer: &mut Serializer<W>) -> Result<(), Error> {
|
||||
fn serialize<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
serializer: &mut Serializer<W>,
|
||||
) -> Result<(), Error> {
|
||||
match self {
|
||||
Some(v) => v.serialize(serializer),
|
||||
None => Ok(()),
|
||||
|
|
|
@ -13,14 +13,10 @@ pub mod ser;
|
|||
pub use ser::Serializer;
|
||||
|
||||
pub trait ToXml {
|
||||
fn to_xml(&self) -> Result<String, Error> {
|
||||
let mut output = String::new();
|
||||
let mut serializer = Serializer::new(&mut output);
|
||||
self.serialize(&mut serializer)?;
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
fn serialize<W: fmt::Write>(&self, serializer: &mut Serializer<W>) -> Result<(), Error>;
|
||||
fn serialize<W: fmt::Write + ?Sized>(
|
||||
&self,
|
||||
serializer: &mut Serializer<W>,
|
||||
) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
pub enum FieldAttribute<'xml> {
|
||||
|
@ -45,6 +41,19 @@ pub fn from_str<'xml, T: FromXml<'xml>>(input: &'xml str) -> Result<T, Error> {
|
|||
T::deserialize(&mut Deserializer::new(input))
|
||||
}
|
||||
|
||||
pub fn to_string(value: &(impl ToXml + ?Sized)) -> Result<String, Error> {
|
||||
let mut output = String::new();
|
||||
to_writer(value, &mut output)?;
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
pub fn to_writer(
|
||||
value: &(impl ToXml + ?Sized),
|
||||
output: &mut (impl fmt::Write + ?Sized),
|
||||
) -> Result<(), Error> {
|
||||
value.serialize(&mut Serializer::new(output))
|
||||
}
|
||||
|
||||
pub enum Kind {
|
||||
Scalar,
|
||||
Element(Id<'static>),
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::fmt::{self, Write};
|
|||
|
||||
use super::{Error, FieldAttribute};
|
||||
|
||||
pub struct Serializer<'xml, W: fmt::Write> {
|
||||
pub struct Serializer<'xml, W: fmt::Write + ?Sized> {
|
||||
// For parent namespaces the key is the namespace and the value is the prefix. We are adding to map
|
||||
// only if the namespaces do not exist, if it does exist then we are using an already defined parent prefix.
|
||||
#[doc(hidden)]
|
||||
|
@ -17,7 +17,7 @@ pub struct Serializer<'xml, W: fmt::Write> {
|
|||
next_field_context: Option<FieldContext<'xml>>,
|
||||
}
|
||||
|
||||
impl<'xml, W: fmt::Write> Serializer<'xml, W> {
|
||||
impl<'xml, W: fmt::Write + ?Sized> Serializer<'xml, W> {
|
||||
pub fn new(output: &'xml mut W) -> Self {
|
||||
Self {
|
||||
parent_namespaces: HashMap::new(),
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::borrow::Cow;
|
|||
|
||||
use similar_asserts::assert_eq;
|
||||
|
||||
use instant_xml::{from_str, Error, FromXml, ToXml};
|
||||
use instant_xml::{from_str, to_string, Error, FromXml, ToXml};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, FromXml, ToXml)]
|
||||
#[xml(ns("URI"))]
|
||||
|
@ -57,13 +57,11 @@ fn escape_back() {
|
|||
#[test]
|
||||
fn special_entities() {
|
||||
assert_eq!(
|
||||
StructSpecialEntities{
|
||||
to_string(&StructSpecialEntities{
|
||||
string: "&\"<>\'aa".to_string(),
|
||||
str: "&\"<>\'bb",
|
||||
cow: Cow::from("&\"<>\'cc"),
|
||||
}
|
||||
.to_xml()
|
||||
.unwrap(),
|
||||
"<StructSpecialEntities xmlns=\"URI\"><string>&"<>'aa</string><str>&"<>'bb</str><cow>&"<>'cc</cow></StructSpecialEntities>"
|
||||
}).unwrap(),
|
||||
"<StructSpecialEntities xmlns=\"URI\"><string>&"<>'aa</string><str>&"<>'bb</str><cow>&"<>'cc</cow></StructSpecialEntities>",
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use similar_asserts::assert_eq;
|
||||
|
||||
use instant_xml::ToXml;
|
||||
use instant_xml::{to_string, ToXml};
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, ToXml)]
|
||||
#[xml(ns(dar = "BAZ", internal = "INTERNAL"))]
|
||||
|
@ -33,7 +33,7 @@ struct Nested {
|
|||
#[test]
|
||||
fn struct_child_namespaces() {
|
||||
assert_eq!(
|
||||
StructChildNamespaces {
|
||||
to_string(&StructChildNamespaces {
|
||||
different_child_namespace: NestedDifferentNamespace {
|
||||
flag_parent_prefix: true,
|
||||
flag_internal_prefix: false,
|
||||
|
@ -42,8 +42,7 @@ fn struct_child_namespaces() {
|
|||
flag_parent_prefix: true,
|
||||
flag_internal_prefix: false,
|
||||
},
|
||||
}
|
||||
.to_xml()
|
||||
})
|
||||
.unwrap(),
|
||||
"<StructChildNamespaces xmlns=\"URI\" xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\"><NestedDifferentNamespace xmlns=\"\" xmlns:internal=\"INTERNAL\"><bar:flag_parent_prefix>true</bar:flag_parent_prefix><internal:flag_internal_prefix>false</internal:flag_internal_prefix></NestedDifferentNamespace><Nested xmlns:internal=\"INTERNAL\"><bar:flag_parent_prefix>true</bar:flag_parent_prefix><internal:flag_internal_prefix>false</internal:flag_internal_prefix></Nested></StructChildNamespaces>"
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use similar_asserts::assert_eq;
|
||||
|
||||
use instant_xml::ToXml;
|
||||
use instant_xml::{to_string, ToXml};
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, ToXml)]
|
||||
#[xml(ns(bar = "BAZ", foo = "BAR"))]
|
||||
|
@ -20,12 +20,11 @@ struct StructWithNamedFields {
|
|||
#[test]
|
||||
fn struct_with_named_fields() {
|
||||
assert_eq!(
|
||||
StructWithNamedFields {
|
||||
to_string(&StructWithNamedFields {
|
||||
flag: true,
|
||||
string: "test".to_string(),
|
||||
number: 1,
|
||||
}
|
||||
.to_xml()
|
||||
})
|
||||
.unwrap(),
|
||||
"<StructWithNamedFields xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\"><flag>true</flag><bar:string>test</bar:string><number xmlns=\"typo\">1</number></StructWithNamedFields>"
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use similar_asserts::assert_eq;
|
||||
|
||||
use instant_xml::ToXml;
|
||||
use instant_xml::{to_string, ToXml};
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, ToXml)]
|
||||
#[xml(ns("URI", dar = "BAZ", internal = "INTERNAL"))]
|
||||
|
@ -37,7 +37,7 @@ struct StructWithCustomField {
|
|||
#[test]
|
||||
fn struct_with_custom_field() {
|
||||
assert_eq!(
|
||||
StructWithCustomField {
|
||||
to_string(&StructWithCustomField {
|
||||
int_attribute: 42,
|
||||
flag_direct_namespace_same_the_same_as_prefix: true,
|
||||
flag_prefix: false,
|
||||
|
@ -46,8 +46,7 @@ fn struct_with_custom_field() {
|
|||
flag_parent_prefix: true,
|
||||
flag_internal_prefix: false,
|
||||
},
|
||||
}
|
||||
.to_xml()
|
||||
})
|
||||
.unwrap(),
|
||||
"<StructWithCustomField xmlns=\"URI\" xmlns:bar=\"BAZ\" xmlns:foo=\"BAR\" int_attribute=\"42\"><flag_direct_namespace_same_the_same_as_prefix xmlns=\"BAZ\">true</flag_direct_namespace_same_the_same_as_prefix><bar:flag_prefix>false</bar:flag_prefix><flag_direct_namespace xmlns=\"DIFFERENT\">true</flag_direct_namespace><Nested xmlns:internal=\"INTERNAL\"><bar:flag_parent_prefix>true</bar:flag_parent_prefix><internal:flag_internal_prefix>false</internal:flag_internal_prefix></Nested></StructWithCustomField>"
|
||||
);
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use similar_asserts::assert_eq;
|
||||
|
||||
use instant_xml::ToXml;
|
||||
use instant_xml::{to_string, ToXml};
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, ToXml)]
|
||||
struct Unit;
|
||||
|
||||
#[test]
|
||||
fn unit() {
|
||||
assert_eq!(Unit.to_xml().unwrap(), "<Unit></Unit>");
|
||||
assert_eq!(to_string(&Unit).unwrap(), "<Unit></Unit>");
|
||||
//assert_eq!(Unit::from_xml("<Unit/>").unwrap(), Unit);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue