miniconf/tree.rs
1use core::any::Any;
2
3use serde::{Deserializer, Serializer};
4
5use crate::{IntoKeys, Keys, 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> to copy T::SCHEMA
150 const SCHEMA: &Schema;
151}
152
153/// Access any node by keys.
154///
155/// This uses the `dyn Any` trait object.
156///
157/// ```
158/// use core::any::Any;
159/// use miniconf::{Indices, IntoKeys, JsonPath, TreeAny, TreeSchema};
160/// #[derive(TreeSchema, TreeAny, Default)]
161/// struct S {
162/// foo: u32,
163/// bar: [u16; 2],
164/// };
165/// let mut s = S::default();
166///
167/// for key in S::SCHEMA.nodes::<Indices<[_; 2]>, 2>() {
168/// let a = s.ref_any_by_key(key.unwrap().into_keys()).unwrap();
169/// assert!([0u32.type_id(), 0u16.type_id()].contains(&(&*a).type_id()));
170/// }
171///
172/// let val: &mut u16 = s.mut_by_key(&JsonPath(".bar[1]")).unwrap();
173/// *val = 3;
174/// assert_eq!(s.bar[1], 3);
175///
176/// let val: &u16 = s.ref_by_key(&JsonPath(".bar[1]")).unwrap();
177/// assert_eq!(*val, 3);
178/// ```
179pub trait TreeAny: TreeSchema {
180 /// Obtain a reference to a `dyn Any` trait object for a leaf node.
181 fn ref_any_by_key(&self, keys: impl Keys) -> Result<&dyn Any, ValueError>;
182
183 /// Obtain a mutable reference to a `dyn Any` trait object for a leaf node.
184 fn mut_any_by_key(&mut self, keys: impl Keys) -> Result<&mut dyn Any, ValueError>;
185
186 /// Obtain a reference to a leaf of known type by key.
187 #[inline]
188 fn ref_by_key<T: Any>(&self, keys: impl IntoKeys) -> Result<&T, ValueError> {
189 self.ref_any_by_key(keys.into_keys())?
190 .downcast_ref()
191 .ok_or(ValueError::Access("Incorrect type"))
192 }
193
194 /// Obtain a mutable reference to a leaf of known type by key.
195 #[inline]
196 fn mut_by_key<T: Any>(&mut self, keys: impl IntoKeys) -> Result<&mut T, ValueError> {
197 self.mut_any_by_key(keys.into_keys())?
198 .downcast_mut()
199 .ok_or(ValueError::Access("Incorrect type"))
200 }
201}
202
203/// Serialize a leaf node by its keys.
204///
205/// See also [`crate::json_core`] or `crate::postcard` for convenient wrappers using this trait.
206///
207/// # Derive macro
208///
209/// See [`macro@crate::TreeSerialize`].
210/// The derive macro attributes are described in the [`TreeSchema`] trait.
211pub trait TreeSerialize: TreeSchema {
212 /// Serialize a node by keys.
213 ///
214 /// ```
215 /// # #[cfg(feature = "json-core")] {
216 /// use miniconf::{IntoKeys, TreeSchema, TreeSerialize};
217 /// #[derive(TreeSchema, TreeSerialize)]
218 /// struct S {
219 /// foo: u32,
220 /// bar: [u16; 2],
221 /// };
222 /// let s = S {
223 /// foo: 9,
224 /// bar: [11, 3],
225 /// };
226 /// let mut buf = [0u8; 10];
227 /// let mut ser = serde_json_core::ser::Serializer::new(&mut buf);
228 /// s.serialize_by_key(["bar", "0"].into_keys(), &mut ser).unwrap();
229 /// let len = ser.end();
230 /// assert_eq!(&buf[..len], b"11");
231 /// # }
232 /// ```
233 ///
234 /// # Args
235 /// * `keys`: A `Keys` identifying the node.
236 /// * `ser`: A `Serializer` to to serialize the value.
237 fn serialize_by_key<S: Serializer>(
238 &self,
239 keys: impl Keys,
240 ser: S,
241 ) -> Result<S::Ok, SerdeError<S::Error>>;
242}
243
244/// Deserialize a leaf node by its keys.
245///
246/// See also [`crate::json_core`] or `crate::postcard` for convenient wrappers using this trait.
247///
248/// # Derive macro
249///
250/// See [`macro@crate::TreeDeserialize`].
251/// The derive macro attributes are described in the [`TreeSchema`] trait.
252pub trait TreeDeserialize<'de>: TreeSchema {
253 /// Deserialize a leaf node by its keys.
254 ///
255 /// ```
256 /// # #[cfg(feature = "derive")] {
257 /// use miniconf::{IntoKeys, TreeDeserialize, TreeSchema};
258 /// #[derive(Default, TreeSchema, TreeDeserialize)]
259 /// struct S {
260 /// foo: u32,
261 /// bar: [u16; 2],
262 /// };
263 /// let mut s = S::default();
264 /// let mut de = serde_json::de::Deserializer::from_slice(b"7");
265 /// s.deserialize_by_key(["bar", "0"].into_keys(), &mut de).unwrap();
266 /// de.end().unwrap();
267 /// assert_eq!(s.bar[0], 7);
268 /// # }
269 /// ```
270 ///
271 /// # Args
272 /// * `keys`: A `Keys` identifying the node.
273 /// * `de`: A `Deserializer` to deserialize the value.
274 fn deserialize_by_key<D: Deserializer<'de>>(
275 &mut self,
276 keys: impl Keys,
277 de: D,
278 ) -> Result<(), SerdeError<D::Error>>;
279
280 /// Blind deserialize a leaf node by its keys.
281 ///
282 /// This method should succeed at least in those cases where
283 /// `deserialize_by_key()` succeeds.
284 ///
285 /// ```
286 /// # #[cfg(feature = "derive")] {
287 /// use miniconf::{IntoKeys, TreeDeserialize, TreeSchema};
288 /// #[derive(Default, TreeSchema, TreeDeserialize)]
289 /// struct S {
290 /// foo: u32,
291 /// bar: [u16; 2],
292 /// };
293 /// let mut de = serde_json::de::Deserializer::from_slice(b"7");
294 /// S::probe_by_key(["bar", "0"].into_keys(), &mut de)
295 /// .unwrap();
296 /// de.end().unwrap();
297 /// # }
298 /// ```
299 ///
300 /// # Args
301 /// * `keys`: A `Keys` identifying the node.
302 /// * `de`: A `Deserializer` to deserialize the value.
303 fn probe_by_key<D: Deserializer<'de>>(
304 keys: impl Keys,
305 de: D,
306 ) -> Result<(), SerdeError<D::Error>>;
307}
308
309/// Shorthand for owned deserialization through [`TreeDeserialize`].
310pub trait TreeDeserializeOwned: for<'de> TreeDeserialize<'de> {}
311impl<T> TreeDeserializeOwned for T where T: for<'de> TreeDeserialize<'de> {}
312
313// Blanket impls for refs and muts
314
315impl<T: TreeSchema + ?Sized> TreeSchema for &T {
316 const SCHEMA: &'static Schema = T::SCHEMA;
317}
318
319impl<T: TreeSchema + ?Sized> TreeSchema for &mut T {
320 const SCHEMA: &'static Schema = T::SCHEMA;
321}
322
323impl<T: TreeSerialize + ?Sized> TreeSerialize for &T {
324 #[inline]
325 fn serialize_by_key<S: Serializer>(
326 &self,
327 keys: impl Keys,
328 ser: S,
329 ) -> Result<S::Ok, SerdeError<S::Error>> {
330 (**self).serialize_by_key(keys, ser)
331 }
332}
333
334impl<T: TreeSerialize + ?Sized> TreeSerialize for &mut T {
335 #[inline]
336 fn serialize_by_key<S: Serializer>(
337 &self,
338 keys: impl Keys,
339 ser: S,
340 ) -> Result<S::Ok, SerdeError<S::Error>> {
341 (**self).serialize_by_key(keys, ser)
342 }
343}
344
345impl<'de, T: TreeDeserialize<'de> + ?Sized> TreeDeserialize<'de> for &mut T {
346 #[inline]
347 fn deserialize_by_key<D: Deserializer<'de>>(
348 &mut self,
349 keys: impl Keys,
350 de: D,
351 ) -> Result<(), SerdeError<D::Error>> {
352 (**self).deserialize_by_key(keys, de)
353 }
354
355 #[inline]
356 fn probe_by_key<D: Deserializer<'de>>(
357 keys: impl Keys,
358 de: D,
359 ) -> Result<(), SerdeError<D::Error>> {
360 T::probe_by_key(keys, de)
361 }
362}
363
364impl<T: TreeAny + ?Sized> TreeAny for &mut T {
365 #[inline]
366 fn ref_any_by_key(&self, keys: impl Keys) -> Result<&dyn Any, ValueError> {
367 (**self).ref_any_by_key(keys)
368 }
369
370 #[inline]
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}