Path: blob/main/crates/core/src/alloc/try_collect.rs
3073 views
use crate::alloc::Vec;1use crate::error::OutOfMemory;2use std_alloc::boxed::Box;34/// Extension trait for an `Iterator` to fallibly collect into a container.5pub trait TryCollect: Iterator {6/// Attempts to collect the iterator `self` into `B`.7///8/// Same as [`Iterator::collect`] except returns OOM instead of aborting.9fn try_collect<B, E>(self) -> Result<B, E>10where11B: TryFromIterator<Self::Item, E>,12Self: Sized,13{14B::try_from_iter(self)15}16}1718impl<I: Iterator> TryCollect for I {}1920/// Analogue of [`FromIterator`] in the standard library, but used with21/// [`TryCollect::try_collect`] instead.22pub trait TryFromIterator<T, E>: Sized {23/// Creates an intance of this collection from the `iter` provided.24///25/// Does not abort on OOM but insteads return an error.26fn try_from_iter<I>(iter: I) -> Result<Self, E>27where28I: Iterator<Item = T>;29}3031impl<T> TryFromIterator<T, OutOfMemory> for Vec<T> {32fn try_from_iter<I>(iter: I) -> Result<Self, OutOfMemory>33where34I: Iterator<Item = T>,35{36let mut result = Vec::with_capacity(iter.size_hint().0)?;37for item in iter {38result.push(item)?;39}40Ok(result)41}42}4344impl<T> TryFromIterator<T, OutOfMemory> for Box<[T]> {45fn try_from_iter<I>(iter: I) -> Result<Self, OutOfMemory>46where47I: Iterator<Item = T>,48{49let vec = Vec::try_from_iter(iter)?;50vec.into_boxed_slice()51}52}5354impl<T, E> TryFromIterator<Result<T, E>, E> for Vec<T>55where56E: From<OutOfMemory>,57{58fn try_from_iter<I>(iter: I) -> Result<Self, E>59where60I: Iterator<Item = Result<T, E>>,61{62let mut result = Vec::with_capacity(iter.size_hint().0)?;63for item in iter {64result.push(item?)?;65}66Ok(result)67}68}6970impl<T, E> TryFromIterator<Result<T, E>, E> for Box<[T]>71where72E: From<OutOfMemory>,73{74fn try_from_iter<I>(iter: I) -> Result<Self, E>75where76I: Iterator<Item = Result<T, E>>,77{78let vec = iter.try_collect::<Vec<_>, E>()?;79Ok(vec.into_boxed_slice()?)80}81}8283/// Analogue of [`Extend`] except handles OOM conditions.84pub trait TryExtend<T> {85/// Extends `self` with the items from `iter`.86///87/// Returns an error if allocation fails while adding items to `self`. If an88/// OOM happens then some items from `iter` may have been added to `self`89/// already. On OOM no further items from the iterator will be consumed.90fn try_extend<I>(&mut self, iter: I) -> Result<(), OutOfMemory>91where92I: IntoIterator<Item = T>;93}9495impl<T> TryExtend<T> for Vec<T> {96fn try_extend<I>(&mut self, iter: I) -> Result<(), OutOfMemory>97where98I: IntoIterator<Item = T>,99{100let iter = iter.into_iter();101self.reserve(iter.size_hint().0)?;102for item in iter {103self.push(item)?;104}105Ok(())106}107}108109#[cfg(test)]110mod tests {111use super::{Box, TryCollect, TryExtend, Vec};112use crate::error::{OutOfMemory, Result};113114#[test]115fn test_vec_collect() -> Result<(), OutOfMemory> {116let v: Vec<i32> = (0..10).try_collect()?;117assert_eq!(&*v, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);118Ok(())119}120121#[test]122fn test_box_collect() -> Result<(), OutOfMemory> {123let v: Box<[i32]> = (0..10).try_collect()?;124assert_eq!(&*v, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);125Ok(())126}127128#[test]129fn test_vec_result_collect() -> Result<()> {130let v: Result<Vec<i32>> = [].into_iter().try_collect();131assert!(v?.is_empty());132133let v: Result<Vec<i32>> = [Ok(1), Ok(2)].into_iter().try_collect();134assert_eq!(&*v?, &[1, 2]);135136let v: Result<Vec<i32>> = [Ok(1), Err(crate::format_err!("hi"))]137.into_iter()138.try_collect();139assert!(v.is_err());140141let v: Result<Vec<i32>> = [Err(crate::format_err!("hi")), Ok(1)]142.into_iter()143.try_collect();144assert!(v.is_err());145Ok(())146}147148#[test]149fn test_box_result_collect() -> Result<()> {150let v: Result<Box<[i32]>> = [].into_iter().try_collect();151assert!(v?.is_empty());152153let v: Result<Box<[i32]>> = [Ok(1), Ok(2)].into_iter().try_collect();154assert_eq!(&*v?, &[1, 2]);155156let v: Result<Box<[i32]>> = [Ok(1), Err(crate::format_err!("hi"))]157.into_iter()158.try_collect();159assert!(v.is_err());160161let v: Result<Box<[i32]>> = [Err(crate::format_err!("hi")), Ok(1)]162.into_iter()163.try_collect();164assert!(v.is_err());165Ok(())166}167168#[test]169fn test_try_extend() -> Result<(), OutOfMemory> {170let mut vec = Vec::new();171vec.try_extend([1, 2, 3].iter().cloned())?;172assert_eq!(&*vec, &[1, 2, 3]);173174vec.try_extend([])?;175assert_eq!(&*vec, &[1, 2, 3]);176Ok(())177}178}179180181