collect_exact/
lib.rs

1//! Allows zero-cost collection into exact-size arrays and tuples.
2//!
3//! ## Usage
4//!
5//! ```rust
6//! use collect_exact::CollectExact;
7//!
8//! let iter = [1, 2, 3].into_iter();
9//! let result = iter.collect_exact::<[u32; 3]>();
10//!
11//! assert_eq!(result, Ok([1, 2, 3]));
12//! ```
13
14#![warn(missing_docs)]
15#![warn(clippy::pedantic)]
16
17mod error;
18mod impls;
19mod result;
20mod tuples;
21
22pub use error::{Error, PrefixError};
23
24/// Extension trait for collecting into collections whose length is known at compile time.
25pub trait CollectExact {
26    /// The type of items in the iterator.
27    type Item;
28
29    /// Transforms an iterator into a collection whose length is known at compile time.
30    ///
31    /// See also [`Iterator::collect`].
32    ///
33    /// # Errors
34    ///
35    /// Returns an error if the iterator does not contain the same number of items as the collection.
36    fn collect_exact<B: FromIteratorExact<Self::Item>>(self) -> Result<B, Error>
37    where
38        Self: Sized;
39
40    /// Transforms a prefix of the iterator into a collection whose length is known at compile time.
41    /// Drops the iterator once it has collected enough items.
42    ///
43    /// See also [`CollectExact::collect_exact`].
44    ///
45    /// # Errors
46    ///
47    /// Returns an error if the iterator contains fewer items than the collection.
48    fn collect_exact_prefix<B: FromIteratorExact<Self::Item>>(self) -> Result<B, PrefixError>
49    where
50        Self: Sized;
51}
52
53/// Conversion from an [`Iterator`] for a collection whose length is known at compile time.
54pub trait FromIteratorExact<T>: Sized {
55    /// Creates a collection from an iterator.
56    ///
57    /// See also [`CollectExact::collect_exact`].
58    ///
59    /// # Errors
60    ///
61    /// Returns an error if the iterator does not contain the same number of items as the collection.
62    fn from_iter_exact<I: IntoIterator<Item = T>>(iter: I) -> Result<Self, Error>;
63
64    /// Creates a collection from a prefix of an iterator.
65    ///
66    /// See also [`CollectExact::collect_exact_prefix`].
67    ///
68    /// # Errors
69    ///
70    /// Returns an error if the iterator contains fewer items than the collection.
71    fn from_iter_exact_prefix<I: IntoIterator<Item = T>>(iter: I) -> Result<Self, PrefixError>;
72}
73
74impl<Iter> CollectExact for Iter
75where
76    Iter: Iterator,
77{
78    type Item = <Self as Iterator>::Item;
79
80    fn collect_exact<B: FromIteratorExact<Self::Item>>(self) -> Result<B, Error>
81    where
82        Self: Sized,
83    {
84        FromIteratorExact::from_iter_exact(self)
85    }
86
87    fn collect_exact_prefix<B: FromIteratorExact<Self::Item>>(self) -> Result<B, PrefixError>
88    where
89        Self: Sized,
90    {
91        FromIteratorExact::from_iter_exact_prefix(self)
92    }
93}
94
95impl<T, const N: usize> FromIteratorExact<T> for [T; N] {
96    fn from_iter_exact<I: IntoIterator<Item = T>>(iter: I) -> Result<Self, Error> {
97        impls::collect_exact(iter.into_iter())
98    }
99
100    fn from_iter_exact_prefix<I: IntoIterator<Item = T>>(iter: I) -> Result<Self, PrefixError> {
101        impls::collect_exact_prefix(iter.into_iter())
102    }
103}