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}