opcua_macros/
lib.rs

1//! Crate containing various procedural macros used by rust OPC-UA.
2
3mod encoding;
4mod events;
5mod utils;
6
7use encoding::{
8    derive_all_inner, derive_ua_nullable_inner, generate_encoding_impl, EncodingToImpl,
9};
10use events::{derive_event_field_inner, derive_event_inner};
11use proc_macro::TokenStream;
12use syn::parse_macro_input;
13
14#[proc_macro_derive(Event, attributes(opcua))]
15/// Derive the `Event` trait. This will also generate
16/// an implementation of the `EventField` trait.
17///
18/// The event struct must have an attribute `opcua` containing
19/// the _identifier_ of the node ID, as well as the namespace URI of the event type.
20///
21/// It must also have a field `base` with a different event type, which may be
22/// the `BaseEventType`, and a field `own_namespace_index` storing the namespace index of
23/// the event.
24///
25/// By default, fields will be given `PascalCase` names, you may use `opcua[rename = ...]`
26/// to rename individual fields.
27///
28/// # Example
29///
30/// ```ignore
31/// #[derive(Event)]
32/// #[opcua(identifier = "s=myevent", namespace = "uri:my:namespace")]
33/// struct MyEvent {
34///     base: BaseEventType,
35///     own_namespace_index: u16,
36///     
37///     #[opcua(rename = "my-field")]
38///     my_field: f32,
39///     my_other_field: EUInformation,
40///     #[opcua(ignore)]
41///     ignored: i32,
42/// }
43/// ```
44pub fn derive_event(item: TokenStream) -> TokenStream {
45    match derive_event_inner(parse_macro_input!(item)) {
46        Ok(r) => r.into(),
47        Err(e) => e.to_compile_error().into(),
48    }
49}
50
51#[proc_macro_derive(EventField, attributes(opcua))]
52/// Derive the `EventField` trait.
53///
54/// The event field may have a field `base`, which unless renamed will
55/// be used as the base type for this field.
56///
57/// By default, fields will be given `PascalCase` names, you may use `opcua[rename = ...]`
58/// to rename individual fields.
59///
60/// # Example
61///
62/// ```ignore
63/// #[derive(EventField)]
64/// struct MyEventField {
65///     float: f32,
66/// }
67/// ```
68pub fn derive_event_field(item: TokenStream) -> TokenStream {
69    match derive_event_field_inner(parse_macro_input!(item)) {
70        Ok(r) => r.into(),
71        Err(e) => e.to_compile_error().into(),
72    }
73}
74
75#[cfg(feature = "json")]
76#[proc_macro_derive(JsonEncodable, attributes(opcua))]
77/// Derive the `JsonEncodable` trait on this struct or enum, creating code
78/// to write the struct to a JSON stream on OPC-UA reversible encoding.
79///
80/// All fields must be marked with `opcua(ignore)` or implement `JsonEncodable`.
81pub fn derive_json_encodable(item: TokenStream) -> TokenStream {
82    match generate_encoding_impl(parse_macro_input!(item), EncodingToImpl::JsonEncode) {
83        Ok(r) => r.into(),
84        Err(e) => e.to_compile_error().into(),
85    }
86}
87
88#[cfg(feature = "json")]
89#[proc_macro_derive(JsonDecodable, attributes(opcua))]
90/// Derive the `JsonDecodable` trait on this struct or enum, creating code
91/// to read the struct from an OPC-UA stream with reversible encoding.
92///
93/// All fields must be marked with `opcua(ignore)` or implement `JsonDecodable`.
94pub fn derive_json_decodable(item: TokenStream) -> TokenStream {
95    match generate_encoding_impl(parse_macro_input!(item), EncodingToImpl::JsonDecode) {
96        Ok(r) => r.into(),
97        Err(e) => e.to_compile_error().into(),
98    }
99}
100
101#[proc_macro_derive(BinaryEncodable, attributes(opcua))]
102/// Derive the `BinaryEncodable` trait on this struct or enum, creating code
103/// to write the struct to an OPC-UA binary stream.
104///
105/// All fields must be marked with `opcua(ignore)` or implement `BinaryEncodable`.
106pub fn derive_binary_encodable(item: TokenStream) -> TokenStream {
107    match generate_encoding_impl(parse_macro_input!(item), EncodingToImpl::BinaryEncode) {
108        Ok(r) => r.into(),
109        Err(e) => e.to_compile_error().into(),
110    }
111}
112
113#[proc_macro_derive(BinaryDecodable, attributes(opcua))]
114/// Derive the `BinaryDecodable` trait on this struct or enum, creating code
115/// to read the struct from an OPC-UA binary stream.
116///
117/// All fields must be marked with `opcua(ignore)` or implement `BinaryDecodable`.
118pub fn derive_binary_decodable(item: TokenStream) -> TokenStream {
119    match generate_encoding_impl(parse_macro_input!(item), EncodingToImpl::BinaryDecode) {
120        Ok(r) => r.into(),
121        Err(e) => e.to_compile_error().into(),
122    }
123}
124
125#[proc_macro_derive(UaEnum, attributes(opcua))]
126/// Derive the `UaEnum` trait on this simple enum, creating code to convert it
127/// to and from OPC-UA string representation and its numeric representation.
128/// The enum must have a `repr([int])` attribute.
129///
130/// This also implements `TryFrom<[int]>` for the given `repr`, `Into<[int]>`, `IntoVariant`, and `Default`
131/// if a variant is labeled with `#[opcua(default)]`
132pub fn derive_ua_enum(item: TokenStream) -> TokenStream {
133    match generate_encoding_impl(parse_macro_input!(item), EncodingToImpl::UaEnum) {
134        Ok(r) => r.into(),
135        Err(e) => e.to_compile_error().into(),
136    }
137}
138
139#[cfg(feature = "xml")]
140#[proc_macro_derive(XmlEncodable, attributes(opcua))]
141/// Derive the `XmlEncodable` trait on this struct or enum, creating
142/// code to write the struct as OPC-UA XML.
143///
144/// All fields must be marked with `opcua(ignore)` or implement `XmlEncodable`.
145pub fn derive_xml_encodable(item: TokenStream) -> TokenStream {
146    match generate_encoding_impl(parse_macro_input!(item), EncodingToImpl::XmlEncode) {
147        Ok(r) => r.into(),
148        Err(e) => e.to_compile_error().into(),
149    }
150}
151
152#[cfg(feature = "xml")]
153#[proc_macro_derive(XmlDecodable, attributes(opcua))]
154/// Derive the `XmlDecodable` trait on this struct or enum, creating
155/// code to read the struct from an OPC-UA xml stream.
156///
157/// All fields must be marked with `opcua(ignore)` or implement `XmlDecodable`.
158pub fn derive_xml_decodable(item: TokenStream) -> TokenStream {
159    match generate_encoding_impl(parse_macro_input!(item), EncodingToImpl::XmlDecode) {
160        Ok(r) => r.into(),
161        Err(e) => e.to_compile_error().into(),
162    }
163}
164
165#[cfg(feature = "xml")]
166#[proc_macro_derive(XmlType, attributes(opcua))]
167/// Derive the `XmlType` trait on this struct or enum. This simply exposes
168/// the type name, which can be overridden with an item-level `opcua(rename = ...)` attribute.
169pub fn derive_xml_type(item: TokenStream) -> TokenStream {
170    match generate_encoding_impl(parse_macro_input!(item), EncodingToImpl::XmlType) {
171        Ok(r) => r.into(),
172        Err(e) => e.to_compile_error().into(),
173    }
174}
175
176#[proc_macro_derive(UaNullable, attributes(opcua))]
177/// Derive the `UaNullable` trait on this struct or enum. This indicates whether the
178/// value is null/default in OPC-UA encoding.
179pub fn derive_ua_nullable(item: TokenStream) -> TokenStream {
180    match derive_ua_nullable_inner(parse_macro_input!(item)) {
181        Ok(r) => r.into(),
182        Err(e) => e.to_compile_error().into(),
183    }
184}
185
186#[proc_macro_attribute]
187/// Derive all the standard encoding traits on this struct or enum.
188/// This will derive `BinaryEncodable`, `BinaryDecodable`, `JsonEncodable`, `JsonDecodable`,
189/// `XmlEncodable`, `XmlDecodable`, `XmlType`, and `UaEnum` if the type is a simple enum.
190///
191/// Normal attributes for those still apply. Note that the XML and JSON traits will
192/// be behind `"xml"` and `"json"` feature gates respectively.
193pub fn ua_encodable(_attr: TokenStream, item: TokenStream) -> TokenStream {
194    match derive_all_inner(parse_macro_input!(item)) {
195        Ok(r) => r.into(),
196        Err(e) => e.to_compile_error().into(),
197    }
198}