Skip to main content

primitives/types/
mod.rs

1pub mod heap_array;
2pub mod identifiers;
3
4use std::{error::Error, fmt::Debug, ops::Add};
5
6pub use heap_array::{HeapArray, HeapMatrix, RowMajorHeapMatrix};
7pub use identifiers::{FaultyPeer, PeerId, PeerIndex, PeerNumber, ProtocolInfo, SessionId};
8use subtle::Choice;
9use typenum::{NonZero, Unsigned, B1};
10
11use crate::utils::IntoExactSizeIterator;
12
13// ---------- Typenum ---------- //
14
15/// A trait to represent positive nonzero unsigned integer typenum constants.
16pub trait Positive: Unsigned + NonZero + Debug + Eq + Send + Clone {
17    const SIZE: usize;
18}
19impl<T: Unsigned + NonZero + Debug + Eq + Send + Clone> Positive for T {
20    const SIZE: usize = <T as Unsigned>::USIZE;
21}
22
23/// A trait to represent nonnegative (zero or positive) unsigned integer typenum constants.
24pub trait NonNegative: Unsigned + Debug + Eq + Send + Clone {}
25impl<T: Unsigned + Debug + Eq + Send + Clone> NonNegative for T {}
26
27/// A trait to represent positive nonzero unsigned integer typenum constants which accept "+1"
28/// operation.
29pub trait PositivePlusOne: Positive + Add<B1, Output: Positive> {}
30impl<T: Positive + Add<B1, Output: Positive>> PositivePlusOne for T {}
31
32// ---------- Traits ---------- //
33
34/// A trait to define batching types that contain a compile-time known size of elements.
35pub trait Batched: Sized + IntoExactSizeIterator<Item = <Self as Batched>::Item> {
36    /// The type of elements contained in the batch.
37    type Item;
38
39    /// The size of the batch.
40    type Size: Positive;
41
42    /// Returns the size of the batch as a usize.
43    fn batch_size() -> usize {
44        Self::Size::SIZE
45    }
46}
47
48/// A type which can be conditionally selected with a loose promise of constant time.
49/// Compared to `subtle::ConditionallySelectable`, this trait does not require
50/// Copy, but the internal elements should be Copy for the promise to loosely hold.
51pub trait ConditionallySelectable: Sized {
52    /// Select `a` or `b` according to `choice`.
53    ///
54    /// # Returns
55    ///
56    /// * `a` if `choice == Choice(0)`;
57    /// * `b` if `choice == Choice(1)`.
58    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self;
59}
60
61impl<T: subtle::ConditionallySelectable> ConditionallySelectable for T {
62    #[inline]
63    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
64        <T as subtle::ConditionallySelectable>::conditional_select(a, b, choice)
65    }
66}
67
68/// Collect an iterator of Results<T, E> into a container of T and a vector of E,
69/// then pack all the errors in a single error of the same type. Requires that E can be
70/// constructed from a Vec<E>.
71pub trait CollectAll<T, E: Error + From<Vec<E>>>: Iterator<Item = Result<T, E>> + Sized {
72    /// Collect the results into a container of successes, or pack all errors.
73    /// Contrary to `collect<Result<Vec<T>, E>>`, this method collects all errors
74    /// instead of stopping at the first one.
75    fn collect_all<TC: FromIterator<T> + Extend<T> + Default>(self) -> Result<TC, E> {
76        let (values, errors): (TC, Vec<E>) =
77            itertools::Itertools::partition_map(self, |v| match v {
78                Ok(v) => itertools::Either::Left(v),
79                Err(e) => itertools::Either::Right(e),
80            });
81        match errors.len() {
82            0 => Ok(values),
83            1 => Err(errors.into_iter().next().unwrap()),
84            _ => Err(E::from(errors)),
85        }
86    }
87
88    /// Collect the results into a container of successes, or pack all errors.
89    /// Contrary to `collect<Result<Vec<T>, E>>`, this method collects all errors
90    /// instead of stopping at the first one.
91    fn collect_all_vec(self) -> Result<Vec<T>, E> {
92        self.collect_all::<Vec<T>>()
93    }
94
95    /// Collect the results, returning Ok(()) if all succeeded, or packing all errors
96    fn collect_errors(self) -> Result<(), E> {
97        let errors: Vec<E> = self.filter_map(Result::err).collect();
98        match errors.len() {
99            0 => Ok(()),
100            1 => Err(errors.into_iter().next().unwrap()),
101            _ => Err(E::from(errors)),
102        }
103    }
104}
105
106impl<T, E: Error + From<Vec<E>>, I: Iterator<Item = Result<T, E>>> CollectAll<T, E> for I {}