1183891f0SNick Fitzgerald use crate::alloc::TryVec;
228f6f5e7SAlex Crichton use crate::error::OutOfMemory;
328f6f5e7SAlex Crichton use std_alloc::boxed::Box;
428f6f5e7SAlex Crichton 
528f6f5e7SAlex Crichton /// Extension trait for an `Iterator` to fallibly collect into a container.
628f6f5e7SAlex Crichton pub trait TryCollect: Iterator {
728f6f5e7SAlex Crichton     /// Attempts to collect the iterator `self` into `B`.
828f6f5e7SAlex Crichton     ///
928f6f5e7SAlex Crichton     /// Same as [`Iterator::collect`] except returns OOM instead of aborting.
try_collect<B, E>(self) -> Result<B, E> where B: TryFromIterator<Self::Item, E>, Self: Sized,1028f6f5e7SAlex Crichton     fn try_collect<B, E>(self) -> Result<B, E>
1128f6f5e7SAlex Crichton     where
1228f6f5e7SAlex Crichton         B: TryFromIterator<Self::Item, E>,
1328f6f5e7SAlex Crichton         Self: Sized,
1428f6f5e7SAlex Crichton     {
1528f6f5e7SAlex Crichton         B::try_from_iter(self)
1628f6f5e7SAlex Crichton     }
1728f6f5e7SAlex Crichton }
1828f6f5e7SAlex Crichton 
1928f6f5e7SAlex Crichton impl<I: Iterator> TryCollect for I {}
2028f6f5e7SAlex Crichton 
2128f6f5e7SAlex Crichton /// Analogue of [`FromIterator`] in the standard library, but used with
2228f6f5e7SAlex Crichton /// [`TryCollect::try_collect`] instead.
2328f6f5e7SAlex Crichton pub trait TryFromIterator<T, E>: Sized {
24*ab78bd82SHo Kim     /// Creates an instance of this collection from the `iter` provided.
2528f6f5e7SAlex Crichton     ///
26*ab78bd82SHo Kim     /// Does not abort on OOM but instead returns an error.
try_from_iter<I>(iter: I) -> Result<Self, E> where I: Iterator<Item = T>2728f6f5e7SAlex Crichton     fn try_from_iter<I>(iter: I) -> Result<Self, E>
2828f6f5e7SAlex Crichton     where
2928f6f5e7SAlex Crichton         I: Iterator<Item = T>;
3028f6f5e7SAlex Crichton }
3128f6f5e7SAlex Crichton 
32183891f0SNick Fitzgerald impl<T> TryFromIterator<T, OutOfMemory> for TryVec<T> {
try_from_iter<I>(iter: I) -> Result<Self, OutOfMemory> where I: Iterator<Item = T>,3328f6f5e7SAlex Crichton     fn try_from_iter<I>(iter: I) -> Result<Self, OutOfMemory>
3428f6f5e7SAlex Crichton     where
3528f6f5e7SAlex Crichton         I: Iterator<Item = T>,
3628f6f5e7SAlex Crichton     {
37183891f0SNick Fitzgerald         let mut result = TryVec::with_capacity(iter.size_hint().0)?;
3828f6f5e7SAlex Crichton         for item in iter {
3928f6f5e7SAlex Crichton             result.push(item)?;
4028f6f5e7SAlex Crichton         }
4128f6f5e7SAlex Crichton         Ok(result)
4228f6f5e7SAlex Crichton     }
4328f6f5e7SAlex Crichton }
4428f6f5e7SAlex Crichton 
4528f6f5e7SAlex Crichton impl<T> TryFromIterator<T, OutOfMemory> for Box<[T]> {
try_from_iter<I>(iter: I) -> Result<Self, OutOfMemory> where I: Iterator<Item = T>,4628f6f5e7SAlex Crichton     fn try_from_iter<I>(iter: I) -> Result<Self, OutOfMemory>
4728f6f5e7SAlex Crichton     where
4828f6f5e7SAlex Crichton         I: Iterator<Item = T>,
4928f6f5e7SAlex Crichton     {
50183891f0SNick Fitzgerald         let vec = TryVec::try_from_iter(iter)?;
5128f6f5e7SAlex Crichton         vec.into_boxed_slice()
5228f6f5e7SAlex Crichton     }
5328f6f5e7SAlex Crichton }
5428f6f5e7SAlex Crichton 
55183891f0SNick Fitzgerald impl<T, E> TryFromIterator<Result<T, E>, E> for TryVec<T>
5628f6f5e7SAlex Crichton where
5728f6f5e7SAlex Crichton     E: From<OutOfMemory>,
5828f6f5e7SAlex Crichton {
try_from_iter<I>(iter: I) -> Result<Self, E> where I: Iterator<Item = Result<T, E>>,5928f6f5e7SAlex Crichton     fn try_from_iter<I>(iter: I) -> Result<Self, E>
6028f6f5e7SAlex Crichton     where
6128f6f5e7SAlex Crichton         I: Iterator<Item = Result<T, E>>,
6228f6f5e7SAlex Crichton     {
63183891f0SNick Fitzgerald         let mut result = TryVec::with_capacity(iter.size_hint().0)?;
6428f6f5e7SAlex Crichton         for item in iter {
6528f6f5e7SAlex Crichton             result.push(item?)?;
6628f6f5e7SAlex Crichton         }
6728f6f5e7SAlex Crichton         Ok(result)
6828f6f5e7SAlex Crichton     }
6928f6f5e7SAlex Crichton }
7028f6f5e7SAlex Crichton 
7128f6f5e7SAlex Crichton impl<T, E> TryFromIterator<Result<T, E>, E> for Box<[T]>
7228f6f5e7SAlex Crichton where
7328f6f5e7SAlex Crichton     E: From<OutOfMemory>,
7428f6f5e7SAlex Crichton {
try_from_iter<I>(iter: I) -> Result<Self, E> where I: Iterator<Item = Result<T, E>>,7528f6f5e7SAlex Crichton     fn try_from_iter<I>(iter: I) -> Result<Self, E>
7628f6f5e7SAlex Crichton     where
7728f6f5e7SAlex Crichton         I: Iterator<Item = Result<T, E>>,
7828f6f5e7SAlex Crichton     {
79183891f0SNick Fitzgerald         let vec = iter.try_collect::<TryVec<_>, E>()?;
8028f6f5e7SAlex Crichton         Ok(vec.into_boxed_slice()?)
8128f6f5e7SAlex Crichton     }
8228f6f5e7SAlex Crichton }
8328f6f5e7SAlex Crichton 
8428f6f5e7SAlex Crichton /// Analogue of [`Extend`] except handles OOM conditions.
8528f6f5e7SAlex Crichton pub trait TryExtend<T> {
8628f6f5e7SAlex Crichton     /// Extends `self` with the items from `iter`.
8728f6f5e7SAlex Crichton     ///
8828f6f5e7SAlex Crichton     /// Returns an error if allocation fails while adding items to `self`. If an
8928f6f5e7SAlex Crichton     /// OOM happens then some items from `iter` may have been added to `self`
9028f6f5e7SAlex Crichton     /// already. On OOM no further items from the iterator will be consumed.
try_extend<I>(&mut self, iter: I) -> Result<(), OutOfMemory> where I: IntoIterator<Item = T>9128f6f5e7SAlex Crichton     fn try_extend<I>(&mut self, iter: I) -> Result<(), OutOfMemory>
9228f6f5e7SAlex Crichton     where
9328f6f5e7SAlex Crichton         I: IntoIterator<Item = T>;
9428f6f5e7SAlex Crichton }
9528f6f5e7SAlex Crichton 
96183891f0SNick Fitzgerald impl<T> TryExtend<T> for TryVec<T> {
try_extend<I>(&mut self, iter: I) -> Result<(), OutOfMemory> where I: IntoIterator<Item = T>,9728f6f5e7SAlex Crichton     fn try_extend<I>(&mut self, iter: I) -> Result<(), OutOfMemory>
9828f6f5e7SAlex Crichton     where
9928f6f5e7SAlex Crichton         I: IntoIterator<Item = T>,
10028f6f5e7SAlex Crichton     {
10128f6f5e7SAlex Crichton         let iter = iter.into_iter();
10228f6f5e7SAlex Crichton         self.reserve(iter.size_hint().0)?;
10328f6f5e7SAlex Crichton         for item in iter {
10428f6f5e7SAlex Crichton             self.push(item)?;
10528f6f5e7SAlex Crichton         }
10628f6f5e7SAlex Crichton         Ok(())
10728f6f5e7SAlex Crichton     }
10828f6f5e7SAlex Crichton }
10928f6f5e7SAlex Crichton 
11028f6f5e7SAlex Crichton #[cfg(test)]
11128f6f5e7SAlex Crichton mod tests {
112183891f0SNick Fitzgerald     use super::{Box, TryCollect, TryExtend, TryVec};
11328f6f5e7SAlex Crichton     use crate::error::{OutOfMemory, Result};
11428f6f5e7SAlex Crichton 
11528f6f5e7SAlex Crichton     #[test]
test_vec_collect() -> Result<(), OutOfMemory>11628f6f5e7SAlex Crichton     fn test_vec_collect() -> Result<(), OutOfMemory> {
117183891f0SNick Fitzgerald         let v: TryVec<i32> = (0..10).try_collect()?;
11828f6f5e7SAlex Crichton         assert_eq!(&*v, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
11928f6f5e7SAlex Crichton         Ok(())
12028f6f5e7SAlex Crichton     }
12128f6f5e7SAlex Crichton 
12228f6f5e7SAlex Crichton     #[test]
test_box_collect() -> Result<(), OutOfMemory>12328f6f5e7SAlex Crichton     fn test_box_collect() -> Result<(), OutOfMemory> {
12428f6f5e7SAlex Crichton         let v: Box<[i32]> = (0..10).try_collect()?;
12528f6f5e7SAlex Crichton         assert_eq!(&*v, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
12628f6f5e7SAlex Crichton         Ok(())
12728f6f5e7SAlex Crichton     }
12828f6f5e7SAlex Crichton 
12928f6f5e7SAlex Crichton     #[test]
test_vec_result_collect() -> Result<()>13028f6f5e7SAlex Crichton     fn test_vec_result_collect() -> Result<()> {
131183891f0SNick Fitzgerald         let v: Result<TryVec<i32>> = [].into_iter().try_collect();
13228f6f5e7SAlex Crichton         assert!(v?.is_empty());
13328f6f5e7SAlex Crichton 
134183891f0SNick Fitzgerald         let v: Result<TryVec<i32>> = [Ok(1), Ok(2)].into_iter().try_collect();
13528f6f5e7SAlex Crichton         assert_eq!(&*v?, &[1, 2]);
13628f6f5e7SAlex Crichton 
137183891f0SNick Fitzgerald         let v: Result<TryVec<i32>> = [Ok(1), Err(crate::format_err!("hi"))]
13828f6f5e7SAlex Crichton             .into_iter()
13928f6f5e7SAlex Crichton             .try_collect();
14028f6f5e7SAlex Crichton         assert!(v.is_err());
14128f6f5e7SAlex Crichton 
142183891f0SNick Fitzgerald         let v: Result<TryVec<i32>> = [Err(crate::format_err!("hi")), Ok(1)]
14328f6f5e7SAlex Crichton             .into_iter()
14428f6f5e7SAlex Crichton             .try_collect();
14528f6f5e7SAlex Crichton         assert!(v.is_err());
14628f6f5e7SAlex Crichton         Ok(())
14728f6f5e7SAlex Crichton     }
14828f6f5e7SAlex Crichton 
14928f6f5e7SAlex Crichton     #[test]
test_box_result_collect() -> Result<()>15028f6f5e7SAlex Crichton     fn test_box_result_collect() -> Result<()> {
15128f6f5e7SAlex Crichton         let v: Result<Box<[i32]>> = [].into_iter().try_collect();
15228f6f5e7SAlex Crichton         assert!(v?.is_empty());
15328f6f5e7SAlex Crichton 
15428f6f5e7SAlex Crichton         let v: Result<Box<[i32]>> = [Ok(1), Ok(2)].into_iter().try_collect();
15528f6f5e7SAlex Crichton         assert_eq!(&*v?, &[1, 2]);
15628f6f5e7SAlex Crichton 
15728f6f5e7SAlex Crichton         let v: Result<Box<[i32]>> = [Ok(1), Err(crate::format_err!("hi"))]
15828f6f5e7SAlex Crichton             .into_iter()
15928f6f5e7SAlex Crichton             .try_collect();
16028f6f5e7SAlex Crichton         assert!(v.is_err());
16128f6f5e7SAlex Crichton 
16228f6f5e7SAlex Crichton         let v: Result<Box<[i32]>> = [Err(crate::format_err!("hi")), Ok(1)]
16328f6f5e7SAlex Crichton             .into_iter()
16428f6f5e7SAlex Crichton             .try_collect();
16528f6f5e7SAlex Crichton         assert!(v.is_err());
16628f6f5e7SAlex Crichton         Ok(())
16728f6f5e7SAlex Crichton     }
16828f6f5e7SAlex Crichton 
16928f6f5e7SAlex Crichton     #[test]
test_try_extend() -> Result<(), OutOfMemory>17028f6f5e7SAlex Crichton     fn test_try_extend() -> Result<(), OutOfMemory> {
171183891f0SNick Fitzgerald         let mut vec = TryVec::new();
17228f6f5e7SAlex Crichton         vec.try_extend([1, 2, 3].iter().cloned())?;
17328f6f5e7SAlex Crichton         assert_eq!(&*vec, &[1, 2, 3]);
17428f6f5e7SAlex Crichton 
17528f6f5e7SAlex Crichton         vec.try_extend([])?;
17628f6f5e7SAlex Crichton         assert_eq!(&*vec, &[1, 2, 3]);
17728f6f5e7SAlex Crichton         Ok(())
17828f6f5e7SAlex Crichton     }
17928f6f5e7SAlex Crichton }
180