penumbra_sdk_tct/internal/
three.rs

1//! A wrapper around [`Vec`] for vectors whose length is at most 3 elements.
2//!
3//! This is used in the implementation of [`frontier::Node`](crate::internal::frontier::Node)s to
4//! store the lefthand siblings of the frontier's rightmost child, which must number at most 3
5//! (because nodes must have at most 4 children total).
6
7use std::marker::PhantomData;
8
9use serde::{de::Visitor, Deserialize, Serialize};
10
11/// A vector capable of storing at most 3 elements.
12#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Derivative, Serialize)]
13#[derivative(Debug = "transparent")]
14pub struct Three<T> {
15    elems: Vec<T>,
16}
17
18// Manual `Clone` implementation to force the cloned `Vec` to be capacity = 4, so we never
19// re-allocate after the clone
20impl<T: Clone> Clone for Three<T> {
21    fn clone(&self) -> Self {
22        let mut elems = Vec::with_capacity(4);
23        elems.extend(self.elems.iter().cloned());
24        Self { elems }
25    }
26}
27
28impl<T> Three<T> {
29    /// Create a new `Three` with no elements, but the capacity for them pre-allocated.
30    ///
31    /// This technically allocates space for 4 elements, so that when [`Self::push`] overfills, it
32    /// does not re-allocate.
33    pub fn new() -> Self {
34        Self {
35            // This has capacity 4 to prevent re-allocating memory when we push to a filled `Three`
36            // and thereby generate a [T; 4].
37            elems: Vec::with_capacity(4),
38        }
39    }
40
41    /// Push a new item into this [`Three`], or return exactly four items (including the pushed
42    /// item) if the [`Three`] is already full.
43    ///
44    /// Note that this takes ownership of `self` and returns a new [`Three`] with the pushed item if
45    /// successful.
46    #[inline]
47    pub fn push(mut self, item: T) -> Result<Self, [T; 4]> {
48        // Push an element into the internal vec
49        self.elems.push(item);
50        // In debug mode, check that the size is never above 4
51        debug_assert!(self.elems.len() <= 4);
52        // If this makes the internal vec >= 4 elements, we're overfull
53        match self.elems.try_into() {
54            Ok(elems) => Err(elems),
55            Err(elems) => Ok(Self { elems }),
56        }
57    }
58
59    /// Push a new item into this [`Three`], or panic if it would overfill it.
60    #[inline]
61    #[cfg_attr(not(feature = "internal"), allow(unused))]
62    pub fn push_mut(&mut self, item: T) -> Self {
63        if let Ok(three) = std::mem::take(self).push(item) {
64            three
65        } else {
66            panic!("Three::push_unchecked: already full");
67        }
68    }
69
70    /// Determine if this [`Three`] is full.
71    ///
72    /// If this returns `true`, then [`Self::push`] will return `Err`; otherwise, [`Self::push`]
73    /// will return `Ok`.
74    #[inline]
75    pub fn is_full(&self) -> bool {
76        self.elems.len() == 3
77    }
78
79    /// Determine if this [`Three`] is empty.
80    #[inline]
81    #[cfg_attr(not(feature = "internal"), allow(unused))]
82    pub fn is_empty(&self) -> bool {
83        self.elems.is_empty()
84    }
85
86    /// Get the number of elements in this [`Three`].
87    #[inline]
88    pub fn len(&self) -> u8 {
89        self.elems.len() as u8
90    }
91
92    /// Get an iterator over the elements of the [`Three`].
93    #[inline]
94    pub fn iter(&self) -> impl Iterator<Item = &T> {
95        self.elems.iter()
96    }
97
98    /// Get an iterator over mutable elements of the [`Three`].
99    #[inline]
100    #[allow(unused)]
101    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
102        self.elems.iter_mut()
103    }
104
105    /// Get an enumeration of the elements of this [`Three`] by reference.
106    pub fn elems(&self) -> Elems<T> {
107        match self.elems.len() {
108            0 => Elems::_0([]),
109            1 => Elems::_1([&self.elems[0]]),
110            2 => Elems::_2([&self.elems[0], &self.elems[1]]),
111            3 => Elems::_3([&self.elems[0], &self.elems[1], &self.elems[2]]),
112            _ => unreachable!("impossible for `Three` to contain more than 3 elements"),
113        }
114    }
115
116    /// Get an enumeration of the elements of this [`Three`] by mutable reference.
117    pub fn elems_mut(&mut self) -> ElemsMut<T> {
118        match self.elems.as_mut_slice() {
119            [] => ElemsMut::_0([]),
120            [a] => ElemsMut::_1([a]),
121            [a, b] => ElemsMut::_2([a, b]),
122            [a, b, c] => ElemsMut::_3([a, b, c]),
123            _ => unreachable!("impossible for `Three` to contain more than 3 elements"),
124        }
125    }
126
127    /// Convert this [`Three`] into an enumeration of its elements.
128    pub fn into_elems(self) -> IntoElems<T> {
129        match self.elems.len() {
130            0 => IntoElems::_0([]),
131            1 => IntoElems::_1(if let Ok(elems) = self.elems.try_into() {
132                elems
133            } else {
134                unreachable!("already checked the length of elements")
135            }),
136            2 => IntoElems::_2(if let Ok(elems) = self.elems.try_into() {
137                elems
138            } else {
139                unreachable!("already checked the length of elements")
140            }),
141            3 => IntoElems::_3(if let Ok(elems) = self.elems.try_into() {
142                elems
143            } else {
144                unreachable!("already checked the length of elements")
145            }),
146            _ => unreachable!("impossible for `Three` to contain more than 3 elements"),
147        }
148    }
149}
150
151impl<T> Default for Three<T> {
152    fn default() -> Self {
153        Self::new()
154    }
155}
156
157/// All the possible cases of the elements in a [`Three`], by reference.
158#[derive(Debug, Clone, Copy, PartialEq, Eq)]
159pub enum Elems<'a, T> {
160    /// Zero elements.
161    _0([&'a T; 0]),
162    /// One element.
163    _1([&'a T; 1]),
164    /// Two elements.
165    _2([&'a T; 2]),
166    /// Three elements.
167    _3([&'a T; 3]),
168}
169
170/// All the possible cases of the elements in a [`Three`], by mutable reference.
171#[derive(Debug, PartialEq, Eq)]
172pub enum ElemsMut<'a, T> {
173    /// Zero elements.
174    _0([&'a mut T; 0]),
175    /// One element.
176    _1([&'a mut T; 1]),
177    /// Two elements.
178    _2([&'a mut T; 2]),
179    /// Three elements.
180    _3([&'a mut T; 3]),
181}
182
183/// All the possible cases of the elements in a [`Three`], by value.
184#[derive(Debug, Clone, Copy, PartialEq, Eq)]
185pub enum IntoElems<T> {
186    /// Zero elements.
187    _0([T; 0]),
188    /// One element.
189    _1([T; 1]),
190    /// Two elements.
191    _2([T; 2]),
192    /// Three elements.
193    _3([T; 3]),
194}
195
196impl<T> From<IntoElems<T>> for Three<T> {
197    fn from(elems: IntoElems<T>) -> Self {
198        match elems {
199            IntoElems::_0(elems) => Self {
200                elems: elems.into(),
201            },
202            IntoElems::_1(elems) => Self {
203                elems: elems.into(),
204            },
205            IntoElems::_2(elems) => Self {
206                elems: elems.into(),
207            },
208            IntoElems::_3(elems) => Self {
209                elems: elems.into(),
210            },
211        }
212    }
213}
214
215impl<T> From<Three<T>> for IntoElems<T> {
216    fn from(three: Three<T>) -> Self {
217        three.into_elems()
218    }
219}
220
221struct ThreeVisitor<T>(PhantomData<T>);
222
223impl<'de, T: Deserialize<'de>> Visitor<'de> for ThreeVisitor<T> {
224    type Value = Three<T>;
225
226    fn expecting(
227        &self,
228        f: &mut std::fmt::Formatter<'_>,
229    ) -> std::result::Result<(), std::fmt::Error> {
230        write!(f, "a vector of at most 3 elements")
231    }
232
233    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
234    where
235        A: serde::de::SeqAccess<'de>,
236    {
237        let mut elems = Vec::with_capacity(4);
238        for _ in 0..=3 {
239            if let Some(elem) = seq.next_element()? {
240                elems.push(elem);
241            } else {
242                break;
243            }
244        }
245        if seq.next_element::<T>()?.is_some() {
246            return Err(serde::de::Error::invalid_length(3, &"at most 3 elements"));
247        }
248        Ok(Three { elems })
249    }
250}
251
252impl<'de, T: Deserialize<'de>> Deserialize<'de> for Three<T> {
253    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
254    where
255        D: serde::Deserializer<'de>,
256    {
257        deserializer.deserialize_seq(ThreeVisitor(PhantomData))
258    }
259}