http_pack/
h3.rs

1use bytes::{Buf, Bytes};
2use h3::quic::RecvStream;
3
4use crate::{EncodeError, PackedRequest, PackedResponse};
5
6#[derive(Debug)]
7pub enum H3PackError {
8    Stream(h3::error::StreamError),
9    Encode(EncodeError),
10}
11
12impl std::fmt::Display for H3PackError {
13    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14        match self {
15            H3PackError::Stream(err) => write!(f, "h3 stream error: {}", err),
16            H3PackError::Encode(err) => write!(f, "encode error: {}", err),
17        }
18    }
19}
20
21impl std::error::Error for H3PackError {}
22
23pub async fn pack_server_request<S, B>(
24    req: http::Request<()>,
25    stream: &mut h3::server::RequestStream<S, B>,
26) -> Result<PackedRequest, H3PackError>
27where
28    S: RecvStream,
29    B: Buf,
30{
31    let body = collect_server_body(stream).await?;
32    let request = req.map(|_| Bytes::from(body));
33    PackedRequest::from_request(&request).map_err(H3PackError::Encode)
34}
35
36pub async fn pack_client_response<S, B>(
37    resp: http::Response<()>,
38    stream: &mut h3::client::RequestStream<S, B>,
39) -> Result<PackedResponse, H3PackError>
40where
41    S: RecvStream,
42    B: Buf,
43{
44    let body = collect_client_body(stream).await?;
45    let response = resp.map(|_| Bytes::from(body));
46    PackedResponse::from_response(&response).map_err(H3PackError::Encode)
47}
48
49async fn collect_server_body<S, B>(
50    stream: &mut h3::server::RequestStream<S, B>,
51) -> Result<Vec<u8>, H3PackError>
52where
53    S: RecvStream,
54    B: Buf,
55{
56    let mut out = Vec::new();
57    loop {
58        match stream.recv_data().await.map_err(H3PackError::Stream)? {
59            Some(mut chunk) => {
60                let remaining = chunk.remaining();
61                if remaining == 0 {
62                    continue;
63                }
64                let bytes = chunk.copy_to_bytes(remaining);
65                out.extend_from_slice(bytes.as_ref());
66            }
67            None => break,
68        }
69    }
70    Ok(out)
71}
72
73async fn collect_client_body<S, B>(
74    stream: &mut h3::client::RequestStream<S, B>,
75) -> Result<Vec<u8>, H3PackError>
76where
77    S: RecvStream,
78    B: Buf,
79{
80    let mut out = Vec::new();
81    loop {
82        match stream.recv_data().await.map_err(H3PackError::Stream)? {
83            Some(mut chunk) => {
84                let remaining = chunk.remaining();
85                if remaining == 0 {
86                    continue;
87                }
88                let bytes = chunk.copy_to_bytes(remaining);
89                out.extend_from_slice(bytes.as_ref());
90            }
91            None => break,
92        }
93    }
94    Ok(out)
95}