#[cfg(feature = "boxed")] use crate::boxed::Box; use crate::collections::{String, Vec}; use crate::Bump; /// A trait for types that support being constructed from an iterator, parameterized by an allocator. pub trait FromIteratorIn { /// The allocator type type Alloc; /// Similar to [`FromIterator::from_iter`][from_iter], but with a given allocator. /// /// [from_iter]: https://doc.rust-lang.org/std/iter/trait.FromIterator.html#tymethod.from_iter /// /// ``` /// # use bumpalo::collections::{FromIteratorIn, Vec}; /// # use bumpalo::Bump; /// # /// let five_fives = std::iter::repeat(5).take(5); /// let bump = Bump::new(); /// /// let v = Vec::from_iter_in(five_fives, &bump); /// /// assert_eq!(v, [5, 5, 5, 5, 5]); /// ``` fn from_iter_in(iter: I, alloc: Self::Alloc) -> Self where I: IntoIterator; } #[cfg(feature = "boxed")] impl<'bump, T> FromIteratorIn for Box<'bump, [T]> { type Alloc = &'bump Bump; fn from_iter_in(iter: I, alloc: Self::Alloc) -> Self where I: IntoIterator, { Box::from_iter_in(iter, alloc) } } impl<'bump, T> FromIteratorIn for Vec<'bump, T> { type Alloc = &'bump Bump; fn from_iter_in(iter: I, alloc: Self::Alloc) -> Self where I: IntoIterator, { Vec::from_iter_in(iter, alloc) } } impl> FromIteratorIn> for Option { type Alloc = V::Alloc; fn from_iter_in(iter: I, alloc: Self::Alloc) -> Self where I: IntoIterator>, { iter.into_iter() .map(|x| x.ok_or(())) .collect_in::>(alloc) .ok() } } impl> FromIteratorIn> for Result { type Alloc = V::Alloc; /// Takes each element in the `Iterator`: if it is an `Err`, no further /// elements are taken, and the `Err` is returned. Should no `Err` occur, a /// container with the values of each `Result` is returned. /// /// Here is an example which increments every integer in a vector, /// checking for overflow: /// /// ``` /// # use bumpalo::collections::{FromIteratorIn, CollectIn, Vec, String}; /// # use bumpalo::Bump; /// # /// let bump = Bump::new(); /// /// let v = vec![1, 2, u32::MAX]; /// let res: Result, &'static str> = v.iter().take(2).map(|x: &u32| /// x.checked_add(1).ok_or("Overflow!") /// ).collect_in(&bump); /// assert_eq!(res, Ok(bumpalo::vec![in ≎ 2, 3])); /// /// let res: Result, &'static str> = v.iter().map(|x: &u32| /// x.checked_add(1).ok_or("Overflow!") /// ).collect_in(&bump); /// assert_eq!(res, Err("Overflow!")); /// ``` fn from_iter_in(iter: I, alloc: Self::Alloc) -> Self where I: IntoIterator>, { let mut iter = iter.into_iter(); let mut error = None; let container = core::iter::from_fn(|| match iter.next() { Some(Ok(x)) => Some(x), Some(Err(e)) => { error = Some(e); None } None => None, }) .collect_in(alloc); match error { Some(e) => Err(e), None => Ok(container), } } } impl<'bump> FromIteratorIn for String<'bump> { type Alloc = &'bump Bump; fn from_iter_in(iter: I, alloc: Self::Alloc) -> Self where I: IntoIterator, { String::from_iter_in(iter, alloc) } } /// Extension trait for iterators, in order to allow allocator-parameterized collections to be constructed more easily. pub trait CollectIn: Iterator + Sized { /// Collect all items from an iterator, into a collection parameterized by an allocator. /// Similar to [`Iterator::collect`][collect]. /// /// [collect]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect /// /// ``` /// # use bumpalo::collections::{FromIteratorIn, CollectIn, Vec, String}; /// # use bumpalo::Bump; /// # /// let bump = Bump::new(); /// /// let str = "hello, world!".to_owned(); /// let bump_str: String = str.chars().collect_in(&bump); /// assert_eq!(&bump_str, &str); /// /// let nums: Vec = (0..=3).collect_in::>(&bump); /// assert_eq!(&nums, &[0,1,2,3]); /// ``` fn collect_in>(self, alloc: C::Alloc) -> C { C::from_iter_in(self, alloc) } } impl CollectIn for I {}