Skip to main content

acktor_ipc/codec/
common_codec.rs

1use std::fmt::Display;
2use std::sync::Arc;
3
4use bytes::{Bytes, BytesMut};
5use prost::Message as _;
6
7use acktor_ipc_proto::utils::{ProtoOption, ProtoResult, ProtoResultType};
8
9use super::errors::{DecodeError, EncodeError};
10use super::protobuf_helper::LENGTH_DELIMITED_TAGS;
11use super::{Decode, DecodeContext, Encode, EncodeContext};
12
13impl<T> Encode for Box<T>
14where
15    T: Encode,
16{
17    const ID: u64 = T::ID;
18
19    fn encoded_len(&self) -> usize {
20        self.as_ref().encoded_len()
21    }
22
23    fn encode(&self, buf: &mut BytesMut, ctx: Option<&EncodeContext>) -> Result<(), EncodeError> {
24        self.as_ref().encode(buf, ctx)
25    }
26}
27
28impl<T> Decode for Box<T>
29where
30    T: Decode,
31{
32    const ID: u64 = T::ID;
33
34    fn decode(buf: Bytes, ctx: Option<&DecodeContext>) -> Result<Self, DecodeError> {
35        T::decode(buf, ctx).map(Box::new)
36    }
37}
38
39impl<T> Encode for Arc<T>
40where
41    T: Encode,
42{
43    const ID: u64 = T::ID;
44
45    fn encoded_len(&self) -> usize {
46        self.as_ref().encoded_len()
47    }
48
49    fn encode(&self, buf: &mut BytesMut, ctx: Option<&EncodeContext>) -> Result<(), EncodeError> {
50        self.as_ref().encode(buf, ctx)
51    }
52}
53
54impl<T> Decode for Arc<T>
55where
56    T: Decode,
57{
58    const ID: u64 = T::ID;
59
60    fn decode(buf: Bytes, ctx: Option<&DecodeContext>) -> Result<Self, DecodeError> {
61        T::decode(buf, ctx).map(Arc::new)
62    }
63}
64
65// Encode a `Result<T, E>`.
66//
67// The `Err` variant is lossy: the error is serialized as its `Display` string and decoded back
68// via `E::from(String)` (see the `Decode` impl below). Any structured data on the error type —
69// enum discriminants, numeric codes, nested fields — is collapsed to the rendered message.
70impl<T, E> Encode for Result<T, E>
71where
72    T: Encode,
73    E: Display,
74{
75    fn encoded_len(&self) -> usize {
76        let inner_len = match self {
77            Ok(ok) => ok.encoded_len(),
78            Err(err) => err.to_string().len(),
79        };
80        // oneof field: 1 byte tag + varint length + data
81        1 + prost::length_delimiter_len(inner_len) + inner_len
82    }
83
84    fn encode(&self, buf: &mut BytesMut, ctx: Option<&EncodeContext>) -> Result<(), EncodeError> {
85        match self {
86            Ok(ok) => {
87                // field 1, wire type LengthDelimited (bytes)
88                buf.extend_from_slice(&[LENGTH_DELIMITED_TAGS[1]]);
89                prost::encoding::encode_varint(ok.encoded_len() as u64, buf);
90                ok.encode(buf, ctx)?;
91            }
92            Err(err) => {
93                // field 2, wire type LengthDelimited (string)
94                let err_str = err.to_string();
95                buf.extend_from_slice(&[LENGTH_DELIMITED_TAGS[2]]);
96                prost::encoding::encode_varint(err_str.len() as u64, buf);
97                buf.extend_from_slice(err_str.as_bytes());
98            }
99        }
100
101        Ok(())
102    }
103
104    fn encode_to_bytes(&self, ctx: Option<&EncodeContext>) -> Result<Bytes, EncodeError> {
105        match self {
106            Ok(ok) => {
107                let inner_len = ok.encoded_len();
108                let total = 1 + prost::length_delimiter_len(inner_len) + inner_len;
109                let mut buf = BytesMut::with_capacity(total);
110                buf.extend_from_slice(&[0x0A]);
111                prost::encoding::encode_varint(inner_len as u64, &mut buf);
112                ok.encode(&mut buf, ctx)?;
113
114                Ok(buf.freeze())
115            }
116            Err(err) => {
117                let err_string = err.to_string();
118                let total = 1 + prost::length_delimiter_len(err_string.len()) + err_string.len();
119                let mut buf = BytesMut::with_capacity(total);
120                buf.extend_from_slice(&[LENGTH_DELIMITED_TAGS[2]]);
121                prost::encoding::encode_varint(err_string.len() as u64, &mut buf);
122                buf.extend_from_slice(err_string.as_bytes());
123
124                Ok(buf.freeze())
125            }
126        }
127    }
128}
129
130impl<T, E> Decode for Result<T, E>
131where
132    T: Decode,
133    E: From<String>,
134{
135    #[inline]
136    fn decode(buf: Bytes, ctx: Option<&DecodeContext>) -> Result<Self, DecodeError> {
137        let result = ProtoResult::decode(buf)?;
138        match result.result {
139            Some(ProtoResultType::Ok(ok)) => Ok(Ok(T::decode(ok, ctx)?)),
140            Some(ProtoResultType::Err(err)) => Ok(Err(E::from(err))),
141            _ => Err("missing field `result` in the `Result` message".into()),
142        }
143    }
144}
145
146impl<T> Encode for Option<T>
147where
148    T: Encode,
149{
150    fn encoded_len(&self) -> usize {
151        match self {
152            // bytes field: 1 byte tag + varint length + data
153            Some(some) => {
154                let inner_len = some.encoded_len();
155                1 + prost::length_delimiter_len(inner_len) + inner_len
156            }
157            // empty message
158            None => 0,
159        }
160    }
161
162    fn encode(&self, buf: &mut BytesMut, ctx: Option<&EncodeContext>) -> Result<(), EncodeError> {
163        if let Some(some) = self {
164            // field 1, wire type LengthDelimited (bytes)
165            buf.extend_from_slice(&[0x0A]);
166            prost::encoding::encode_varint(some.encoded_len() as u64, buf);
167            some.encode(buf, ctx)?;
168        }
169
170        Ok(())
171    }
172
173    fn encode_to_bytes(&self, ctx: Option<&EncodeContext>) -> Result<Bytes, EncodeError> {
174        match self {
175            Some(some) => {
176                let inner_len = some.encoded_len();
177                let total = 1 + prost::length_delimiter_len(inner_len) + inner_len;
178                let mut buf = BytesMut::with_capacity(total);
179                buf.extend_from_slice(&[0x0A]);
180                prost::encoding::encode_varint(inner_len as u64, &mut buf);
181                some.encode(&mut buf, ctx)?;
182
183                Ok(buf.freeze())
184            }
185            None => Ok(Bytes::new()),
186        }
187    }
188}
189
190impl<T> Decode for Option<T>
191where
192    T: Decode,
193{
194    fn decode(buf: Bytes, ctx: Option<&DecodeContext>) -> Result<Self, DecodeError> {
195        let option = ProtoOption::decode(buf)?;
196        match option.option {
197            Some(bytes) => Ok(Some(T::decode(bytes, ctx)?)),
198            None => Ok(None),
199        }
200    }
201}