Skip to main content

ts_bart/node/
child.rs

1use core::fmt::{Debug, Formatter};
2
3use crate::Storage;
4
5/// Entries in a node's `children` array.
6#[derive(Clone, Copy, PartialEq, Eq, Hash)]
7pub enum Child<Node, T> {
8    /// Child containing another node.
9    Path(Node),
10
11    /// Path-compressed single descendant.
12    ///
13    /// If a prefix would be inserted that spans multiple octet strides and
14    /// there is no child for the starting octet, it is instead stored as a
15    /// single leaf. This is the primary mechanism for path compression.
16    Leaf {
17        /// The complete prefix for this route.
18        prefix: ipnet::IpNet,
19        /// Value stored for this route.
20        value: T,
21    },
22
23    /// Fringe nodes store single /8s for this depth in the trie.
24    ///
25    /// This can be seen as an optimization over [`Leaf`][Self::Leaf]
26    /// for cases where `prefix` lies on this depth's `/8` boundary.
27    Fringe(T),
28}
29
30impl<Node, T> Debug for Child<Node, T>
31where
32    Node: Debug,
33    T: Debug,
34{
35    #[inline]
36    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
37        match self {
38            Self::Path(inner) => inner.fmt(f),
39            Self::Leaf { prefix, value } => {
40                write!(f, "Leaf({prefix}: {value:?})")
41            }
42            Self::Fringe(fringe) => f.debug_tuple("Fringe").field(fringe).finish(),
43        }
44    }
45}
46
47impl<Node, T> Child<&Node, &T> {
48    /// When this holds refs, clone the values in the refs to return a
49    /// child-of-owned.
50    #[inline]
51    pub fn cloned(self) -> Child<Node, T>
52    where
53        Node: Clone,
54        T: Clone,
55    {
56        match self {
57            Self::Path(n) => Child::Path(n.clone()),
58            Self::Leaf { prefix, value } => Child::Leaf {
59                prefix,
60                value: value.clone(),
61            },
62            Self::Fringe(value) => Child::Fringe(value.clone()),
63        }
64    }
65}
66
67impl<Node, T> Child<Node, T> {
68    /// Convert this ref-to-child into a child-of-ref.
69    #[inline]
70    pub const fn as_ref(&self) -> Child<&Node, &T> {
71        match self {
72            Self::Path(node) => Child::Path(node),
73            Self::Leaf { prefix, value } => Child::Leaf {
74                prefix: *prefix,
75                value,
76            },
77            Self::Fringe(t) => Child::Fringe(t),
78        }
79    }
80
81    /// Convert this ref-mut-to-child into a child-of-ref-mut.
82    #[inline]
83    pub const fn as_mut(&mut self) -> Child<&mut Node, &mut T> {
84        match self {
85            Self::Path(node) => Child::Path(node),
86            Self::Leaf { prefix, value } => Child::Leaf {
87                prefix: *prefix,
88                value,
89            },
90            Self::Fringe(t) => Child::Fringe(t),
91        }
92    }
93
94    /// If this is a path node, apply `f` to the contained value.
95    #[inline]
96    pub fn map_node<Nu>(self, f: impl FnOnce(Node) -> Nu) -> Child<Nu, T> {
97        match self {
98            Self::Path(node) => Child::Path(f(node)),
99            Self::Leaf { prefix, value } => Child::Leaf { prefix, value },
100            Self::Fringe(t) => Child::Fringe(t),
101        }
102    }
103
104    /// Get the value directly contained in this node, if it's a leaf or fringe.
105    /// Return `None` iff this is a [`Path`][Child::Path].
106    #[inline]
107    pub fn into_value(self) -> Option<T> {
108        match self {
109            Child::Leaf { value, .. } | Child::Fringe(value) => Some(value),
110            Child::Path(_) => None,
111        }
112    }
113
114    /// When `Node` is a [`Storage`], this is [`as_ref`][Self::as_ref] except
115    /// that it also unwraps the node container type.
116    #[inline]
117    pub fn as_node_ref<C, Inner>(&self) -> Child<&Inner, &T>
118    where
119        C: Storage<Container<Inner> = Node> + ?Sized,
120    {
121        self.as_ref().map_node(C::as_ref)
122    }
123
124    /// When `Node` is a [`Storage`], this is [`as_mut`][Self::as_mut] except
125    /// that it also unwraps the node container type.
126    #[inline]
127    pub fn as_node_mut<C, Inner>(&mut self) -> Child<&mut Inner, &mut T>
128    where
129        C: Storage<Container<Inner> = Node> + ?Sized,
130    {
131        self.as_mut().map_node(C::as_mut)
132    }
133
134    /// Return the child node if this is a [`Path`][Child::Path].
135    #[inline]
136    pub fn into_node(self) -> Option<Node> {
137        match self {
138            Child::Path(node) => Some(node),
139            _ => None,
140        }
141    }
142
143    /// Construct a default leaf value for testing.
144    #[cfg(test)]
145    pub fn dummy_leaf() -> Self
146    where
147        T: Default,
148    {
149        Self::Leaf {
150            prefix: Default::default(),
151            value: Default::default(),
152        }
153    }
154
155    /// Construct a default fringe value for testing.
156    #[cfg(test)]
157    pub fn dummy_fringe() -> Self
158    where
159        T: Default,
160    {
161        Self::Fringe(Default::default())
162    }
163}