Skip to main content

zebra_chain/serialization/
constraint.rs

1//! Serialization constraint helpers.
2
3use bounded_vec::BoundedVec;
4
5/// A vector type that must contain at least one element.
6///
7/// This is a type alias for `BoundedVec<T, 1, { usize::MAX }>`, provided by the
8/// [`bounded_vec`] crate. All functionality, including length constraints and safe
9/// construction, is inherited from `BoundedVec`.
10///
11/// [`bounded_vec`]: https://docs.rs/bounded-vec
12pub type AtLeastOne<T> = BoundedVec<T, 1, { usize::MAX }>;
13
14/// Create an initialized [`AtLeastOne`] instance.
15///
16/// This macro is similar to the [`vec!`][`std::vec!`] macro, but doesn't support creating an empty
17/// `AtLeastOne` instance.
18///
19/// # Security
20///
21/// This macro must only be used in tests, because it skips the `TrustedPreallocate` memory
22/// denial of service checks.
23#[cfg(any(test, feature = "proptest-impl"))]
24#[macro_export]
25macro_rules! at_least_one {
26    ($element:expr; 0) => (
27        compile_error!("At least one element needed to create an `AtLeastOne<T>`")
28    );
29
30    ($element:expr; $count:expr) => (
31        {
32            <Vec<_> as std::convert::TryInto<$crate::serialization::AtLeastOne<_>>>::try_into(
33                vec![$element; $count],
34            ).expect("at least one element in `AtLeastOne<_>`")
35        }
36    );
37
38    ($($element:expr),+ $(,)?) => (
39        {
40            <Vec<_> as std::convert::TryInto<$crate::serialization::AtLeastOne<_>>>::try_into(
41                vec![$($element),*],
42            ).expect("at least one element in `AtLeastOne<_>`")
43        }
44    );
45}
46
47#[cfg(test)]
48mod tests {
49    use super::AtLeastOne;
50
51    #[test]
52    fn at_least_one_count_form_works() {
53        let v: AtLeastOne<i32> = at_least_one![42; 1];
54        assert_eq!(v.as_slice(), [42]);
55
56        let v2: AtLeastOne<u8> = at_least_one![5; 2];
57        assert_eq!(v2.as_slice(), [5, 5]);
58    }
59}