Skip to main content

alux_http/
chunks.rs

1//! States a body produced over time, rather than one that is already in hand.
2
3use alux_ext::ext;
4use core::future::Future;
5use futures::{Stream, stream};
6
7/// States a body produced over time: the chunks it carries, and what taking the next one means.
8///
9/// A domain answering with a body it cannot hold all at once states this rather than naming a
10/// stream type. What a chunk is, what a failure part-way through means, and how bytes actually move
11/// are then the interpretation's to choose, which is the whole reason a program states a surface
12/// rather than a framework's callbacks.
13pub trait ChunksAlg {
14    /// What one chunk carries.
15    type Chunk;
16
17    /// What a body failing part-way through means.
18    type Error;
19
20    /// Takes the next chunk, or nothing where the body has ended.
21    fn next_chunk(&mut self) -> impl Future<Output = Option<Result<Self::Chunk, Self::Error>>> + Send;
22}
23
24/// The operations a body stated as chunks derives.
25#[ext(name = ChunksExt)]
26pub impl<This> This
27where
28    This: ChunksAlg + Send + 'static,
29    This::Chunk: Send,
30{
31    /// Reads this body as the sequence of chunks it produces.
32    ///
33    /// Nothing is converted and nothing is carried: a chunk stays what the domain said it was, and
34    /// a failure stays what the domain said it meant. An interpretation states what to make of
35    /// either, which is the only part of moving bytes that is its own.
36    fn moving(self) -> impl Stream<Item = Result<Self::Chunk, Self::Error>> {
37        stream::unfold(self, |mut chunks| async move {
38            let taken = chunks.next_chunk().await?;
39
40            Some((taken, chunks))
41        })
42    }
43
44    /// Takes every chunk this body produces, in the order it produces them.
45    ///
46    /// A sequence read whole is what anything states that cannot act on a piece at a time: a part's
47    /// content read into a value, or an answer compared against what a caller would have received.
48    async fn gathered(mut self) -> Result<Vec<Self::Chunk>, Self::Error> {
49        let mut taken = Vec::new();
50        while let Some(chunk) = self.next_chunk().await {
51            taken.push(chunk?);
52        }
53
54        Ok(taken)
55    }
56}