use smallvec::SmallVec; use std::collections::{BTreeMap, BTreeSet}; use std::convert::Infallible; use std::fmt::Debug; /// Partial variant of `std::iter::FromIterator`. /// /// This trait is implemented for types which can be constructed from an iterator of decoded SSZ /// values, but which may refuse values once a length limit is reached. pub trait TryFromIter: Sized { type Error: Debug; fn try_from_iter(iter: I) -> Result where I: IntoIterator; } // It would be nice to be able to do a blanket impl, e.g. // // `impl TryFromIter for C where C: FromIterator` // // However this runs into trait coherence issues due to the type parameter `T` on `TryFromIter`. // // E.g. If we added an impl downstream for `List` then another crate downstream of that // could legally add an impl of `FromIterator for List` which would create // two conflicting implementations for `List`. Hence the `List` impl is disallowed // by the compiler in the presence of the blanket impl. That's obviously annoying, so we opt to // abandon the blanket impl in favour of impls for selected types. impl TryFromIter for Vec { type Error = Infallible; fn try_from_iter(values: I) -> Result where I: IntoIterator, { // Pre-allocate the expected size of the Vec, which is parsed from the SSZ input bytes as // `num_items`. This length has already been checked to be less than or equal to the type's // maximum length in `decode_list_of_variable_length_items`. let iter = values.into_iter(); let (_, opt_max_len) = iter.size_hint(); let mut vec = Vec::with_capacity(opt_max_len.unwrap_or(0)); vec.extend(iter); Ok(vec) } } impl TryFromIter for SmallVec<[T; N]> { type Error = Infallible; fn try_from_iter(iter: I) -> Result where I: IntoIterator, { Ok(Self::from_iter(iter)) } } impl TryFromIter<(K, V)> for BTreeMap where K: Ord, { type Error = Infallible; fn try_from_iter(iter: I) -> Result where I: IntoIterator, { Ok(Self::from_iter(iter)) } } impl TryFromIter for BTreeSet where T: Ord, { type Error = Infallible; fn try_from_iter(iter: I) -> Result where I: IntoIterator, { Ok(Self::from_iter(iter)) } } /// Partial variant of `collect`. pub trait TryCollect: Iterator { fn try_collect(self) -> Result where C: TryFromIter; } impl TryCollect for I where I: Iterator, { fn try_collect(self) -> Result where C: TryFromIter, { C::try_from_iter(self) } }