Skip to main content

ryft_core/
parameters.rs

1use std::collections::{BTreeMap, HashMap};
2use std::fmt::{Debug, Display};
3use std::hash::{BuildHasher, Hash};
4use std::marker::PhantomData;
5
6use convert_case::{Case, Casing};
7use half::{bf16, f16};
8use paste::paste;
9
10use crate::errors::Error;
11
12/// Helper trait used to encode type equality constraints in the associated type bounds of [`Parameterized`].
13/// A type `X` implements [`SameAs<Y>`] only when `X` and `Y` are the exact same type.
14pub trait SameAs<T> {}
15
16impl<T> SameAs<T> for T {}
17
18/// Marker trait for leaf parameter values in a [`Parameterized`] type. This trait is intentionally empty. A type
19/// implementing [`Parameter`] is treated as an _indivisible leaf_ by [`Parameterized`] traversals. The reason we
20/// need this trait in the first place is so that we can distinguish between leaf and container behavior in blanket
21/// implementations. For example, `Vec<V>` implements `Parameterized<P>` when `V: Parameterized<P>`. Therefore,
22/// `Vec<P>` is treated as a collection of leaf parameters because `P: Parameter` implies `P: Parameterized<P>`,
23/// and not as a single leaf. Without this marker, expressing both leaf and container semantics would require
24/// overlapping blanket implementations or a stable specialization feature.
25///
26/// Note that `ryft` provides a derive macro for this trait that you can use for custom types which need to
27/// implement [`Parameter`] by tagging them with `#[derive(Parameter)]`.
28pub trait Parameter {}
29
30impl Parameter for bool {}
31impl Parameter for i8 {}
32impl Parameter for i16 {}
33impl Parameter for i32 {}
34impl Parameter for i64 {}
35impl Parameter for i128 {}
36impl Parameter for u8 {}
37impl Parameter for u16 {}
38impl Parameter for u32 {}
39impl Parameter for u64 {}
40impl Parameter for u128 {}
41impl Parameter for bf16 {}
42impl Parameter for f16 {}
43impl Parameter for f32 {}
44impl Parameter for f64 {}
45impl Parameter for usize {}
46
47impl<P: Parameter> Parameter for Option<P> {}
48
49/// Placeholder [`Parameter`] type for [`Parameterized`] types that is used represent
50/// [`Parameterized::parameter_structure`]. That is, it is used to replace every nested parameter in a [`Parameterized`]
51/// type yielding a _structure-only_ representation that can later be used with [`Parameterized::from_parameters`] to
52/// instantiate a [`Parameterized`] value with the same shape but different types of parameters.
53#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
54pub struct Placeholder;
55
56impl Display for Placeholder {
57    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58        write!(f, "<Parameter>")
59    }
60}
61
62impl Debug for Placeholder {
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        write!(f, "<Parameter>")
65    }
66}
67
68impl Parameter for Placeholder {}
69
70/// Segment in a [`ParameterPath`]. [`Parameterized::named_parameters`], [`Parameterized::named_parameters_mut`],
71/// and [`Parameterized::into_named_parameters`] produce paths that are made out of [`ParameterPathSegment`]s.
72#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
73pub enum ParameterPathSegment {
74    /// Field in a struct.
75    Field(&'static str),
76
77    /// Variant of an enum.
78    Variant(&'static str),
79
80    /// Index/position in a tuple.
81    TupleIndex(usize),
82
83    /// Index/position in indexable containers (e.g., arrays and [`Vec`]).
84    Index(usize),
85
86    /// [`Debug`]-formatted key of a map entry (e.g., [`HashMap`] or [`BTreeMap`]).
87    Key(String),
88}
89
90/// Path to a [`Parameter`] nested inside a [`Parameterized`] type instance, composed of [`ParameterPathSegment`]s.
91///
92/// # Example
93///
94/// ```rust
95/// # use ryft_core::parameters::Parameterized;
96///
97/// let value = vec![(4, 2)];
98/// let paths = value.parameter_paths().map(|path| path.to_string()).collect::<Vec<_>>();
99/// assert_eq!(paths, vec!["$[0].0", "$[0].1"]);
100/// ```
101#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
102pub struct ParameterPath {
103    /// [`ParameterPathSegment`]s stored in leaf-to-root (i.e., reverse) order so that parent containers can append
104    /// their [`ParameterPathSegment`] in `O(1)` time in functions like [`Parameterized::named_parameters`],
105    /// [`Parameterized::named_parameters_mut`], and [`Parameterized::into_named_parameters`].
106    segments: Vec<ParameterPathSegment>,
107}
108
109impl ParameterPath {
110    /// Creates a new empty (i.e., root) [`ParameterPath`].
111    pub fn root() -> Self {
112        Self::default()
113    }
114
115    /// Returns the number of [`ParameterPathSegment`]s in this [`ParameterPath`].
116    pub fn len(&self) -> usize {
117        self.segments.len()
118    }
119
120    /// Returns `true` if this [`ParameterPath`] contains no [`ParameterPathSegment`]s (i.e., is the root path).
121    pub fn is_empty(&self) -> bool {
122        self.segments.is_empty()
123    }
124
125    /// Returns `true` if this [`ParameterPath`] is the root path (i.e., is empty).
126    pub fn is_root(&self) -> bool {
127        self.is_empty()
128    }
129
130    /// Returns `true` if this [`ParameterPath`] is a prefix of `other`.
131    pub fn is_prefix_of(&self, other: &Self) -> bool {
132        self.len() <= other.len() && self.segments().zip(other.segments()).all(|(left, right)| left == right)
133    }
134
135    /// Returns an iterator over the [`ParameterPathSegment`]s in this [`ParameterPath`] in root-to-leaf order.
136    pub fn segments(&self) -> impl DoubleEndedIterator<Item = &ParameterPathSegment> + '_ {
137        self.segments.iter().rev()
138    }
139
140    /// Returns a new [`ParameterPath`] with the provided [`ParameterPathSegment`] appended to it.
141    ///
142    /// # Example
143    ///
144    /// ```rust
145    /// # use ryft_core::parameters::ParameterPath;
146    /// let path = ParameterPath::root()
147    ///     .field("weights")
148    ///     .index(1)
149    ///     .tuple_index(0);
150    /// assert_eq!(path.to_string(), "$.weights[1].0");
151    /// ```
152    pub fn with_segment(mut self, segment: ParameterPathSegment) -> Self {
153        self.segments.insert(0, segment);
154        self
155    }
156
157    /// Returns a new [`ParameterPath`] with a [`ParameterPathSegment::Field`] segment appended
158    /// to the end of this [`ParameterPath`].
159    pub fn field(self, name: &'static str) -> Self {
160        self.with_segment(ParameterPathSegment::Field(name))
161    }
162
163    /// Returns a new [`ParameterPath`] with a [`ParameterPathSegment::Variant`] segment appended
164    /// to the end of this [`ParameterPath`].
165    pub fn variant(self, name: &'static str) -> Self {
166        self.with_segment(ParameterPathSegment::Variant(name))
167    }
168
169    /// Returns a new [`ParameterPath`] with a [`ParameterPathSegment::Index`] segment appended
170    /// to the end of this [`ParameterPath`].
171    pub fn index(self, index: usize) -> Self {
172        self.with_segment(ParameterPathSegment::Index(index))
173    }
174
175    /// Returns a new [`ParameterPath`] with a [`ParameterPathSegment::TupleIndex`] segment appended
176    /// to the end of this [`ParameterPath`].
177    pub fn tuple_index(self, index: usize) -> Self {
178        self.with_segment(ParameterPathSegment::TupleIndex(index))
179    }
180
181    /// Returns a new [`ParameterPath`] with a [`ParameterPathSegment::Key`] segment appended
182    /// to the end of this [`ParameterPath`].
183    pub fn key<K: Debug>(self, key: K) -> Self {
184        self.with_segment(ParameterPathSegment::Key(format!("{key:?}")))
185    }
186}
187
188impl Display for ParameterPath {
189    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
190        write!(f, "$")?;
191        for segment in self.segments() {
192            match segment {
193                ParameterPathSegment::Field(name) => write!(f, ".{name}")?,
194                ParameterPathSegment::Variant(name) => write!(f, ".{}", name.to_case(Case::Snake))?,
195                ParameterPathSegment::TupleIndex(index) => write!(f, ".{index}")?,
196                ParameterPathSegment::Index(index) => write!(f, "[{index}]")?,
197                ParameterPathSegment::Key(key) => write!(f, "[{key}]")?,
198            }
199        }
200        Ok(())
201    }
202}
203
204impl Debug for ParameterPath {
205    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
206        write!(f, "ParameterPath[{self}]")
207    }
208}
209
210/// Type-level family that maps [`Parameter`] types nested in a type while preserving its overall
211/// structure. This is used internally by [`Parameterized`] and is based on the _type family_ approach described in
212/// [this blog post](https://smallcultfollowing.com/babysteps/blog/2016/11/03/associated-type-constructors-part-2-family-traits/).
213/// This trait is generic over `P` (instead of using a non-generic family trait with `type To<P: Parameter>`) so
214/// that each family can constrain the parameter domain at the `impl` level. For example, a family can implement
215/// `ParameterizedFamily<P>` only for `P: Parameter + Clone`. With a generic associated type `To<P>` on a non-generic
216/// family trait, the declaration would quantify over all `P: Parameter`, and implementations would not be allowed to
217/// add stricter per-family bounds on `P`.
218pub trait ParameterizedFamily<P: Parameter>: Sized {
219    /// Type obtained by replacing [`Parameter`] types nested in this type with `P`.
220    type To: Parameterized<P, Family = Self, ParameterStructure = <Self as ParameterizedFamily<Placeholder>>::To>
221    where
222        Self: ParameterizedFamily<Placeholder>;
223}
224
225/// Recursively traversable data structure that contains arbitrarily nested [`Parameter`] values of type `P`.
226///
227/// # What is a [`Parameterized`] type?
228///
229/// A [`Parameterized`] type is a container-like structure that typically contains other container-like structures
230/// that eventually bottom out to [`Parameter`] values. For example, we may have a `((usize, P), HashMap<String, P>)`
231/// type which contains parameters of type `P` nested inside it. [`Parameterized`] types can be thought of as tree-like
232/// structures that contain [`Parameter`] values at their leaves (of type `P`). Values of such types can be viewed as
233/// having two parts:
234///
235///   1. Their _structure_, which can be obtained via [`Self::parameter_structure`].
236///   2. Their _parameter_ values, which can be obtained via [`Self::parameters`], [`Self::parameters_mut`],
237///      [`Self::into_parameters`], [`Self::named_parameters`], [`Self::named_parameters_mut`],
238///      and [`Self::into_named_parameters`].
239///
240/// In the context of machine learning (ML), a [`Parameterized`] can contain model parameters, dataset entries,
241/// reinforcement learning agent observations, etc. Ryft provides built-in [`Parameterized`] implementations for a wide
242/// range of container-like types, including but not limited to:
243///
244///   - **Parameters:** All `P: Parameter` are `Parameterized<P>`.
245///   - **Tuples:** `()` is `Parameterized<P>` for all `P: Parameter`, `(V0)` is `Parameterized<P>` when
246///     `V0: Parameterized<P>`, `(V0, V1)` is `Parameterized<P>` when `V0: Parameterized<P>` and `V1: Parameterized<P>`,
247///     etc., up to size 12. Note that tuples with mixed [`Parameterized`] and non-[`Parameterized`] elements are
248///     supported only when they appear within types for which we derive [`Parameterized`] implementations using the
249///     `#[derive(Parameterized)]` macro (described in the [_Custom Parameterized Types_](#custom-parameterized-types)
250///     section below).
251///   - **Options:** `Option<V>` is `Parameterized<P>` when `V: Parameterized<P>`, _only_ when it appears within
252///     a type for which we derive a [`Parameterized`] implementation using the `#[derive(Parameterized)]` macro.
253///     That is because we need `Option<P>` to be a [`Parameter`] when `P: Parameter` in order to support some of
254///     the manipulation functions that are described in the
255///     [_Working with Parameterized Values_](#working-with-parameterized-values) section below.
256///   - **Arrays:** `[V; N]` is `Parameterized<P>` for any `N` when `V: Parameterized<P>`.
257///   - **Vectors:** `Vec<V>` is `Parameterized<P>` when `V: Parameterized<P>`.
258///   - **Maps:** `HashMap<K, V>` is `Parameterized<P>` when `K: Clone + Debug + Ord` and `V: Parameterized<P>`,
259///     and `BTreeMap<K, V>` is `Parameterized<P>` when `K: Clone + Debug + Ord` and `V: Parameterized<P>`.
260///   - **Phantom Data:** `PhantomData<P>` is `Parameterized<P>` for all `P: Parameter`, containing no parameters.
261///
262/// Note that Ryft does not provide a generic `impl<P: Parameter, V: Parameterized<P>> Parameterized<P> for Box<V>`
263/// because it overlaps with the blanket leaf implementation `impl<P: Parameter> Parameterized<P> for P`. Since `Box`
264/// is a fundamental type, downstream crates may implement [`Parameter`] for `Box<T>` for some local type `T`, and
265/// the generic `Box` implementation would then become non-coherent under Rust's orphan/coherence rules.
266///
267/// Ryft also provides a convenient `#[derive(Parameterized)]` macro that can be used to automatically derive
268/// [`Parameterized`] implementations for custom types. Refer to the
269/// [_Custom Parameterized Types_](#custom-parameterized-types) section below for information on that macro.
270///
271/// The [`Parameterized`] type and the functionality it provides is inspired by and shares a lot of commonalities with
272/// [JAX PyTrees](https://docs.jax.dev/en/latest/pytrees.html#working-with-pytrees) and
273/// [Equinox's PyTree manipulation APIs](https://docs.kidger.site/equinox/api/manipulation/).
274///
275/// ## Examples
276///
277/// The following are simple examples showing what [`Parameterized`] types are and how they are structured:
278///
279/// ```rust
280/// # use std::collections::BTreeMap;
281/// # use ryft::*;
282///
283/// // Simple tuple with 3 [`Parameter`]s.
284/// let value = (1, 2, 3);
285/// let parameters = value.parameters().collect::<Vec<_>>();
286/// assert_eq!(value.parameter_count(), 3);
287/// assert_eq!(parameters, vec![&1, &2, &3]);
288/// assert_eq!(value.parameter_structure(), (Placeholder, Placeholder, Placeholder));
289///
290/// // Nested tuple structure with 3 [`Parameter`]s.
291/// let value = (1, (2, 3), ());
292/// let parameters = value.parameters().collect::<Vec<_>>();
293/// assert_eq!(value.parameter_count(), 3);
294/// assert_eq!(parameters, vec![&1, &2, &3]);
295/// assert_eq!(value.parameter_structure(), (Placeholder, (Placeholder, Placeholder), ()));
296///
297/// // Nested map and tuple structure with 5 [`Parameter`]s.
298/// let value = (1, BTreeMap::from([("a", vec![2]), ("b", vec![3, 4])]), (5,));
299/// let parameters = value.parameters().collect::<Vec<_>>();
300/// assert_eq!(value.parameter_count(), 5);
301/// assert_eq!(parameters, vec![&1, &2, &3, &4, &5]);
302/// assert_eq!(
303///     value.parameter_structure(),
304///     (Placeholder, BTreeMap::from([("a", vec![Placeholder]), ("b", vec![Placeholder, Placeholder])]), (Placeholder,)),
305/// );
306/// ```
307///
308/// Note that the value returned by [`Parameterized::parameter_structure`] is effectively a "shape template"
309/// for a [`Parameterized`] value: every parameter in that value is replaced by [`Placeholder`], while values of
310/// non-parameter types are preserved exactly as they are (i.e., they are cloned). This is useful because flattening,
311/// which is described in more detail in the next section, discards structural boundary information, and
312/// [`Parameterized::ParameterStructure`] keeps that information so functions like [`Self::from_parameters`]
313/// can rebuild values that have the same structure as the original value, but different parameters.
314///
315/// # Working with Parameterized Values
316///
317/// The more interesting part about [`Parameterized`] types is what they enable us to do. The following operations are
318/// fundamental to [`Parameterized`] types and are almost always involved when working with such types and values:
319///
320///   - **Flattening:** Given a parameterized value, _flattening_ consists of obtaining a flat iterator over the
321///     parameters that are contained in that value. These parameters may be arbitrarily nested in the value, but we
322///     guarantee that they will always be returned in the same order. This is crucial in enabling the next operation,
323///     _unflattening_, which is the inverse of the flattening operation. This operation is exposed via the
324///     [`Self::parameters`], [`Self::parameters_mut`], and [`Self::into_parameters`] functions.
325///   - **Unflattening:** Given a [`Parameterized::ParameterStructure`] and an iterator over parameter values,
326///     _unflattening_ consists of constructing the fully structured [`Parameterized`] value that contains those
327///     parameters. The [`Parameterized::ParameterStructure`] is necessary in enabling this because _flattening_ is a
328///     lossy operation for certain types. For example, consider a tuple with two `Vec<P>` elements. After flattening
329///     we obtain a single iterator over parameters of type `P` without having any way of recovering the number of
330///     parameters that should go in the first vector versus the second. The [`Parameterized::ParameterStructure`] is
331///     used to provide that information and make recovery possible. An even more straightforward example is a value
332///     contains additional non-parameter information (e.g., consider a `(P, usize)` tuple). The unflattening operation
333///     is exposed via the [`Self::from_parameters`] function.
334///   - **Mapping:** Given a `Parameterized<P>` value, _mapping_ consists of using a function to map all the parameters
335///     nested in that value to new parameters of potentially different types yielding a `Parameterized<T>` value with
336///     the same structure. This is effectively a composition of _flattening_, _mapping_ the individual parameters, and
337///     _unflattening_ to obtain the final structured value. This operation is important in enabling things like tracing
338///     of functions that take parameterized data structures as inputs, whereby we can map all the nested parameters to
339///     tracer variables. It can also be used in a similar way to enable automatic differentiation, etc. It is a
340///     fundamental component of how the core features of Ryft are implemented. This operation is exposed via the
341///     [`Self::map_parameters`] function.
342///
343/// These core operations are also supported with _named_ parameters, where each parameter is paired with a
344/// [`ParameterPath`] specifying where in the nested data structure it belongs. This is useful for things like saving
345/// model checkpoints, etc. These _named_ parameter operation variants are exposed via the [`Self::named_parameters`],
346/// [`Self::named_parameters_mut`], [`Self::into_named_parameters`], [`Self::from_named_parameters`],
347/// [`Self::from_broadcasted_named_parameters`], [`Self::map_named_parameters`], and [`Self::map_named_parameters`]
348/// functions.
349///
350/// Note that, the [`Parameterized`] trait also defines a bunch of additional functions that are implemented using the
351/// aforementioned core primitives like [`Self::partition_parameters`], [`Self::filter_parameters`], etc. You should
352/// refer to the full list of the [`Parameterized`] trait functions and their documentation for more information.
353///
354/// ## Examples
355///
356/// The following examples show the flattening, unflattening, and mapping operations in action:
357///
358/// ```rust
359/// # use std::collections::{BTreeMap, HashMap};
360/// # use ryft::*;
361///
362/// type Value = (i32, BTreeMap<&'static str, Vec<i32>>, (i32,));
363/// let value = (1, BTreeMap::from([("a", vec![2]), ("b", vec![3, 4])]), (5,));
364///
365/// // Flattening:
366/// assert_eq!(value.parameters().copied().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5]);
367///
368/// // Unflattening:
369/// assert_eq!(
370///     Value::from_parameters(value.parameter_structure(), vec![10, 20, 30, 40, 50])?,
371///     (10, BTreeMap::from([("a", vec![20]), ("b", vec![30, 40])]), (50,)),
372/// );
373///
374/// // Mapping:
375/// assert_eq!(
376///     value.clone().map_parameters(|parameter| (parameter as i64) * 10)?,
377///     (10_i64, BTreeMap::from([("a", vec![20_i64]), ("b", vec![30_i64, 40_i64])]), (50_i64,)),
378/// );
379///
380/// // Flattening to named parameters:
381/// assert_eq!(
382///     value.named_parameters().map(|(path, parameter)| (path.to_string(), *parameter)).collect::<Vec<_>>(),
383///     vec![
384///         ("$.0".to_string(), 1),
385///         ("$.1[\"a\"][0]".to_string(), 2),
386///         ("$.1[\"b\"][0]".to_string(), 3),
387///         ("$.1[\"b\"][1]".to_string(), 4),
388///         ("$.2.0".to_string(), 5),
389///     ],
390/// );
391///
392/// // Unflattening from named parameters:
393/// assert_eq!(
394///     Value::from_named_parameters(
395///         value.parameter_structure(),
396///         value.clone().into_named_parameters().collect::<HashMap<_, _>>(),
397///     )?,
398///     value,
399/// );
400///
401/// // Mapping named parameters:
402/// assert_eq!(
403///     value.clone().map_named_parameters(|path, parameter| (parameter as i64) + (path.len() as i64))?,
404///     (2_i64, BTreeMap::from([("a", vec![5_i64]), ("b", vec![6_i64, 7_i64])]), (7_i64,)),
405/// );
406///
407/// // Unflattening from broadcasted named parameters:
408/// assert_eq!(
409///     Value::from_broadcasted_named_parameters(
410///         value.parameter_structure(),
411///         HashMap::from([
412///             (ParameterPath::root(), 0),
413///             (ParameterPath::root().with_segment(ParameterPathSegment::TupleIndex(1)), 10),
414///             (
415///                 ParameterPath::root()
416///                     .with_segment(ParameterPathSegment::TupleIndex(1))
417///                     .with_segment(ParameterPathSegment::Key(format!("{:?}", "b")))
418///                     .with_segment(ParameterPathSegment::Index(1)),
419///                 30,
420///             ),
421///         ]),
422///     )?,
423///     (0, BTreeMap::from([("a", vec![10]), ("b", vec![10, 30])]), (0,)),
424/// );
425///
426/// # Ok::<(), ryft::Error>(())
427/// ```
428///
429/// # Custom Parameterized Types
430///
431/// Ryft provides a `#[derive(Parameterized)]` procedural macro (via the `ryft-macros` crate) that can be used to
432/// generate implementations of both [`ParameterizedFamily`] and [`Parameterized`] for custom structs and enums.
433/// Concretely, the derived implementations:
434///
435///   - Preserve the container shape and non-parameter data.
436///   - Treat every field or nested field that references the parameter type as part of the types parameters.
437///   - Recursively delegate traversal to nested [`Parameterized`] field types.
438///   - Preserve the variant information when traversing and rebuilding enums.
439///
440/// The macro has the following requirements:
441///
442///   - The type on which it is used must be a struct or an enum. Unions are not supported.
443///   - There must be exactly one generic type bounded by [`Parameter`].
444///   - The parameter type must be _owned_ in parameter fields (i.e., parameter references or pointers are not allowed).
445///   - Nested tuples that mix parameterized and non-parameterized elements are supported inside derived structs and
446///     enums. However, the same kinds of mixed tuples are not generally supported inside other generic containers
447///     (e.g., `Vec<(P, usize)>`), unless those container element types already satisfy the required [`Parameterized`]
448///     bounds.
449///   - The generated implementation reserves internal identifiers (e.g., `'__p` and `__P`) for macro-internal
450///     lifetime and type parameters. User-defined generics should avoid these names. The safest approach is not use
451///     names that start with `__` but, if you do, be aware of the possibility for name conflicts due to these internal
452///     identifiers.
453///
454/// Furthermore, it makes the following assumptions:
455///
456///   - All fields that reference or depend on the parameter type are treated as parameter fields.
457///   - Non-parameter fields are carried through unchanged and may induce additional trait bounds in the generated
458///     implementations (e.g., a [`Clone`] bound is required for implementing [`Self::parameter_structure`]).
459///   - Generic parameters and their attributes are otherwise carried through as they are.
460///
461/// This macro also supports a container-level derive attribute, `#[ryft(crate = "...")]`, that overrides the path used
462/// reference Ryft types from the generated code. This is primarily meant for deriving implementations inside wrapper
463/// crates that re-export `ryft` under a different path. It should not be needed for the majority of use cases. Note
464/// also that the `#[ryft(...)]` attribute is not supported on individual struct fields or enum variants.
465///
466/// ## Examples
467///
468/// The following examples show how to use the `#[derive(Parameterized)]` macro:
469///
470/// ```rust
471/// # use ryft::*;
472///
473/// #[derive(Debug, Clone, PartialEq, Eq, Parameterized)]
474/// struct Layer<P: Parameter> {
475///     weights: Vec<P>,
476///     bias: P,
477///     metadata: (usize, usize),
478/// }
479///
480/// #[derive(Debug, Clone, PartialEq, Eq, Parameterized)]
481/// enum Block<P: Parameter> {
482///     Identity,
483///     Residual {
484///         trunk: Layer<P>,
485///         shortcut: (P, usize),
486///         tag: &'static str,
487///     },
488/// }
489///
490/// let layer = Layer { weights: vec![1, 2, 3], bias: 4, metadata: (3, 1) };
491/// assert_eq!(layer.parameter_count(), 4);
492/// assert_eq!(layer.parameters().collect::<Vec<_>>(), vec![&1, &2, &3, &4]);
493/// assert_eq!(
494///     layer.named_parameters().map(|(path, parameter)| (path.to_string(), *parameter)).collect::<Vec<_>>(),
495///     vec![
496///         ("$.weights[0]".to_string(), 1),
497///         ("$.weights[1]".to_string(), 2),
498///         ("$.weights[2]".to_string(), 3),
499///         ("$.bias".to_string(), 4),
500///     ],
501/// );
502/// assert_eq!(
503///     layer.parameter_structure(),
504///     Layer {
505///         weights: vec![Placeholder, Placeholder, Placeholder],
506///         bias: Placeholder,
507///         metadata: (3, 1),
508///     },
509/// );
510///
511/// let block = Block::Residual {
512///     trunk: Layer { weights: vec![10_i32, 20, 30], bias: 40, metadata: (2, 3) },
513///     shortcut: (50, 7),
514///     tag: "residual",
515/// };
516/// assert_eq!(block.parameter_count(), 5);
517/// assert_eq!(block.parameters().collect::<Vec<_>>(), vec![&10, &20, &30, &40, &50]);
518/// assert_eq!(
519///     block.named_parameters().map(|(path, parameter)| (path.to_string(), *parameter)).collect::<Vec<_>>(),
520///     vec![
521///         ("$.residual.trunk.weights[0]".to_string(), 10),
522///         ("$.residual.trunk.weights[1]".to_string(), 20),
523///         ("$.residual.trunk.weights[2]".to_string(), 30),
524///         ("$.residual.trunk.bias".to_string(), 40),
525///         ("$.residual.shortcut.0".to_string(), 50),
526///     ],
527/// );
528/// assert_eq!(
529///     block.parameter_structure(),
530///     Block::Residual {
531///         trunk: Layer {
532///             weights: vec![Placeholder, Placeholder, Placeholder],
533///             bias: Placeholder,
534///             metadata: (2, 3),
535///         },
536///         shortcut: (Placeholder, 7),
537///         tag: "residual",
538///     },
539/// );
540/// assert_eq!(
541///     Block::from_parameters(
542///         block.parameter_structure(),
543///         vec![1i64, 2i64, 3i64, 4i64, 5i64],
544///     )?,
545///     Block::Residual {
546///         trunk: Layer { weights: vec![1i64, 2i64, 3i64], bias: 4i64, metadata: (2, 3) },
547///         shortcut: (5i64, 7),
548///         tag: "residual",
549///     },
550/// );
551///
552/// # Ok::<(), ryft::Error>(())
553/// ```
554pub trait Parameterized<P: Parameter>: Sized {
555    /// [`ParameterizedFamily`] that this type belongs to and which can be used to reparameterize it.
556    type Family: ParameterizedFamily<P, To = Self> + ParameterizedFamily<Placeholder, To = Self::ParameterStructure>;
557
558    /// Reparameterized form of this [`Parameterized`] type with all of its nested `P` parameter types replaced by `T`.
559    /// This preserves the same [`Family`](Self::Family) and [`ParameterStructure`](Self::ParameterStructure), and is
560    /// such that reparameterizing back to `P` recovers [`Self`].
561    type To<T: Parameter>: Parameterized<T, Family = Self::Family, ParameterStructure = Self::ParameterStructure>
562        + SameAs<<Self::Family as ParameterizedFamily<T>>::To>
563    where
564        Self::Family: ParameterizedFamily<T>;
565
566    /// Type that represents a shape-only representation of this [`Parameterized`] type with all nested `P` parameter
567    /// types replaced by [`Placeholder`]. This must always be set to `Self::To<Placeholder>`. The only reason this is
568    /// not done by default is that defaulted associated types are not supported in stable Rust, and this forces us to
569    /// require that all implementations provide an implementation for this associated type as well.
570    type ParameterStructure: Parameterized<Placeholder, Family = Self::Family, To<P> = Self>
571        + SameAs<Self::To<Placeholder>>;
572
573    /// Iterator returned by [`Self::parameters`] for a borrow of the underlying [`Parameter`]s with lifetime `'t`.
574    /// This is an associated type instead of an `impl Iterator` in the corresponding function signature, so that
575    /// implementations can expose and reuse a concrete iterator type. In particular, `#[derive(Parameterized)]` for
576    /// enums synthesizes concrete enum iterators here, avoiding an additional heap allocation and dynamic dispatch.
577    type ParameterIterator<'t, T: 't + Parameter>: 't + Iterator<Item = &'t T>
578    where
579        Self: 't;
580
581    /// Iterator returned by [`Self::parameters_mut`] for a mutable borrow of the underlying [`Parameter`]s with
582    /// lifetime `'t`. Similar to [`Self::ParameterIterator`], this is an associated type instead of an `impl Iterator`
583    /// in the corresponding function signature, so that implementations can expose and reuse a concrete iterator type,
584    /// potentially avoiding additional heap allocations and dynamic dispatch.
585    type ParameterIteratorMut<'t, T: 't + Parameter>: 't + Iterator<Item = &'t mut T>
586    where
587        Self: 't;
588
589    /// Iterator returned by [`Self::into_parameters`], consuming `self` and returning the underlying [`Parameter`]s.
590    /// Similar to [`Self::ParameterIterator`], this is an associated type instead of an `impl Iterator` in the
591    /// corresponding function signature, so that implementations can expose and reuse a concrete iterator type,
592    /// potentially avoiding additional heap allocations and dynamic dispatch.
593    type ParameterIntoIterator<T: Parameter>: Iterator<Item = T>;
594
595    /// Iterator returned by [`Self::named_parameters`], borrowing the underlying [`Parameter`]s and pairing them with
596    /// their corresponding [`ParameterPath`]s. Similar to [`Self::ParameterIterator`], this is an associated type
597    /// instead of an `impl Iterator` in the corresponding function signature, so that implementations can expose and
598    /// reuse a concrete iterator type, potentially avoiding additional heap allocations and dynamic dispatch.
599    type NamedParameterIterator<'t, T: 't + Parameter>: 't + Iterator<Item = (ParameterPath, &'t T)>
600    where
601        Self: 't;
602
603    /// Iterator returned by [`Self::named_parameters_mut`], mutably borrowing the underlying [`Parameter`]s and pairing
604    /// them with their corresponding [`ParameterPath`]s. Similar to [`Self::ParameterIterator`], this is an associated
605    /// type instead of an `impl Iterator` in the corresponding function signature, so that implementations can expose
606    /// and reuse a concrete iterator type, potentially avoiding additional heap allocations and dynamic dispatch.
607    type NamedParameterIteratorMut<'t, T: 't + Parameter>: 't + Iterator<Item = (ParameterPath, &'t mut T)>
608    where
609        Self: 't;
610
611    /// Iterator returned by [`Self::into_named_parameters`], consuming `self` and returning the underlying
612    /// [`Parameter`]s together with their corresponding [`ParameterPath`]s. Similar to [`Self::ParameterIterator`],
613    /// this is an associated type instead of an `impl Iterator` in the corresponding function signature, so that
614    /// implementations can expose and reuse a concrete iterator type, potentially avoiding additional heap allocations
615    /// and dynamic dispatch.
616    type NamedParameterIntoIterator<T: Parameter>: Iterator<Item = (ParameterPath, T)>;
617
618    /// Returns the number of parameters in this [`Parameterized`] value.
619    fn parameter_count(&self) -> usize;
620
621    /// Returns the structure of this value by replacing all of its nested parameters with [`Placeholder`]s.
622    fn parameter_structure(&self) -> Self::ParameterStructure;
623
624    /// Returns an iterator over references to all parameters in this [`Parameterized`] value. The returned
625    /// iterator traverses the parameters in the same order as [`Self::parameters_mut`], [`Self::into_parameters`],
626    /// [`Self::named_parameters`], [`Self::named_parameters_mut`], and [`Self::into_named_parameters`].
627    fn parameters(&self) -> Self::ParameterIterator<'_, P>;
628
629    /// Returns an iterator over mutable references to all parameters in this [`Parameterized`] value. The returned
630    /// iterator traverses the parameters in the same order as [`Self::parameters`], [`Self::into_parameters`],
631    /// [`Self::named_parameters`], [`Self::named_parameters_mut`], and [`Self::into_named_parameters`].
632    fn parameters_mut(&mut self) -> Self::ParameterIteratorMut<'_, P>;
633
634    /// Consumes this [`Parameterized`] value and returns an iterator over all parameters contained in it. The
635    /// returned iterator traverses the parameters in the same order as [`Self::parameters`], [`Self::parameters_mut`],
636    /// [`Self::named_parameters`], [`Self::named_parameters_mut`], and [`Self::into_named_parameters`].
637    fn into_parameters(self) -> Self::ParameterIntoIterator<P>;
638
639    /// Returns an iterator over references to all parameters in this [`Parameterized`] value, paired with their
640    /// corresponding [`ParameterPath`]s. The returned iterator traverses the parameters in the same order as
641    /// [`Self::parameters`], [`Self::parameters_mut`], [`Self::into_parameters`], [`Self::named_parameters_mut`],
642    /// and [`Self::into_named_parameters`].
643    fn named_parameters(&self) -> Self::NamedParameterIterator<'_, P>;
644
645    /// Returns an iterator over mutable references to all parameters in this [`Parameterized`] value, paired with
646    /// their corresponding [`ParameterPath`]s. The returned iterator traverses the parameters in the same order as
647    /// [`Self::parameters`], [`Self::parameters_mut`], [`Self::into_parameters`], [`Self::named_parameters`], and
648    /// [`Self::into_named_parameters`].
649    fn named_parameters_mut(&mut self) -> Self::NamedParameterIteratorMut<'_, P>;
650
651    /// Consumes this [`Parameterized`] value and returns an iterator over all parameters contained in it, paired with
652    /// their corresponding [`ParameterPath`]s. The returned iterator traverses the parameters in the same order as
653    /// [`Self::parameters`], [`Self::parameters_mut`], [`Self::into_parameters`], [`Self::named_parameters`],
654    /// and [`Self::named_parameters_mut`].
655    fn into_named_parameters(self) -> Self::NamedParameterIntoIterator<P>;
656
657    /// Returns an iterator over the [`ParameterPath`]s to all nested parameters in this [`Parameterized`] value.
658    /// The returned iterator traverses the paths in the same order as [`Self::parameters`], [`Self::parameters_mut`],
659    /// [`Self::into_parameters`], [`Self::named_parameters`], [`Self::named_parameters_mut`], and
660    /// [`Self::into_named_parameters`].
661    fn parameter_paths<'p>(&'p self) -> impl 'p + Iterator<Item = ParameterPath>
662    where
663        P: 'p,
664    {
665        self.named_parameters().map(|(path, _)| path)
666    }
667
668    /// Reconstructs a value of this [`Parameterized`] type having the provided `structure` and consuming values
669    /// from the provided `parameters` to populate its parameters. This function may not consume all the provided
670    /// parameters, but if there are not enough parameters in the provided iterator, it will return a
671    /// [`Error::MissingParameters`] error.
672    fn from_parameters_with_remainder<I: Iterator<Item = P>>(
673        structure: Self::ParameterStructure,
674        parameters: &mut I,
675    ) -> Result<Self, Error>;
676
677    /// Reconstructs a value of this [`Parameterized`] type having the provided `structure` and consuming values
678    /// from the provided `parameters` to populate its parameters. This function expects to fully consume the provided
679    /// iterator. If it does not contain enough values, then it will return a [`Error::MissingParameters`] error, while
680    /// if it contains too many values, it will return an [`Error::UnusedParameters`]. If you do not want to fully
681    /// consume the provided iterator, then you must use [`Self::from_parameters_with_remainder`] instead.
682    fn from_parameters<I: IntoIterator<Item = P>>(
683        structure: Self::ParameterStructure,
684        parameters: I,
685    ) -> Result<Self, Error> {
686        let mut parameters = parameters.into_iter();
687        let parameterized = Self::from_parameters_with_remainder(structure, &mut parameters)?;
688        parameters
689            .next()
690            .map(|_| Err(Error::UnusedParameters { paths: None }))
691            .unwrap_or_else(|| Ok(parameterized))
692    }
693
694    /// Reconstructs a value of this [`Parameterized`] type having the provided `structure` and consuming named values
695    /// from the provided `parameters` to populate its parameters. Unlike [`Self::from_broadcasted_named_parameters`],
696    /// this function is strict in that keys in `parameters` must match exactly leaf [`ParameterPath`]s in `structure`,
697    /// and path prefix matching is not being used. If there are missing parameters preventing reconstruction from
698    /// being feasible, then this function will return a [`Error::MissingParameters`] error. Furthermore, if extra
699    /// paths remain after reconstruction, then it will return an [`Error::UnusedParameters`] error. For fully worked
700    /// examples, refer to the examples provided in the top-level documentation of the [`Parameterized`] trait.
701    fn from_named_parameters<I: IntoIterator<Item = (ParameterPath, P)>>(
702        structure: Self::ParameterStructure,
703        parameters: I,
704    ) -> Result<Self, Error> {
705        // We try to consume parameters in lockstep with `structure.named_parameters()` first. If we encounter any
706        // out-of-order parameters, we lazily materialize the remaining entries into a hash map and continue with
707        // keyed lookups.
708        let expected_count = structure.parameter_count();
709        let mut values = Vec::new();
710        values.reserve_exact(expected_count);
711        let mut matching_paths = Vec::new();
712        matching_paths.reserve_exact(expected_count);
713        let mut missing_paths = Vec::new();
714        let mut deferred_parameters = None::<HashMap<_, _>>;
715        let mut matching_path_indices = None::<HashMap<ParameterPath, usize>>;
716        let mut parameters = parameters.into_iter();
717        let mut next_parameter = parameters.next();
718
719        for (expected_path, _) in structure.named_parameters() {
720            if let Some(deferred_parameters) = deferred_parameters.as_mut() {
721                // Once we fall back to deferred lookups, reconstruction is direct keyed removal
722                // for the remaining expected paths.
723                match deferred_parameters.remove(&expected_path) {
724                    Some(parameter) => values.push(parameter),
725                    None => missing_paths.push(expected_path.to_string()),
726                }
727                continue;
728            }
729
730            match next_parameter.take() {
731                Some((provided_path, parameter)) if provided_path == expected_path => {
732                    // As long as the provided parameter paths match the structure parameter paths that we are
733                    // iterating over, we just consume the provided parameters without materializing a hash map.
734                    values.push(parameter);
735                    matching_paths.push(expected_path);
736                    next_parameter = parameters.next();
737                }
738                Some((provided_path, parameter)) => {
739                    // Once there is a mismatch, we materialize the hash map and continue via keyed lookup.
740                    let mut deferred = HashMap::with_capacity(parameters.size_hint().0 + 1);
741                    let matching_path_indices = matching_path_indices.get_or_insert_with(|| {
742                        matching_paths
743                            .iter()
744                            .cloned()
745                            .enumerate()
746                            .map(|(index, path)| (path, index))
747                            .collect::<HashMap<_, _>>()
748                    });
749
750                    // For duplicate parameter paths, the last provided value wins. Duplicates targeting
751                    // already matched paths update `values` in place; all others remain deferred.
752                    let parameters = std::iter::once((provided_path, parameter)).chain(parameters.by_ref());
753                    for (provided_path, parameter) in parameters {
754                        if let Some(index) = matching_path_indices.get(&provided_path).copied() {
755                            values[index] = parameter;
756                        } else {
757                            deferred.insert(provided_path, parameter);
758                        }
759                    }
760
761                    match deferred.remove(&expected_path) {
762                        Some(parameter) => values.push(parameter),
763                        None => missing_paths.push(expected_path.to_string()),
764                    }
765
766                    deferred_parameters = Some(deferred);
767                }
768                None => missing_paths.push(expected_path.to_string()),
769            }
770        }
771
772        if deferred_parameters.is_none() {
773            if let Some((provided_path, parameter)) = next_parameter.take() {
774                // No mismatch occurred during traversal, but additional parameters remain. We need to materialize
775                // the remaining parameters while still applying duplicate overrides for previously matched paths.
776                let mut deferred = HashMap::with_capacity(parameters.size_hint().0 + 1);
777                let matching_path_indices = matching_path_indices.get_or_insert_with(|| {
778                    matching_paths
779                        .iter()
780                        .cloned()
781                        .enumerate()
782                        .map(|(index, path)| (path, index))
783                        .collect::<HashMap<_, _>>()
784                });
785
786                let parameters = std::iter::once((provided_path, parameter)).chain(parameters);
787                for (provided_path, parameter) in parameters {
788                    if let Some(index) = matching_path_indices.get(&provided_path).copied() {
789                        values[index] = parameter;
790                    } else {
791                        deferred.insert(provided_path, parameter);
792                    }
793                }
794
795                deferred_parameters = Some(deferred);
796            }
797        }
798
799        if !missing_paths.is_empty() {
800            Err(Error::MissingParameters { expected_count, paths: Some(missing_paths) })
801        } else if deferred_parameters.is_some_and(|deferred_parameters| !deferred_parameters.is_empty()) {
802            Err(Error::UnusedParameters { paths: None })
803        } else {
804            Self::from_parameters(structure, values)
805        }
806    }
807
808    /// Reconstructs a value of this [`Parameterized`] type having the provided `structure` and consuming named values
809    /// from the provided `parameters` to populate its parameters, where keys in `parameters` are interpreted as path
810    /// prefixes. Unlike [`Self::from_named_parameters`], this function does not require exact leaf paths, and each
811    /// leaf path in `structure` receives the value from the most specific matching path prefix (i.e., the longest
812    /// shared path prefix). If any leaf path is not covered by a provided prefix, then this function will return
813    /// a [`Error::MissingParameters`] error. Furthermore, if there are any remaining [`ParameterPath`]s with no match
814    /// in `structure`, then it will return an [`Error::UnusedParameters`] error. Note that since one prefix value may
815    /// need to populate multiple leaves, this function requires `P: Clone`. For fully worked examples, refer to the
816    /// examples provided in the top-level documentation of the [`Parameterized`] trait.
817    fn from_broadcasted_named_parameters<I: IntoIterator<Item = (ParameterPath, P)>>(
818        structure: Self::ParameterStructure,
819        parameters: I,
820    ) -> Result<Self, Error>
821    where
822        P: Clone,
823    {
824        // This function uses a small local prefix trie to resolve each leaf parameter path to the most specific
825        // matching prefix (i.e., the longest matching prefix) in path-depth time, instead of scanning all prefixes
826        // for every leaf. That is usually much faster when many prefixes are provided, at the cost of the additional
827        // trie construction/allocation overhead, which can be less favorable for very small prefix sets.
828
829        #[derive(Default)]
830        struct PrefixTrieNode {
831            children: HashMap<ParameterPathSegment, usize>,
832            selected_prefix_index: Option<usize>,
833        }
834
835        let paths = structure.named_parameters().map(|(path, _)| path).collect::<Vec<_>>();
836        let expected_count = paths.len();
837        let mut path_prefixes = parameters.into_iter().map(|(path, value)| (path, value, 0usize)).collect::<Vec<_>>();
838
839        // Build a trie of provided path prefixes so that each lef parameter path can be resolved by walking segments
840        // instead of scanning all prefixes. This turns per-path prefix selection into a path-depth walk.
841        let mut prefix_trie = vec![PrefixTrieNode::default()];
842        for (prefix_index, (path, _, _)) in path_prefixes.iter().enumerate() {
843            let mut node_index = 0usize;
844            for segment in path.segments() {
845                let child_index = if let Some(child_index) = prefix_trie[node_index].children.get(segment).copied() {
846                    child_index
847                } else {
848                    prefix_trie.push(PrefixTrieNode::default());
849                    let child_index = prefix_trie.len() - 1;
850                    prefix_trie[node_index].children.insert(segment.clone(), child_index);
851                    child_index
852                };
853                node_index = child_index;
854            }
855            prefix_trie[node_index].selected_prefix_index = Some(prefix_index);
856        }
857
858        // Keep values in `structure.named_parameters()` order so that reconstruction can use `from_parameters`.
859        let mut values = Vec::with_capacity(expected_count);
860        let mut missing_paths = Vec::new();
861        for path in paths {
862            let mut trie_node_index = 0usize;
863            let mut selected_prefix_index = prefix_trie[trie_node_index].selected_prefix_index;
864            // As we descend the trie, track the deepest prefix node encountered. That is the "most specific" match.
865            for segment in path.segments() {
866                let Some(next_trie_node_index) = prefix_trie[trie_node_index].children.get(segment).copied() else {
867                    break;
868                };
869                trie_node_index = next_trie_node_index;
870                if let Some(prefix_index) = prefix_trie[trie_node_index].selected_prefix_index {
871                    selected_prefix_index = Some(prefix_index);
872                }
873            }
874            if let Some(selected_prefix_index) = selected_prefix_index {
875                let (_, value, matched_count) = &mut path_prefixes[selected_prefix_index];
876                values.push(value.clone());
877                *matched_count += 1;
878            } else {
879                missing_paths.push(path.to_string());
880            }
881        }
882
883        let mut unused_prefix_paths = path_prefixes
884            .into_iter()
885            .filter_map(|(path, _, matched_count)| if matched_count == 0 { Some(path.to_string()) } else { None })
886            .collect::<Vec<_>>();
887
888        if !missing_paths.is_empty() {
889            Err(Error::MissingParameters { expected_count, paths: Some(missing_paths) })
890        } else if !unused_prefix_paths.is_empty() {
891            unused_prefix_paths.sort_unstable();
892            Err(Error::UnusedParameters { paths: Some(unused_prefix_paths) })
893        } else {
894            Self::from_parameters(structure, values)
895        }
896    }
897
898    /// Maps each nested [`Parameter`] of type `P` in this value using the provided `map_fn` to a [`Parameter`] of type
899    /// `T`, while preserving the [`Parameterized`] structure of this type. Nested parameters are visited in the same
900    /// order as [`Self::parameters`], [`Self::parameters_mut`], [`Self::into_parameters`], [`Self::named_parameters`],
901    /// [`Self::named_parameters_mut`], and [`Self::into_named_parameters`].
902    fn map_parameters<T: Parameter, F: FnMut(P) -> T>(self, map_fn: F) -> Result<Self::To<T>, Error>
903    where
904        Self::Family: ParameterizedFamily<T>,
905    {
906        Self::To::<T>::from_parameters(self.parameter_structure(), self.into_parameters().map(map_fn))
907    }
908
909    /// Maps each nested [`Parameter`] of type `P` in this value using the provided `map_fn`, which receives the
910    /// [`ParameterPath`] for each [`Parameter`] along with its value, and returns a new [`Parameter`] value of type
911    /// `T`, while preserving the [`Parameterized`] structure of this type. Nested parameters are visited in the
912    /// same order as [`Self::parameters`], [`Self::parameters_mut`], [`Self::into_parameters`],
913    /// [`Self::named_parameters`], [`Self::named_parameters_mut`], and [`Self::into_named_parameters`].
914    fn map_named_parameters<T: Parameter, F: FnMut(&ParameterPath, P) -> T>(
915        self,
916        map_fn: F,
917    ) -> Result<Self::To<T>, Error>
918    where
919        Self::Family: ParameterizedFamily<T>,
920    {
921        let mut map_fn = map_fn;
922        let structure = self.parameter_structure();
923        let mut mapped_parameters = HashMap::with_capacity(structure.parameter_count());
924        for (path, parameter) in self.into_named_parameters() {
925            let mapped_parameter = map_fn(&path, parameter);
926            mapped_parameters.insert(path, mapped_parameter);
927        }
928        Self::To::<T>::from_named_parameters(structure, mapped_parameters)
929    }
930
931    /// Filters all nested [`Parameter`]s of type `P` in this value according to the provided `predicate`, producing a
932    /// structure-preserving [`Parameterized`] value with `Option<P>` leaves. Specifically, this value is a
933    /// `Parameterized<P>` and this function returns a `Parameterized<Option<P>>` where each parameter of this value
934    /// for which `predicate` returns `true` is kept as [`Some`], while all other parameters are replaced by [`None`].
935    ///
936    /// This function is inspired by
937    /// [Equinox's `filter` function](https://docs.kidger.site/equinox/api/manipulation/#equinox.filter).
938    ///
939    /// # Example
940    ///
941    /// ```rust
942    /// # use ryft::Parameterized;
943    ///
944    /// let value = vec![(1_i32, 2_i32), (3_i32, 4_i32)];
945    ///
946    /// // Keep only the second tuple element across all top-level entries.
947    /// let filtered = value.filter_parameters(|path, _| path.to_string().ends_with(".1"))?;
948    ///
949    /// assert_eq!(filtered, vec![(None, Some(2)), (None, Some(4))]);
950    ///
951    /// # Ok::<(), ryft::Error>(())
952    /// ```
953    fn filter_parameters<F: FnMut(&ParameterPath, &P) -> bool>(self, predicate: F) -> Result<Self::To<Option<P>>, Error>
954    where
955        Self::Family: ParameterizedFamily<Option<P>>,
956    {
957        let mut predicate = predicate;
958        self.map_named_parameters(|path, parameter| predicate(path, &parameter).then_some(parameter))
959    }
960
961    /// Partitions all nested [`Parameter`]s of type `P` in this value into two structure-preserving [`Parameterized`]
962    /// values, according to the provided `predicate`. Specifically, this value is a `Parameterized<P>` and this
963    /// function returns a pair of `Parameterized<Option<P>>` values. The first one contains [`Some`] for each parameter
964    /// for which the provided `predicate` returns `true`, and [`None`] elsewhere, and the opposite holds for the second
965    /// returned value. This function is equivalent to using [`Self::filter_parameters`] twice on the same value, but it
966    /// avoids traversing the structure twice.
967    ///
968    /// This function is inspired by
969    /// [Equinox's `partition` function](https://docs.kidger.site/equinox/api/manipulation/#equinox.partition).
970    ///
971    /// # Example
972    ///
973    /// ```rust
974    /// # use ryft::Parameterized;
975    ///
976    /// let value = vec![(1_i32, 2_i32), (3_i32, 4_i32)];
977    ///
978    /// // Keep only parameters under the second top-level element in `partition_0`.
979    /// let (partition_0, partition_1) = value.partition_parameters(|path, _| path.to_string().starts_with("$[1]"))?;
980    ///
981    /// assert_eq!(partition_0, vec![(None, None), (Some(3), Some(4))]);
982    /// assert_eq!(partition_1, vec![(Some(1), Some(2)), (None, None)]);
983    ///
984    /// # Ok::<(), ryft::Error>(())
985    /// ```
986    fn partition_parameters<F: FnMut(&ParameterPath, &P) -> bool>(
987        self,
988        predicate: F,
989    ) -> Result<(Self::To<Option<P>>, Self::To<Option<P>>), Error>
990    where
991        Self::Family: ParameterizedFamily<Option<P>>,
992    {
993        let structure = self.parameter_structure();
994        let mut predicate = predicate;
995        let mut partition_0_parameters = Vec::new();
996        let mut partition_1_parameters = Vec::new();
997        partition_0_parameters.reserve_exact(structure.parameter_count());
998        partition_1_parameters.reserve_exact(structure.parameter_count());
999        for (path, parameter) in self.into_named_parameters() {
1000            if predicate(&path, &parameter) {
1001                partition_0_parameters.push(Some(parameter));
1002                partition_1_parameters.push(None);
1003            } else {
1004                partition_0_parameters.push(None);
1005                partition_1_parameters.push(Some(parameter));
1006            }
1007        }
1008        let partition_0 = Self::To::from_parameters(structure, partition_0_parameters)?;
1009        let partition_1 = Self::To::from_parameters(partition_0.parameter_structure(), partition_1_parameters)?;
1010        Ok((partition_0, partition_1))
1011    }
1012
1013    /// Combines multiple structure-aligned `Parameterized<Option<P>>` values into a single `Parameterized<P>` value,
1014    /// using left-to-right precedence at each parameter location. That is, for each leaf [`ParameterPath`] in
1015    /// `structure`, this function selects the first [`Some`] value from `values` and uses it for the corresponding
1016    /// location in the resulting [`Parameterized`] value that the function returns. If multiple non-`None` values are
1017    /// present for the same leaf, then they must all be equal, and otherwise this function returns an
1018    /// [`Error::AmbiguousParameterCombination`] error. If no [`Some`] value is found for some leaf
1019    /// [`ParameterPath`], then this function will return a [`Error::MissingParameters`] error. Furthermore, if any of
1020    /// the provided `values` contains additional [`Parameter`]s, beyond those that correspond to ones in `structure`,
1021    /// then this function will return an [`Error::UnusedParameters`] error.
1022    ///
1023    /// This function is typically used to reconstruct values from the results of calling [`Self::filter_parameters`]
1024    /// and [`Self::partition_parameters`]. It is inspired by
1025    /// [Equinox's `combine` function](https://docs.kidger.site/equinox/api/manipulation/#equinox.combine).
1026    ///
1027    /// # Example
1028    ///
1029    /// ```rust
1030    /// # use ryft::Parameterized;
1031    ///
1032    /// let value = vec![(1_i32, 2_i32), (3_i32, 4_i32)];
1033    /// let structure = value.parameter_structure();
1034    ///
1035    /// // Split by top-level element and then reconstruct the original value.
1036    /// let (partition_0, partition_1) = value.partition_parameters(|path, _| path.to_string().starts_with("$[0]"))?;
1037    /// let combined = Vec::<(i32, i32)>::combine_parameters(
1038    ///     structure,
1039    ///     vec![partition_0, partition_1],
1040    /// )?;
1041    ///
1042    /// assert_eq!(combined, vec![(1, 2), (3, 4)]);
1043    ///
1044    /// # Ok::<(), ryft::Error>(())
1045    /// ```
1046    fn combine_parameters<I: IntoIterator<Item = Self::To<Option<P>>>>(
1047        structure: Self::ParameterStructure,
1048        values: I,
1049    ) -> Result<Self, Error>
1050    where
1051        P: Debug + PartialEq,
1052        Self::Family: ParameterizedFamily<Option<P>>,
1053    {
1054        let expected_paths = structure.named_parameters().map(|(path, _)| path).collect::<Vec<_>>();
1055        let expected_count = expected_paths.len();
1056        let mut value_parameters = values.into_iter().map(|value| value.into_named_parameters()).collect::<Vec<_>>();
1057        let mut parameters = Vec::new();
1058        let mut missing_paths = Vec::new();
1059        parameters.reserve_exact(expected_count);
1060        for path in expected_paths {
1061            let mut collected_values = Vec::new();
1062            let mut has_missing_candidates = false;
1063            for iterator in &mut value_parameters {
1064                let Some((_, candidate)) = iterator.next() else {
1065                    has_missing_candidates = true;
1066                    continue;
1067                };
1068                let Some(candidate) = candidate else {
1069                    continue;
1070                };
1071                if !collected_values.iter().any(|value| value == &candidate) {
1072                    collected_values.push(candidate);
1073                }
1074            }
1075            if has_missing_candidates || collected_values.is_empty() {
1076                missing_paths.push(path.to_string());
1077            } else if collected_values.len() > 1 {
1078                return Err(Error::AmbiguousParameterCombination {
1079                    values: collected_values.into_iter().map(|value| format!("{value:?}")).collect(),
1080                });
1081            } else {
1082                parameters.push(collected_values.pop().unwrap());
1083            }
1084        }
1085
1086        let mut unused_paths = value_parameters
1087            .iter_mut()
1088            .flat_map(|iterator| iterator.map(|(path, _)| path.to_string()))
1089            .collect::<Vec<_>>();
1090
1091        if !missing_paths.is_empty() {
1092            Err(Error::MissingParameters { expected_count, paths: Some(missing_paths) })
1093        } else if !unused_paths.is_empty() {
1094            unused_paths.sort_unstable();
1095            Err(Error::UnusedParameters { paths: Some(unused_paths) })
1096        } else {
1097            Self::from_parameters(structure, parameters)
1098        }
1099    }
1100
1101    /// Replaces nested [`Parameter`]s of type `P` in this value using a structure-aligned `Parameterized<Option<P>>`
1102    /// replacement value. For each parameter, [`Some`] in `replacement` overrides the current value from `self`,
1103    /// while [`None`] keeps the current value unchanged. If `replacement` is missing parameters for the expected
1104    /// structure, this function will return a [`Error::MissingParameters`] error. Furthermore, if `replacement`
1105    /// contains extra parameters, this function will return an [`Error::UnusedParameters`] error.
1106    ///
1107    /// # Example
1108    ///
1109    /// ```rust
1110    /// # use ryft::Parameterized;
1111    ///
1112    /// let value = vec![(1_i32, 2_i32), (3_i32, 4_i32)];
1113    ///
1114    /// // Replace only the first field of the second tuple.
1115    /// let replaced = value.replace_parameters(vec![(None, None), (Some(99), None)])?;
1116    ///
1117    /// assert_eq!(replaced, vec![(1, 2), (99, 4)]);
1118    ///
1119    /// # Ok::<(), ryft::Error>(())
1120    /// ```
1121    fn replace_parameters(self, replacement: Self::To<Option<P>>) -> Result<Self, Error>
1122    where
1123        Self::Family: ParameterizedFamily<Option<P>>,
1124    {
1125        let structure = self.parameter_structure();
1126        let expected_count = structure.parameter_count();
1127        let expected_paths = structure.named_parameters().map(|(path, _)| path).collect::<Vec<_>>();
1128        let mut parameters = self.into_named_parameters();
1129        let mut replacements = replacement.into_named_parameters();
1130        let mut replaced_parameters = Vec::new();
1131        replaced_parameters.reserve_exact(expected_count);
1132        let mut missing_paths = Vec::new();
1133
1134        for path in expected_paths {
1135            let parameter = parameters.next().map(|(_, parameter)| parameter);
1136            let replacement = replacements.next().map(|(_, replacement)| replacement);
1137            if let (Some(parameter), Some(replacement)) = (parameter, replacement) {
1138                replaced_parameters.push(replacement.unwrap_or(parameter));
1139            } else {
1140                missing_paths.push(path.to_string());
1141            }
1142        }
1143
1144        let mut unused_paths = parameters
1145            .map(|(path, _)| path.to_string())
1146            .chain(replacements.map(|(path, _)| path.to_string()))
1147            .collect::<Vec<_>>();
1148
1149        if !missing_paths.is_empty() {
1150            Err(Error::MissingParameters { expected_count, paths: Some(missing_paths) })
1151        } else if !unused_paths.is_empty() {
1152            unused_paths.sort_unstable();
1153            Err(Error::UnusedParameters { paths: Some(unused_paths) })
1154        } else {
1155            Self::from_parameters(structure, replaced_parameters)
1156        }
1157    }
1158}
1159
1160/// Iterator adapter that prefixes each yielded [`ParameterPath`] with [`Self::segment`]. This exists as a dedicated
1161/// type (instead of using only standard [`Iterator`] combinators) because many [`Parameterized`] associated iterator
1162/// types must be named concrete types. A closure-based `map(move |...| ...)` adapter would capture the prefix segment
1163/// and produce an unnameable closure type, which is not usable directly in those associated type definitions on stable
1164/// Rust. [`PathPrefixedParameterIterator`] preserves static dispatch and avoids heap allocation and dynamic dispatch.
1165pub struct PathPrefixedParameterIterator<P, I: Iterator<Item = (ParameterPath, P)>> {
1166    /// Underlying [`Iterator`] that yields `(path, value)` pairs before prefixing with [`Self::segment`].
1167    pub iterator: I,
1168
1169    /// [`ParameterPathSegment`] to prepend to each path produced by [`Self::iterator`].
1170    pub segment: ParameterPathSegment,
1171}
1172
1173impl<P, I: Iterator<Item = (ParameterPath, P)>> Iterator for PathPrefixedParameterIterator<P, I> {
1174    type Item = (ParameterPath, P);
1175
1176    fn next(&mut self) -> Option<Self::Item> {
1177        self.iterator.next().map(|(mut path, parameter)| {
1178            path.segments.push(self.segment.clone());
1179            (path, parameter)
1180        })
1181    }
1182}
1183
1184pub struct ParameterParameterizedFamily;
1185
1186impl<P: Parameter> ParameterizedFamily<P> for ParameterParameterizedFamily {
1187    type To = P;
1188}
1189
1190impl<P: Parameter> Parameterized<P> for P {
1191    type Family = ParameterParameterizedFamily;
1192
1193    type To<T: Parameter>
1194        = <Self::Family as ParameterizedFamily<T>>::To
1195    where
1196        Self::Family: ParameterizedFamily<T>;
1197
1198    type ParameterStructure = Self::To<Placeholder>;
1199
1200    type ParameterIterator<'t, T: 't + Parameter>
1201        = std::iter::Once<&'t T>
1202    where
1203        Self: 't;
1204
1205    type ParameterIteratorMut<'t, T: 't + Parameter>
1206        = std::iter::Once<&'t mut T>
1207    where
1208        Self: 't;
1209
1210    type ParameterIntoIterator<T: Parameter> = std::iter::Once<T>;
1211
1212    type NamedParameterIterator<'t, T: 't + Parameter>
1213        = std::iter::Once<(ParameterPath, &'t T)>
1214    where
1215        Self: 't;
1216
1217    type NamedParameterIteratorMut<'t, T: 't + Parameter>
1218        = std::iter::Once<(ParameterPath, &'t mut T)>
1219    where
1220        Self: 't;
1221
1222    type NamedParameterIntoIterator<T: Parameter> = std::iter::Once<(ParameterPath, T)>;
1223
1224    fn parameter_count(&self) -> usize {
1225        1
1226    }
1227
1228    fn parameter_structure(&self) -> Self::ParameterStructure {
1229        Placeholder
1230    }
1231
1232    fn parameters(&self) -> Self::ParameterIterator<'_, P> {
1233        std::iter::once(self)
1234    }
1235
1236    fn parameters_mut(&mut self) -> Self::ParameterIteratorMut<'_, P> {
1237        std::iter::once(self)
1238    }
1239
1240    fn into_parameters(self) -> Self::ParameterIntoIterator<P> {
1241        std::iter::once(self)
1242    }
1243
1244    fn named_parameters(&self) -> Self::NamedParameterIterator<'_, P> {
1245        std::iter::once((ParameterPath::root(), self))
1246    }
1247
1248    fn named_parameters_mut(&mut self) -> Self::NamedParameterIteratorMut<'_, P> {
1249        std::iter::once((ParameterPath::root(), self))
1250    }
1251
1252    fn into_named_parameters(self) -> Self::NamedParameterIntoIterator<P> {
1253        std::iter::once((ParameterPath::root(), self))
1254    }
1255
1256    fn from_parameters_with_remainder<I: Iterator<Item = P>>(
1257        _structure: Self::ParameterStructure,
1258        parameters: &mut I,
1259    ) -> Result<Self, Error> {
1260        parameters.next().ok_or(Error::MissingParameters { expected_count: 1, paths: None })
1261    }
1262}
1263
1264pub struct PhantomDataParameterizedFamily;
1265
1266impl<P: Parameter> ParameterizedFamily<P> for PhantomDataParameterizedFamily {
1267    type To = PhantomData<P>;
1268}
1269
1270impl<P: Parameter> Parameterized<P> for PhantomData<P> {
1271    type Family = PhantomDataParameterizedFamily;
1272
1273    type To<T: Parameter>
1274        = <Self::Family as ParameterizedFamily<T>>::To
1275    where
1276        Self::Family: ParameterizedFamily<T>;
1277
1278    type ParameterStructure = Self::To<Placeholder>;
1279
1280    type ParameterIterator<'t, T: 't + Parameter>
1281        = std::iter::Empty<&'t T>
1282    where
1283        Self: 't;
1284
1285    type ParameterIteratorMut<'t, T: 't + Parameter>
1286        = std::iter::Empty<&'t mut T>
1287    where
1288        Self: 't;
1289
1290    type ParameterIntoIterator<T: Parameter> = std::iter::Empty<T>;
1291
1292    type NamedParameterIterator<'t, T: 't + Parameter>
1293        = std::iter::Empty<(ParameterPath, &'t T)>
1294    where
1295        Self: 't;
1296
1297    type NamedParameterIteratorMut<'t, T: 't + Parameter>
1298        = std::iter::Empty<(ParameterPath, &'t mut T)>
1299    where
1300        Self: 't;
1301
1302    type NamedParameterIntoIterator<T: Parameter> = std::iter::Empty<(ParameterPath, T)>;
1303
1304    fn parameter_count(&self) -> usize {
1305        0
1306    }
1307
1308    fn parameter_structure(&self) -> Self::ParameterStructure {
1309        PhantomData
1310    }
1311
1312    fn parameters(&self) -> Self::ParameterIterator<'_, P> {
1313        std::iter::empty()
1314    }
1315
1316    fn parameters_mut(&mut self) -> Self::ParameterIteratorMut<'_, P> {
1317        std::iter::empty()
1318    }
1319
1320    fn into_parameters(self) -> Self::ParameterIntoIterator<P> {
1321        std::iter::empty()
1322    }
1323
1324    fn named_parameters(&self) -> Self::NamedParameterIterator<'_, P> {
1325        std::iter::empty()
1326    }
1327
1328    fn named_parameters_mut(&mut self) -> Self::NamedParameterIteratorMut<'_, P> {
1329        std::iter::empty()
1330    }
1331
1332    fn into_named_parameters(self) -> Self::NamedParameterIntoIterator<P> {
1333        std::iter::empty()
1334    }
1335
1336    fn from_parameters_with_remainder<I: Iterator<Item = P>>(
1337        _structure: Self::ParameterStructure,
1338        _parameters: &mut I,
1339    ) -> Result<Self, Error> {
1340        Ok(PhantomData)
1341    }
1342}
1343
1344// Use declarative macros to provide implementations for tuples of [`Parameterized`] items. Note that if a tuple
1345// contains a mix of [`Parameterized`] and non-[`Parameterized`] items, then the generated implementations here
1346// will not cover it. Instead, such tuples are supported when nested within `struct`s or `enum`s by using our
1347// `#[derive(Parameterized)]` macro as it provides special treatment for them.
1348
1349macro_rules! tuple_parameterized_family_impl {
1350    ($($F:ident),*) => {
1351        impl<P: Parameter, $($F: ParameterizedFamily<P> + ParameterizedFamily<Placeholder>),*> ParameterizedFamily<P>
1352            for ($($F,)*)
1353        {
1354            type To = ($(<$F as ParameterizedFamily<P>>::To,)*);
1355        }
1356    };
1357}
1358
1359tuple_parameterized_family_impl!();
1360tuple_parameterized_family_impl!(F0);
1361tuple_parameterized_family_impl!(F0, F1);
1362tuple_parameterized_family_impl!(F0, F1, F2);
1363tuple_parameterized_family_impl!(F0, F1, F2, F3);
1364tuple_parameterized_family_impl!(F0, F1, F2, F3, F4);
1365tuple_parameterized_family_impl!(F0, F1, F2, F3, F4, F5);
1366tuple_parameterized_family_impl!(F0, F1, F2, F3, F4, F5, F6);
1367tuple_parameterized_family_impl!(F0, F1, F2, F3, F4, F5, F6, F7);
1368tuple_parameterized_family_impl!(F0, F1, F2, F3, F4, F5, F6, F7, F8);
1369tuple_parameterized_family_impl!(F0, F1, F2, F3, F4, F5, F6, F7, F8, F9);
1370tuple_parameterized_family_impl!(F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10);
1371tuple_parameterized_family_impl!(F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11);
1372
1373macro_rules! tuple_parameterized_impl {
1374    ($($T:ident:$index:tt),*) => {
1375        paste! {
1376            impl<P: Parameter$(, $T: Parameterized<P>)*> Parameterized<P> for ($($T,)*) {
1377                type Family = ($($T::Family,)*);
1378
1379                type To<T: Parameter>
1380                    = <Self::Family as ParameterizedFamily<T>>::To
1381                where
1382                    Self::Family: ParameterizedFamily<T>;
1383
1384                type ParameterStructure = Self::To<Placeholder>;
1385
1386                type ParameterIterator<'t, T: 't + Parameter>
1387                    = tuple_parameter_iterator_ty!('t, T, ($($T:$index,)*))
1388                where
1389                    Self: 't;
1390
1391                type ParameterIteratorMut<'t, T: 't + Parameter>
1392                    = tuple_parameter_iterator_mut_ty!('t, T, ($($T:$index,)*))
1393                where
1394                    Self: 't;
1395
1396                type ParameterIntoIterator<T: Parameter>
1397                    = tuple_parameter_into_iterator_ty!(T, ($($T:$index,)*));
1398
1399                type NamedParameterIterator<'t, T: 't + Parameter>
1400                    = tuple_named_parameter_iterator_ty!('t, T, ($($T:$index,)*))
1401                where
1402                    Self: 't;
1403
1404                type NamedParameterIteratorMut<'t, T: 't + Parameter>
1405                    = tuple_named_parameter_iterator_mut_ty!('t, T, ($($T:$index,)*))
1406                where
1407                    Self: 't;
1408
1409                type NamedParameterIntoIterator<T: Parameter>
1410                    = tuple_named_parameter_into_iterator_ty!(T, ($($T:$index,)*));
1411
1412                fn parameter_count(&self) -> usize {
1413                    let ($([<$T:lower>],)*) = &self;
1414                    $([<$T:lower>].parameter_count()+)* 0usize
1415                }
1416
1417                fn parameter_structure(&self) -> Self::ParameterStructure {
1418                    let ($([<$T:lower>],)*) = &self;
1419                    ($([<$T:lower>].parameter_structure(),)*)
1420                }
1421
1422                fn parameters(&self) -> Self::ParameterIterator<'_, P> {
1423                    let ($([<$T:lower>],)*) = self;
1424                    tuple_parameter_iterator!(P, ($([<$T:lower>]:$index,)*))
1425                }
1426
1427                fn parameters_mut(&mut self) -> Self::ParameterIteratorMut<'_, P> {
1428                    let ($([<$T:lower>],)*) = self;
1429                    tuple_parameter_iterator_mut!(P, ($([<$T:lower>]:$index,)*))
1430                }
1431
1432                fn into_parameters(self) -> Self::ParameterIntoIterator<P> {
1433                    let ($([<$T:lower>],)*) = self;
1434                    tuple_parameter_into_iterator!(P, ($([<$T:lower>]:$index,)*))
1435                }
1436
1437                fn named_parameters(&self) -> Self::NamedParameterIterator<'_, P> {
1438                    let ($([<$T:lower>],)*) = self;
1439                    tuple_named_parameter_iterator!(P, ($([<$T:lower>]:$index,)*))
1440                }
1441
1442                fn named_parameters_mut(&mut self) -> Self::NamedParameterIteratorMut<'_, P> {
1443                    let ($([<$T:lower>],)*) = self;
1444                    tuple_named_parameter_iterator_mut!(P, ($([<$T:lower>]:$index,)*))
1445                }
1446
1447                fn into_named_parameters(self) -> Self::NamedParameterIntoIterator<P> {
1448                    let ($([<$T:lower>],)*) = self;
1449                    tuple_named_parameter_into_iterator!(P, ($([<$T:lower>]:$index,)*))
1450                }
1451
1452                #[allow(unused_variables)]
1453                fn from_parameters_with_remainder<I: Iterator<Item = P>>(
1454                    structure: Self::ParameterStructure,
1455                    parameters: &mut I,
1456                ) -> Result<Self, Error> {
1457                    let ($([<$T:lower _field>],)*) = structure;
1458                    $(let [<$T:lower>] = $T::from_parameters_with_remainder([<$T:lower _field>], parameters)?;)*
1459                    Ok(($([<$T:lower>],)*))
1460                }
1461            }
1462        }
1463    };
1464}
1465
1466macro_rules! tuple_parameter_iterator_ty {
1467    ($t:lifetime, $T:ty, ()) => {
1468        std::iter::Empty<&$t $T>
1469    };
1470
1471    ($t:lifetime, $T:ty, ($head:ident:$index:tt, $($tail:ident:$tail_index:tt,)*)) => {
1472        std::iter::Chain<
1473            $head::ParameterIterator<$t, $T>,
1474            tuple_parameter_iterator_ty!($t, $T, ($($tail:$tail_index,)*)),
1475        >
1476    };
1477}
1478
1479macro_rules! tuple_parameter_iterator_mut_ty {
1480    ($t:lifetime, $T:ty, ()) => {
1481        std::iter::Empty<&$t mut $T>
1482    };
1483
1484    ($t:lifetime, $T:ty, ($head:ident:$index:tt, $($tail:ident:$tail_index:tt,)*)) => {
1485        std::iter::Chain<
1486            $head::ParameterIteratorMut<$t, $T>,
1487            tuple_parameter_iterator_mut_ty!($t, $T, ($($tail:$tail_index,)*)),
1488        >
1489    };
1490}
1491
1492macro_rules! tuple_parameter_into_iterator_ty {
1493    ($T:ty, ()) => {
1494        std::iter::Empty<$T>
1495    };
1496
1497    ($T:ty, ($head:ident:$index:tt, $($tail:ident:$tail_index:tt,)*)) => {
1498        std::iter::Chain<
1499            $head::ParameterIntoIterator<$T>,
1500            tuple_parameter_into_iterator_ty!($T, ($($tail:$tail_index,)*)),
1501        >
1502    };
1503}
1504
1505macro_rules! tuple_named_parameter_iterator_ty {
1506    ($t:lifetime, $T:ty, ()) => {
1507        std::iter::Empty<(ParameterPath, &$t $T)>
1508    };
1509
1510    ($t:lifetime, $T:ty, ($head:ident:$index:tt, $($tail:ident:$tail_index:tt,)*)) => {
1511        std::iter::Chain<
1512            PathPrefixedParameterIterator<&$t $T, $head::NamedParameterIterator<$t, $T>>,
1513            tuple_named_parameter_iterator_ty!($t, $T, ($($tail:$tail_index,)*)),
1514        >
1515    };
1516}
1517
1518macro_rules! tuple_named_parameter_iterator_mut_ty {
1519    ($t:lifetime, $T:ty, ()) => {
1520        std::iter::Empty<(ParameterPath, &$t mut $T)>
1521    };
1522
1523    ($t:lifetime, $T:ty, ($head:ident:$index:tt, $($tail:ident:$tail_index:tt,)*)) => {
1524        std::iter::Chain<
1525            PathPrefixedParameterIterator<&$t mut $T, $head::NamedParameterIteratorMut<$t, $T>>,
1526            tuple_named_parameter_iterator_mut_ty!($t, $T, ($($tail:$tail_index,)*)),
1527        >
1528    };
1529}
1530
1531macro_rules! tuple_named_parameter_into_iterator_ty {
1532    ($T:ty, ()) => {
1533        std::iter::Empty<(ParameterPath, $T)>
1534    };
1535
1536    ($T:ty, ($head:ident:$index:tt, $($tail:ident:$tail_index:tt,)*)) => {
1537        std::iter::Chain<
1538            PathPrefixedParameterIterator<$T, $head::NamedParameterIntoIterator<$T>>,
1539            tuple_named_parameter_into_iterator_ty!($T, ($($tail:$tail_index,)*)),
1540        >
1541    };
1542}
1543
1544macro_rules! tuple_parameter_iterator {
1545    ($T:tt, ()) => {
1546        std::iter::empty::<&'_ $T>()
1547    };
1548
1549    ($T:tt, ($head:ident:$index:tt, $($tail:ident:$tail_index:tt,)*)) => {
1550        $head.parameters().chain(tuple_parameter_iterator!($T, ($($tail:$tail_index,)*)))
1551    };
1552}
1553
1554macro_rules! tuple_parameter_iterator_mut {
1555    ($T:tt, ()) => {
1556        std::iter::empty::<&'_ mut $T>()
1557    };
1558
1559    ($T:tt, ($head:ident:$index:tt, $($tail:ident:$tail_index:tt,)*)) => {
1560        $head.parameters_mut().chain(tuple_parameter_iterator_mut!($T, ($($tail:$tail_index,)*)))
1561    };
1562}
1563
1564macro_rules! tuple_parameter_into_iterator {
1565    ($T:tt, ()) => {
1566        std::iter::empty::<$T>()
1567    };
1568
1569    ($T:tt, ($head:ident:$index:tt, $($tail:ident:$tail_index:tt,)*)) => {
1570        $head.into_parameters().chain(tuple_parameter_into_iterator!($T, ($($tail:$tail_index,)*)))
1571    };
1572}
1573
1574macro_rules! tuple_named_parameter_iterator {
1575    ($T:tt, ()) => {
1576        std::iter::empty::<(ParameterPath, &'_ $T)>()
1577    };
1578
1579    ($T:tt, ($head:ident:$index:tt, $($tail:ident:$tail_index:tt,)*)) => {{
1580        let iterator = $head.named_parameters();
1581        let iterator = PathPrefixedParameterIterator { iterator, segment: ParameterPathSegment::TupleIndex($index) };
1582        iterator.chain(tuple_named_parameter_iterator!($T, ($($tail:$tail_index,)*)))
1583    }};
1584}
1585
1586macro_rules! tuple_named_parameter_iterator_mut {
1587    ($T:tt, ()) => {
1588        std::iter::empty::<(ParameterPath, &'_ mut $T)>()
1589    };
1590
1591    ($T:tt, ($head:ident:$index:tt, $($tail:ident:$tail_index:tt,)*)) => {{
1592        let iterator = $head.named_parameters_mut();
1593        let iterator = PathPrefixedParameterIterator { iterator, segment: ParameterPathSegment::TupleIndex($index) };
1594        iterator.chain(tuple_named_parameter_iterator_mut!($T, ($($tail:$tail_index,)*)))
1595    }};
1596}
1597
1598macro_rules! tuple_named_parameter_into_iterator {
1599    ($T:tt, ()) => {
1600        std::iter::empty::<(ParameterPath, $T)>()
1601    };
1602
1603    ($T:tt, ($head:ident:$index:tt, $($tail:ident:$tail_index:tt,)*)) => {{
1604        let iterator = $head.into_named_parameters();
1605        let iterator = PathPrefixedParameterIterator { iterator, segment: ParameterPathSegment::TupleIndex($index) };
1606        iterator.chain(tuple_named_parameter_into_iterator!($T, ($($tail:$tail_index,)*)))
1607    }};
1608}
1609
1610tuple_parameterized_impl!();
1611tuple_parameterized_impl!(V0:0);
1612tuple_parameterized_impl!(V0:0, V1:1);
1613tuple_parameterized_impl!(V0:0, V1:1, V2:2);
1614tuple_parameterized_impl!(V0:0, V1:1, V2:2, V3:3);
1615tuple_parameterized_impl!(V0:0, V1:1, V2:2, V3:3, V4:4);
1616tuple_parameterized_impl!(V0:0, V1:1, V2:2, V3:3, V4:4, V5:5);
1617tuple_parameterized_impl!(V0:0, V1:1, V2:2, V3:3, V4:4, V5:5, V6:6);
1618tuple_parameterized_impl!(V0:0, V1:1, V2:2, V3:3, V4:4, V5:5, V6:6, V7:7);
1619tuple_parameterized_impl!(V0:0, V1:1, V2:2, V3:3, V4:4, V5:5, V6:6, V7:7, V8:8);
1620tuple_parameterized_impl!(V0:0, V1:1, V2:2, V3:3, V4:4, V5:5, V6:6, V7:7, V8:8, V9:9);
1621tuple_parameterized_impl!(V0:0, V1:1, V2:2, V3:3, V4:4, V5:5, V6:6, V7:7, V8:8, V9:9, V10:10);
1622tuple_parameterized_impl!(V0:0, V1:1, V2:2, V3:3, V4:4, V5:5, V6:6, V7:7, V8:8, V9:9, V10:10, V11:11);
1623
1624pub struct ArrayParameterizedFamily<F, const N: usize>(PhantomData<F>);
1625
1626impl<P: Parameter, F: ParameterizedFamily<P> + ParameterizedFamily<Placeholder>, const N: usize> ParameterizedFamily<P>
1627    for ArrayParameterizedFamily<F, N>
1628{
1629    type To = [<F as ParameterizedFamily<P>>::To; N];
1630}
1631
1632impl<P: Parameter, V: Parameterized<P>, const N: usize> Parameterized<P> for [V; N] {
1633    type Family = ArrayParameterizedFamily<V::Family, N>;
1634
1635    type To<T: Parameter>
1636        = <Self::Family as ParameterizedFamily<T>>::To
1637    where
1638        Self::Family: ParameterizedFamily<T>;
1639
1640    type ParameterStructure = Self::To<Placeholder>;
1641
1642    type ParameterIterator<'t, T: 't + Parameter>
1643        = std::iter::FlatMap<
1644        std::slice::Iter<'t, V>,
1645        <V as Parameterized<P>>::ParameterIterator<'t, T>,
1646        fn(&'t V) -> <V as Parameterized<P>>::ParameterIterator<'t, T>,
1647    >
1648    where
1649        Self: 't;
1650
1651    type ParameterIteratorMut<'t, T: 't + Parameter>
1652        = std::iter::FlatMap<
1653        std::slice::IterMut<'t, V>,
1654        <V as Parameterized<P>>::ParameterIteratorMut<'t, T>,
1655        fn(&'t mut V) -> <V as Parameterized<P>>::ParameterIteratorMut<'t, T>,
1656    >
1657    where
1658        Self: 't;
1659
1660    type ParameterIntoIterator<T: Parameter> = std::iter::FlatMap<
1661        std::array::IntoIter<V, N>,
1662        <V as Parameterized<P>>::ParameterIntoIterator<T>,
1663        fn(V) -> <V as Parameterized<P>>::ParameterIntoIterator<T>,
1664    >;
1665
1666    type NamedParameterIterator<'t, T: 't + Parameter>
1667        = std::iter::FlatMap<
1668        std::iter::Enumerate<std::slice::Iter<'t, V>>,
1669        PathPrefixedParameterIterator<&'t T, <V as Parameterized<P>>::NamedParameterIterator<'t, T>>,
1670        fn(
1671            (usize, &'t V),
1672        ) -> PathPrefixedParameterIterator<&'t T, <V as Parameterized<P>>::NamedParameterIterator<'t, T>>,
1673    >
1674    where
1675        Self: 't;
1676
1677    type NamedParameterIteratorMut<'t, T: 't + Parameter>
1678        = std::iter::FlatMap<
1679        std::iter::Enumerate<std::slice::IterMut<'t, V>>,
1680        PathPrefixedParameterIterator<&'t mut T, <V as Parameterized<P>>::NamedParameterIteratorMut<'t, T>>,
1681        fn(
1682            (usize, &'t mut V),
1683        )
1684            -> PathPrefixedParameterIterator<&'t mut T, <V as Parameterized<P>>::NamedParameterIteratorMut<'t, T>>,
1685    >
1686    where
1687        Self: 't;
1688
1689    type NamedParameterIntoIterator<T: Parameter> = std::iter::FlatMap<
1690        std::iter::Enumerate<std::array::IntoIter<V, N>>,
1691        PathPrefixedParameterIterator<T, <V as Parameterized<P>>::NamedParameterIntoIterator<T>>,
1692        fn((usize, V)) -> PathPrefixedParameterIterator<T, <V as Parameterized<P>>::NamedParameterIntoIterator<T>>,
1693    >;
1694
1695    fn parameter_count(&self) -> usize {
1696        self.iter().map(|value| value.parameter_count()).sum()
1697    }
1698
1699    fn parameter_structure(&self) -> Self::ParameterStructure {
1700        std::array::from_fn(|i| self[i].parameter_structure())
1701    }
1702
1703    fn parameters(&self) -> Self::ParameterIterator<'_, P> {
1704        self.iter().flat_map(V::parameters)
1705    }
1706
1707    fn parameters_mut(&mut self) -> Self::ParameterIteratorMut<'_, P> {
1708        self.iter_mut().flat_map(V::parameters_mut)
1709    }
1710
1711    fn into_parameters(self) -> Self::ParameterIntoIterator<P> {
1712        self.into_iter().flat_map(V::into_parameters)
1713    }
1714
1715    fn named_parameters(&self) -> Self::NamedParameterIterator<'_, P> {
1716        self.iter().enumerate().flat_map(|(index, value)| PathPrefixedParameterIterator {
1717            iterator: value.named_parameters(),
1718            segment: ParameterPathSegment::Index(index),
1719        })
1720    }
1721
1722    fn named_parameters_mut(&mut self) -> Self::NamedParameterIteratorMut<'_, P> {
1723        self.iter_mut().enumerate().flat_map(|(index, value)| PathPrefixedParameterIterator {
1724            iterator: value.named_parameters_mut(),
1725            segment: ParameterPathSegment::Index(index),
1726        })
1727    }
1728
1729    fn into_named_parameters(self) -> Self::NamedParameterIntoIterator<P> {
1730        self.into_iter().enumerate().flat_map(|(index, value)| PathPrefixedParameterIterator {
1731            iterator: value.into_named_parameters(),
1732            segment: ParameterPathSegment::Index(index),
1733        })
1734    }
1735
1736    fn from_parameters_with_remainder<I: Iterator<Item = P>>(
1737        structure: Self::ParameterStructure,
1738        parameters: &mut I,
1739    ) -> Result<Self, Error> {
1740        // TODO(eaplatanios): Make this more efficient by using [`std::array::try_from_fn`] once it becomes stable.
1741        //  Tracking issue: https://github.com/rust-lang/rust/issues/89379.
1742        Ok(unsafe {
1743            structure
1744                .into_iter()
1745                .map(|value_structure| V::from_parameters_with_remainder(value_structure, parameters))
1746                .collect::<Result<Vec<V>, _>>()?
1747                .try_into()
1748                .unwrap_unchecked()
1749        })
1750    }
1751}
1752
1753pub struct VecParameterizedFamily<F>(PhantomData<F>);
1754
1755impl<P: Parameter, F: ParameterizedFamily<P> + ParameterizedFamily<Placeholder>> ParameterizedFamily<P>
1756    for VecParameterizedFamily<F>
1757{
1758    type To = Vec<<F as ParameterizedFamily<P>>::To>;
1759}
1760
1761impl<P: Parameter, V: Parameterized<P>> Parameterized<P> for Vec<V> {
1762    type Family = VecParameterizedFamily<V::Family>;
1763
1764    type To<T: Parameter>
1765        = <Self::Family as ParameterizedFamily<T>>::To
1766    where
1767        Self::Family: ParameterizedFamily<T>;
1768
1769    type ParameterStructure = Self::To<Placeholder>;
1770
1771    type ParameterIterator<'t, T: 't + Parameter>
1772        = std::iter::FlatMap<
1773        std::slice::Iter<'t, V>,
1774        <V as Parameterized<P>>::ParameterIterator<'t, T>,
1775        fn(&'t V) -> <V as Parameterized<P>>::ParameterIterator<'t, T>,
1776    >
1777    where
1778        Self: 't;
1779
1780    type ParameterIteratorMut<'t, T: 't + Parameter>
1781        = std::iter::FlatMap<
1782        std::slice::IterMut<'t, V>,
1783        <V as Parameterized<P>>::ParameterIteratorMut<'t, T>,
1784        fn(&'t mut V) -> <V as Parameterized<P>>::ParameterIteratorMut<'t, T>,
1785    >
1786    where
1787        Self: 't;
1788
1789    type ParameterIntoIterator<T: Parameter> = std::iter::FlatMap<
1790        std::vec::IntoIter<V>,
1791        <V as Parameterized<P>>::ParameterIntoIterator<T>,
1792        fn(V) -> <V as Parameterized<P>>::ParameterIntoIterator<T>,
1793    >;
1794
1795    type NamedParameterIterator<'t, T: 't + Parameter>
1796        = std::iter::FlatMap<
1797        std::iter::Enumerate<std::slice::Iter<'t, V>>,
1798        PathPrefixedParameterIterator<&'t T, <V as Parameterized<P>>::NamedParameterIterator<'t, T>>,
1799        fn(
1800            (usize, &'t V),
1801        ) -> PathPrefixedParameterIterator<&'t T, <V as Parameterized<P>>::NamedParameterIterator<'t, T>>,
1802    >
1803    where
1804        Self: 't;
1805
1806    type NamedParameterIteratorMut<'t, T: 't + Parameter>
1807        = std::iter::FlatMap<
1808        std::iter::Enumerate<std::slice::IterMut<'t, V>>,
1809        PathPrefixedParameterIterator<&'t mut T, <V as Parameterized<P>>::NamedParameterIteratorMut<'t, T>>,
1810        fn(
1811            (usize, &'t mut V),
1812        )
1813            -> PathPrefixedParameterIterator<&'t mut T, <V as Parameterized<P>>::NamedParameterIteratorMut<'t, T>>,
1814    >
1815    where
1816        Self: 't;
1817
1818    type NamedParameterIntoIterator<T: Parameter> = std::iter::FlatMap<
1819        std::iter::Enumerate<std::vec::IntoIter<V>>,
1820        PathPrefixedParameterIterator<T, <V as Parameterized<P>>::NamedParameterIntoIterator<T>>,
1821        fn((usize, V)) -> PathPrefixedParameterIterator<T, <V as Parameterized<P>>::NamedParameterIntoIterator<T>>,
1822    >;
1823
1824    fn parameter_count(&self) -> usize {
1825        self.iter().map(|value| value.parameter_count()).sum()
1826    }
1827
1828    fn parameter_structure(&self) -> Self::ParameterStructure {
1829        self.iter().map(|value| value.parameter_structure()).collect()
1830    }
1831
1832    fn parameters(&self) -> Self::ParameterIterator<'_, P> {
1833        self.iter().flat_map(|value| value.parameters())
1834    }
1835
1836    fn parameters_mut(&mut self) -> Self::ParameterIteratorMut<'_, P> {
1837        self.iter_mut().flat_map(|value| value.parameters_mut())
1838    }
1839
1840    fn into_parameters(self) -> Self::ParameterIntoIterator<P> {
1841        self.into_iter().flat_map(|value| value.into_parameters())
1842    }
1843
1844    fn named_parameters(&self) -> Self::NamedParameterIterator<'_, P> {
1845        self.iter().enumerate().flat_map(|(index, value)| PathPrefixedParameterIterator {
1846            iterator: value.named_parameters(),
1847            segment: ParameterPathSegment::Index(index),
1848        })
1849    }
1850
1851    fn named_parameters_mut(&mut self) -> Self::NamedParameterIteratorMut<'_, P> {
1852        self.iter_mut().enumerate().flat_map(|(index, value)| PathPrefixedParameterIterator {
1853            iterator: value.named_parameters_mut(),
1854            segment: ParameterPathSegment::Index(index),
1855        })
1856    }
1857
1858    fn into_named_parameters(self) -> Self::NamedParameterIntoIterator<P> {
1859        self.into_iter().enumerate().flat_map(|(index, value)| PathPrefixedParameterIterator {
1860            iterator: value.into_named_parameters(),
1861            segment: ParameterPathSegment::Index(index),
1862        })
1863    }
1864
1865    fn from_parameters_with_remainder<I: Iterator<Item = P>>(
1866        structure: Self::ParameterStructure,
1867        parameters: &mut I,
1868    ) -> Result<Self, Error> {
1869        let expected_count = structure.len();
1870        let mut values = Vec::new();
1871        values.reserve_exact(expected_count);
1872        for value_structure in structure {
1873            values.push(V::from_parameters_with_remainder(value_structure, parameters).map_err(
1874                |error| match error {
1875                    Error::MissingParameters { paths, .. } => Error::MissingParameters { expected_count, paths },
1876                    error => error,
1877                },
1878            )?);
1879        }
1880        Ok(values)
1881    }
1882}
1883
1884pub struct HashMapParameterizedFamily<K, F, S>(PhantomData<(K, F, S)>);
1885
1886impl<
1887    P: Parameter,
1888    K: Clone + Debug + Eq + Ord + Hash,
1889    F: ParameterizedFamily<P> + ParameterizedFamily<Placeholder>,
1890    S: BuildHasher + Clone,
1891> ParameterizedFamily<P> for HashMapParameterizedFamily<K, F, S>
1892{
1893    type To = HashMap<K, <F as ParameterizedFamily<P>>::To, S>;
1894}
1895
1896// TODO(eaplatanios): Find a simple way to avoid the need for sorting.
1897// The [`Parameterized`] implementation for [`HashMap`] is quite inefficient. That is because for most operations that
1898// require traversal of the [`HashMap`] we end up having to perform a sort of the results that we obtain (by key) to
1899// comply with the requirements of the [`Parameterized`].
1900impl<P: Parameter, K: Clone + Debug + Eq + Ord + Hash, V: Parameterized<P>, S: BuildHasher + Clone> Parameterized<P>
1901    for HashMap<K, V, S>
1902{
1903    type Family = HashMapParameterizedFamily<K, V::Family, S>;
1904
1905    type To<T: Parameter>
1906        = <Self::Family as ParameterizedFamily<T>>::To
1907    where
1908        Self::Family: ParameterizedFamily<T>;
1909
1910    type ParameterStructure = Self::To<Placeholder>;
1911
1912    type ParameterIterator<'t, T: 't + Parameter>
1913        = std::iter::FlatMap<
1914        std::vec::IntoIter<(K, &'t V)>,
1915        <V as Parameterized<P>>::ParameterIterator<'t, T>,
1916        fn((K, &'t V)) -> <V as Parameterized<P>>::ParameterIterator<'t, T>,
1917    >
1918    where
1919        Self: 't;
1920
1921    type ParameterIteratorMut<'t, T: 't + Parameter>
1922        = std::iter::FlatMap<
1923        std::vec::IntoIter<(K, *mut V)>,
1924        <V as Parameterized<P>>::ParameterIteratorMut<'t, T>,
1925        fn((K, *mut V)) -> <V as Parameterized<P>>::ParameterIteratorMut<'t, T>,
1926    >
1927    where
1928        Self: 't;
1929
1930    type ParameterIntoIterator<T: Parameter> = std::iter::FlatMap<
1931        std::vec::IntoIter<(K, V)>,
1932        <V as Parameterized<P>>::ParameterIntoIterator<T>,
1933        fn((K, V)) -> <V as Parameterized<P>>::ParameterIntoIterator<T>,
1934    >;
1935
1936    type NamedParameterIterator<'t, T: 't + Parameter>
1937        = std::iter::FlatMap<
1938        std::vec::IntoIter<(&'t K, &'t V)>,
1939        PathPrefixedParameterIterator<&'t T, <V as Parameterized<P>>::NamedParameterIterator<'t, T>>,
1940        fn(
1941            (&'t K, &'t V),
1942        ) -> PathPrefixedParameterIterator<&'t T, <V as Parameterized<P>>::NamedParameterIterator<'t, T>>,
1943    >
1944    where
1945        Self: 't;
1946
1947    type NamedParameterIteratorMut<'t, T: 't + Parameter>
1948        = std::iter::FlatMap<
1949        std::vec::IntoIter<(K, *mut V)>,
1950        PathPrefixedParameterIterator<&'t mut T, <V as Parameterized<P>>::NamedParameterIteratorMut<'t, T>>,
1951        fn(
1952            (K, *mut V),
1953        )
1954            -> PathPrefixedParameterIterator<&'t mut T, <V as Parameterized<P>>::NamedParameterIteratorMut<'t, T>>,
1955    >
1956    where
1957        Self: 't;
1958
1959    type NamedParameterIntoIterator<T: Parameter> = std::iter::FlatMap<
1960        std::vec::IntoIter<(K, V)>,
1961        PathPrefixedParameterIterator<T, <V as Parameterized<P>>::NamedParameterIntoIterator<T>>,
1962        fn((K, V)) -> PathPrefixedParameterIterator<T, <V as Parameterized<P>>::NamedParameterIntoIterator<T>>,
1963    >;
1964
1965    fn parameter_count(&self) -> usize {
1966        self.values().map(|value| value.parameter_count()).sum()
1967    }
1968
1969    fn parameter_structure(&self) -> Self::ParameterStructure {
1970        let mut structure = HashMap::with_capacity_and_hasher(self.len(), self.hasher().clone());
1971        let mut sorted_entries = self.iter().map(|(k, v)| (k.clone(), v.parameter_structure())).collect::<Vec<_>>();
1972        sorted_entries.sort_unstable_by(|(l, _), (r, _)| l.cmp(r));
1973        structure.extend(sorted_entries);
1974        structure
1975    }
1976
1977    fn parameters(&self) -> Self::ParameterIterator<'_, P> {
1978        let mut sorted_entries = self.iter().map(|(k, v)| (k.clone(), v)).collect::<Vec<_>>();
1979        sorted_entries.sort_unstable_by(|(l, _), (r, _)| l.cmp(r));
1980        sorted_entries.into_iter().flat_map(|(_, v)| V::parameters(v))
1981    }
1982
1983    fn parameters_mut(&mut self) -> Self::ParameterIteratorMut<'_, P> {
1984        // Note that each pointer below originates from a distinct `iter_mut()` item, and so the pointers hereare unique
1985        // and non-overlapping. We do not structurally modify the map after collecting the pointers and so they remain
1986        // valid for the duration of this traversal.
1987        let mut sorted_entries = self.iter_mut().map(|(k, v)| (k.clone(), v as *mut V)).collect::<Vec<_>>();
1988        sorted_entries.sort_unstable_by(|(l, _), (r, _)| l.cmp(r));
1989        sorted_entries.into_iter().flat_map(|(_, v)| V::parameters_mut(unsafe { &mut *v }))
1990    }
1991
1992    fn into_parameters(self) -> Self::ParameterIntoIterator<P> {
1993        let mut sorted_entries = self.into_iter().collect::<Vec<_>>();
1994        sorted_entries.sort_unstable_by(|(l, _), (r, _)| l.cmp(r));
1995        sorted_entries.into_iter().flat_map(|(_, v)| V::into_parameters(v))
1996    }
1997
1998    fn named_parameters(&self) -> Self::NamedParameterIterator<'_, P> {
1999        let mut sorted_entries = self.iter().collect::<Vec<_>>();
2000        sorted_entries.sort_unstable_by(|(l, _), (r, _)| l.cmp(r));
2001        sorted_entries.into_iter().flat_map(|(k, v)| PathPrefixedParameterIterator {
2002            iterator: v.named_parameters(),
2003            segment: ParameterPathSegment::Key(format!("{k:?}")),
2004        })
2005    }
2006
2007    fn named_parameters_mut(&mut self) -> Self::NamedParameterIteratorMut<'_, P> {
2008        // Note that each pointer below originates from a distinct `iter_mut()` item, and so the pointers hereare unique
2009        // and non-overlapping. We do not structurally modify the map after collecting the pointers and so they remain
2010        // valid for the duration of this traversal.
2011        let mut sorted_entries = self.iter_mut().map(|(k, v)| (k.clone(), v as *mut V)).collect::<Vec<_>>();
2012        sorted_entries.sort_unstable_by(|(l, _), (r, _)| l.cmp(r));
2013        sorted_entries.into_iter().flat_map(|(k, v)| PathPrefixedParameterIterator {
2014            iterator: (unsafe { &mut *v }).named_parameters_mut(),
2015            segment: ParameterPathSegment::Key(format!("{k:?}")),
2016        })
2017    }
2018
2019    fn into_named_parameters(self) -> Self::NamedParameterIntoIterator<P> {
2020        let mut sorted_entries = self.into_iter().collect::<Vec<_>>();
2021        sorted_entries.sort_unstable_by(|(l, _), (r, _)| l.cmp(r));
2022        sorted_entries.into_iter().flat_map(|(k, v)| PathPrefixedParameterIterator {
2023            iterator: v.into_named_parameters(),
2024            segment: ParameterPathSegment::Key(format!("{k:?}")),
2025        })
2026    }
2027
2028    fn from_parameters_with_remainder<I: Iterator<Item = P>>(
2029        structure: Self::ParameterStructure,
2030        parameters: &mut I,
2031    ) -> Result<Self, Error> {
2032        let expected_count = structure.len();
2033        let mut values = HashMap::with_capacity_and_hasher(expected_count, structure.hasher().clone());
2034        let mut sorted_entries = structure.into_iter().collect::<Vec<_>>();
2035        sorted_entries.sort_unstable_by(|(l, _), (r, _)| l.cmp(r));
2036        for (key, value_structure) in sorted_entries {
2037            values.insert(
2038                key,
2039                V::from_parameters_with_remainder(value_structure, parameters).map_err(|error| match error {
2040                    Error::MissingParameters { paths, .. } => Error::MissingParameters { expected_count, paths },
2041                    error => error,
2042                })?,
2043            );
2044        }
2045        Ok(values)
2046    }
2047}
2048
2049pub struct BTreeMapParameterizedFamily<K, F>(PhantomData<(K, F)>);
2050
2051impl<P: Parameter, K: Clone + Debug + Ord, F: ParameterizedFamily<P> + ParameterizedFamily<Placeholder>>
2052    ParameterizedFamily<P> for BTreeMapParameterizedFamily<K, F>
2053{
2054    type To = BTreeMap<K, <F as ParameterizedFamily<P>>::To>;
2055}
2056
2057impl<P: Parameter, K: Clone + Debug + Ord, V: Parameterized<P>> Parameterized<P> for BTreeMap<K, V> {
2058    type Family = BTreeMapParameterizedFamily<K, V::Family>;
2059
2060    type To<T: Parameter>
2061        = <Self::Family as ParameterizedFamily<T>>::To
2062    where
2063        Self::Family: ParameterizedFamily<T>;
2064
2065    type ParameterStructure = Self::To<Placeholder>;
2066
2067    type ParameterIterator<'t, T: 't + Parameter>
2068        = std::iter::FlatMap<
2069        std::collections::btree_map::Values<'t, K, V>,
2070        <V as Parameterized<P>>::ParameterIterator<'t, T>,
2071        fn(&'t V) -> <V as Parameterized<P>>::ParameterIterator<'t, T>,
2072    >
2073    where
2074        Self: 't;
2075
2076    type ParameterIteratorMut<'t, T: 't + Parameter>
2077        = std::iter::FlatMap<
2078        std::collections::btree_map::ValuesMut<'t, K, V>,
2079        <V as Parameterized<P>>::ParameterIteratorMut<'t, T>,
2080        fn(&'t mut V) -> <V as Parameterized<P>>::ParameterIteratorMut<'t, T>,
2081    >
2082    where
2083        Self: 't;
2084
2085    type ParameterIntoIterator<T: Parameter> = std::iter::FlatMap<
2086        std::collections::btree_map::IntoValues<K, V>,
2087        <V as Parameterized<P>>::ParameterIntoIterator<T>,
2088        fn(V) -> <V as Parameterized<P>>::ParameterIntoIterator<T>,
2089    >;
2090
2091    type NamedParameterIterator<'t, T: 't + Parameter>
2092        = std::iter::FlatMap<
2093        std::collections::btree_map::Iter<'t, K, V>,
2094        PathPrefixedParameterIterator<&'t T, <V as Parameterized<P>>::NamedParameterIterator<'t, T>>,
2095        fn(
2096            (&'t K, &'t V),
2097        ) -> PathPrefixedParameterIterator<&'t T, <V as Parameterized<P>>::NamedParameterIterator<'t, T>>,
2098    >
2099    where
2100        Self: 't;
2101
2102    type NamedParameterIteratorMut<'t, T: 't + Parameter>
2103        = std::iter::FlatMap<
2104        std::collections::btree_map::IterMut<'t, K, V>,
2105        PathPrefixedParameterIterator<&'t mut T, <V as Parameterized<P>>::NamedParameterIteratorMut<'t, T>>,
2106        fn(
2107            (&'t K, &'t mut V),
2108        )
2109            -> PathPrefixedParameterIterator<&'t mut T, <V as Parameterized<P>>::NamedParameterIteratorMut<'t, T>>,
2110    >
2111    where
2112        Self: 't;
2113
2114    type NamedParameterIntoIterator<T: Parameter> = std::iter::FlatMap<
2115        std::collections::btree_map::IntoIter<K, V>,
2116        PathPrefixedParameterIterator<T, <V as Parameterized<P>>::NamedParameterIntoIterator<T>>,
2117        fn((K, V)) -> PathPrefixedParameterIterator<T, <V as Parameterized<P>>::NamedParameterIntoIterator<T>>,
2118    >;
2119
2120    fn parameter_count(&self) -> usize {
2121        self.values().map(|value| value.parameter_count()).sum()
2122    }
2123
2124    fn parameter_structure(&self) -> Self::ParameterStructure {
2125        BTreeMap::from_iter(self.iter().map(|(key, value)| (key.clone(), value.parameter_structure())))
2126    }
2127
2128    fn parameters(&self) -> Self::ParameterIterator<'_, P> {
2129        self.values().flat_map(V::parameters)
2130    }
2131
2132    fn parameters_mut(&mut self) -> Self::ParameterIteratorMut<'_, P> {
2133        self.values_mut().flat_map(V::parameters_mut)
2134    }
2135
2136    fn into_parameters(self) -> Self::ParameterIntoIterator<P> {
2137        self.into_values().flat_map(V::into_parameters)
2138    }
2139
2140    fn named_parameters(&self) -> Self::NamedParameterIterator<'_, P> {
2141        self.iter().flat_map(|(key, value)| PathPrefixedParameterIterator {
2142            iterator: value.named_parameters(),
2143            segment: ParameterPathSegment::Key(format!("{key:?}")),
2144        })
2145    }
2146
2147    fn named_parameters_mut(&mut self) -> Self::NamedParameterIteratorMut<'_, P> {
2148        self.iter_mut().flat_map(|(key, value)| PathPrefixedParameterIterator {
2149            iterator: value.named_parameters_mut(),
2150            segment: ParameterPathSegment::Key(format!("{key:?}")),
2151        })
2152    }
2153
2154    fn into_named_parameters(self) -> Self::NamedParameterIntoIterator<P> {
2155        self.into_iter().flat_map(|(key, value)| PathPrefixedParameterIterator {
2156            iterator: value.into_named_parameters(),
2157            segment: ParameterPathSegment::Key(format!("{key:?}")),
2158        })
2159    }
2160
2161    fn from_parameters_with_remainder<I: Iterator<Item = P>>(
2162        structure: Self::ParameterStructure,
2163        parameters: &mut I,
2164    ) -> Result<Self, Error> {
2165        let expected_count = structure.len();
2166        let mut values = BTreeMap::new();
2167        for (key, value_structure) in structure {
2168            values.insert(
2169                key,
2170                V::from_parameters_with_remainder(value_structure, parameters).map_err(|error| match error {
2171                    Error::MissingParameters { paths, .. } => Error::MissingParameters { expected_count, paths },
2172                    error => error,
2173                })?,
2174            );
2175        }
2176        Ok(values)
2177    }
2178}
2179
2180#[cfg(test)]
2181mod tests {
2182    use std::collections::{BTreeMap, HashMap};
2183
2184    use ryft::*;
2185
2186    #[test]
2187    fn test_placeholder() {
2188        let placeholder = Placeholder;
2189        assert_eq!(format!("{placeholder}"), "<Parameter>");
2190        assert_eq!(format!("{placeholder:?}"), "<Parameter>");
2191    }
2192
2193    #[test]
2194    fn test_parameter_path() {
2195        let path = ParameterPath::root();
2196        assert_eq!(path.len(), 0);
2197        assert!(path.is_empty());
2198        assert!(path.is_root());
2199        let path_prefix = ParameterPath::root().variant("ResidualConnection").field("weights");
2200        let path = path_prefix.clone().index(2).tuple_index(1).key("alpha");
2201        assert_eq!(path_prefix.len(), 2);
2202        assert_eq!(path.len(), 5);
2203        assert!(!path.is_root());
2204        assert!(path.is_prefix_of(&path));
2205        assert!(path_prefix.is_prefix_of(&path));
2206        assert!(!path.is_prefix_of(&path_prefix));
2207        assert_eq!(
2208            path.segments().cloned().collect::<Vec<_>>(),
2209            vec![
2210                ParameterPathSegment::Variant("ResidualConnection"),
2211                ParameterPathSegment::Field("weights"),
2212                ParameterPathSegment::Index(2),
2213                ParameterPathSegment::TupleIndex(1),
2214                ParameterPathSegment::Key(format!("{:?}", "alpha")),
2215            ],
2216        );
2217        assert_eq!(format!("{path}"), "$.residual_connection.weights[2].1[\"alpha\"]");
2218        assert_eq!(format!("{path:?}"), "ParameterPath[$.residual_connection.weights[2].1[\"alpha\"]]");
2219    }
2220
2221    #[test]
2222    fn test_parameterized() {
2223        #[derive(Parameterized, Clone, Debug, PartialEq, Eq)]
2224        struct Block<P: Parameter> {
2225            pair: (P, usize),
2226            gain: P,
2227            name: &'static str,
2228        }
2229
2230        #[derive(Parameterized, Clone, Debug, PartialEq, Eq)]
2231        #[allow(dead_code)]
2232        enum Controller<P: Parameter> {
2233            Identity,
2234            Blend { alpha: P, branch: Block<P> },
2235        }
2236
2237        #[derive(Parameterized, Clone, Debug, PartialEq, Eq)]
2238        struct Layer<P: Parameter> {
2239            weights: Vec<P>,
2240            bias: P,
2241            tag: &'static str,
2242        }
2243
2244        #[derive(Parameterized, Clone, Debug, PartialEq, Eq)]
2245        struct Network<P: Parameter> {
2246            stem: Layer<P>,
2247            controller: Controller<P>,
2248            heads: [Block<P>; 2],
2249            metadata: (usize, &'static str),
2250        }
2251
2252        let value = Network {
2253            stem: Layer { weights: vec![1, 2], bias: 3, tag: "stem" },
2254            controller: Controller::Blend { alpha: 4, branch: Block { pair: (5, 10), gain: 6, name: "branch" } },
2255            heads: [
2256                Block { pair: (7, 11), gain: 8, name: "head_0" },
2257                Block { pair: (9, 12), gain: 10, name: "head_1" },
2258            ],
2259            metadata: (42, "meta"),
2260        };
2261
2262        let expected_parameter_paths = vec![
2263            "$.stem.weights[0]".to_string(),
2264            "$.stem.weights[1]".to_string(),
2265            "$.stem.bias".to_string(),
2266            "$.controller.blend.alpha".to_string(),
2267            "$.controller.blend.branch.pair.0".to_string(),
2268            "$.controller.blend.branch.gain".to_string(),
2269            "$.heads[0].pair.0".to_string(),
2270            "$.heads[0].gain".to_string(),
2271            "$.heads[1].pair.0".to_string(),
2272            "$.heads[1].gain".to_string(),
2273        ];
2274
2275        // Test [`Parameterized::parameter_count`].
2276        assert_eq!(value.parameter_count(), 10);
2277
2278        // Test [`Parameterized::parameter_structure`].
2279        let structure = value.parameter_structure();
2280        assert_eq!(
2281            structure,
2282            Network {
2283                stem: Layer { weights: vec![Placeholder, Placeholder], bias: Placeholder, tag: "stem" },
2284                controller: Controller::Blend {
2285                    alpha: Placeholder,
2286                    branch: Block { pair: (Placeholder, 10), gain: Placeholder, name: "branch" },
2287                },
2288                heads: [
2289                    Block { pair: (Placeholder, 11), gain: Placeholder, name: "head_0" },
2290                    Block { pair: (Placeholder, 12), gain: Placeholder, name: "head_1" },
2291                ],
2292                metadata: (42, "meta"),
2293            },
2294        );
2295
2296        // Test [`Parameterized::parameters`].
2297        assert_eq!(value.parameters().copied().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
2298
2299        // Test [`Parameterized::parameters_mut`].
2300        let mut value_clone = value.clone();
2301        for parameter in value_clone.parameters_mut() {
2302            *parameter += 100;
2303        }
2304        assert_eq!(
2305            value_clone.parameters().copied().collect::<Vec<_>>(),
2306            vec![101, 102, 103, 104, 105, 106, 107, 108, 109, 110]
2307        );
2308
2309        // Test [`Parameterized::into_parameters`].
2310        assert_eq!(value.clone().into_parameters().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
2311
2312        // Test [`Parameterized::named_parameters`].
2313        assert_eq!(
2314            value.named_parameters().map(|(path, parameter)| (path.to_string(), *parameter)).collect::<Vec<_>>(),
2315            expected_parameter_paths
2316                .iter()
2317                .cloned()
2318                .zip(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
2319                .collect::<Vec<_>>()
2320        );
2321
2322        // Test [`Parameterized::named_parameters_mut`].
2323        let mut value_clone = value.clone();
2324        let mut seen_parameter_paths = Vec::new();
2325        for (path, parameter) in value_clone.named_parameters_mut() {
2326            seen_parameter_paths.push(path.to_string());
2327            *parameter += path.len() as i32;
2328        }
2329        assert_eq!(seen_parameter_paths, expected_parameter_paths);
2330        assert_eq!(value_clone.parameters().copied().collect::<Vec<_>>(), vec![4, 5, 5, 7, 10, 10, 11, 11, 13, 13]);
2331
2332        // Test [`Parameterized::into_named_parameters`].
2333        assert_eq!(
2334            value
2335                .clone()
2336                .into_named_parameters()
2337                .map(|(path, parameter)| (path.to_string(), parameter))
2338                .collect::<Vec<_>>(),
2339            vec![
2340                ("$.stem.weights[0]".to_string(), 1),
2341                ("$.stem.weights[1]".to_string(), 2),
2342                ("$.stem.bias".to_string(), 3),
2343                ("$.controller.blend.alpha".to_string(), 4),
2344                ("$.controller.blend.branch.pair.0".to_string(), 5),
2345                ("$.controller.blend.branch.gain".to_string(), 6),
2346                ("$.heads[0].pair.0".to_string(), 7),
2347                ("$.heads[0].gain".to_string(), 8),
2348                ("$.heads[1].pair.0".to_string(), 9),
2349                ("$.heads[1].gain".to_string(), 10),
2350            ]
2351        );
2352
2353        // Test [`Parameterized::parameter_paths`].
2354        assert_eq!(value.parameter_paths().map(|path| path.to_string()).collect::<Vec<_>>(), expected_parameter_paths);
2355
2356        // Test [`Parameterized::from_parameters_with_remainder`].
2357        let mut parameters = vec![11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 500].into_iter();
2358        assert_eq!(
2359            Network::from_parameters_with_remainder(structure.clone(), &mut parameters),
2360            Ok(Network {
2361                stem: Layer { weights: vec![11, 12], bias: 13, tag: "stem" },
2362                controller: Controller::Blend { alpha: 14, branch: Block { pair: (15, 10), gain: 16, name: "branch" } },
2363                heads: [
2364                    Block { pair: (17, 11), gain: 18, name: "head_0" },
2365                    Block { pair: (19, 12), gain: 20, name: "head_1" },
2366                ],
2367                metadata: (42, "meta"),
2368            })
2369        );
2370        assert_eq!(parameters.collect::<Vec<_>>(), vec![500]);
2371
2372        // Test [`Parameterized::from_parameters`].
2373        assert_eq!(
2374            Network::from_parameters(structure.clone(), vec![21, 22, 23, 24, 25, 26, 27, 28, 29, 30]),
2375            Ok(Network {
2376                stem: Layer { weights: vec![21, 22], bias: 23, tag: "stem" },
2377                controller: Controller::Blend { alpha: 24, branch: Block { pair: (25, 10), gain: 26, name: "branch" } },
2378                heads: [
2379                    Block { pair: (27, 11), gain: 28, name: "head_0" },
2380                    Block { pair: (29, 12), gain: 30, name: "head_1" },
2381                ],
2382                metadata: (42, "meta"),
2383            })
2384        );
2385        assert_eq!(
2386            Network::from_parameters(structure.clone(), vec![31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 999]),
2387            Err(Error::UnusedParameters { paths: None })
2388        );
2389
2390        // Test [`Parameterized::from_named_parameters`].
2391        let mut parameters = value.clone().into_named_parameters().collect::<Vec<_>>();
2392        parameters.reverse();
2393        assert_eq!(Network::from_named_parameters(structure.clone(), parameters), Ok(value.clone()));
2394
2395        // Test [`Parameterized::from_broadcasted_named_parameters`].
2396        assert_eq!(
2397            Network::from_broadcasted_named_parameters(
2398                structure.clone(),
2399                HashMap::from([
2400                    (ParameterPath::root(), 1),
2401                    (ParameterPath::root().field("controller"), 2),
2402                    (ParameterPath::root().field("controller").variant("Blend").field("branch"), 10),
2403                    (ParameterPath::root().field("controller").variant("Blend").field("branch").field("gain"), 20),
2404                    (ParameterPath::root().field("heads").index(1), 30),
2405                ])
2406            ),
2407            Ok(Network {
2408                stem: Layer { weights: vec![1, 1], bias: 1, tag: "stem" },
2409                controller: Controller::Blend { alpha: 2, branch: Block { pair: (10, 10), gain: 20, name: "branch" } },
2410                heads: [
2411                    Block { pair: (1, 11), gain: 1, name: "head_0" },
2412                    Block { pair: (30, 12), gain: 30, name: "head_1" },
2413                ],
2414                metadata: (42, "meta"),
2415            })
2416        );
2417
2418        // Test [`Parameterized::map_parameters`].
2419        assert_eq!(
2420            value.clone().map_parameters(|parameter| i64::from(parameter) * 10),
2421            Ok(Network {
2422                stem: Layer { weights: vec![10i64, 20i64], bias: 30i64, tag: "stem" },
2423                controller: Controller::Blend {
2424                    alpha: 40i64,
2425                    branch: Block { pair: (50i64, 10), gain: 60i64, name: "branch" },
2426                },
2427                heads: [
2428                    Block { pair: (70i64, 11), gain: 80i64, name: "head_0" },
2429                    Block { pair: (90i64, 12), gain: 100i64, name: "head_1" },
2430                ],
2431                metadata: (42, "meta"),
2432            })
2433        );
2434
2435        // Test [`Parameterized::map_named_parameters`].
2436        assert_eq!(
2437            value
2438                .clone()
2439                .map_named_parameters(|path, parameter| i64::from(parameter) + (path.len() as i64))
2440                .unwrap()
2441                .into_parameters()
2442                .collect::<Vec<_>>(),
2443            vec![4i64, 5i64, 5i64, 7i64, 10i64, 10i64, 11i64, 11i64, 13i64, 13i64],
2444        );
2445
2446        // Test [`Parameterized::filter_parameters`].
2447        assert_eq!(
2448            value
2449                .clone()
2450                .filter_parameters(|path, _| path.to_string().ends_with(".bias") || path.to_string().ends_with(".gain"))
2451                .unwrap()
2452                .into_parameters()
2453                .collect::<Vec<_>>(),
2454            vec![None, None, Some(3), None, None, Some(6), None, Some(8), None, Some(10)],
2455        );
2456
2457        // Test [`Parameterized::partition_parameters`].
2458        let (partition_0, partition_1) =
2459            value.clone().partition_parameters(|path, _| path.to_string().starts_with("$.heads[1]")).unwrap();
2460        assert_eq!(
2461            partition_0.clone().into_parameters().collect::<Vec<_>>(),
2462            vec![None, None, None, None, None, None, None, None, Some(9), Some(10)],
2463        );
2464        assert_eq!(
2465            partition_1.clone().into_parameters().collect::<Vec<_>>(),
2466            vec![Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), None, None],
2467        );
2468
2469        // Test [`Parameterized::combine_parameters`].
2470        assert_eq!(Network::combine_parameters(structure.clone(), vec![partition_0, partition_1]), Ok(value.clone()));
2471
2472        // Test [`Parameterized::replace_parameters`].
2473        assert_eq!(
2474            value
2475                .clone()
2476                .replace_parameters(
2477                    value
2478                        .map_parameters(|parameter| match parameter {
2479                            2 => Some(200),
2480                            5 => Some(500),
2481                            7 => Some(700),
2482                            10 => Some(1000),
2483                            _ => None,
2484                        })
2485                        .unwrap()
2486                )
2487                .unwrap()
2488                .into_parameters()
2489                .collect::<Vec<_>>(),
2490            vec![1, 200, 3, 4, 500, 6, 700, 8, 9, 1000],
2491        );
2492    }
2493
2494    #[test]
2495    fn test_parameterized_parameter() {
2496        let value = 7i32;
2497        assert_eq!(value.parameter_count(), 1);
2498        assert_eq!(value.parameter_structure(), Placeholder);
2499        assert_eq!(value.parameters().copied().collect::<Vec<_>>(), vec![7]);
2500        assert_eq!(
2501            value.named_parameters().map(|(path, parameter)| (path.to_string(), *parameter)).collect::<Vec<_>>(),
2502            vec![("$".to_string(), 7)],
2503        );
2504        assert_eq!(value.parameter_paths().map(|path| path.to_string()).collect::<Vec<_>>(), vec!["$".to_string()]);
2505    }
2506
2507    #[test]
2508    fn test_parameterized_tuple() {
2509        let value = (0i32, (1i32, 2i32), (3i32, (4i32, 5i32)), 6i32, ((7i32, 8i32), 9i32));
2510        assert_eq!(value.parameter_count(), 10);
2511        assert_eq!(
2512            value.parameter_structure(),
2513            (
2514                Placeholder,
2515                (Placeholder, Placeholder),
2516                (Placeholder, (Placeholder, Placeholder)),
2517                Placeholder,
2518                ((Placeholder, Placeholder), Placeholder),
2519            ),
2520        );
2521        assert_eq!(value.parameters().copied().collect::<Vec<_>>(), vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
2522        assert_eq!(
2523            value.named_parameters().map(|(path, parameter)| (path.to_string(), *parameter)).collect::<Vec<_>>(),
2524            vec![
2525                ("$.0".to_string(), 0),
2526                ("$.1.0".to_string(), 1),
2527                ("$.1.1".to_string(), 2),
2528                ("$.2.0".to_string(), 3),
2529                ("$.2.1.0".to_string(), 4),
2530                ("$.2.1.1".to_string(), 5),
2531                ("$.3".to_string(), 6),
2532                ("$.4.0.0".to_string(), 7),
2533                ("$.4.0.1".to_string(), 8),
2534                ("$.4.1".to_string(), 9),
2535            ],
2536        );
2537        assert_eq!(
2538            value.parameter_paths().map(|path| path.to_string()).collect::<Vec<_>>(),
2539            vec![
2540                "$.0".to_string(),
2541                "$.1.0".to_string(),
2542                "$.1.1".to_string(),
2543                "$.2.0".to_string(),
2544                "$.2.1.0".to_string(),
2545                "$.2.1.1".to_string(),
2546                "$.3".to_string(),
2547                "$.4.0.0".to_string(),
2548                "$.4.0.1".to_string(),
2549                "$.4.1".to_string(),
2550            ],
2551        );
2552    }
2553
2554    #[test]
2555    fn test_parameterized_array() {
2556        let value = [(1, 2), (3, 4), (5, 6)];
2557        assert_eq!(value.parameter_count(), 6);
2558        assert_eq!(
2559            value.parameter_structure(),
2560            [(Placeholder, Placeholder), (Placeholder, Placeholder), (Placeholder, Placeholder)],
2561        );
2562        assert_eq!(value.parameters().copied().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6]);
2563        assert_eq!(
2564            value.named_parameters().map(|(path, parameter)| (path.to_string(), *parameter)).collect::<Vec<_>>(),
2565            vec![
2566                ("$[0].0".to_string(), 1),
2567                ("$[0].1".to_string(), 2),
2568                ("$[1].0".to_string(), 3),
2569                ("$[1].1".to_string(), 4),
2570                ("$[2].0".to_string(), 5),
2571                ("$[2].1".to_string(), 6),
2572            ],
2573        );
2574        assert_eq!(
2575            value.parameter_paths().map(|path| path.to_string()).collect::<Vec<_>>(),
2576            vec![
2577                "$[0].0".to_string(),
2578                "$[0].1".to_string(),
2579                "$[1].0".to_string(),
2580                "$[1].1".to_string(),
2581                "$[2].0".to_string(),
2582                "$[2].1".to_string(),
2583            ],
2584        );
2585    }
2586
2587    #[test]
2588    fn test_parameterized_vec() {
2589        let value = vec![(1, 2), (3, 4)];
2590        assert_eq!(value.parameter_count(), 4);
2591        assert_eq!(value.parameter_structure(), vec![(Placeholder, Placeholder), (Placeholder, Placeholder)]);
2592        assert_eq!(value.parameters().copied().collect::<Vec<_>>(), vec![1, 2, 3, 4]);
2593        assert_eq!(
2594            value.named_parameters().map(|(path, parameter)| (path.to_string(), *parameter)).collect::<Vec<_>>(),
2595            vec![
2596                ("$[0].0".to_string(), 1),
2597                ("$[0].1".to_string(), 2),
2598                ("$[1].0".to_string(), 3),
2599                ("$[1].1".to_string(), 4),
2600            ],
2601        );
2602        assert_eq!(
2603            value.parameter_paths().map(|path| path.to_string()).collect::<Vec<_>>(),
2604            vec!["$[0].0".to_string(), "$[0].1".to_string(), "$[1].0".to_string(), "$[1].1".to_string()],
2605        );
2606    }
2607
2608    #[test]
2609    fn test_parameterized_hash_map() {
2610        let value = HashMap::from([("zeta", (1, 2)), ("alpha", (3, 4)), ("mu", (5, 6))]);
2611        assert_eq!(value.parameter_count(), 6);
2612        assert_eq!(
2613            value.parameter_structure(),
2614            HashMap::from([
2615                ("alpha", (Placeholder, Placeholder)),
2616                ("mu", (Placeholder, Placeholder)),
2617                ("zeta", (Placeholder, Placeholder)),
2618            ]),
2619        );
2620        assert_eq!(value.parameters().copied().collect::<Vec<_>>(), vec![3, 4, 5, 6, 1, 2]);
2621        assert_eq!(
2622            value.named_parameters().map(|(path, parameter)| (path.to_string(), *parameter)).collect::<Vec<_>>(),
2623            vec![
2624                ("$[\"alpha\"].0".to_string(), 3),
2625                ("$[\"alpha\"].1".to_string(), 4),
2626                ("$[\"mu\"].0".to_string(), 5),
2627                ("$[\"mu\"].1".to_string(), 6),
2628                ("$[\"zeta\"].0".to_string(), 1),
2629                ("$[\"zeta\"].1".to_string(), 2),
2630            ],
2631        );
2632        assert_eq!(
2633            value.parameter_paths().map(|path| path.to_string()).collect::<Vec<_>>(),
2634            vec![
2635                "$[\"alpha\"].0".to_string(),
2636                "$[\"alpha\"].1".to_string(),
2637                "$[\"mu\"].0".to_string(),
2638                "$[\"mu\"].1".to_string(),
2639                "$[\"zeta\"].0".to_string(),
2640                "$[\"zeta\"].1".to_string(),
2641            ],
2642        );
2643    }
2644
2645    #[test]
2646    fn test_parameterized_b_tree_map() {
2647        let value = BTreeMap::from([("left", (1, 2)), ("right", (3, 4))]);
2648        assert_eq!(value.parameter_count(), 4);
2649        assert_eq!(
2650            value.parameter_structure(),
2651            BTreeMap::from([("left", (Placeholder, Placeholder)), ("right", (Placeholder, Placeholder))]),
2652        );
2653        assert_eq!(value.parameters().copied().collect::<Vec<_>>(), vec![1, 2, 3, 4]);
2654        assert_eq!(
2655            value.named_parameters().map(|(path, parameter)| (path.to_string(), *parameter)).collect::<Vec<_>>(),
2656            vec![
2657                ("$[\"left\"].0".to_string(), 1),
2658                ("$[\"left\"].1".to_string(), 2),
2659                ("$[\"right\"].0".to_string(), 3),
2660                ("$[\"right\"].1".to_string(), 4),
2661            ],
2662        );
2663        assert_eq!(
2664            value.parameter_paths().map(|path| path.to_string()).collect::<Vec<_>>(),
2665            vec![
2666                "$[\"left\"].0".to_string(),
2667                "$[\"left\"].1".to_string(),
2668                "$[\"right\"].0".to_string(),
2669                "$[\"right\"].1".to_string(),
2670            ],
2671        );
2672    }
2673}