1use std::{io::Read, marker::PhantomData};
6
7use bytes::{Buf, BufMut};
8use tonic::{
9 Status,
10 codec::{Codec, DecodeBuf, Decoder, EncodeBuf, Encoder},
11};
12
13const MAX_DECOMPRESSED_SIZE: u64 = 128 << 20;
15
16fn decompress_snappy<R: Read>(src: R) -> std::io::Result<Vec<u8>> {
19 decompress_snappy_bounded(src, MAX_DECOMPRESSED_SIZE)
20}
21
22fn decompress_snappy_bounded<R: Read>(src: R, max_allowed: u64) -> std::io::Result<Vec<u8>> {
26 let mut snappy_decoder = snap::read::FrameDecoder::new(src).take(max_allowed);
27 let mut bytes = Vec::new();
28 snappy_decoder.read_to_end(&mut bytes)?;
29 Ok(bytes)
30}
31
32#[derive(Debug)]
33pub struct BcsEncoder<T>(PhantomData<T>);
34
35impl<T: serde::Serialize> Encoder for BcsEncoder<T> {
36 type Item = T;
37 type Error = Status;
38
39 fn encode(&mut self, item: Self::Item, buf: &mut EncodeBuf<'_>) -> Result<(), Self::Error> {
40 bcs::serialize_into(&mut buf.writer(), &item).map_err(|e| Status::internal(e.to_string()))
41 }
42}
43
44#[derive(Debug)]
45pub struct BcsDecoder<U>(PhantomData<U>);
46
47impl<U: serde::de::DeserializeOwned> Decoder for BcsDecoder<U> {
48 type Item = U;
49 type Error = Status;
50
51 fn decode(&mut self, buf: &mut DecodeBuf<'_>) -> Result<Option<Self::Item>, Self::Error> {
52 if !buf.has_remaining() {
53 return Ok(None);
54 }
55
56 let chunk = buf.chunk();
57
58 let item: Self::Item =
59 bcs::from_bytes(chunk).map_err(|e| Status::internal(e.to_string()))?;
60 buf.advance(chunk.len());
61
62 Ok(Some(item))
63 }
64}
65
66#[derive(Debug, Clone)]
68pub struct BcsCodec<T, U>(PhantomData<(T, U)>);
69
70impl<T, U> Default for BcsCodec<T, U> {
71 fn default() -> Self {
72 Self(PhantomData)
73 }
74}
75
76impl<T, U> Codec for BcsCodec<T, U>
77where
78 T: serde::Serialize + Send + 'static,
79 U: serde::de::DeserializeOwned + Send + 'static,
80{
81 type Encode = T;
82 type Decode = U;
83 type Encoder = BcsEncoder<T>;
84 type Decoder = BcsDecoder<U>;
85
86 fn encoder(&mut self) -> Self::Encoder {
87 BcsEncoder(PhantomData)
88 }
89
90 fn decoder(&mut self) -> Self::Decoder {
91 BcsDecoder(PhantomData)
92 }
93}
94
95#[derive(Debug)]
96pub struct BcsSnappyEncoder<T>(PhantomData<T>);
97
98impl<T: serde::Serialize> Encoder for BcsSnappyEncoder<T> {
99 type Item = T;
100 type Error = Status;
101
102 fn encode(&mut self, item: Self::Item, buf: &mut EncodeBuf<'_>) -> Result<(), Self::Error> {
103 let mut snappy_encoder = snap::write::FrameEncoder::new(buf.writer());
104 bcs::serialize_into(&mut snappy_encoder, &item).map_err(|e| Status::internal(e.to_string()))
105 }
106}
107
108#[derive(Debug)]
109pub struct BcsSnappyDecoder<U>(PhantomData<U>);
110
111impl<U: serde::de::DeserializeOwned> Decoder for BcsSnappyDecoder<U> {
112 type Item = U;
113 type Error = Status;
114
115 fn decode(&mut self, buf: &mut DecodeBuf<'_>) -> Result<Option<Self::Item>, Self::Error> {
116 if !buf.has_remaining() {
117 return Ok(None);
118 }
119 let bytes = decompress_snappy(buf.reader()).map_err(|e| Status::internal(e.to_string()))?;
120 let item =
121 bcs::from_bytes(bytes.as_slice()).map_err(|e| Status::internal(e.to_string()))?;
122 Ok(Some(item))
123 }
124}
125
126#[derive(Debug, Clone)]
129pub struct BcsSnappyCodec<T, U>(PhantomData<(T, U)>);
130
131impl<T, U> Default for BcsSnappyCodec<T, U> {
132 fn default() -> Self {
133 Self(PhantomData)
134 }
135}
136
137impl<T, U> Codec for BcsSnappyCodec<T, U>
138where
139 T: serde::Serialize + Send + 'static,
140 U: serde::de::DeserializeOwned + Send + 'static,
141{
142 type Encode = T;
143 type Decode = U;
144 type Encoder = BcsSnappyEncoder<T>;
145 type Decoder = BcsSnappyDecoder<U>;
146
147 fn encoder(&mut self) -> Self::Encoder {
148 BcsSnappyEncoder(PhantomData)
149 }
150
151 fn decoder(&mut self) -> Self::Decoder {
152 BcsSnappyDecoder(PhantomData)
153 }
154}
155
156pub mod anemo {
158 use std::marker::PhantomData;
159
160 use ::anemo::rpc::codec::{Codec, Decoder, Encoder};
161 use bytes::Buf;
162
163 #[derive(Debug)]
164 pub struct BcsSnappyEncoder<T>(PhantomData<T>);
165
166 impl<T: serde::Serialize> Encoder for BcsSnappyEncoder<T> {
167 type Item = T;
168 type Error = bcs::Error;
169
170 fn encode(&mut self, item: Self::Item) -> Result<bytes::Bytes, Self::Error> {
171 let mut buf = Vec::<u8>::new();
172 let mut snappy_encoder = snap::write::FrameEncoder::new(&mut buf);
173 bcs::serialize_into(&mut snappy_encoder, &item)?;
174 drop(snappy_encoder);
175 Ok(buf.into())
176 }
177 }
178
179 #[derive(Debug)]
180 pub struct BcsSnappyDecoder<U>(PhantomData<U>);
181
182 impl<U: serde::de::DeserializeOwned> Decoder for BcsSnappyDecoder<U> {
183 type Item = U;
184 type Error = bcs::Error;
185
186 fn decode(&mut self, buf: bytes::Bytes) -> Result<Self::Item, Self::Error> {
187 let bytes = super::decompress_snappy(buf.reader())?;
188 bcs::from_bytes(bytes.as_slice())
189 }
190 }
191
192 #[derive(Debug, Clone)]
195 pub struct BcsSnappyCodec<T, U>(PhantomData<(T, U)>);
196
197 impl<T, U> Default for BcsSnappyCodec<T, U> {
198 fn default() -> Self {
199 Self(PhantomData)
200 }
201 }
202
203 impl<T, U> Codec for BcsSnappyCodec<T, U>
204 where
205 T: serde::Serialize + Send + 'static,
206 U: serde::de::DeserializeOwned + Send + 'static,
207 {
208 type Encode = T;
209 type Decode = U;
210 type Encoder = BcsSnappyEncoder<T>;
211 type Decoder = BcsSnappyDecoder<U>;
212
213 fn encoder(&mut self) -> Self::Encoder {
214 BcsSnappyEncoder(PhantomData)
215 }
216
217 fn decoder(&mut self) -> Self::Decoder {
218 BcsSnappyDecoder(PhantomData)
219 }
220
221 fn format_name(&self) -> &'static str {
222 "bcs"
223 }
224 }
225}
226
227#[cfg(test)]
228mod tests {
229 use ::anemo::rpc::codec::{
230 Codec as AnemoCodec, Decoder as AnemoDecoder, Encoder as AnemoEncoder,
231 };
232
233 use super::*;
234
235 fn snappy_compress(raw: &[u8]) -> Vec<u8> {
236 let mut out = Vec::new();
237 let mut encoder = snap::write::FrameEncoder::new(&mut out);
238 std::io::Write::write_all(&mut encoder, raw).unwrap();
239 drop(encoder);
240 out
241 }
242
243 #[test]
244 fn anemo_roundtrip() {
245 let mut codec: anemo::BcsSnappyCodec<Vec<u64>, Vec<u64>> = anemo::BcsSnappyCodec::default();
246 let value = vec![1u64, 2, 3, 4, 5, 6, 7, 8, 9, 10];
247 let encoded = codec.encoder().encode(value.clone()).unwrap();
248 let decoded = codec.decoder().decode(encoded).unwrap();
249 assert_eq!(decoded, value);
250 }
251
252 #[test]
253 fn bounded_helper_respects_output_limit() {
254 let raw = vec![0u8; 2 * 1024 * 1024];
257 let compressed = snappy_compress(&raw);
258 let limit = 1024u64;
259 let out = decompress_snappy_bounded(&compressed[..], limit).unwrap();
260 assert_eq!(out.len() as u64, limit);
261 assert!((out.len() as u64) < raw.len() as u64);
262 }
263
264 mod tonic_via_streaming {
269 use std::{
270 pin::Pin,
271 task::{Context, Poll},
272 };
273
274 use bytes::{BufMut, Bytes, BytesMut};
275 use futures::StreamExt;
276 use http_body::{Body as HttpBody, Frame};
277
278 use super::{super::*, snappy_compress};
279
280 struct OneFrameBody(Option<Bytes>);
283
284 impl OneFrameBody {
285 fn new(payload: Bytes) -> Self {
286 let mut framed = BytesMut::with_capacity(5 + payload.len());
287 framed.put_u8(0);
288 framed.put_u32(payload.len() as u32);
289 framed.put_slice(&payload);
290 Self(Some(framed.freeze()))
291 }
292 }
293
294 impl HttpBody for OneFrameBody {
295 type Data = Bytes;
296 type Error = std::convert::Infallible;
297
298 fn poll_frame(
299 mut self: Pin<&mut Self>,
300 _cx: &mut Context<'_>,
301 ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
302 Poll::Ready(self.0.take().map(|b| Ok(Frame::data(b))))
303 }
304
305 fn is_end_stream(&self) -> bool {
306 self.0.is_none()
307 }
308 }
309
310 #[tokio::test]
311 async fn tonic_roundtrip() {
312 let mut codec: BcsSnappyCodec<Vec<u64>, Vec<u64>> = BcsSnappyCodec::default();
313 let value = vec![1u64, 2, 3, 4, 5, 6, 7, 8, 9, 10];
314 let raw = bcs::to_bytes(&value).unwrap();
315 let compressed = snappy_compress(&raw);
316 let body = OneFrameBody::new(Bytes::from(compressed));
317 let mut stream =
318 tonic::codec::Streaming::new_request(codec.decoder(), body, None, None);
319 let decoded = stream.next().await.unwrap().unwrap();
320 assert_eq!(decoded, value);
321 }
322 }
323}