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}