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}