1#![recursion_limit = "256"]
2
3extern crate proc_macro;
4
5mod into_owned;
6mod types;
7mod xml_read;
8mod xml_write;
9
10use proc_macro::TokenStream;
11use quote::quote;
12use syn::{parse_macro_input, DeriveInput, GenericParam};
13
14use crate::{types::Element, xml_read::read, xml_write::write};
15
16#[proc_macro_derive(XmlRead, attributes(xml))]
17pub fn derive_xml_read(input: TokenStream) -> TokenStream {
18 let input = parse_macro_input!(input as DeriveInput);
19
20 let name = &input.ident;
21 let generics = &input.generics;
22
23 let lifetime = match &generics.params.last() {
24 Some(GenericParam::Lifetime(lt)) => Some(lt),
25 _ => None,
26 };
27
28 let element = Element::parse(&input);
29
30 let impl_read = read(&element);
31
32 let gen = quote! {
33 impl #generics #name #generics {
34 pub(crate) fn from_str(string: & #lifetime str) -> Result<#name #generics> {
35 let mut reader = xmlparser::Tokenizer::from(string).peekable();
36 Self::from_reader(&mut reader)
37 }
38
39 pub(crate) fn from_reader(
40 reader: &mut std::iter::Peekable<xmlparser::Tokenizer #generics>
41 ) -> Result<#name #generics> {
42 use xmlparser::{ElementEnd, Token, Tokenizer};
43
44 #impl_read
45 }
46 }
47 };
48
49 gen.into()
50}
51
52#[proc_macro_derive(XmlWrite, attributes(xml))]
53pub fn derive_xml_write(input: TokenStream) -> TokenStream {
54 let input = parse_macro_input!(input as DeriveInput);
55
56 let name = &input.ident;
57 let generics = &input.generics;
58
59 let element = Element::parse(&input);
60
61 let impl_write = write(&element);
62
63 let gen = quote! {
64 impl #generics #name #generics {
65 pub(crate) fn write<W: std::io::Write>(&self, mut writer: W) -> Result<()> {
66 #impl_write
67
68 Ok(())
69 }
70 }
71 };
72
73 gen.into()
74}
75
76#[proc_macro_derive(IntoOwned)]
77pub fn derive_into_owned(input: TokenStream) -> TokenStream {
78 let input = parse_macro_input!(input as DeriveInput);
79
80 let name = &input.ident;
81 let generics = &input.generics;
82
83 let element = Element::parse(&input);
84
85 let impl_into_owned = into_owned::impl_into_owned(&element);
86
87 let lifetime = match &generics.params.last() {
88 Some(GenericParam::Lifetime(_)) => Some(quote!( <'static> )),
89 _ => None,
90 };
91
92 let gen = quote! {
93 impl #generics #name #generics {
94 pub fn into_owned(self) -> #name #lifetime {
95 #impl_into_owned
96 }
97 }
98 };
99
100 gen.into()
101}