1use serde::Serialize;
2use serde::de::DeserializeOwned;
3
4use crate::{Bytes, Result};
5use alloc::string::String;
6use myrmic_common::cells::Sri;
7
8pub trait Decoder: Sized {
14 fn from_args(length: usize) -> Result<Self> {
22 let mut bytes = alloc::vec![0u8; length];
23 let n = crate::get_arguments(&mut bytes).map_err(|_| "failed to read arguments")?;
24 bytes.truncate(n);
25 let absent = bytes.is_empty();
26
27 Self::from_bytes(bytes).map_err(|err| {
28 if absent {
29 "no payload was sent; declare the handler's payload as `Option<_>` \
30 to accept an invocation sent without one"
31 } else {
32 err
33 }
34 })
35 }
36
37 fn from_bytes(bytes: Bytes) -> Result<Self>;
39}
40
41pub trait Encoder {
46 fn to_bytes(&self) -> Result<Bytes>;
48}
49
50pub trait Codec {
73 fn encode<T: Serialize + ?Sized>(value: &T) -> Result<Bytes>;
75 fn decode<T: DeserializeOwned>(bytes: &[u8]) -> Result<T>;
77}
78
79pub struct Json;
81
82impl Codec for Json {
83 fn encode<T: Serialize + ?Sized>(value: &T) -> Result<Bytes> {
84 serde_json::to_vec(value).map_err(|_| "failed to serialize json")
85 }
86
87 fn decode<T: DeserializeOwned>(bytes: &[u8]) -> Result<T> {
88 serde_json::from_slice(bytes).map_err(|_| "failed to deserialize json")
89 }
90}
91
92pub struct Postcard;
94
95impl Codec for Postcard {
96 fn encode<T: Serialize + ?Sized>(value: &T) -> Result<Bytes> {
97 postcard::to_allocvec(value).map_err(|_| "failed to serialize postcard")
98 }
99
100 fn decode<T: DeserializeOwned>(bytes: &[u8]) -> Result<T> {
101 postcard::from_bytes(bytes).map_err(|_| "failed to deserialize postcard")
102 }
103}
104
105impl Decoder for Bytes {
108 fn from_bytes(bytes: Bytes) -> Result<Self> {
109 Ok(bytes)
110 }
111}
112
113impl Encoder for Bytes {
115 fn to_bytes(&self) -> Result<Bytes> {
116 Ok(self.clone())
117 }
118}
119
120impl Decoder for Sri {
121 fn from_bytes(bytes: Bytes) -> Result<Self> {
122 let (hi, lo): (i64, i64) = <Postcard as Codec>::decode(&bytes)?;
123 Ok(Sri::from_parts(hi, lo))
124 }
125}
126
127impl Encoder for Sri {
128 fn to_bytes(&self) -> Result<Bytes> {
129 let parts = self.to_parts();
130 <Postcard as Codec>::encode(&parts)
131 }
132}
133
134pub struct Void;
139
140impl Decoder for Void {
141 fn from_args(length: usize) -> Result<Self> {
142 if length == 0 {
143 Ok(Void)
144 } else {
145 Err("this handler does not accept a payload")
146 }
147 }
148
149 fn from_bytes(bytes: Bytes) -> Result<Self> {
150 if bytes.is_empty() {
151 Ok(Void)
152 } else {
153 Err("this handler does not accept a payload")
154 }
155 }
156}
157
158impl Encoder for Void {
159 fn to_bytes(&self) -> Result<Bytes> {
160 Ok(Bytes::new())
161 }
162}
163
164impl<T: Decoder> Decoder for Option<T> {
165 fn from_args(length: usize) -> Result<Self> {
166 if length == 0 {
167 Ok(None)
168 } else {
169 T::from_args(length).map(Some)
170 }
171 }
172
173 fn from_bytes(bytes: Bytes) -> Result<Self> {
174 if bytes.is_empty() {
175 Ok(None)
176 } else {
177 T::from_bytes(bytes).map(Some)
178 }
179 }
180}
181
182impl<T: Encoder> Encoder for Option<T> {
183 fn to_bytes(&self) -> Result<Bytes> {
184 match self {
185 Some(value) => T::to_bytes(value),
186 None => Ok(Bytes::new()),
187 }
188 }
189}
190
191macro_rules! json_scalar {
200 ($($ty:ty),* $(,)?) => {$(
201 impl Decoder for $ty {
202 fn from_bytes(bytes: Bytes) -> Result<Self> {
203 <Json as Codec>::decode(&bytes)
204 }
205 }
206
207 impl Encoder for $ty {
208 fn to_bytes(&self) -> Result<Bytes> {
209 <Json as Codec>::encode(self)
210 }
211 }
212 )*};
213}
214
215json_scalar!(String, bool, char, f32, f64);
218
219macro_rules! json_int {
227 ($($ty:ty),* $(,)?) => {$(
228 impl Decoder for $ty {
229 fn from_bytes(bytes: Bytes) -> Result<Self> {
230 if let Ok(value) = <Json as Codec>::decode::<$ty>(&bytes) {
231 return Ok(value);
232 }
233 let number: serde_json::Number = <Json as Codec>::decode(&bytes)?;
234 let f = number.as_f64().ok_or("expected a number")?;
235 if f as i128 as f64 == f && f >= <$ty>::MIN as f64 && f <= <$ty>::MAX as f64 {
239 Ok(f as $ty)
240 } else {
241 Err("number is not a whole value in range for the target type")
242 }
243 }
244 }
245
246 impl Encoder for $ty {
247 fn to_bytes(&self) -> Result<Bytes> {
248 <Json as Codec>::encode(self)
249 }
250 }
251 )*};
252}
253
254json_int!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128,);
255
256#[cfg(test)]
257mod tests {
258 use core::ffi::c_int;
259
260 use spin::Mutex;
261
262 use super::{Decoder, Encoder};
263 use crate::{Bytes, Callback, JsonValue, Result};
264 use alloc::string::String;
265 use alloc::vec::Vec;
266 use myrmic_common::cells::Command;
267
268 fn dec<T: Decoder>(bytes: &[u8]) -> Result<T> {
269 T::from_bytes(Bytes::from(bytes))
270 }
271
272 fn enc<T: Encoder>(value: &T) -> Vec<u8> {
273 value.to_bytes().unwrap()
274 }
275
276 fn enc_str<T: Encoder>(value: &T) -> String {
277 String::from_utf8(enc(value)).unwrap()
278 }
279
280 #[test]
281 fn integer_encodes_as_json_number() {
282 assert_eq!(enc_str(&42u32), "42");
283 }
284
285 #[test]
286 fn json_number_decodes_into_integer() {
287 assert_eq!(dec::<u32>(b"42").unwrap(), 42);
289 }
290
291 #[test]
292 fn integral_float_decodes_into_integer() {
293 assert_eq!(dec::<u32>(b"42.0").unwrap(), 42);
294 }
295
296 #[test]
297 fn fractional_number_rejected_for_integer() {
298 assert!(dec::<u32>(b"42.5").is_err());
299 }
300
301 #[test]
302 fn out_of_range_number_rejected_for_integer() {
303 assert!(dec::<u8>(b"300").is_err());
304 }
305
306 #[test]
307 fn signed_integer_round_trips() {
308 assert_eq!(dec::<i64>(&enc(&-5i64)).unwrap(), -5);
309 }
310
311 #[test]
312 fn max_u128_round_trips_exactly() {
313 let v = u128::MAX;
314 assert_eq!(dec::<u128>(&enc(&v)).unwrap(), v);
315 }
316
317 #[test]
318 fn float_decodes_from_any_json_number() {
319 assert_eq!(dec::<f64>(b"42").unwrap(), 42.0);
320 assert_eq!(dec::<f32>(b"1.5").unwrap(), 1.5);
321 }
322
323 #[test]
324 fn float_encodes_as_json_number() {
325 assert_eq!(enc_str(&1.5f64), "1.5");
326 }
327
328 #[test]
329 fn bool_round_trips_as_json() {
330 assert_eq!(enc_str(&true), "true");
331 assert!(dec::<bool>(b"true").unwrap());
332 }
333
334 #[test]
335 fn char_round_trips_as_json_string() {
336 assert_eq!(enc_str(&'a'), "\"a\"");
337 assert_eq!(dec::<char>(b"\"a\"").unwrap(), 'a');
338 }
339
340 #[test]
341 fn string_round_trips_as_json_string() {
342 assert_eq!(enc_str(&String::from("jsontest")), "\"jsontest\"");
344 assert_eq!(dec::<String>(b"\"jsontest\"").unwrap(), "jsontest");
345 }
346
347 #[test]
348 fn optional_callback_absorbs_only_the_empty_buffer() {
349 assert!(dec::<Option<Callback<JsonValue>>>(b"").unwrap().is_none());
351
352 let decoded = dec::<Option<Callback<JsonValue>>>(b"on_reply").unwrap();
353 assert_eq!(Command::from(decoded.unwrap()).as_ref(), "on_reply");
354
355 assert!(dec::<Option<Callback<JsonValue>>>(b"\"on_reply\"").is_err());
359
360 assert!(dec::<Callback<JsonValue>>(b"").is_err());
362 }
363
364 #[test]
365 fn zero_length_from_args_never_touches_the_inner_decoder() {
366 assert!(<Option<Probe>>::from_args(0).unwrap().is_none());
370 assert!(<Option<Probe>>::from_bytes(Bytes::new()).unwrap().is_none());
371 }
372
373 #[test]
374 fn an_absent_payload_is_reported_with_advice() {
375 assert_eq!(
379 from_args_with::<u32>(b"").unwrap_err(),
380 "no payload was sent; declare the handler's payload as `Option<_>` \
381 to accept an invocation sent without one"
382 );
383 assert_eq!(
384 from_args_with::<Callback<JsonValue>>(b"").unwrap_err(),
385 "no payload was sent; declare the handler's payload as `Option<_>` \
386 to accept an invocation sent without one"
387 );
388
389 assert!(from_args_with::<Option<u32>>(b"").unwrap().is_none());
391 assert_eq!(from_args_with::<Option<u32>>(b"42").unwrap(), Some(42));
392
393 assert_eq!(
396 from_args_with::<u32>(b"42.5").unwrap_err(),
397 "number is not a whole value in range for the target type"
398 );
399 assert_eq!(
400 from_args_with::<Callback<JsonValue>>(b"\"on_reply\"").unwrap_err(),
401 "name can only contain ASCII alphanumeric characters and underscores"
402 );
403 }
404
405 struct Probe;
407
408 impl Decoder for Probe {
409 fn from_args(_length: usize) -> Result<Self> {
410 panic!("a zero-length argument buffer was delegated to the inner decoder");
411 }
412
413 fn from_bytes(_bytes: Bytes) -> Result<Self> {
414 panic!("an empty byte buffer was delegated to the inner decoder");
415 }
416 }
417
418 fn from_args_with<T: Decoder>(payload: &[u8]) -> Result<T> {
421 *ARGUMENTS.lock() = payload.to_vec();
422
423 T::from_args(payload.len())
424 }
425
426 static ARGUMENTS: Mutex<Vec<u8>> = Mutex::new(Vec::new());
428
429 #[unsafe(no_mangle)]
432 extern "C" fn get_arguments(buffer: *mut u8, length: c_int) -> c_int {
433 let payload = ARGUMENTS.lock();
434 let n = payload.len().min(length as usize);
435 unsafe { core::ptr::copy_nonoverlapping(payload.as_ptr(), buffer, n) };
438
439 n as c_int
440 }
441}