comnum_spec/blocks/schema/
macros.rs1macro_rules! json_param {
7 ($(#[$m:meta])* $name:ident, $schema:expr $(,)?) => {
8 $(#[$m])*
9 #[derive(Clone, Debug, serde::Deserialize)]
10 #[serde(transparent)]
11 pub(crate) struct $name(pub(crate) serde_json::Value);
12
13 impl $crate::blocks::schema::ParamType for $name {
14 fn schema() -> serde_json::Value {
15 $schema
16 }
17 }
18 };
19}
20
21#[macro_export]
61macro_rules! block_params {
62 (@default required) => { $crate::blocks::schema::ParamDefault::Required };
63 (@default absent) => { $crate::blocks::schema::ParamDefault::Absent("none") };
64 (@default absent $text:literal) => { $crate::blocks::schema::ParamDefault::Absent($text) };
65 (@default $v:expr => $text:literal) => {
66 $crate::blocks::schema::ParamDefault::Value($crate::__macro::json!($v), $text.to_string())
67 };
68 (@default $v:expr) => {
69 $crate::blocks::schema::ParamDefault::Value(
70 $crate::__macro::json!($v),
71 $crate::blocks::schema::shown(stringify!($v)),
72 )
73 };
74 (@or $d:literal) => { $d };
75 (@or $d:literal $v:literal) => { $v };
76 (@bound) => { None };
77 (@bound $b:literal) => { Some(f64::from($b)) };
78 (@choices) => { &[] };
79 (@choices [$($c:literal),+ $(,)?]) => { &[$($c),+] };
80 (@choices ($c:expr)) => { &$c };
81 (@info $v:ident, $field:ident, $ty:ty, [flatten], $($rest:tt)*) => {
82 $v.extend(<$ty as $crate::blocks::schema::Params>::params());
83 };
84 (
85 @info $v:ident, $field:ident, $ty:ty, [$($def:tt)+], [$($unit:literal)?], [$($choices:tt)?],
86 [$($gt:literal)?], [$($ge:literal)?], [$($le:literal)?], [$($lt:literal)?], $doc:expr
87 ) => {
88 $v.push($crate::blocks::schema::ParamInfo {
89 name: stringify!($field),
90 default: $crate::block_params!(@default $($def)+),
91 unit: $crate::block_params!(@or "" $($unit)?),
92 choices: $crate::block_params!(@choices $($choices)?),
93 gt: $crate::block_params!(@bound $($gt)?),
94 ge: $crate::block_params!(@bound $($ge)?),
95 le: $crate::block_params!(@bound $($le)?),
96 lt: $crate::block_params!(@bound $($lt)?),
97 doc: $doc,
98 schema: <$ty as $crate::blocks::schema::ParamType>::schema(),
99 variants: <$ty as $crate::blocks::schema::ParamType>::variants(),
100 fields: <$ty as $crate::blocks::schema::ParamType>::fields(),
101 });
102 };
103 (@take $kind:ident, $m:ident, $params:ident, $field:ident, $ty:ty, [flatten]) => {
104 <$ty as $crate::blocks::schema::Params>::take_from($kind, $m, $params)?
105 };
106 (@take $kind:ident, $m:ident, $params:ident, $field:ident, $ty:ty, [$($def:tt)+]) => {
107 $crate::blocks::schema::take($kind, $m, $params, stringify!($field))?
108 };
109 (
110 $(#[$sattr:meta])*
111 $vis:vis struct $name:ident {
112 $(
113 $(#[$fattr:meta])*
114 $field:ident : $ty:ty [ $($def:tt)+ ]
115 $($unit:literal)?
116 $(one_of $choices:tt)?
117 $(> $gt:literal)?
118 $(>= $ge:literal)?
119 $(<= $le:literal)?
120 $(< $lt:literal)?
121 , $doc:expr ;
122 )*
123 }
124 ) => {
125 $(#[$sattr])*
126 $vis struct $name {
127 $( $(#[$fattr])* $field: $ty, )*
128 }
129
130 impl $crate::blocks::schema::Params for $name {
131 #[allow(unused_mut, reason = "a block without parameters")]
132 fn params() -> Vec<$crate::blocks::schema::ParamInfo> {
133 let mut v = Vec::new();
134 $(
135 $crate::block_params!(
136 @info v, $field, $ty, [$($def)+], [$($unit)?], [$($choices)?],
137 [$($gt)?], [$($ge)?], [$($le)?], [$($lt)?], $doc
138 );
139 )*
140 v
141 }
142
143 #[allow(unused_variables, reason = "a block without parameters")]
144 fn take_from(
145 kind: &str,
146 m: &mut $crate::__macro::Map<String, $crate::__macro::Json>,
147 params: &[$crate::blocks::schema::ParamInfo],
148 ) -> $crate::__macro::Result<Self> {
149 Ok($name {
150 $( $field: $crate::block_params!(@take kind, m, params, $field, $ty, [$($def)+]), )*
151 })
152 }
153 }
154 };
155}