miniconf/tree.rs
1use core::any::Any;
2
3use serde::{Deserializer, Serializer};
4
5use crate::{ExactSize, IntoKeys, Keys, NodeIter, Schema, SerdeError, ValueError};
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 [`Schema::transcode()`].
16/// An iterator of keys for the nodes is available through [`Schema::nodes()`].
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::TreeSchema`], [`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::{Path, Tree, TreeSchema};
44/// #[derive(Tree, Default)]
45/// struct S {
46/// #[tree(rename = "OTHER")]
47/// a: f32,
48/// };
49/// let name = S::SCHEMA.transcode::<Path<String, '/'>>([0usize]).unwrap();
50/// assert_eq!(name.0.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::{Tree};
61/// #[derive(Tree)]
62/// struct S(i32, #[tree(skip)] ());
63/// ```
64///
65/// ```compile_fail
66/// use miniconf::{Tree};
67/// #[derive(Tree)]
68/// struct S(#[tree(skip)] (), i32);
69/// ```
70///
71/// ## Type
72///
73/// The type to use when accessing the field/variant through `TreeDeserialize::probe`
74/// can be overridden using the `typ` derive macro attribute (`#[tree(typ="[f32; 4]")]`).
75///
76/// ## Implementation overrides
77///
78/// `#[tree(with=path)]`
79///
80/// This overrides the calls to the child node/variant traits using pub functions
81/// and constants in the module at the given path:
82/// (`SCHEMA`, `serialize_by_key`, `deserialize_by_key`, `probe_by_key`,
83/// `ref_any_by_key`, `mut_any_by_key`).
84///
85/// Also use this to relax bounds and deny operations.
86/// ```
87/// # use miniconf::{SerdeError, Tree, Keys, ValueError, TreeDeserialize};
88/// # use serde::Deserializer;
89/// #[derive(Tree, Default)]
90/// struct S {
91/// #[tree(with=check)]
92/// b: f32,
93/// }
94/// mod check {
95/// use miniconf::{SerdeError, Deserializer, TreeDeserialize, ValueError, Keys};
96/// pub use miniconf::leaf::{SCHEMA, serialize_by_key, probe_by_key, ref_any_by_key, mut_any_by_key};
97///
98/// pub fn deserialize_by_key<'de, D: Deserializer<'de>>(
99/// value: &mut f32,
100/// keys: impl Keys,
101/// de: D
102/// ) -> Result<(), SerdeError<D::Error>> {
103/// let mut new = *value;
104/// new.deserialize_by_key(keys, de)?;
105/// if new < 0.0 {
106/// Err(ValueError::Access("fail").into())
107/// } else {
108/// *value = new;
109/// Ok(())
110/// }
111/// }
112/// }
113/// ```
114///
115/// ### `defer`
116///
117/// The `defer` attribute is a shorthand for `with()` that defers
118/// child trait implementations to a given expression.
119///
120/// # Array
121///
122/// Blanket implementations of the `Tree*` traits are provided for homogeneous arrays
123/// [`[T; N]`](core::array).
124///
125/// # Option
126///
127/// Blanket implementations of the `Tree*` traits are provided for [`Option<T>`].
128///
129/// These implementations do not alter the path hierarchy and do not consume any items from the `keys`
130/// iterators. The `TreeSchema` behavior of an [`Option`] is such that the `None` variant makes the
131/// corresponding part of the tree inaccessible at run-time. It will still be iterated over (e.g.
132/// by [`Schema::nodes()`]) but attempts to access it (e.g. [`TreeSerialize::serialize_by_key()`],
133/// [`TreeDeserialize::deserialize_by_key()`], [`TreeAny::ref_any_by_key()`], or
134/// [`TreeAny::mut_any_by_key()`]) return the special [`ValueError::Absent`].
135///
136/// This is the same behavior as for other `enums` that have the `Tree*` traits derived.
137///
138/// # Tuples
139///
140/// Blanket impementations for the `Tree*` traits are provided for heterogeneous tuples `(T0, T1, ...)`
141/// up to length eight.
142///
143/// # Examples
144///
145/// See the [`crate`] documentation for a longer example showing how the traits and the derive
146/// macros work.
147pub trait TreeSchema {
148 /// Schema for this tree level
149 // Reference for Option<T> and others to copy T::SCHEMA
150 const SCHEMA: &Schema;
151
152 /// Return an exact size iterator of all leaf nodes
153 ///
154 /// This ensures sufficient state depth at compile time.
155 fn nodes<N, const D: usize>() -> ExactSize<NodeIter<N, D>> {
156 const { assert!(D >= Self::SCHEMA.shape().max_depth) }
157 Self::SCHEMA.nodes()
158 }
159}
160
161/// Access any node by keys.
162///
163/// This uses the `dyn Any` trait object.
164///
165/// ```
166/// use core::any::Any;
167/// use miniconf::{Indices, IntoKeys, JsonPath, TreeAny, TreeSchema};
168/// #[derive(TreeSchema, TreeAny, Default)]
169/// struct S {
170/// foo: u32,
171/// bar: [u16; 2],
172/// };
173/// let mut s = S::default();
174///
175/// for key in S::SCHEMA.nodes::<Indices<[_; 2]>, 2>() {
176/// let a = s.ref_any_by_key(key.unwrap().into_keys()).unwrap();
177/// assert!([0u32.type_id(), 0u16.type_id()].contains(&(&*a).type_id()));
178/// }
179///
180/// let val: &mut u16 = s.mut_by_key(JsonPath(".bar[1]")).unwrap();
181/// *val = 3;
182/// assert_eq!(s.bar[1], 3);
183///
184/// let val: &u16 = s.ref_by_key(JsonPath(".bar[1]")).unwrap();
185/// assert_eq!(*val, 3);
186/// ```
187pub trait TreeAny: TreeSchema {
188 /// Obtain a reference to a `dyn Any` trait object for a leaf node.
189 fn ref_any_by_key(&self, keys: impl Keys) -> Result<&dyn Any, ValueError>;
190
191 /// Obtain a mutable reference to a `dyn Any` trait object for a leaf node.
192 fn mut_any_by_key(&mut self, keys: impl Keys) -> Result<&mut dyn Any, ValueError>;
193
194 /// Obtain a reference to a leaf of known type by key.
195 fn ref_by_key<T: Any>(&self, keys: impl IntoKeys) -> Result<&T, ValueError> {
196 self.ref_any_by_key(keys.into_keys())?
197 .downcast_ref()
198 .ok_or(ValueError::Access("Incorrect type"))
199 }
200
201 /// Obtain a mutable reference to a leaf of known type by key.
202 fn mut_by_key<T: Any>(&mut self, keys: impl IntoKeys) -> Result<&mut T, ValueError> {
203 self.mut_any_by_key(keys.into_keys())?
204 .downcast_mut()
205 .ok_or(ValueError::Access("Incorrect type"))
206 }
207}
208
209/// Serialize a leaf node by its keys.
210///
211/// See also [`crate::json_core`] or `crate::postcard` for convenient wrappers using this trait.
212///
213/// # Derive macro
214///
215/// See [`macro@crate::TreeSerialize`].
216/// The derive macro attributes are described in the [`TreeSchema`] trait.
217pub trait TreeSerialize: TreeSchema {
218 /// Serialize a node by keys.
219 ///
220 /// ```
221 /// # #[cfg(feature = "json-core")] {
222 /// use miniconf::{IntoKeys, TreeSchema, TreeSerialize};
223 /// #[derive(TreeSchema, TreeSerialize)]
224 /// struct S {
225 /// foo: u32,
226 /// bar: [u16; 2],
227 /// };
228 /// let s = S {
229 /// foo: 9,
230 /// bar: [11, 3],
231 /// };
232 /// let mut buf = [0u8; 10];
233 /// let mut ser = serde_json_core::ser::Serializer::new(&mut buf);
234 /// s.serialize_by_key(["bar", "0"].into_keys(), &mut ser).unwrap();
235 /// let len = ser.end();
236 /// assert_eq!(&buf[..len], b"11");
237 /// # }
238 /// ```
239 ///
240 /// # Args
241 /// * `keys`: A `Keys` identifying the node.
242 /// * `ser`: A `Serializer` to to serialize the value.
243 fn serialize_by_key<S: Serializer>(
244 &self,
245 keys: impl Keys,
246 ser: S,
247 ) -> Result<S::Ok, SerdeError<S::Error>>;
248}
249
250/// Deserialize a leaf node by its keys.
251///
252/// See also [`crate::json_core`] or `crate::postcard` for convenient wrappers using this trait.
253///
254/// # Derive macro
255///
256/// See [`macro@crate::TreeDeserialize`].
257/// The derive macro attributes are described in the [`TreeSchema`] trait.
258pub trait TreeDeserialize<'de>: TreeSchema {
259 /// Deserialize a leaf node by its keys.
260 ///
261 /// ```
262 /// # #[cfg(feature = "derive")] {
263 /// use miniconf::{IntoKeys, TreeDeserialize, TreeSchema};
264 /// #[derive(Default, TreeSchema, TreeDeserialize)]
265 /// struct S {
266 /// foo: u32,
267 /// bar: [u16; 2],
268 /// };
269 /// let mut s = S::default();
270 /// let mut de = serde_json::de::Deserializer::from_slice(b"7");
271 /// s.deserialize_by_key(["bar", "0"].into_keys(), &mut de).unwrap();
272 /// de.end().unwrap();
273 /// assert_eq!(s.bar[0], 7);
274 /// # }
275 /// ```
276 ///
277 /// # Args
278 /// * `keys`: A `Keys` identifying the node.
279 /// * `de`: A `Deserializer` to deserialize the value.
280 fn deserialize_by_key<D: Deserializer<'de>>(
281 &mut self,
282 keys: impl Keys,
283 de: D,
284 ) -> Result<(), SerdeError<D::Error>>;
285
286 /// Blind deserialize a leaf node by its keys.
287 ///
288 /// This method should succeed at least in those cases where
289 /// `deserialize_by_key()` succeeds.
290 ///
291 /// ```
292 /// # #[cfg(feature = "derive")] {
293 /// use miniconf::{IntoKeys, TreeDeserialize, TreeSchema};
294 /// #[derive(Default, TreeSchema, TreeDeserialize)]
295 /// struct S {
296 /// foo: u32,
297 /// bar: [u16; 2],
298 /// };
299 /// let mut de = serde_json::de::Deserializer::from_slice(b"7");
300 /// S::probe_by_key(["bar", "0"].into_keys(), &mut de)
301 /// .unwrap();
302 /// de.end().unwrap();
303 /// # }
304 /// ```
305 ///
306 /// # Args
307 /// * `keys`: A `Keys` identifying the node.
308 /// * `de`: A `Deserializer` to deserialize the value.
309 fn probe_by_key<D: Deserializer<'de>>(
310 keys: impl Keys,
311 de: D,
312 ) -> Result<(), SerdeError<D::Error>>;
313}
314
315/// Shorthand for owned deserialization through [`TreeDeserialize`].
316pub trait TreeDeserializeOwned: for<'de> TreeDeserialize<'de> {}
317impl<T> TreeDeserializeOwned for T where T: for<'de> TreeDeserialize<'de> {}
318
319// Blanket impls for refs and muts
320
321impl<T: TreeSchema + ?Sized> TreeSchema for &T {
322 const SCHEMA: &'static Schema = T::SCHEMA;
323}
324
325impl<T: TreeSchema + ?Sized> TreeSchema for &mut T {
326 const SCHEMA: &'static Schema = T::SCHEMA;
327}
328
329impl<T: TreeSerialize + ?Sized> TreeSerialize for &T {
330 fn serialize_by_key<S: Serializer>(
331 &self,
332 keys: impl Keys,
333 ser: S,
334 ) -> Result<S::Ok, SerdeError<S::Error>> {
335 (**self).serialize_by_key(keys, ser)
336 }
337}
338
339impl<T: TreeSerialize + ?Sized> TreeSerialize for &mut T {
340 fn serialize_by_key<S: Serializer>(
341 &self,
342 keys: impl Keys,
343 ser: S,
344 ) -> Result<S::Ok, SerdeError<S::Error>> {
345 (**self).serialize_by_key(keys, ser)
346 }
347}
348
349impl<'de, T: TreeDeserialize<'de> + ?Sized> TreeDeserialize<'de> for &mut T {
350 fn deserialize_by_key<D: Deserializer<'de>>(
351 &mut self,
352 keys: impl Keys,
353 de: D,
354 ) -> Result<(), SerdeError<D::Error>> {
355 (**self).deserialize_by_key(keys, de)
356 }
357
358 fn probe_by_key<D: Deserializer<'de>>(
359 keys: impl Keys,
360 de: D,
361 ) -> Result<(), SerdeError<D::Error>> {
362 T::probe_by_key(keys, de)
363 }
364}
365
366impl<T: TreeAny + ?Sized> TreeAny for &mut T {
367 fn ref_any_by_key(&self, keys: impl Keys) -> Result<&dyn Any, ValueError> {
368 (**self).ref_any_by_key(keys)
369 }
370
371 fn mut_any_by_key(&mut self, keys: impl Keys) -> Result<&mut dyn Any, ValueError> {
372 (**self).mut_any_by_key(keys)
373 }
374}