diff options
Diffstat (limited to 'third_party/rust/bumpalo/src/collections/collect_in.rs')
-rw-r--r-- | third_party/rust/bumpalo/src/collections/collect_in.rs | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/third_party/rust/bumpalo/src/collections/collect_in.rs b/third_party/rust/bumpalo/src/collections/collect_in.rs new file mode 100644 index 0000000000..3e1adeaeaa --- /dev/null +++ b/third_party/rust/bumpalo/src/collections/collect_in.rs @@ -0,0 +1,152 @@ +#[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<A> { + /// 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<I>(iter: I, alloc: Self::Alloc) -> Self + where + I: IntoIterator<Item = A>; +} + +#[cfg(feature = "boxed")] +impl<'bump, T> FromIteratorIn<T> for Box<'bump, [T]> { + type Alloc = &'bump Bump; + + fn from_iter_in<I>(iter: I, alloc: Self::Alloc) -> Self + where + I: IntoIterator<Item = T>, + { + Box::from_iter_in(iter, alloc) + } +} + +impl<'bump, T> FromIteratorIn<T> for Vec<'bump, T> { + type Alloc = &'bump Bump; + + fn from_iter_in<I>(iter: I, alloc: Self::Alloc) -> Self + where + I: IntoIterator<Item = T>, + { + Vec::from_iter_in(iter, alloc) + } +} + +impl<T, V: FromIteratorIn<T>> FromIteratorIn<Option<T>> for Option<V> { + type Alloc = V::Alloc; + fn from_iter_in<I>(iter: I, alloc: Self::Alloc) -> Self + where + I: IntoIterator<Item = Option<T>>, + { + iter.into_iter() + .map(|x| x.ok_or(())) + .collect_in::<Result<_, _>>(alloc) + .ok() + } +} + +impl<T, E, V: FromIteratorIn<T>> FromIteratorIn<Result<T, E>> for Result<V, E> { + 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<Vec<u32>, &'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<Vec<u32>, &'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<I>(iter: I, alloc: Self::Alloc) -> Self + where + I: IntoIterator<Item = Result<T, E>>, + { + 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<char> for String<'bump> { + type Alloc = &'bump Bump; + + fn from_iter_in<I>(iter: I, alloc: Self::Alloc) -> Self + where + I: IntoIterator<Item = char>, + { + 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<i32> = (0..=3).collect_in::<Vec<_>>(&bump); + /// assert_eq!(&nums, &[0,1,2,3]); + /// ``` + fn collect_in<C: FromIteratorIn<Self::Item>>(self, alloc: C::Alloc) -> C { + C::from_iter_in(self, alloc) + } +} + +impl<I: Iterator> CollectIn for I {} |