1use crate::pb::Trailer;
15use bytes::{Buf, BufMut, Bytes, BytesMut};
16use prost::Message;
17
18pub const LEN_PREFIX: usize = 4;
19
20#[derive(Debug, thiserror::Error)]
21pub enum FetchError {
22 #[error("response body exceeds configured size limit ({limit} bytes)")]
23 TooLarge { limit: usize },
24 #[error("response body truncated: expected {expected} more bytes, had {had}")]
25 Truncated { expected: usize, had: usize },
26 #[error("failed to decode Trailer: {0}")]
27 Decode(#[from] prost::DecodeError),
28}
29
30pub fn encode_response_body(message: &[u8], trailer: &Trailer) -> Bytes {
32 let trailer_len = trailer.encoded_len();
33 let mut buf = BytesMut::with_capacity(LEN_PREFIX + message.len() + LEN_PREFIX + trailer_len);
34 buf.put_u32(message.len() as u32);
35 buf.put_slice(message);
36 buf.put_u32(trailer_len as u32);
37 trailer.encode(&mut buf).expect("BytesMut has capacity");
38 buf.freeze()
39}
40
41pub const EMPTY_MESSAGE_BLOCK: [u8; LEN_PREFIX] = [0; LEN_PREFIX];
44
45pub fn encode_request_body(message: &[u8]) -> Bytes {
50 let mut buf = BytesMut::with_capacity(LEN_PREFIX + message.len());
51 buf.put_u32(message.len() as u32);
52 buf.put_slice(message);
53 buf.freeze()
54}
55
56pub fn encode_trailer_block(trailer: &Trailer) -> Bytes {
61 let trailer_len = trailer.encoded_len();
62 let mut buf = BytesMut::with_capacity(LEN_PREFIX + trailer_len);
63 buf.put_u32(trailer_len as u32);
64 trailer.encode(&mut buf).expect("BytesMut has capacity");
65 buf.freeze()
66}
67
68pub fn decode_response_body(mut body: Bytes, limit: usize) -> Result<(Bytes, Trailer), FetchError> {
72 if body.len() > limit {
73 return Err(FetchError::TooLarge { limit });
74 }
75
76 let message = take_block(&mut body)?;
77 let trailer_bytes = take_block(&mut body)?;
78 let trailer = Trailer::decode(trailer_bytes)?;
79 Ok((message, trailer))
80}
81
82fn take_block(body: &mut Bytes) -> Result<Bytes, FetchError> {
84 if body.remaining() < LEN_PREFIX {
85 return Err(FetchError::Truncated {
86 expected: LEN_PREFIX,
87 had: body.remaining(),
88 });
89 }
90 let len = body.get_u32() as usize;
91 if body.remaining() < len {
92 return Err(FetchError::Truncated {
93 expected: len,
94 had: body.remaining(),
95 });
96 }
97 Ok(body.split_to(len))
98}