diff --git a/opcua-macros/src/binary/mod.rs b/opcua-macros/src/binary/mod.rs deleted file mode 100644 index dd47223d4..000000000 --- a/opcua-macros/src/binary/mod.rs +++ /dev/null @@ -1,14 +0,0 @@ -use gen::{generate_binary_decode_impl, generate_binary_encode_impl, parse_binary_struct}; -use proc_macro2::TokenStream; -use syn::DeriveInput; - -mod gen; -pub fn derive_binary_encode_inner(input: DeriveInput) -> syn::Result { - let struct_data = parse_binary_struct(input)?; - generate_binary_encode_impl(struct_data) -} - -pub fn derive_binary_decode_inner(input: DeriveInput) -> syn::Result { - let struct_data = parse_binary_struct(input)?; - generate_binary_decode_impl(struct_data) -} diff --git a/opcua-macros/src/encoding/attribute.rs b/opcua-macros/src/encoding/attribute.rs new file mode 100644 index 000000000..1f34f3b66 --- /dev/null +++ b/opcua-macros/src/encoding/attribute.rs @@ -0,0 +1,47 @@ +use syn::{parse::Parse, Ident, LitStr, Token}; + +use crate::utils::ItemAttr; + +#[derive(Debug, Default)] +pub(crate) struct EncodingFieldAttribute { + pub rename: Option, + pub ignore: bool, + pub required: bool, +} + +impl Parse for EncodingFieldAttribute { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let mut slf = Self::default(); + + loop { + let ident: Ident = input.parse()?; + match ident.to_string().as_str() { + "rename" => { + input.parse::()?; + let val: LitStr = input.parse()?; + slf.rename = Some(val.value()); + } + "ignore" => { + slf.ignore = true; + } + "required" => { + slf.required = true; + } + _ => return Err(syn::Error::new_spanned(ident, "Unknown attribute value")), + } + if !input.peek(Token![,]) { + break; + } + input.parse::()?; + } + Ok(slf) + } +} + +impl ItemAttr for EncodingFieldAttribute { + fn combine(&mut self, other: Self) { + self.rename = other.rename; + self.ignore |= other.ignore; + self.required |= other.required; + } +} diff --git a/opcua-macros/src/binary/gen.rs b/opcua-macros/src/encoding/binary.rs similarity index 86% rename from opcua-macros/src/binary/gen.rs rename to opcua-macros/src/encoding/binary.rs index 8399b99bd..99b1ff0a6 100644 --- a/opcua-macros/src/binary/gen.rs +++ b/opcua-macros/src/encoding/binary.rs @@ -1,16 +1,9 @@ use proc_macro2::TokenStream; use quote::quote; -use syn::DeriveInput; -use crate::utils::{EmptyAttribute, EncodingFieldAttribute, StructItem}; +use super::EncodingStruct; -pub type BinaryStruct = StructItem; - -pub fn parse_binary_struct(input: DeriveInput) -> syn::Result { - BinaryStruct::from_input(input) -} - -pub fn generate_binary_encode_impl(strct: BinaryStruct) -> syn::Result { +pub fn generate_binary_encode_impl(strct: EncodingStruct) -> syn::Result { let mut byte_len_body = quote! {}; let mut encode_body = quote! {}; @@ -50,7 +43,7 @@ pub fn generate_binary_encode_impl(strct: BinaryStruct) -> syn::Result syn::Result { +pub fn generate_binary_decode_impl(strct: EncodingStruct) -> syn::Result { let mut decode_impl = quote! {}; let mut decode_build = quote! {}; diff --git a/opcua-macros/src/json/gen.rs b/opcua-macros/src/encoding/json.rs similarity index 90% rename from opcua-macros/src/json/gen.rs rename to opcua-macros/src/encoding/json.rs index 252ae1e5f..991072c4e 100644 --- a/opcua-macros/src/json/gen.rs +++ b/opcua-macros/src/encoding/json.rs @@ -1,18 +1,12 @@ use convert_case::{Case, Casing}; use proc_macro2::{Span, TokenStream}; -use syn::{DeriveInput, Ident}; - -use crate::utils::{EmptyAttribute, EncodingFieldAttribute, StructItem}; +use syn::Ident; use quote::quote; -pub type JsonStruct = StructItem; - -pub fn parse_json_struct(input: DeriveInput) -> syn::Result { - JsonStruct::from_input(input) -} +use super::EncodingStruct; -pub fn generate_json_encode_impl(strct: JsonStruct) -> syn::Result { +pub fn generate_json_encode_impl(strct: EncodingStruct) -> syn::Result { let ident = strct.ident; let mut body = quote! {}; for field in strct.fields { @@ -53,7 +47,7 @@ pub fn generate_json_encode_impl(strct: JsonStruct) -> syn::Result }) } -pub fn generate_json_decode_impl(strct: JsonStruct) -> syn::Result { +pub fn generate_json_decode_impl(strct: EncodingStruct) -> syn::Result { let ident = strct.ident; let mut items = quote! {}; let mut items_match = quote! {}; diff --git a/opcua-macros/src/encoding/mod.rs b/opcua-macros/src/encoding/mod.rs new file mode 100644 index 000000000..ae4d72169 --- /dev/null +++ b/opcua-macros/src/encoding/mod.rs @@ -0,0 +1,50 @@ +use attribute::EncodingFieldAttribute; +use binary::{generate_binary_decode_impl, generate_binary_encode_impl}; +use json::{generate_json_decode_impl, generate_json_encode_impl}; +use proc_macro2::TokenStream; +use syn::DeriveInput; +use xml::generate_xml_impl; + +use crate::utils::{EmptyAttribute, StructItem}; + +mod attribute; +mod binary; +#[cfg(feature = "json")] +mod json; +#[cfg(feature = "xml")] +mod xml; + +pub(crate) type EncodingStruct = StructItem; + +pub(crate) fn parse_encoding_input(input: DeriveInput) -> syn::Result { + EncodingStruct::from_input(input) +} + +pub enum EncodingToImpl { + BinaryEncode, + BinaryDecode, + #[cfg(feature = "json")] + JsonEncode, + #[cfg(feature = "json")] + JsonDecode, + #[cfg(feature = "xml")] + FromXml, +} + +pub fn generate_encoding_impl( + input: DeriveInput, + target: EncodingToImpl, +) -> syn::Result { + let input = parse_encoding_input(input)?; + + match target { + EncodingToImpl::BinaryEncode => generate_binary_encode_impl(input), + EncodingToImpl::BinaryDecode => generate_binary_decode_impl(input), + #[cfg(feature = "json")] + EncodingToImpl::JsonEncode => generate_json_encode_impl(input), + #[cfg(feature = "json")] + EncodingToImpl::JsonDecode => generate_json_decode_impl(input), + #[cfg(feature = "xml")] + EncodingToImpl::FromXml => generate_xml_impl(input), + } +} diff --git a/opcua-macros/src/xml/gen.rs b/opcua-macros/src/encoding/xml.rs similarity index 73% rename from opcua-macros/src/xml/gen.rs rename to opcua-macros/src/encoding/xml.rs index f59ffb41b..9b42ee980 100644 --- a/opcua-macros/src/xml/gen.rs +++ b/opcua-macros/src/encoding/xml.rs @@ -1,17 +1,11 @@ use convert_case::{Case, Casing}; use proc_macro2::TokenStream; -use syn::DeriveInput; -use crate::utils::{EmptyAttribute, EncodingFieldAttribute, StructItem}; use quote::quote; -pub type XmlStruct = StructItem; +use super::EncodingStruct; -pub fn parse_xml_struct(input: DeriveInput) -> syn::Result { - XmlStruct::from_input(input) -} - -pub fn generate_xml_impl(strct: XmlStruct) -> syn::Result { +pub fn generate_xml_impl(strct: EncodingStruct) -> syn::Result { let ident = strct.ident; let mut body = quote! {}; let mut build = quote! {}; diff --git a/opcua-macros/src/json/mod.rs b/opcua-macros/src/json/mod.rs deleted file mode 100644 index 7b783a4b2..000000000 --- a/opcua-macros/src/json/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -use gen::{generate_json_decode_impl, generate_json_encode_impl, parse_json_struct}; -use proc_macro2::TokenStream; -use syn::DeriveInput; - -mod gen; - -pub fn derive_json_encode_inner(input: DeriveInput) -> syn::Result { - let struct_data = parse_json_struct(input)?; - generate_json_encode_impl(struct_data) -} - -pub fn derive_json_decode_inner(input: DeriveInput) -> syn::Result { - let struct_data = parse_json_struct(input)?; - generate_json_decode_impl(struct_data) -} diff --git a/opcua-macros/src/lib.rs b/opcua-macros/src/lib.rs index 901421b47..1b39d4fe1 100644 --- a/opcua-macros/src/lib.rs +++ b/opcua-macros/src/lib.rs @@ -2,15 +2,11 @@ //! Crate containing various procedural macros used by rust OPC-UA. -mod binary; +mod encoding; mod events; -#[cfg(feature = "json")] -mod json; mod utils; -#[cfg(feature = "xml")] -mod xml; -use binary::{derive_binary_decode_inner, derive_binary_encode_inner}; +use encoding::{generate_encoding_impl, EncodingToImpl}; use events::{derive_event_field_inner, derive_event_inner}; use proc_macro::TokenStream; use syn::parse_macro_input; @@ -83,9 +79,7 @@ pub fn derive_event_field(item: TokenStream) -> TokenStream { /// /// All fields must be marked with `opcua(ignore)` or implement `FromXml`. pub fn derive_from_xml(item: TokenStream) -> TokenStream { - use xml::derive_from_xml_inner; - - match derive_from_xml_inner(parse_macro_input!(item)) { + match generate_encoding_impl(parse_macro_input!(item), EncodingToImpl::FromXml) { Ok(r) => r.into(), Err(e) => e.to_compile_error().into(), } @@ -98,9 +92,7 @@ pub fn derive_from_xml(item: TokenStream) -> TokenStream { /// /// All fields must be marked with `opcua(ignore)` or implement `JsonEncodable`. pub fn derive_json_encodable(item: TokenStream) -> TokenStream { - use json::derive_json_encode_inner; - - match derive_json_encode_inner(parse_macro_input!(item)) { + match generate_encoding_impl(parse_macro_input!(item), EncodingToImpl::JsonEncode) { Ok(r) => r.into(), Err(e) => e.to_compile_error().into(), } @@ -113,9 +105,7 @@ pub fn derive_json_encodable(item: TokenStream) -> TokenStream { /// /// All fields must be marked with `opcua(ignore)` or implement `JsonDecodable`. pub fn derive_json_decodable(item: TokenStream) -> TokenStream { - use json::derive_json_decode_inner; - - match derive_json_decode_inner(parse_macro_input!(item)) { + match generate_encoding_impl(parse_macro_input!(item), EncodingToImpl::JsonDecode) { Ok(r) => r.into(), Err(e) => e.to_compile_error().into(), } @@ -127,7 +117,7 @@ pub fn derive_json_decodable(item: TokenStream) -> TokenStream { /// /// All fields must be marked with `opcua(ignore)` or implement `BinaryEncodable`. pub fn derive_binary_encodable(item: TokenStream) -> TokenStream { - match derive_binary_encode_inner(parse_macro_input!(item)) { + match generate_encoding_impl(parse_macro_input!(item), EncodingToImpl::BinaryEncode) { Ok(r) => r.into(), Err(e) => e.to_compile_error().into(), } @@ -139,7 +129,7 @@ pub fn derive_binary_encodable(item: TokenStream) -> TokenStream { /// /// All fields must be marked with `opcua(ignore)` or implement `BinaryDecodable`. pub fn derive_binary_decodable(item: TokenStream) -> TokenStream { - match derive_binary_decode_inner(parse_macro_input!(item)) { + match generate_encoding_impl(parse_macro_input!(item), EncodingToImpl::BinaryDecode) { Ok(r) => r.into(), Err(e) => e.to_compile_error().into(), } diff --git a/opcua-macros/src/utils.rs b/opcua-macros/src/utils.rs index cf42b72db..178d12358 100644 --- a/opcua-macros/src/utils.rs +++ b/opcua-macros/src/utils.rs @@ -1,4 +1,4 @@ -use syn::{parse::Parse, DeriveInput, Field, Ident, LitStr, Token, Type}; +use syn::{parse::Parse, DeriveInput, Field, Ident, Type}; #[derive(Debug, Default)] pub struct EmptyAttribute; @@ -32,50 +32,6 @@ pub struct StructItem { pub attribute: TAttr, } -#[derive(Debug, Default)] -pub(super) struct EncodingFieldAttribute { - pub rename: Option, - pub ignore: bool, - pub required: bool, -} - -impl Parse for EncodingFieldAttribute { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let mut slf = Self::default(); - - loop { - let ident: Ident = input.parse()?; - match ident.to_string().as_str() { - "rename" => { - input.parse::()?; - let val: LitStr = input.parse()?; - slf.rename = Some(val.value()); - } - "ignore" => { - slf.ignore = true; - } - "required" => { - slf.required = true; - } - _ => return Err(syn::Error::new_spanned(ident, "Unknown attribute value")), - } - if !input.peek(Token![,]) { - break; - } - input.parse::()?; - } - Ok(slf) - } -} - -impl ItemAttr for EncodingFieldAttribute { - fn combine(&mut self, other: Self) { - self.rename = other.rename; - self.ignore |= other.ignore; - self.required |= other.required; - } -} - impl StructItem { diff --git a/opcua-macros/src/xml/mod.rs b/opcua-macros/src/xml/mod.rs deleted file mode 100644 index 2b02e2ca2..000000000 --- a/opcua-macros/src/xml/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -use gen::{generate_xml_impl, parse_xml_struct}; -use proc_macro2::TokenStream; -use syn::DeriveInput; - -mod gen; - -pub fn derive_from_xml_inner(input: DeriveInput) -> syn::Result { - let struct_data = parse_xml_struct(input)?; - generate_xml_impl(struct_data) -}