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}