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