mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-14 02:22:21 +00:00
xml: Implement XmlSerialize for enums
This commit is contained in:
@@ -172,4 +172,38 @@ impl Variant {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn se_branch(&self) -> proc_macro2::TokenStream {
|
||||||
|
let ident = self.ident();
|
||||||
|
let variant_name = self.xml_name();
|
||||||
|
|
||||||
|
match &self.variant.fields {
|
||||||
|
Fields::Named(_) => {
|
||||||
|
panic!(
|
||||||
|
"struct variants are not supported, please use a tuple variant with a struct"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => {
|
||||||
|
if unnamed.len() != 1 {
|
||||||
|
panic!("tuple variants should contain exactly one element");
|
||||||
|
}
|
||||||
|
quote! {
|
||||||
|
if let Self::#ident(val) = &self {
|
||||||
|
if !enum_untagged {
|
||||||
|
::rustical_xml::XmlSerialize::serialize(val, None, Some(#variant_name), writer)?;
|
||||||
|
} else {
|
||||||
|
::rustical_xml::XmlSerialize::serialize(val, None, None, writer)?;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Fields::Unit => {
|
||||||
|
quote! {
|
||||||
|
if let Self::#ident = self {
|
||||||
|
::rustical_xml::XmlSerialize::serialize(&(), ns, tag, writer)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,27 +92,38 @@ impl Enum {
|
|||||||
pub fn impl_se(&self) -> proc_macro2::TokenStream {
|
pub fn impl_se(&self) -> proc_macro2::TokenStream {
|
||||||
let (impl_generics, type_generics, where_clause) = self.generics.split_for_impl();
|
let (impl_generics, type_generics, where_clause) = self.generics.split_for_impl();
|
||||||
let ident = &self.ident;
|
let ident = &self.ident;
|
||||||
|
let enum_untagged = self.attrs.untagged.is_present();
|
||||||
|
let variant_serializers = self.variants.iter().map(Variant::se_branch);
|
||||||
|
|
||||||
// TODO: Implement attributes
|
|
||||||
quote! {
|
quote! {
|
||||||
impl #impl_generics ::rustical_xml::XmlSerialize for #ident #type_generics #where_clause {
|
impl #impl_generics ::rustical_xml::XmlSerialize for #ident #type_generics #where_clause {
|
||||||
fn serialize<W: ::std::io::Write>(
|
fn serialize<W: ::std::io::Write>(
|
||||||
&self,
|
&self,
|
||||||
|
ns: Option<&[u8]>,
|
||||||
tag: Option<&[u8]>,
|
tag: Option<&[u8]>,
|
||||||
writer: &mut ::quick_xml::Writer<W>
|
writer: &mut ::quick_xml::Writer<W>
|
||||||
) -> ::std::io::Result<()> {
|
) -> ::std::io::Result<()> {
|
||||||
use ::quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
|
use ::quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
|
||||||
|
|
||||||
let tag_str = tag.map(String::from_utf8_lossy);
|
let tag_str = tag.map(String::from_utf8_lossy);
|
||||||
|
const enum_untagged: bool = #enum_untagged;
|
||||||
|
|
||||||
if let Some(tag) = &tag_str {
|
if let Some(tag) = &tag_str {
|
||||||
writer.write_event(Event::Start(BytesStart::new(tag.to_owned())))?;
|
let bytes_start = BytesStart::new(tag.to_owned());
|
||||||
|
writer.write_event(Event::Start(bytes_start))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#(#variant_serializers);*
|
||||||
|
|
||||||
if let Some(tag) = &tag_str {
|
if let Some(tag) = &tag_str {
|
||||||
writer.write_event(Event::End(BytesEnd::new(tag.to_owned())))?;
|
writer.write_event(Event::End(BytesEnd::new(tag.to_owned())))?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn attributes<'a>(&self) -> Vec<::quick_xml::events::attributes::Attribute<'a>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use quick_xml::events::BytesEnd;
|
||||||
use quick_xml::events::{BytesStart, Event};
|
use quick_xml::events::{BytesStart, Event};
|
||||||
use std::io::BufRead;
|
use std::io::BufRead;
|
||||||
|
|
||||||
@@ -34,6 +35,27 @@ impl XmlDeserialize for () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl XmlSerialize for () {
|
||||||
|
fn serialize<W: std::io::Write>(
|
||||||
|
&self,
|
||||||
|
ns: Option<&[u8]>,
|
||||||
|
tag: Option<&[u8]>,
|
||||||
|
writer: &mut quick_xml::Writer<W>,
|
||||||
|
) -> std::io::Result<()> {
|
||||||
|
let tag_str = tag.map(String::from_utf8_lossy);
|
||||||
|
|
||||||
|
if let Some(tag) = &tag_str {
|
||||||
|
writer.write_event(Event::Empty(BytesStart::new(tag.clone())))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(refining_impl_trait)]
|
||||||
|
fn attributes<'a>(&self) -> Vec<quick_xml::events::attributes::Attribute<'a>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: actually implement
|
// TODO: actually implement
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Unparsed(BytesStart<'static>);
|
pub struct Unparsed(BytesStart<'static>);
|
||||||
|
|||||||
27
crates/xml/tests/se_enum.rs
Normal file
27
crates/xml/tests/se_enum.rs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
use rustical_xml::{XmlRootTag, XmlSerialize, XmlSerializeRoot};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_struct_value_tagged() {
|
||||||
|
#[derive(Debug, XmlRootTag, XmlSerialize, PartialEq)]
|
||||||
|
#[xml(root = b"propfind")]
|
||||||
|
struct Document {
|
||||||
|
prop: Prop,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, XmlSerialize, PartialEq)]
|
||||||
|
enum Prop {
|
||||||
|
Test(String),
|
||||||
|
Hello(usize),
|
||||||
|
Unit,
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
let mut writer = quick_xml::Writer::new(&mut buf);
|
||||||
|
Document {
|
||||||
|
prop: Prop::Test("asd".to_owned()),
|
||||||
|
}
|
||||||
|
.serialize_root(&mut writer)
|
||||||
|
.unwrap();
|
||||||
|
let out = String::from_utf8(buf).unwrap();
|
||||||
|
assert_eq!(out, "<propfind><prop><test>asd</test></prop></propfind>");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user