Skip to main content

dataport_macros/
lib.rs

1// Copyright © 2025 Stephan Kunz
2//! Macros for port and port collection creation.
3
4#[doc(hidden)]
5extern crate proc_macro;
6
7mod implementation;
8
9use proc_macro::TokenStream;
10use quote::{ToTokens, quote};
11use syn::parse_macro_input;
12
13use crate::implementation::{Params, PortVariant, quote_from_input, quote_from_type, quote_from_value};
14
15/// Creates an array of ports.
16/// # Usage:
17/// port_array!(<comma_separated_list_of_name/port_pairs>)
18///
19/// Best to use with port generation macros:
20/// port_array!(
21///     inbound!(<name>, <type>, <value>),
22///     outbound!(<name>, <type>),
23///     inoutbound!(<name>. <value>)
24/// )
25#[proc_macro]
26pub fn create_port_array(input: TokenStream) -> TokenStream {
27	let output: proc_macro2::TokenStream = input.into();
28	quote! {
29		dataport::PortArray::from_array([#output])
30	}
31	.into()
32}
33
34/// Creates a list of ports.
35/// # Usage:
36/// port_list!(<comma_separated_list_of_name/port_pairs>)
37///
38/// Best to use with port generation macros:
39/// port_list!(
40///     inoutbound!(<name>, <type>, <value>),
41///     inbound!(<name>, <type>),
42///     outbound!(<name>. <value>)
43/// )
44#[proc_macro]
45pub fn create_port_vec(input: TokenStream) -> TokenStream {
46	let output: proc_macro2::TokenStream = input.into();
47	quote! {
48		dataport::PortVec::from_array([#output])
49	}
50	.into()
51}
52
53/// Creates a map of ports.
54/// # Usage:
55/// port_map!(<comma_separated_list_of_name/port_pairs>)
56///
57/// Best to use with port generation macros:
58/// port_map!(
59///     outbound!(<name>, <type>, <value>),
60///     inoutbound!(<name>, <type>),
61///     inbound!(<name>. <value>)
62/// )
63#[proc_macro]
64pub fn create_port_map(input: TokenStream) -> TokenStream {
65	let output: proc_macro2::TokenStream = input.into();
66	quote! {
67		dataport::PortMap::from_array([#output])
68	}
69	.into()
70}
71
72/// Creates a name/inbound_port pair.
73/// # Usages:
74/// inbound!(name, type)
75/// inbound!(name, value)
76/// inbound!(name, type, value)
77#[proc_macro]
78pub fn create_inbound_entry(input: TokenStream) -> TokenStream {
79	let params = parse_macro_input!(input as Params);
80
81	let name = params.port_name;
82	if let Some(value) = params.port_value {
83		if let Some(tp) = params.port_type {
84			quote_from_input(name, tp, value, params.collection, PortVariant::InBound, false).into()
85		} else {
86			quote_from_value(PortVariant::InBound, name, value.to_token_stream(), false).into()
87		}
88	} else if let Some(tp) = params.port_type {
89		quote_from_type(PortVariant::InBound, name, tp, false).into()
90	} else {
91		panic!("missing type or value as parameter")
92	}
93}
94
95/// Creates a name/inbound_port pair with a parseable data type.
96/// # Usages:
97/// inbound!(name, type)
98/// inbound!(name, value)
99/// inbound!(name, type, value)
100#[proc_macro]
101pub fn create_inbound_entry_parseable(input: TokenStream) -> TokenStream {
102	let params = parse_macro_input!(input as Params);
103
104	let name = params.port_name;
105	if let Some(value) = params.port_value {
106		if let Some(tp) = params.port_type {
107			quote_from_input(name, tp, value, params.collection, PortVariant::InBound, true).into()
108		} else {
109			quote_from_value(PortVariant::InBound, name, value.to_token_stream(), true).into()
110		}
111	} else if let Some(tp) = params.port_type {
112		quote_from_type(PortVariant::InBound, name, tp, true).into()
113	} else {
114		panic!("missing type or value as parameter")
115	}
116}
117
118/// Creates a name/inoutbound_port pair.
119/// # Usages:
120/// inoutbound!(name, type)
121/// inoutbound!(name, value)
122/// inoutbound!(name, type, value)
123#[proc_macro]
124pub fn create_inoutbound_entry(input: TokenStream) -> TokenStream {
125	let params = parse_macro_input!(input as Params);
126
127	let name = params.port_name;
128	if let Some(value) = params.port_value {
129		if let Some(tp) = params.port_type {
130			quote_from_input(name, tp, value, params.collection, PortVariant::InOutBound, false).into()
131		} else {
132			quote_from_value(PortVariant::InOutBound, name, value.to_token_stream(), false).into()
133		}
134	} else if let Some(tp) = params.port_type {
135		quote_from_type(PortVariant::InOutBound, name, tp, false).into()
136	} else {
137		panic!("missing type or value as parameter")
138	}
139}
140
141/// Creates a name/inoutbound_port pair with a parseable data type.
142/// # Usages:
143/// inoutbound!(name, type)
144/// inoutbound!(name, value)
145/// inoutbound!(name, type, value)
146#[proc_macro]
147pub fn create_inoutbound_entry_parseable(input: TokenStream) -> TokenStream {
148	let params = parse_macro_input!(input as Params);
149
150	let name = params.port_name;
151	if let Some(value) = params.port_value {
152		if let Some(tp) = params.port_type {
153			quote_from_input(name, tp, value, params.collection, PortVariant::InOutBound, true).into()
154		} else {
155			quote_from_value(PortVariant::InOutBound, name, value.to_token_stream(), true).into()
156		}
157	} else if let Some(tp) = params.port_type {
158		quote_from_type(PortVariant::InOutBound, name, tp, true).into()
159	} else {
160		panic!("missing type or value as parameter")
161	}
162}
163
164/// Creates a name/outbound_port pair.
165/// # Usages:
166/// outbound!(name, type)
167/// outbound!(name, value)
168/// outbound!(name, type, value)
169#[proc_macro]
170pub fn create_outbound_entry(input: TokenStream) -> TokenStream {
171	let params = parse_macro_input!(input as Params);
172
173	let name = params.port_name;
174	if let Some(value) = params.port_value {
175		if let Some(tp) = params.port_type {
176			quote_from_input(name, tp, value, params.collection, PortVariant::OutBound, false).into()
177		} else {
178			quote_from_value(PortVariant::OutBound, name, value.to_token_stream(), false).into()
179		}
180	} else if let Some(tp) = params.port_type {
181		quote_from_type(PortVariant::OutBound, name, tp, false).into()
182	} else {
183		panic!("missing type or value as parameter")
184	}
185}
186/// Creates a name/outbound_port pair with a parseable data type.
187/// # Usages:
188/// outbound!(name, type)
189/// outbound!(name, value)
190/// outbound!(name, type, value)
191#[proc_macro]
192pub fn create_outbound_entry_parseable(input: TokenStream) -> TokenStream {
193	let params = parse_macro_input!(input as Params);
194
195	let name = params.port_name;
196	if let Some(value) = params.port_value {
197		if let Some(tp) = params.port_type {
198			quote_from_input(name, tp, value, params.collection, PortVariant::OutBound, true).into()
199		} else {
200			quote_from_value(PortVariant::OutBound, name, value.to_token_stream(), true).into()
201		}
202	} else if let Some(tp) = params.port_type {
203		quote_from_type(PortVariant::OutBound, name, tp, true).into()
204	} else {
205		panic!("missing type or value as parameter")
206	}
207}