1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
//! Module to extend the functionality of types in `patination_stream` module to allow for
//! collecting elements of the stream into collection.
//!
//! Majority of the code is borrowed from
//! <https://github.com/tokio-rs/tokio/blob/fc9518b62714daac9a38b46c698b94ac5d5b1ca2/tokio-stream/src/stream_ext/collect.rs>
pub(crate) mod sealed {
/// A trait that signifies that elements can be collected into `T`.
///
/// Currently the trait may not be implemented by clients so we can make changes in the future
/// without breaking code depending on it.
pub trait Collectable<T> {
type Collection;
fn initialize() -> Self::Collection;
fn extend(collection: &mut Self::Collection, item: T) -> bool;
fn finalize(collection: Self::Collection) -> Self;
}
}
impl<T> sealed::Collectable<T> for Vec<T> {
type Collection = Self;
fn initialize() -> Self::Collection {
Vec::default()
}
fn extend(collection: &mut Self::Collection, item: T) -> bool {
collection.push(item);
true
}
fn finalize(collection: Self::Collection) -> Self {
collection
}
}
impl<T, U, E> sealed::Collectable<Result<T, E>> for Result<U, E>
where
U: sealed::Collectable<T>,
{
type Collection = Result<U::Collection, E>;
fn initialize() -> Self::Collection {
Ok(U::initialize())
}
fn extend(collection: &mut Self::Collection, item: Result<T, E>) -> bool {
match item {
Ok(item) => {
let collection = collection.as_mut().ok().expect("invalid state");
U::extend(collection, item)
}
Err(e) => {
*collection = Err(e);
false
}
}
}
fn finalize(collection: Self::Collection) -> Self {
match collection {
Ok(collection) => Ok(U::finalize(collection)),
err @ Err(_) => Err(err.map(drop).unwrap_err()),
}
}
}