1#![warn(missing_docs, non_ascii_idents, trivial_numeric_casts,
9 noop_method_call, single_use_lifetimes, trivial_casts,
10 unused_lifetimes, nonstandard_style, variant_size_differences)]
11#![deny(keyword_idents)]
12#![warn(clippy::missing_docs_in_private_items)]
13#![allow(clippy::needless_return, clippy::while_let_on_iterator)]
14
15pub use struct_metadata_derive::{Described, MetadataKind};
16
17use std::collections::HashMap;
18
19#[derive(Debug, PartialEq, Eq, Clone)]
21pub struct Descriptor<Metadata: Default> {
22 pub docs: Option<Vec<&'static str>>,
24 pub metadata: Metadata,
26 pub kind: Kind<Metadata>,
28}
29
30impl<Metadata: MetadataKind> Descriptor<Metadata> {
31 pub fn propagate(&mut self, context: Option<&Metadata> ) {
33 let context = match context {
34 Some(context) => {
35 self.metadata.forward_propagate_context(context);
36 context
37 },
38 None => {
39 &self.metadata
40 }
41 };
42 match &mut self.kind {
43 Kind::Struct { children, .. } => {
44 for child in children {
45 child.metadata.forward_propagate_entry_defaults(context, &child.type_info.metadata);
46 child.type_info.propagate(Some(&child.metadata));
47 child.metadata.backward_propagate_entry_defaults(context, &child.type_info.metadata);
48 }
49 },
50 Kind::Aliased { kind, .. } |
51 Kind::Sequence(kind) |
52 Kind::Option(kind) => {
53 self.metadata.forward_propagate_child_defaults(&kind.metadata);
54 kind.propagate(Some(&self.metadata));
55 self.metadata.backward_propagate_child_defaults(&kind.metadata);
56 },
57 Kind::Mapping(key, value) => {
65 self.metadata.forward_propagate_child_defaults(&key.metadata);
66 self.metadata.forward_propagate_child_defaults(&value.metadata);
67 key.propagate(Some(&self.metadata));
68 value.propagate(Some(&self.metadata));
69 self.metadata.backward_propagate_child_defaults(&value.metadata);
70 self.metadata.backward_propagate_child_defaults(&key.metadata);
71
72 },
73 _ => {}
74 }
75 }
76
77 }
91
92#[derive(Debug, PartialEq, Eq, Clone)]
94#[non_exhaustive]
95pub enum Kind<Metadata: Default> {
96 Struct {
98 name: &'static str,
100 children: Vec<Entry<Metadata>>,
102 },
103 Aliased {
105 name: &'static str,
107 kind: Box<Descriptor<Metadata>>
109 },
110 Enum {
112 name: &'static str,
114 variants: Vec<Variant<Metadata>>,
116 },
117 Sequence( Box<Descriptor<Metadata>> ),
119 Option( Box<Descriptor<Metadata>> ),
121 Mapping( Box<Descriptor<Metadata>>, Box<Descriptor<Metadata>> ),
123 DateTime,
125 String,
127 U128,
129 I128,
131 U64,
133 I64,
135 U32,
137 I32,
139 U16,
141 I16,
143 U8,
145 I8,
147 F64,
149 F32,
151 Bool,
153 JSON,
155 Any,
157}
158
159impl<Metadata: MetadataKind> Kind<Metadata> {
160 pub fn name(&self) -> &'static str {
162 match self {
163 Kind::Struct { name, .. } => name,
164 Kind::Aliased { name, .. } => name,
165 Kind::Enum { name, .. } => name,
166 Kind::Sequence(_) => "sequence",
167 Kind::Option(_) => "option",
168 Kind::Mapping(_, _) => "mapping",
169 Kind::DateTime => "datetime",
170 Kind::String => "string",
171 Kind::U128 => "u128",
172 Kind::I128 => "i128",
173 Kind::U64 => "u64",
174 Kind::I64 => "i64",
175 Kind::U32 => "u32",
176 Kind::I32 => "i32",
177 Kind::U16 => "u16",
178 Kind::I16 => "i16",
179 Kind::U8 => "u8",
180 Kind::I8 => "i8",
181 Kind::F64 => "f64",
182 Kind::F32 => "f32",
183 Kind::Bool => "bool",
184 Kind::JSON => "json",
185 Kind::Any => "any",
186 }
187 }
188
189 pub fn new_struct(name: &'static str, mut children: Vec<Entry<Metadata>>, flattened_children: &mut [Descriptor<Metadata>], flattened_metadata: &mut [Metadata]) -> Self {
194 for (child, meta) in flattened_children.iter_mut().zip(flattened_metadata.iter_mut()) {
195 if let Kind::Struct { children: flattening, .. } = &mut child.kind {
196 for child in flattening.iter_mut() {
197 child.metadata.forward_propagate_entry_defaults(meta, &child.type_info.metadata);
198 child.type_info.propagate(Some(&child.metadata));
199 child.metadata.backward_propagate_entry_defaults(meta, &child.type_info.metadata);
200 }
201 children.append(flattening)
202 }
203 }
204
205 Self::Struct { name, children }
206 }
207}
208
209#[derive(Debug, PartialEq, Eq, Clone)]
211pub struct Variant<Metadata: Default> {
212 pub label: &'static str,
215 pub docs: Option<Vec<&'static str>>,
217 pub metadata: Metadata,
219 pub aliases: &'static [&'static str]
221}
222
223#[derive(Debug, Clone)]
225pub struct Entry<Metadata: Default> {
226 pub label: &'static str,
229 pub docs: Option<Vec<&'static str>>,
231 pub metadata: Metadata,
233 pub type_info: Descriptor<Metadata>,
235 pub has_default: bool,
237 pub aliases: &'static [&'static str]
239}
240
241impl<T: PartialEq + Default> PartialEq for Entry<T> {
242 fn eq(&self, other: &Self) -> bool {
243 self.label == other.label && self.docs == other.docs && self.metadata == other.metadata && self.type_info == other.type_info && self.has_default == other.has_default
244 }
245}
246
247impl<T: Eq + Default> Eq for Entry<T> {}
248
249pub trait Described<M: Default=HashMap<&'static str, &'static str>> {
251 fn metadata() -> Descriptor<M>;
253}
254
255macro_rules! basic_described {
257 ($type_name:ident, $type_macro:ident) => {
258 impl<M: Default> Described<M> for $type_name {
259 fn metadata() -> Descriptor<M> { Descriptor { docs: None, metadata: M::default(), kind: Kind::$type_macro } }
260 }
261 };
262}
263
264basic_described!{String, String}
265basic_described!{i128, I128}
266basic_described!{u128, U128}
267basic_described!{i64, I64}
268basic_described!{u64, U64}
269basic_described!{i32, I32}
270basic_described!{u32, U32}
271basic_described!{i16, I16}
272basic_described!{u16, U16}
273basic_described!{i8, I8}
274basic_described!{u8, U8}
275basic_described!{f64, F64}
276basic_described!{f32, F32}
277basic_described!{bool, Bool}
278
279
280impl<M: Default, T: Described<M>> Described<M> for Option<T> {
281 fn metadata() -> Descriptor<M> {
282 Descriptor {
283 docs: None,
284 metadata: M::default(),
285 kind: Kind::Option(Box::new(T::metadata()))
286 }
287 }
288}
289
290#[cfg(feature = "std")]
291impl<M: Default, T: Described<M>> Described<M> for Box<T> {
292 fn metadata() -> Descriptor<M> { T::metadata() }
293}
294
295#[cfg(feature = "std")]
296impl<M: Default, T: Described<M>> Described<M> for Vec<T> {
297 fn metadata() -> Descriptor<M> {
298 Descriptor {
299 docs: None,
300 metadata: M::default(),
301 kind: Kind::Sequence(Box::new(T::metadata()))
302 }
303 }
304}
305
306#[cfg(feature = "std")]
307impl<M: Default, K: Described<M> + core::hash::Hash, V: Described<M>> Described<M> for HashMap<K, V> {
308 fn metadata() -> Descriptor<M> {
309 Descriptor {
310 docs: None,
311 metadata: M::default(),
312 kind: Kind::Mapping(Box::new(K::metadata()), Box::new(V::metadata()))
313 }
314 }
315}
316
317#[cfg(feature = "chrono")]
318impl<M: Default, Tz: chrono::TimeZone> Described<M> for chrono::DateTime<Tz> {
319 fn metadata() -> Descriptor<M> {
320 Descriptor { docs: None, metadata: M::default(), kind: Kind::DateTime }
321 }
322}
323
324#[cfg(feature = "serde_json")]
325impl<M: Default> Described<M> for serde_json::Value {
326 fn metadata() -> Descriptor<M> {
327 Descriptor { docs: None, metadata: M::default(), kind: Kind::JSON }
328 }
329}
330
331#[cfg(feature = "serde_json")]
332impl<M: Default, K: Described<M>, V: Described<M>> Described<M> for serde_json::Map<K, V> {
333 fn metadata() -> Descriptor<M> {
334 Descriptor {
335 docs: None,
336 metadata: M::default(),
337 kind: Kind::Mapping(Box::new(K::metadata()), Box::new(V::metadata()))
338 }
339 }
340}
341
342pub trait MetadataKind: Default {
344 fn forward_propagate_context(&mut self, _context: &Self) {}
346 fn forward_propagate_entry_defaults(&mut self, _context: &Self, _kind: &Self) {}
348 fn backward_propagate_entry_defaults(&mut self, _context: &Self, _kind: &Self) {}
350 fn forward_propagate_child_defaults(&mut self, _kind: &Self) {}
352 fn backward_propagate_child_defaults(&mut self, _kind: &Self) {}
354}
355
356impl<K, V> MetadataKind for HashMap<K, V> {}
357impl<V> MetadataKind for Vec<V> {}