1use crate::errors::CodecError;
7use crate::util;
8
9pub trait RpcCodec: Sized {
11 fn from_slice(buf: &[u8]) -> Result<Self, CodecError>;
12 fn fill_buf(&self, buf: &mut Vec<u8>) -> Result<(), CodecError>;
13}
14
15impl RpcCodec for () {
16 fn from_slice(_buf: &[u8]) -> Result<Self, CodecError> {
17 Ok(())
18 }
19
20 fn fill_buf(&self, _buf: &mut Vec<u8>) -> Result<(), CodecError> {
21 Ok(())
22 }
23}
24
25impl RpcCodec for Vec<u8> {
28 fn from_slice(buf: &[u8]) -> Result<Self, CodecError> {
29 Ok(buf.to_vec())
30 }
31
32 fn fill_buf(&self, buf: &mut Vec<u8>) -> Result<(), CodecError> {
33 buf.extend_from_slice(&self);
34 Ok(())
35 }
36}
37
38macro_rules! decl_tuple_codec {
39 ( $($vident:ident: $tident:ident),* ) => {
40 impl<$($tident: RpcCodec),*> RpcCodec for ($($tident),*) {
41 fn from_slice(buf: &[u8]) -> Result<Self, CodecError> {
42 let mut cur = util::Cursor::new(buf);
43
44 $(let $vident = cur.take_len_tagged_inst::<$tident>()?;)*
45
46 if !cur.is_at_end() {
47 return Err(CodecError::LeftoverBytes(
48 cur.remaining_bytes(),
49 cur.inner().len(),
50 ));
51 }
52
53
54 Ok(($($vident),*))
55 }
56
57 fn fill_buf(&self, buf: &mut Vec<u8>) -> Result<(), CodecError> {
58 let ($($vident),*) = self;
59
60 $(util::write_len_tagged_inst($vident, buf)?;)*
61
62 Ok(())
63 }
64 }
65 }
66}
67
68decl_tuple_codec!(t1: T1, t2: T2);
69decl_tuple_codec!(t1: T1, t2: T2, t3: T3);
70decl_tuple_codec!(t1: T1, t2: T2, t3: T3, t4: T4);
71
72impl RpcCodec for String {
111 fn from_slice(buf: &[u8]) -> Result<Self, CodecError> {
112 Ok(std::str::from_utf8(buf)
113 .map_err(|_| CodecError::NonUtf8String)?
114 .to_owned())
115 }
116
117 fn fill_buf(&self, buf: &mut Vec<u8>) -> Result<(), CodecError> {
118 buf.extend_from_slice(self.as_bytes());
119 Ok(())
120 }
121}
122
123macro_rules! decl_int_codec {
124 ( $ity:ty ) => {
125 impl RpcCodec for $ity {
126 fn from_slice(buf: &[u8]) -> Result<Self, CodecError> {
127 const NBYTES: usize = (<$ity>::BITS / 8) as usize;
128 let mut cur = util::Cursor::new(buf);
129 let ibuf = cur.take_arr::<NBYTES>()?;
130 Ok(<$ity>::from_be_bytes(ibuf))
131 }
132
133 fn fill_buf(&self, buf: &mut Vec<u8>) -> Result<(), CodecError> {
134 buf.extend_from_slice(&self.to_be_bytes());
135 Ok(())
136 }
137 }
138 };
139}
140
141decl_int_codec!(i8);
142decl_int_codec!(i16);
143decl_int_codec!(i32);
144decl_int_codec!(i64);
145decl_int_codec!(u16);
146decl_int_codec!(u32);
147decl_int_codec!(u64);
148
149macro_rules! decl_intvec_codec {
150 ( $ity:ty ) => {
151 impl RpcCodec for Vec<$ity> {
152 fn from_slice(buf: &[u8]) -> Result<Self, CodecError> {
153 const NBYTES: usize = (<$ity>::BITS / 8) as usize;
154
155 let leftover = buf.len() % NBYTES;
157 if leftover > 0 {
158 return Err(CodecError::LeftoverBytes(leftover, buf.len()));
159 }
160
161 let mut cur = util::Cursor::new(buf);
162
163 let cnt = buf.len() / NBYTES;
164 let mut list = Vec::new();
165
166 for _ in 0..cnt {
167 let ibuf = cur.take_arr::<NBYTES>()?;
168 list.push(<$ity>::from_be_bytes(ibuf));
169 }
170
171 Ok(list)
172 }
173
174 fn fill_buf(&self, buf: &mut Vec<u8>) -> Result<(), CodecError> {
175 for i in self {
176 buf.extend_from_slice(&i.to_be_bytes());
177 }
178 Ok(())
179 }
180 }
181 };
182}
183
184decl_intvec_codec!(i8);
185decl_intvec_codec!(i16);
186decl_intvec_codec!(i32);
187decl_intvec_codec!(i64);
188decl_intvec_codec!(u16);
189decl_intvec_codec!(u32);
190decl_intvec_codec!(u64);
191
192#[cfg(test)]
193mod tests {
194 use crate::*;
195
196 #[test]
197 fn test_tuple_3() {
198 type Tup = (String, String, Vec<u8>);
199 let val: Tup = ("foo".to_string(), "bar".to_string(), vec![2, 5, 7, 10, 12]);
200
201 let buf = encode_to_vec(&val).expect("test: encode");
202 eprintln!("val {val:?}, buf {buf:?}");
203 let dec = <Tup as RpcCodec>::from_slice(&buf).expect("test: decode");
204
205 assert_eq!(dec, val);
206 }
207
208 #[test]
209 fn test_int_arr() {
210 let v: Vec<i16> = vec![5, 10, 15, -1, -2];
211 let buf = encode_to_vec(&v).expect("test: encode");
212 assert_eq!(buf.as_slice(), &[0, 5, 0, 10, 0, 15, 255, 255, 255, 254]);
213 let res = <Vec<i16> as RpcCodec>::from_slice(&buf).expect("test: decode");
214 assert_eq!(res, v);
215 }
216
217 #[test]
218 fn test_int_arr_fail() {
219 let raw_buf = &[0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3];
220 let res = <Vec<u64> as RpcCodec>::from_slice(raw_buf);
221 eprintln!("result {res:?}");
222 if !matches!(res, Err(CodecError::LeftoverBytes(_, _))) {
223 panic!("not expected result");
224 }
225 }
226
227 #[test]
228 fn test_string_invalid() {
229 let buf = vec![0xff];
232 let res = <String as RpcCodec>::from_slice(&buf);
233 eprintln!("result {res:?}");
234 if !matches!(res, Err(CodecError::NonUtf8String)) {
235 panic!("not expected result");
236 }
237 }
238}