zebra_chain/serialization/
constraint.rs

1//! Serialization constraint helpers.
2
3use std::ops::Deref;
4
5use crate::serialization::SerializationError;
6
7/// A `Vec<T>` wrapper that ensures there is at least one `T` in the vector.
8///
9/// You can initialize `AtLeastOne` using:
10/// ```
11/// # use zebra_chain::serialization::{AtLeastOne, SerializationError};
12/// # use std::convert::{TryFrom, TryInto};
13/// #
14/// let v: AtLeastOne<u32> = vec![42].try_into()?;
15/// assert_eq!(v.as_slice(), [42]);
16///
17/// let v: AtLeastOne<u32> = vec![42].as_slice().try_into()?;
18/// assert_eq!(v.as_slice(), [42]);
19///
20/// let v: AtLeastOne<u32> = [42].try_into()?;
21/// assert_eq!(v.as_slice(), [42]);
22///
23/// let v = AtLeastOne::<u32>::try_from(&[42])?;
24/// assert_eq!(v.as_slice(), [42]);
25/// #
26/// # Ok::<(), SerializationError>(())
27/// ```
28///
29/// And access the inner vector via [deref coercion](https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-coercion),
30/// an explicit conversion, or as a slice:
31/// ```
32/// # use zebra_chain::serialization::AtLeastOne;
33/// # use std::convert::TryInto;
34/// #
35/// # let v: AtLeastOne<u32> = vec![42].try_into().unwrap();
36/// #
37/// let first = v.iter().next().expect("AtLeastOne always has a first element");
38/// assert_eq!(*first, 42);
39///
40/// let s = v.as_slice();
41/// #
42/// # assert_eq!(s, [42]);
43///
44/// let mut m = v.into_vec();
45/// #
46/// # assert_eq!(m.as_slice(), [42]);
47///
48/// ```
49///
50/// `AtLeastOne` also re-implements some slice methods with different return
51/// types, to avoid redundant unwraps:
52/// ```
53/// # use zebra_chain::serialization::AtLeastOne;
54/// # use std::convert::TryInto;
55/// #
56/// # let v: AtLeastOne<u32> = vec![42].try_into().unwrap();
57/// #
58/// let first = v.first();
59/// assert_eq!(*first, 42);
60///
61/// let (first, rest) = v.split_first();
62/// assert_eq!(*first, 42);
63/// assert!(rest.is_empty());
64/// ```
65#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
66pub struct AtLeastOne<T> {
67    /// The inner vector, which must have at least one element.
68    ///
69    /// `inner` is private, so that it can't be modified in ways that break the
70    /// type constraint.
71    inner: Vec<T>,
72}
73
74// CORRECTNESS
75//
76// All conversions to `AtLeastOne<T>` must go through `TryFrom<Vec<T>>`,
77// so that the type constraint is satisfied.
78
79impl<T> TryFrom<Vec<T>> for AtLeastOne<T> {
80    type Error = SerializationError;
81
82    fn try_from(vec: Vec<T>) -> Result<Self, Self::Error> {
83        if vec.is_empty() {
84            Err(SerializationError::Parse("expected at least one item"))
85        } else {
86            Ok(AtLeastOne { inner: vec })
87        }
88    }
89}
90
91impl<T> TryFrom<&Vec<T>> for AtLeastOne<T>
92where
93    T: Clone,
94{
95    type Error = SerializationError;
96
97    fn try_from(vec: &Vec<T>) -> Result<Self, Self::Error> {
98        if vec.is_empty() {
99            Err(SerializationError::Parse("expected at least one item"))
100        } else {
101            Ok(AtLeastOne {
102                inner: vec.to_vec(),
103            })
104        }
105    }
106}
107
108impl<T> TryFrom<&[T]> for AtLeastOne<T>
109where
110    T: Clone,
111{
112    type Error = SerializationError;
113
114    fn try_from(slice: &[T]) -> Result<Self, Self::Error> {
115        slice.to_vec().try_into()
116    }
117}
118
119// TODO:
120// - reject [T; 0] at compile time and impl From instead?
121impl<T, const N: usize> TryFrom<[T; N]> for AtLeastOne<T>
122where
123    T: Clone,
124{
125    type Error = SerializationError;
126
127    fn try_from(slice: [T; N]) -> Result<Self, Self::Error> {
128        slice.to_vec().try_into()
129    }
130}
131
132// TODO:
133// - reject [T; 0] at compile time and impl From instead?
134// - remove when std is updated so that `TryFrom<&U>` is always implemented when
135//   `TryFrom<U>`
136impl<T, const N: usize> TryFrom<&[T; N]> for AtLeastOne<T>
137where
138    T: Clone,
139{
140    type Error = SerializationError;
141
142    fn try_from(slice: &[T; N]) -> Result<Self, Self::Error> {
143        slice.to_vec().try_into()
144    }
145}
146
147// Deref and AsRef (but not DerefMut or AsMut, because that could break the constraint)
148
149impl<T> Deref for AtLeastOne<T> {
150    type Target = Vec<T>;
151
152    fn deref(&self) -> &Self::Target {
153        &self.inner
154    }
155}
156
157impl<T> AsRef<[T]> for AtLeastOne<T> {
158    fn as_ref(&self) -> &[T] {
159        self.inner.as_ref()
160    }
161}
162
163// Extracting one or more items
164
165impl<T> From<AtLeastOne<T>> for Vec<T> {
166    fn from(vec1: AtLeastOne<T>) -> Self {
167        vec1.inner
168    }
169}
170
171// `IntoIterator` for `T` and `&mut T`, because iterators can't remove items
172
173impl<T> IntoIterator for AtLeastOne<T> {
174    type Item = T;
175
176    type IntoIter = std::vec::IntoIter<T>;
177
178    fn into_iter(self) -> std::vec::IntoIter<T> {
179        self.inner.into_iter()
180    }
181}
182
183impl<T> AtLeastOne<T> {
184    /// Returns an iterator that allows modifying each value.
185    pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
186        self.inner.iter_mut()
187    }
188}
189
190impl<T> AtLeastOne<T> {
191    /// Returns a new `AtLeastOne`, containing a single `item`.
192    ///
193    /// Skips the `TrustedPreallocate` memory denial of service checks.
194    /// (`TrustedPreallocate` can not defend against a single item
195    /// that causes a denial of service by itself.)
196    pub fn from_one(item: T) -> AtLeastOne<T> {
197        AtLeastOne { inner: vec![item] }
198    }
199
200    /// Returns a reference to the inner vector.
201    pub fn as_vec(&self) -> &Vec<T> {
202        &self.inner
203    }
204
205    /// Converts `self` into a vector without clones or allocation.
206    ///
207    /// The resulting vector can be converted back into `AtLeastOne` via `try_into`.
208    pub fn into_vec(self) -> Vec<T> {
209        self.inner
210    }
211
212    /// Returns the first element.
213    ///
214    /// Unlike `Vec` or slice, `AtLeastOne` always has a first element.
215    pub fn first(&self) -> &T {
216        &self.inner[0]
217    }
218
219    /// Returns a mutable reference to the first element.
220    ///
221    /// Unlike `Vec` or slice, `AtLeastOne` always has a first element.
222    pub fn first_mut(&mut self) -> &mut T {
223        &mut self.inner[0]
224    }
225
226    /// Appends an element to the back of the collection.
227    pub fn push(&mut self, element: T) {
228        self.inner.push(element);
229    }
230
231    /// Returns the first and all the rest of the elements of the vector.
232    ///
233    /// Unlike `Vec` or slice, `AtLeastOne` always has a first element.
234    pub fn split_first(&self) -> (&T, &[T]) {
235        (&self.inner[0], &self.inner[1..])
236    }
237}
238
239// TODO: consider implementing `push`, `append`, and `Extend`,
240// because adding elements can't break the constraint.
241
242/// Create an initialized [`AtLeastOne`] instance.
243///
244/// This macro is similar to the [`vec!`][`std::vec!`] macro, but doesn't support creating an empty
245/// `AtLeastOne` instance.
246///
247/// # Security
248///
249/// This macro must only be used in tests, because it skips the `TrustedPreallocate` memory
250/// denial of service checks.
251#[cfg(any(test, feature = "proptest-impl"))]
252#[macro_export]
253macro_rules! at_least_one {
254    ($element:expr; 0) => (
255        compile_error!("At least one element needed to create an `AtLeastOne<T>`")
256    );
257
258    ($element:expr; $count:expr) => (
259        {
260            <Vec<_> as std::convert::TryInto<$crate::serialization::AtLeastOne<_>>>::try_into(
261                vec![$element; $expr],
262            ).expect("at least one element in `AtLeastOne<_>`")
263        }
264    );
265
266    ($($element:expr),+ $(,)?) => (
267        {
268            <Vec<_> as std::convert::TryInto<$crate::serialization::AtLeastOne<_>>>::try_into(
269                vec![$($element),*],
270            ).expect("at least one element in `AtLeastOne<_>`")
271        }
272    );
273}