miniconf/
tree.rs

1use core::{any::Any, num::NonZero};
2
3use serde::{Deserializer, Serializer};
4
5use crate::{Error, IntoKeys, Keys, Node, NodeIter, Transcode, Traversal, Walk};
6
7/// Traversal, iteration of keys in a tree.
8///
9/// See also the sub-traits [`TreeSerialize`], [`TreeDeserialize`], [`TreeAny`].
10///
11/// # Keys
12///
13/// There is a one-to-one relationship between nodes and keys.
14/// The keys used to identify nodes support [`Keys`]/[`IntoKeys`]. They can be
15/// obtained from other [`IntoKeys`] through [`Transcode`]/[`TreeKey::transcode()`].
16/// An iterator of keys for the nodes is available through [`TreeKey::nodes()`]/[`NodeIter`].
17///
18/// * `usize` is modelled after ASN.1 Object Identifiers, see [`crate::Indices`].
19/// * `&str` keys are sequences of names, like path names. When concatenated, they are separated
20///   by some path hierarchy separator, e.g. `'/'`, see [`crate::Path`], or by some more
21///   complex notation, see [`crate::JsonPath`].
22/// * [`crate::Packed`] is a bit-packed compact compressed notation of
23///   hierarchical compound indices.
24/// * See the `scpi` example for how to implement case-insensitive, relative, and abbreviated/partial
25///   matches.
26///
27/// # Derive macros
28///
29/// Derive macros to automatically implement the correct traits on a struct or enum are available through
30/// [`macro@crate::TreeKey`], [`macro@crate::TreeSerialize`], [`macro@crate::TreeDeserialize`],
31/// and [`macro@crate::TreeAny`].
32/// A shorthand derive macro that derives all four trait implementations is also available at
33/// [`macro@crate::Tree`].
34///
35/// The derive macros support per-field/per-variant attributes to control the derived trait implementations.
36///
37/// ## Rename
38///
39/// The key for named struct fields or enum variants may be changed from the default field ident using
40/// the `rename` derive macro attribute.
41///
42/// ```
43/// use miniconf::{Leaf, Path, Tree, TreeKey};
44/// #[derive(Tree, Default)]
45/// struct S {
46///     #[tree(rename = "OTHER")]
47///     a: Leaf<f32>,
48/// };
49/// let (name, _node) = S::transcode::<Path<String, '/'>, _>([0usize]).unwrap();
50/// assert_eq!(name.as_str(), "/OTHER");
51/// ```
52///
53/// ## Skip
54///
55/// Named fields/variants may be omitted from the derived `Tree` trait implementations using the
56/// `skip` attribute.
57/// Note that for tuple structs skipping is only supported for terminal fields:
58///
59/// ```
60/// use miniconf::{Leaf, Tree};
61/// #[derive(Tree)]
62/// struct S(Leaf<i32>, #[tree(skip)] ());
63/// ```
64///
65/// ```compile_fail
66/// use miniconf::{Tree, Leaf};
67/// #[derive(Tree)]
68/// struct S(#[tree(skip)] (), Leaf<i32>);
69/// ```
70///
71/// ## Type
72///
73/// The type to use when accessing the field/variant through `TreeKey`/`TreeDeserialize::probe`
74/// can be overridden using the `typ` derive macro attribute (`#[tree(typ="[f32; 4]")]`).
75///
76/// ## Deny
77///
78/// `#[tree(deny(operation="message", ...))]`
79///
80/// This returns `Err(`[`Traversal::Access`]`)` for the respective operation
81/// (`traverse`, `serialize`, `deserialize`, `probe`, `ref_any`, `mut_any`) on a
82/// field/variant and suppresses the respective traits bounds on type paramters
83/// of the struct/enum.
84///
85/// ## Implementation overrides
86///
87/// `#[tree(with(operation=expr, ...))]`
88///
89/// This overrides the call to the child node/variant trait for the given `operation`
90/// (`traverse`, `traverse_all`, `serialize`, `deserialize`, `probe`, `ref_any`, `mut_any`).
91/// `expr` should be a method on `self` (not the field!) or `value`
92/// (associated function for `traverse`, `traverse_all` and `probe`)
93/// taking the arguments of the respective trait's method.
94///
95/// ```
96/// # use miniconf::{Error, Leaf, Tree, Keys, Traversal, TreeDeserialize};
97/// # use serde::Deserializer;
98/// #[derive(Tree, Default)]
99/// struct S {
100///     #[tree(with(deserialize=self.check))]
101///     b: Leaf<f32>,
102/// };
103/// impl S {
104///     fn check<'de, K: Keys, D: Deserializer<'de>>(&mut self, keys: K, de: D) -> Result<(), Error<D::Error>> {
105///         let old = *self.b;
106///         self.b.deserialize_by_key(keys, de)?;
107///         if *self.b < 0.0 {
108///             *self.b = old;
109///             Err(Traversal::Access(0, "fail").into())
110///         } else {
111///             Ok(())
112///         }
113///     }
114/// }
115/// ```
116///
117/// ### `defer`
118///
119/// The `defer` attribute is a shorthand for `with()` that defers
120/// child trait implementations to a given expression.
121///
122/// # Array
123///
124/// Blanket implementations of the `Tree*` traits are provided for homogeneous arrays
125/// [`[T; N]`](core::array).
126///
127/// # Option
128///
129/// Blanket implementations of the `Tree*` traits are provided for [`Option<T>`].
130///
131/// These implementations do not alter the path hierarchy and do not consume any items from the `keys`
132/// iterators. The `TreeKey` behavior of an [`Option`] is such that the `None` variant makes the
133/// corresponding part of the tree inaccessible at run-time. It will still be iterated over (e.g.
134/// by [`TreeKey::nodes()`]) but attempts to access it (e.g. [`TreeSerialize::serialize_by_key()`],
135/// [`TreeDeserialize::deserialize_by_key()`], [`TreeAny::ref_any_by_key()`], or
136/// [`TreeAny::mut_any_by_key()`]) return the special [`Traversal::Absent`].
137///
138/// This is the same behavior as for other `enums` that have the `Tree*` traits derived.
139///
140/// # Tuples
141///
142/// Blanket impementations for the `Tree*` traits are provided for heterogeneous tuples `(T0, T1, ...)`
143/// up to length eight.
144///
145/// # Examples
146///
147/// See the [`crate`] documentation for a longer example showing how the traits and the derive
148/// macros work.
149pub trait TreeKey {
150    /// Walk metadata about all paths.
151    ///
152    /// ```
153    /// use miniconf::{Leaf, Metadata, TreeKey};
154    /// #[derive(TreeKey)]
155    /// struct S {
156    ///     foo: Leaf<u32>,
157    ///     bar: [Leaf<u16>; 2],
158    /// };
159    /// let m: Metadata = S::traverse_all();
160    /// assert_eq!((m.max_depth, m.max_length, m.count.get()), (2, 4, 3));
161    /// ```
162    fn traverse_all<W: Walk>() -> W;
163
164    /// Traverse from the root to a leaf and call a function for each node.
165    ///
166    /// If a leaf is found early (`keys` being longer than required)
167    /// `Err(Traversal(TooLong(depth)))` is returned.
168    /// If `keys` is exhausted before reaching a leaf node,
169    /// `Err(Traversal(TooShort(depth)))` is returned.
170    /// `Traversal::Access/Invalid/Absent/Finalization` are never returned.
171    ///
172    /// This method should fail if and only if the key is invalid.
173    /// It should succeed at least when any of the other key based methods
174    /// in `TreeAny`, `TreeSerialize`, and `TreeDeserialize` succeed.
175    ///
176    /// ```
177    /// use miniconf::{IntoKeys, Leaf, TreeKey};
178    /// #[derive(TreeKey)]
179    /// struct S {
180    ///     foo: Leaf<u32>,
181    ///     bar: [Leaf<u16>; 2],
182    /// };
183    /// let mut ret = [(1, Some("bar"), 2), (0, None, 2)].into_iter();
184    /// let func = |index, name, len: core::num::NonZero<usize>| -> Result<(), ()> {
185    ///     assert_eq!(ret.next().unwrap(), (index, name, len.get()));
186    ///     Ok(())
187    /// };
188    /// assert_eq!(S::traverse_by_key(["bar", "0"].into_keys(), func), Ok(2));
189    /// ```
190    ///
191    /// # Args
192    /// * `keys`: An `Iterator` of `Key`s identifying the node.
193    /// * `func`: A `FnMut` to be called for each (internal and leaf) node on the path.
194    ///   Its arguments are the index and the optional name of the node and the number
195    ///   of top-level nodes at the given depth. Returning `Err(E)` aborts the traversal.
196    ///   Returning `Ok(())` continues the downward traversal.
197    ///
198    /// # Returns
199    /// Node depth on success (number of keys consumed/number of calls to `func`)
200    ///
201    /// # Design note
202    /// Writing this to return an iterator instead of using a callback
203    /// would have worse performance (O(n^2) instead of O(n) for matching)
204    fn traverse_by_key<K, F, E>(keys: K, func: F) -> Result<usize, Error<E>>
205    where
206        K: Keys,
207        F: FnMut(usize, Option<&'static str>, NonZero<usize>) -> Result<(), E>;
208
209    /// Transcode keys to a new keys type representation
210    ///
211    /// The keys can be
212    /// * too short: the internal node is returned
213    /// * matched length: the leaf node is returned
214    /// * too long: Err(TooLong(depth)) is returned
215    ///
216    /// In order to not require `N: Default`, use [`Transcode::transcode`] on
217    /// an existing `&mut N`.
218    ///
219    /// ```
220    /// use miniconf::{Indices, JsonPath, Leaf, Node, Packed, Path, TreeKey};
221    /// #[derive(TreeKey)]
222    /// struct S {
223    ///     foo: Leaf<u32>,
224    ///     bar: [Leaf<u16>; 5],
225    /// };
226    ///
227    /// let idx = [1, 1];
228    ///
229    /// let (path, node) = S::transcode::<Path<String, '/'>, _>(idx).unwrap();
230    /// assert_eq!(path.as_str(), "/bar/1");
231    /// let (path, node) = S::transcode::<JsonPath<String>, _>(idx).unwrap();
232    /// assert_eq!(path.as_str(), ".bar[1]");
233    /// let (indices, node) = S::transcode::<Indices<[_; 2]>, _>(&path).unwrap();
234    /// assert_eq!(&indices[..node.depth()], idx);
235    /// let (indices, node) = S::transcode::<Indices<[_; 2]>, _>(["bar", "1"]).unwrap();
236    /// assert_eq!(&indices[..node.depth()], [1, 1]);
237    /// let (packed, node) = S::transcode::<Packed, _>(["bar", "4"]).unwrap();
238    /// assert_eq!(packed.into_lsb().get(), 0b1_1_100);
239    /// let (path, node) = S::transcode::<Path<String, '/'>, _>(packed).unwrap();
240    /// assert_eq!(path.as_str(), "/bar/4");
241    /// let ((), node) = S::transcode(&path).unwrap();
242    /// assert_eq!(node, Node::leaf(2));
243    /// ```
244    ///
245    /// # Args
246    /// * `keys`: `IntoKeys` to identify the node.
247    ///
248    /// # Returns
249    /// Transcoded target and node information on success
250    #[inline]
251    fn transcode<N, K>(keys: K) -> Result<(N, Node), Traversal>
252    where
253        K: IntoKeys,
254        N: Transcode + Default,
255    {
256        let mut target = N::default();
257        let node = target.transcode::<Self, _>(keys)?;
258        Ok((target, node))
259    }
260
261    /// Return an iterator over nodes of a given type
262    ///
263    /// This is a walk of all leaf nodes.
264    /// The iterator will walk all paths, including those that may be absent at
265    /// runtime (see [`TreeKey#option`]).
266    /// An iterator with an exact and trusted `size_hint()` can be obtained from
267    /// this through [`NodeIter::exact_size()`].
268    /// The `D` const generic of [`NodeIter`] is the maximum key depth.
269    ///
270    /// ```
271    /// use miniconf::{Indices, JsonPath, Leaf, Node, Packed, Path, TreeKey};
272    /// #[derive(TreeKey)]
273    /// struct S {
274    ///     foo: Leaf<u32>,
275    ///     bar: [Leaf<u16>; 2],
276    /// };
277    ///
278    /// let paths: Vec<_> = S::nodes::<Path<String, '/'>, 2>()
279    ///     .exact_size()
280    ///     .map(|p| p.unwrap().0.into_inner())
281    ///     .collect();
282    /// assert_eq!(paths, ["/foo", "/bar/0", "/bar/1"]);
283    ///
284    /// let paths: Vec<_> = S::nodes::<JsonPath<String>, 2>()
285    ///     .exact_size()
286    ///     .map(|p| p.unwrap().0.into_inner())
287    ///     .collect();
288    /// assert_eq!(paths, [".foo", ".bar[0]", ".bar[1]"]);
289    ///
290    /// let indices: Vec<_> = S::nodes::<Indices<[_; 2]>, 2>()
291    ///     .exact_size()
292    ///     .map(|p| {
293    ///         let (idx, node) = p.unwrap();
294    ///         (idx.into_inner(), node.depth)
295    ///     })
296    ///     .collect();
297    /// assert_eq!(indices, [([0, 0], 1), ([1, 0], 2), ([1, 1], 2)]);
298    ///
299    /// let packed: Vec<_> = S::nodes::<Packed, 2>()
300    ///     .exact_size()
301    ///     .map(|p| p.unwrap().0.into_lsb().get())
302    ///     .collect();
303    /// assert_eq!(packed, [0b1_0, 0b1_1_0, 0b1_1_1]);
304    ///
305    /// let nodes: Vec<_> = S::nodes::<(), 2>()
306    ///     .exact_size()
307    ///     .map(|p| p.unwrap().1)
308    ///     .collect();
309    /// assert_eq!(nodes, [Node::leaf(1), Node::leaf(2), Node::leaf(2)]);
310    /// ```
311    #[inline]
312    fn nodes<N, const D: usize>() -> NodeIter<Self, N, D>
313    where
314        N: Transcode + Default,
315    {
316        NodeIter::default()
317    }
318}
319
320/// Access any node by keys.
321///
322/// This uses the `dyn Any` trait object.
323///
324/// ```
325/// use core::any::Any;
326/// use miniconf::{Indices, IntoKeys, JsonPath, Leaf, TreeAny, TreeKey};
327/// #[derive(TreeKey, TreeAny, Default)]
328/// struct S {
329///     foo: Leaf<u32>,
330///     bar: [Leaf<u16>; 2],
331/// };
332/// let mut s = S::default();
333///
334/// for node in S::nodes::<Indices<[_; 2]>, 2>() {
335///     let (key, node) = node.unwrap();
336///     let a = s
337///         .ref_any_by_key(key.into_iter().take(node.depth()).into_keys())
338///         .unwrap();
339///     assert!([0u32.type_id(), 0u16.type_id()].contains(&(&*a).type_id()));
340/// }
341///
342/// let val: &mut u16 = s.mut_by_key(&JsonPath::from(".bar[1]")).unwrap();
343/// *val = 3;
344/// assert_eq!(*s.bar[1], 3);
345///
346/// let val: &u16 = s.ref_by_key(&JsonPath::from(".bar[1]")).unwrap();
347/// assert_eq!(*val, 3);
348/// ```
349pub trait TreeAny {
350    /// Obtain a reference to a `dyn Any` trait object for a leaf node.
351    fn ref_any_by_key<K>(&self, keys: K) -> Result<&dyn Any, Traversal>
352    where
353        K: Keys;
354
355    /// Obtain a mutable reference to a `dyn Any` trait object for a leaf node.
356    fn mut_any_by_key<K>(&mut self, keys: K) -> Result<&mut dyn Any, Traversal>
357    where
358        K: Keys;
359
360    /// Obtain a reference to a leaf of known type by key.
361    #[inline]
362    fn ref_by_key<T: Any, K: IntoKeys>(&self, keys: K) -> Result<&T, Traversal> {
363        self.ref_any_by_key(keys.into_keys())?
364            .downcast_ref()
365            .ok_or(Traversal::Access(0, "Incorrect type"))
366    }
367
368    /// Obtain a mutable reference to a leaf of known type by key.
369    #[inline]
370    fn mut_by_key<T: Any, K: IntoKeys>(&mut self, keys: K) -> Result<&mut T, Traversal> {
371        self.mut_any_by_key(keys.into_keys())?
372            .downcast_mut()
373            .ok_or(Traversal::Access(0, "Incorrect type"))
374    }
375}
376
377/// Serialize a leaf node by its keys.
378///
379/// See also [`crate::json`] or `crate::postcard` for convenient wrappers using this trait.
380///
381/// # Derive macro
382///
383/// See [`macro@crate::TreeSerialize`].
384/// The derive macro attributes are described in the [`TreeKey`] trait.
385pub trait TreeSerialize {
386    /// Serialize a node by keys.
387    ///
388    /// ```
389    /// # #[cfg(feature = "json-core")] {
390    /// use miniconf::{IntoKeys, Leaf, TreeKey, TreeSerialize};
391    /// #[derive(TreeKey, TreeSerialize)]
392    /// struct S {
393    ///     foo: Leaf<u32>,
394    ///     bar: [Leaf<u16>; 2],
395    /// };
396    /// let s = S {
397    ///     foo: 9.into(),
398    ///     bar: [11.into(), 3.into()],
399    /// };
400    /// let mut buf = [0u8; 10];
401    /// let mut ser = serde_json_core::ser::Serializer::new(&mut buf);
402    /// s.serialize_by_key(["bar", "0"].into_keys(), &mut ser)
403    ///     .unwrap();
404    /// let len = ser.end();
405    /// assert_eq!(&buf[..len], b"11");
406    /// # }
407    /// ```
408    ///
409    /// # Args
410    /// * `keys`: A `Keys` identifying the node.
411    /// * `ser`: A `Serializer` to to serialize the value.
412    fn serialize_by_key<K, S>(&self, keys: K, ser: S) -> Result<S::Ok, Error<S::Error>>
413    where
414        K: Keys,
415        S: Serializer;
416}
417
418/// Deserialize a leaf node by its keys.
419///
420/// See also [`crate::json`] or `crate::postcard` for convenient wrappers using this trait.
421///
422/// # Derive macro
423///
424/// See [`macro@crate::TreeDeserialize`].
425/// The derive macro attributes are described in the [`TreeKey`] trait.
426pub trait TreeDeserialize<'de> {
427    /// Deserialize a leaf node by its keys.
428    ///
429    /// ```
430    /// # #[cfg(feature = "derive")] {
431    /// use miniconf::{IntoKeys, Leaf, TreeDeserialize, TreeKey};
432    /// #[derive(Default, TreeKey, TreeDeserialize)]
433    /// struct S {
434    ///     foo: Leaf<u32>,
435    ///     bar: [Leaf<u16>; 2],
436    /// };
437    /// let mut s = S::default();
438    /// let mut de = serde_json::de::Deserializer::from_slice(b"7");
439    /// s.deserialize_by_key(["bar", "0"].into_keys(), &mut de)
440    ///     .unwrap();
441    /// de.end().unwrap();
442    /// assert_eq!(*s.bar[0], 7);
443    /// # }
444    /// ```
445    ///
446    /// # Args
447    /// * `keys`: A `Keys` identifying the node.
448    /// * `de`: A `Deserializer` to deserialize the value.
449    fn deserialize_by_key<K, D>(&mut self, keys: K, de: D) -> Result<(), Error<D::Error>>
450    where
451        K: Keys,
452        D: Deserializer<'de>;
453
454    /// Blind deserialize a leaf node by its keys.
455    ///
456    /// This method should succeed at least in those cases where
457    /// `deserialize_by_key()` succeeds.
458    ///
459    /// ```
460    /// # #[cfg(feature = "derive")] {
461    /// use miniconf::{IntoKeys, Leaf, TreeDeserialize, TreeKey};
462    /// #[derive(Default, TreeKey, TreeDeserialize)]
463    /// struct S {
464    ///     foo: Leaf<u32>,
465    ///     bar: [Leaf<u16>; 2],
466    /// };
467    /// let mut de = serde_json::de::Deserializer::from_slice(b"7");
468    /// S::probe_by_key(["bar", "0"].into_keys(), &mut de)
469    ///     .unwrap();
470    /// de.end().unwrap();
471    /// # }
472    /// ```
473    ///
474    /// # Args
475    /// * `keys`: A `Keys` identifying the node.
476    /// * `de`: A `Deserializer` to deserialize the value.
477    fn probe_by_key<K, D>(keys: K, de: D) -> Result<(), Error<D::Error>>
478    where
479        K: Keys,
480        D: Deserializer<'de>;
481}
482
483/// Shorthand for owned deserialization through [`TreeDeserialize`].
484pub trait TreeDeserializeOwned: for<'de> TreeDeserialize<'de> {}
485impl<T> TreeDeserializeOwned for T where T: for<'de> TreeDeserialize<'de> {}
486
487// Blanket impls for refs and muts
488
489impl<T: TreeKey> TreeKey for &T {
490    #[inline]
491    fn traverse_all<W: Walk>() -> W {
492        T::traverse_all()
493    }
494
495    #[inline]
496    fn traverse_by_key<K, F, E>(keys: K, func: F) -> Result<usize, Error<E>>
497    where
498        K: Keys,
499        F: FnMut(usize, Option<&'static str>, NonZero<usize>) -> Result<(), E>,
500    {
501        T::traverse_by_key(keys, func)
502    }
503}
504
505impl<T: TreeKey> TreeKey for &mut T {
506    #[inline]
507    fn traverse_all<W: Walk>() -> W {
508        T::traverse_all()
509    }
510
511    #[inline]
512    fn traverse_by_key<K, F, E>(keys: K, func: F) -> Result<usize, Error<E>>
513    where
514        K: Keys,
515        F: FnMut(usize, Option<&'static str>, NonZero<usize>) -> Result<(), E>,
516    {
517        T::traverse_by_key(keys, func)
518    }
519}
520
521impl<T: TreeSerialize> TreeSerialize for &T {
522    #[inline]
523    fn serialize_by_key<K, S>(&self, keys: K, ser: S) -> Result<S::Ok, Error<S::Error>>
524    where
525        K: Keys,
526        S: Serializer,
527    {
528        (**self).serialize_by_key(keys, ser)
529    }
530}
531
532impl<T: TreeSerialize> TreeSerialize for &mut T {
533    #[inline]
534    fn serialize_by_key<K, S>(&self, keys: K, ser: S) -> Result<S::Ok, Error<S::Error>>
535    where
536        K: Keys,
537        S: Serializer,
538    {
539        (**self).serialize_by_key(keys, ser)
540    }
541}
542
543impl<'de, T: TreeDeserialize<'de>> TreeDeserialize<'de> for &mut T {
544    #[inline]
545    fn deserialize_by_key<K, D>(&mut self, keys: K, de: D) -> Result<(), Error<D::Error>>
546    where
547        K: Keys,
548        D: Deserializer<'de>,
549    {
550        (**self).deserialize_by_key(keys, de)
551    }
552
553    #[inline]
554    fn probe_by_key<K, D>(keys: K, de: D) -> Result<(), Error<D::Error>>
555    where
556        K: Keys,
557        D: Deserializer<'de>,
558    {
559        T::probe_by_key(keys, de)
560    }
561}
562
563impl<T: TreeAny> TreeAny for &mut T {
564    #[inline]
565    fn ref_any_by_key<K>(&self, keys: K) -> Result<&dyn Any, Traversal>
566    where
567        K: Keys,
568    {
569        (**self).ref_any_by_key(keys)
570    }
571
572    #[inline]
573    fn mut_any_by_key<K>(&mut self, keys: K) -> Result<&mut dyn Any, Traversal>
574    where
575        K: Keys,
576    {
577        (**self).mut_any_by_key(keys)
578    }
579}