trillium_grpc/codec/
prost_codec.rs1use crate::{Codec, Status};
2use bytes::{Bytes, BytesMut};
3use prost::Message;
4
5pub struct Prost;
7
8impl<T> Codec<T> for Prost
9where
10 T: Message + Default + 'static,
11{
12 fn content_type_suffix() -> &'static str {
13 "proto"
14 }
15
16 fn encode(value: &T) -> Result<Bytes, Status> {
17 let mut buf = BytesMut::with_capacity(value.encoded_len());
18 value
19 .encode(&mut buf)
20 .map_err(|e| Status::internal(format!("prost encode failed: {e}")))?;
21 Ok(buf.freeze())
22 }
23
24 fn decode(bytes: &[u8]) -> Result<T, Status> {
25 T::decode(bytes).map_err(|e| Status::invalid_argument(format!("prost decode failed: {e}")))
26 }
27}
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32
33 #[test]
39 fn prost_codec_suffix() {
40 assert_eq!(<Prost as Codec<Vec<u8>>>::content_type_suffix(), "proto");
41 }
42
43 #[test]
44 fn prost_codec_encode_empty() {
45 let value: Vec<u8> = Vec::new();
46 let encoded = <Prost as Codec<Vec<u8>>>::encode(&value).unwrap();
47 assert!(encoded.is_empty());
48 }
49
50 #[test]
51 fn prost_codec_decode_empty() {
52 let decoded: Vec<u8> = <Prost as Codec<Vec<u8>>>::decode(&[]).unwrap();
53 assert!(decoded.is_empty());
54 }
55
56 #[test]
57 fn prost_codec_decode_garbage_is_invalid_argument() {
58 let err = <Prost as Codec<Vec<u8>>>::decode(&[0xFF, 0xFF, 0xFF, 0xFF]).unwrap_err();
60 assert_eq!(err.code, crate::Code::InvalidArgument);
61 }
62}