Skip to main content

firewood_storage/node/
children.rs

1// Copyright (C) 2025, Ava Labs, Inc. All rights reserved.
2// See the file LICENSE.md for licensing terms.
3
4use crate::PathComponent;
5
6const MAX_CHILDREN: usize = PathComponent::LEN;
7
8/// Type alias for an iterator over the slots of a branch node's children
9/// with its corresponding [`PathComponent`].
10pub type ChildrenSlots<T> = std::iter::Zip<
11    std::array::IntoIter<PathComponent, MAX_CHILDREN>,
12    std::array::IntoIter<T, MAX_CHILDREN>,
13>;
14
15/// The type of iterator returned by [`Children::iter_present`].
16pub type IterPresentRef<'a, T> = std::iter::FilterMap<
17    ChildrenSlots<&'a Option<T>>,
18    fn((PathComponent, &'a Option<T>)) -> Option<(PathComponent, &'a T)>,
19>;
20
21/// The type of iterator returned by [`Children::iter_present`].
22pub type IterPresentMut<'a, T> = std::iter::FilterMap<
23    ChildrenSlots<&'a mut Option<T>>,
24    fn((PathComponent, &'a mut Option<T>)) -> Option<(PathComponent, &'a mut T)>,
25>;
26
27/// Type alias for a collection of children in a branch node.
28#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
29pub struct Children<T>([T; MAX_CHILDREN]);
30
31impl<T: std::fmt::Debug> std::fmt::Debug for Children<T> {
32    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33        f.debug_map()
34            .entries(self.iter().map(|(pc, child)| (pc.as_u8(), child)))
35            .finish()
36    }
37}
38
39impl<T> Children<T> {
40    /// Creates a new [`Children`] by calling `f` for each possible
41    /// [`PathComponent`].
42    #[must_use]
43    pub fn from_fn(f: impl FnMut(PathComponent) -> T) -> Self {
44        Self(PathComponent::ALL.map(f))
45    }
46
47    /// Borrows each element and returns a [`Children`] wrapping the references.
48    #[must_use]
49    pub const fn each_ref(&self) -> Children<&T> {
50        Children(self.0.each_ref())
51    }
52
53    /// Borrows each element mutably and returns a [`Children`] wrapping the
54    /// mutable references.
55    #[must_use]
56    pub const fn each_mut(&mut self) -> Children<&mut T> {
57        Children(self.0.each_mut())
58    }
59
60    /// Returns a reference to the element at `index`.
61    ///
62    /// This is infallible because `index` is guaranteed to be in-bounds.
63    #[must_use]
64    pub const fn get(&self, index: PathComponent) -> &T {
65        #![expect(clippy::indexing_slicing)]
66        &self.0[index.as_usize()]
67    }
68
69    /// Returns a mutable reference to the element at `index`.
70    ///
71    /// This is infallible because `index` is guaranteed to be in-bounds.
72    #[must_use]
73    pub const fn get_mut(&mut self, index: PathComponent) -> &mut T {
74        #![expect(clippy::indexing_slicing)]
75        &mut self.0[index.as_usize()]
76    }
77
78    /// Replaces the element at `index` with `value`, returning the previous
79    /// value.
80    ///
81    /// This is infallible because `index` is guaranteed to be in-bounds.
82    pub const fn replace(&mut self, index: PathComponent, value: T) -> T {
83        #![expect(clippy::indexing_slicing)]
84        std::mem::replace(&mut self.0[index.as_usize()], value)
85    }
86
87    /// Maps each element to another value using `f`, returning a new
88    /// [`Children`] containing the results.
89    #[must_use]
90    pub fn map<O>(self, mut f: impl FnMut(PathComponent, T) -> O) -> Children<O> {
91        let mut pc = const { PathComponent::ALL[0] };
92        Children(self.0.map(|child| {
93            let out = f(pc, child);
94            pc = pc.wrapping_next();
95            out
96        }))
97    }
98
99    /// Returns an iterator over each element with its corresponding
100    /// [`PathComponent`].
101    pub fn iter(&self) -> ChildrenSlots<&T> {
102        self.into_iter()
103    }
104
105    /// Returns a mutable iterator over each element with its corresponding
106    /// [`PathComponent`].
107    pub fn iter_mut(&mut self) -> ChildrenSlots<&mut T> {
108        self.into_iter()
109    }
110
111    /// Merges this collection of children with another collection of children
112    /// using the given function.
113    ///
114    /// If the function returns an error, the merge is aborted and the error is
115    /// returned. Because this method takes `self` and `other` by value, they
116    /// will be dropped if the merge fails.
117    pub fn merge<U, V, E>(
118        self,
119        other: Children<U>,
120        mut merge: impl FnMut(PathComponent, T, U) -> Result<Option<V>, E>,
121    ) -> Result<Children<Option<V>>, E> {
122        let iter = self.0.into_iter().zip(other.0);
123        let mut output = [const { None }; MAX_CHILDREN];
124        for (slot, (pc, (a, b))) in output
125            .iter_mut()
126            .zip(PathComponent::ALL.into_iter().zip(iter))
127        {
128            *slot = merge(pc, a, b)?;
129        }
130        Ok(Children(output))
131    }
132}
133
134impl<T> Children<Option<T>> {
135    /// Creates a new [`Children`] with all elements set to `None`.
136    #[must_use]
137    pub const fn new() -> Self {
138        Self([const { None }; MAX_CHILDREN])
139    }
140
141    /// Returns the number of [`Some`] elements in this collection.
142    #[must_use]
143    pub fn count(&self) -> usize {
144        self.0.iter().filter(|c| c.is_some()).count()
145    }
146
147    /// Sets the element at `index` to `None`, returning the previous value.
148    #[must_use]
149    pub const fn take(&mut self, index: PathComponent) -> Option<T> {
150        self.replace(index, None)
151    }
152
153    /// Returns an iterator over each [`Some`] element with its corresponding
154    /// [`PathComponent`].
155    pub fn iter_present(&self) -> IterPresentRef<'_, T> {
156        self.into_iter()
157            .filter_map(|(pc, opt)| opt.as_ref().map(|v| (pc, v)))
158    }
159}
160
161impl<T> Default for Children<Option<T>> {
162    fn default() -> Self {
163        Self::new()
164    }
165}
166
167impl<'a, T> Children<&'a Option<T>> {
168    /// Returns the number of [`Some`] elements in this collection.
169    #[must_use]
170    pub fn count(&self) -> usize {
171        self.0.iter().filter(|c| c.is_some()).count()
172    }
173
174    /// Returns an iterator over each [`Some`] element with its corresponding
175    /// [`PathComponent`].
176    pub fn iter_present(self) -> IterPresentRef<'a, T> {
177        self.into_iter()
178            .filter_map(|(pc, opt)| opt.as_ref().map(|v| (pc, v)))
179    }
180}
181
182impl<'a, T> Children<&'a mut Option<T>> {
183    /// Returns the number of [`Some`] elements in this collection.
184    #[must_use]
185    pub fn count(&self) -> usize {
186        self.0.iter().filter(|c| c.is_some()).count()
187    }
188
189    /// Returns an iterator over each [`Some`] element with its corresponding
190    /// [`PathComponent`].
191    pub fn iter_present(self) -> IterPresentMut<'a, T> {
192        self.into_iter()
193            .filter_map(|(pc, opt)| opt.as_mut().map(|v| (pc, v)))
194    }
195}
196
197impl<T> std::ops::Index<PathComponent> for Children<T> {
198    type Output = T;
199
200    fn index(&self, index: PathComponent) -> &Self::Output {
201        self.get(index)
202    }
203}
204
205impl<T> std::ops::IndexMut<PathComponent> for Children<T> {
206    fn index_mut(&mut self, index: PathComponent) -> &mut Self::Output {
207        self.get_mut(index)
208    }
209}
210
211impl<T> IntoIterator for Children<T> {
212    type Item = (PathComponent, T);
213    type IntoIter = ChildrenSlots<T>;
214
215    fn into_iter(self) -> Self::IntoIter {
216        PathComponent::ALL.into_iter().zip(self.0)
217    }
218}
219
220impl<'a, T: 'a> IntoIterator for &'a Children<T> {
221    type Item = (PathComponent, &'a T);
222    type IntoIter = ChildrenSlots<&'a T>;
223
224    fn into_iter(self) -> Self::IntoIter {
225        self.each_ref().into_iter()
226    }
227}
228
229impl<'a, T: 'a> IntoIterator for &'a mut Children<T> {
230    type Item = (PathComponent, &'a mut T);
231    type IntoIter = ChildrenSlots<&'a mut T>;
232
233    fn into_iter(self) -> Self::IntoIter {
234        self.each_mut().into_iter()
235    }
236}