Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restructure encoding macros #12

Merged
merged 1 commit into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions opcua-macros/src/binary/mod.rs

This file was deleted.

47 changes: 47 additions & 0 deletions opcua-macros/src/encoding/attribute.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
pub ignore: bool,
pub required: bool,
}

impl Parse for EncodingFieldAttribute {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let mut slf = Self::default();

loop {
let ident: Ident = input.parse()?;
match ident.to_string().as_str() {
"rename" => {
input.parse::<Token![=]>()?;
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::<Token![,]>()?;
}
Ok(slf)
}
}

impl ItemAttr for EncodingFieldAttribute {
fn combine(&mut self, other: Self) {
self.rename = other.rename;
self.ignore |= other.ignore;
self.required |= other.required;
}
}
Original file line number Diff line number Diff line change
@@ -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<EncodingFieldAttribute, EmptyAttribute>;

pub fn parse_binary_struct(input: DeriveInput) -> syn::Result<BinaryStruct> {
BinaryStruct::from_input(input)
}

pub fn generate_binary_encode_impl(strct: BinaryStruct) -> syn::Result<TokenStream> {
pub fn generate_binary_encode_impl(strct: EncodingStruct) -> syn::Result<TokenStream> {
let mut byte_len_body = quote! {};
let mut encode_body = quote! {};

Expand Down Expand Up @@ -50,7 +43,7 @@ pub fn generate_binary_encode_impl(strct: BinaryStruct) -> syn::Result<TokenStre
})
}

pub fn generate_binary_decode_impl(strct: BinaryStruct) -> syn::Result<TokenStream> {
pub fn generate_binary_decode_impl(strct: EncodingStruct) -> syn::Result<TokenStream> {
let mut decode_impl = quote! {};
let mut decode_build = quote! {};

Expand Down
14 changes: 4 additions & 10 deletions opcua-macros/src/json/gen.rs → opcua-macros/src/encoding/json.rs
Original file line number Diff line number Diff line change
@@ -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<EncodingFieldAttribute, EmptyAttribute>;

pub fn parse_json_struct(input: DeriveInput) -> syn::Result<JsonStruct> {
JsonStruct::from_input(input)
}
use super::EncodingStruct;

pub fn generate_json_encode_impl(strct: JsonStruct) -> syn::Result<TokenStream> {
pub fn generate_json_encode_impl(strct: EncodingStruct) -> syn::Result<TokenStream> {
let ident = strct.ident;
let mut body = quote! {};
for field in strct.fields {
Expand Down Expand Up @@ -53,7 +47,7 @@ pub fn generate_json_encode_impl(strct: JsonStruct) -> syn::Result<TokenStream>
})
}

pub fn generate_json_decode_impl(strct: JsonStruct) -> syn::Result<TokenStream> {
pub fn generate_json_decode_impl(strct: EncodingStruct) -> syn::Result<TokenStream> {
let ident = strct.ident;
let mut items = quote! {};
let mut items_match = quote! {};
Expand Down
50 changes: 50 additions & 0 deletions opcua-macros/src/encoding/mod.rs
Original file line number Diff line number Diff line change
@@ -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<EncodingFieldAttribute, EmptyAttribute>;

pub(crate) fn parse_encoding_input(input: DeriveInput) -> syn::Result<EncodingStruct> {
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<TokenStream> {
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),
}
}
10 changes: 2 additions & 8 deletions opcua-macros/src/xml/gen.rs → opcua-macros/src/encoding/xml.rs
Original file line number Diff line number Diff line change
@@ -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<EncodingFieldAttribute, EmptyAttribute>;
use super::EncodingStruct;

pub fn parse_xml_struct(input: DeriveInput) -> syn::Result<XmlStruct> {
XmlStruct::from_input(input)
}

pub fn generate_xml_impl(strct: XmlStruct) -> syn::Result<TokenStream> {
pub fn generate_xml_impl(strct: EncodingStruct) -> syn::Result<TokenStream> {
let ident = strct.ident;
let mut body = quote! {};
let mut build = quote! {};
Expand Down
15 changes: 0 additions & 15 deletions opcua-macros/src/json/mod.rs

This file was deleted.

24 changes: 7 additions & 17 deletions opcua-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(),
}
Expand All @@ -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(),
}
Expand All @@ -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(),
}
Expand All @@ -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(),
}
Expand All @@ -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(),
}
Expand Down
46 changes: 1 addition & 45 deletions opcua-macros/src/utils.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -32,50 +32,6 @@ pub struct StructItem<TFieldAttr, TAttr> {
pub attribute: TAttr,
}

#[derive(Debug, Default)]
pub(super) struct EncodingFieldAttribute {
pub rename: Option<String>,
pub ignore: bool,
pub required: bool,
}

impl Parse for EncodingFieldAttribute {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let mut slf = Self::default();

loop {
let ident: Ident = input.parse()?;
match ident.to_string().as_str() {
"rename" => {
input.parse::<Token![=]>()?;
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::<Token![,]>()?;
}
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<TFieldAttr: Parse + ItemAttr + Default, TAttr: Parse + ItemAttr + Default>
StructItem<TFieldAttr, TAttr>
{
Expand Down
10 changes: 0 additions & 10 deletions opcua-macros/src/xml/mod.rs

This file was deleted.

Loading