1pub trait Action {
2 const ACTION: &'static str;
3
4 #[cfg(feature = "serde")]
8 fn to_json_slice<'buf>(
9 &self,
10 buf: &'buf mut [u8],
11 ) -> Result<&'buf [u8], serde_json_core::ser::Error>
12 where
13 Self: serde::Serialize,
14 {
15 let len = serde_json_core::to_slice(self, buf)?;
16 Ok(&buf[..len])
17 }
18
19 #[cfg(feature = "serde")]
22 fn to_json_str<'buf>(
23 &self,
24 buf: &'buf mut [u8],
25 ) -> Result<&'buf str, serde_json_core::ser::Error>
26 where
27 Self: serde::Serialize,
28 {
29 let bytes = self.to_json_slice(buf)?;
30 Ok(core::str::from_utf8(bytes).expect("serde-json-core always emits valid UTF-8"))
31 }
32
33 #[cfg(feature = "serde")]
37 fn from_json_slice(data: &[u8]) -> Result<Self, serde_json_core::de::Error>
38 where
39 Self: Sized + serde::de::DeserializeOwned,
40 {
41 serde_json_core::from_slice(data).map(|(value, _remainder)| value)
42 }
43
44 #[cfg(feature = "serde")]
48 fn from_json_str(data: &str) -> Result<Self, serde_json_core::de::Error>
49 where
50 Self: Sized + serde::de::DeserializeOwned,
51 {
52 serde_json_core::from_str(data).map(|(value, _remainder)| value)
53 }
54}
55
56#[cfg(all(test, feature = "serde"))]
57mod tests {
58 use super::*;
59
60 #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
61 struct SampleRequest {
62 #[serde(rename = "idTag")]
63 id_tag: heapless::String<20>,
64 }
65
66 impl Action for SampleRequest {
67 const ACTION: &'static str = "Sample";
68 }
69
70 fn sample() -> SampleRequest {
71 SampleRequest {
72 id_tag: heapless::String::try_from("ABC123").unwrap(),
73 }
74 }
75
76 #[test]
77 fn to_json_slice_writes_json_into_the_given_buffer() {
78 let mut buf = [0u8; 64];
79 let json = sample().to_json_slice(&mut buf).unwrap();
80
81 assert_eq!(json, br#"{"idTag":"ABC123"}"#);
82 }
83
84 #[test]
85 fn to_json_slice_errors_when_the_buffer_is_too_small() {
86 let mut buf = [0u8; 4];
87
88 assert!(sample().to_json_slice(&mut buf).is_err());
89 }
90
91 #[test]
92 fn to_json_str_writes_json_into_the_given_buffer_as_utf8() {
93 let mut buf = [0u8; 64];
94 let json = sample().to_json_str(&mut buf).unwrap();
95
96 assert_eq!(json, r#"{"idTag":"ABC123"}"#);
97 }
98
99 #[test]
100 fn from_json_slice_parses_bytes_back_into_the_struct() {
101 let parsed = SampleRequest::from_json_slice(br#"{"idTag":"ABC123"}"#).unwrap();
102
103 assert_eq!(parsed, sample());
104 }
105
106 #[test]
107 fn from_json_str_parses_a_str_back_into_the_struct() {
108 let parsed = SampleRequest::from_json_str(r#"{"idTag":"ABC123"}"#).unwrap();
109
110 assert_eq!(parsed, sample());
111 }
112
113 #[test]
114 fn round_trips_through_bytes() {
115 let mut buf = [0u8; 64];
116 let json = sample().to_json_slice(&mut buf).unwrap();
117 let parsed = SampleRequest::from_json_slice(json).unwrap();
118
119 assert_eq!(parsed, sample());
120 }
121}