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}