coap_message_demos/
cbor.rs1use coap_handler::{Attribute, Handler, Reporting};
4use coap_handler_implementations::{
5 DeleteRenderable, FetchRenderable, GetRenderable, HandlerBuilder, IPatchRenderable,
6 PostRenderable, PutRenderable, ReportingHandlerBuilder, TypeHandler, TypeRenderable,
7 new_dispatcher, with_get_put_fetch,
8};
9use coap_message_utils::Error;
10use core::default::Default;
11use heapless::{String, Vec};
12
13#[derive(minicbor::Decode, minicbor::Encode, Clone)]
20#[cbor(map)]
21pub struct MyCBOR {
22 #[n(0)]
23 hidden: bool,
24 #[n(1)]
25 number: usize,
26 #[cbor(n(2), with = "minicbor_adapters")]
27 label: String<32>,
28 #[cbor(n(3), with = "minicbor_adapters")]
29 list: Vec<usize, 16>,
30}
31
32impl Default for MyCBOR {
33 fn default() -> Self {
34 Self {
35 hidden: false,
36 number: 32,
37 label: "Hello".try_into().unwrap(),
38 list: Vec::from_slice(&[1, 2, 3]).expect("More than 3 entries allocated"),
39 }
40 }
41}
42
43impl GetRenderable for MyCBOR {
44 type Get = MyCBOR;
45
46 fn get(&mut self) -> Result<MyCBOR, Error> {
47 if self.hidden {
48 return Err(Error::forbidden());
49 }
50 Ok(self.clone())
51 }
52}
53
54impl PutRenderable for MyCBOR {
55 fn put(&mut self, new: &MyCBOR) -> Result<(), Error> {
56 if new.label.contains('<') {
57 return Err(Error::bad_request());
59 }
60 *self = new.clone();
61 Ok(())
62 }
63 type Put = MyCBOR;
64}
65
66pub struct MyCborView {
72 index: u8,
73 data: MyCBOR,
79}
80
81impl<C> minicbor::encode::Encode<C> for MyCborView {
82 fn encode<W: minicbor::encode::Write>(
83 &self,
84 e: &mut minicbor::Encoder<W>,
85 _ctx: &mut C,
86 ) -> Result<(), minicbor::encode::Error<W::Error>> {
87 match self.index {
88 0 => e.encode(self.data.hidden),
89 1 => e.encode(self.data.number),
90 2 => e.encode(self.data.label.as_str()),
91 3 => e.encode(self.data.list.as_slice()),
92 _ => e.encode(()),
93 }?;
94 Ok(())
95 }
96}
97
98impl FetchRenderable for MyCBOR {
99 type FetchIn = u8;
100 type FetchOut = MyCborView;
101
102 fn fetch(&mut self, index: &Self::FetchIn) -> Result<Self::FetchOut, Error> {
103 let data = self.clone();
104 if data.hidden && *index >= 2 {
105 return Err(Error::forbidden());
108 }
109 Ok(MyCborView {
110 index: *index,
111 data,
112 })
113 }
114}
115
116pub fn single_cbor_tree() -> impl Handler + Reporting {
122 let cbor: MyCBOR = Default::default();
123
124 new_dispatcher()
125 .at_with_attributes(
126 &["cbor"],
127 &[Attribute::Ct(60)],
128 TypeHandler::new_minicbor_2(with_get_put_fetch(cbor)),
129 )
130 .with_wkc()
131}
132
133#[cfg(feature = "std")]
139pub fn double_cbor_with_access() -> (
140 impl Handler + Reporting,
141 std::sync::Arc<std::sync::Mutex<MyCBOR>>,
142) {
143 let cbor: std::sync::Arc<std::sync::Mutex<MyCBOR>> = Default::default();
144
145 let handler = new_dispatcher()
146 .at_with_attributes(
147 &["cbor", "1"],
148 &[],
149 TypeHandler::new_minicbor_2(with_get_put_fetch(TryingThroughMutex(cbor.clone()))),
150 )
151 .at_with_attributes(
152 &["cbor", "2"],
153 &[],
154 TypeHandler::new_minicbor_2(with_get_put_fetch(TryingThroughMutex(cbor.clone()))),
155 )
156 .with_wkc();
157
158 (handler, cbor)
159}
160
161#[cfg(feature = "std")]
176pub struct TryingThroughMutex<T>(pub std::sync::Arc<std::sync::Mutex<T>>);
177
178#[cfg(feature = "std")]
179impl<T: TypeRenderable> TypeRenderable for TryingThroughMutex<T> {}
180
181#[cfg(feature = "std")]
182impl<T: GetRenderable> GetRenderable for TryingThroughMutex<T> {
183 type Get = T::Get;
184
185 fn get(&mut self) -> Result<Self::Get, Error> {
186 self.0
187 .try_lock()
188 .map_err(|_| Error::service_unavailable())?
189 .get()
190 }
191}
192
193#[cfg(feature = "std")]
194impl<T: PutRenderable> PutRenderable for TryingThroughMutex<T> {
195 type Put = T::Put;
196
197 fn put(&mut self, new: &Self::Put) -> Result<(), Error> {
198 self.0
199 .try_lock()
200 .map(|mut s| s.put(new))
201 .unwrap_or(Err(Error::service_unavailable()))
202 }
203}
204
205#[cfg(feature = "std")]
206impl<T: PostRenderable> PostRenderable for TryingThroughMutex<T> {
207 type PostIn = T::PostIn;
208 type PostOut = T::PostOut;
209
210 fn post(&mut self, request: &Self::PostIn) -> Result<Self::PostOut, Error> {
211 self.0
212 .try_lock()
213 .map(|mut s| s.post(request))
214 .unwrap_or(Err(Error::service_unavailable()))
215 }
216}
217
218#[cfg(feature = "std")]
219impl<T: DeleteRenderable> DeleteRenderable for TryingThroughMutex<T> {}
220
221#[cfg(feature = "std")]
222impl<T: FetchRenderable> FetchRenderable for TryingThroughMutex<T> {
223 type FetchIn = T::FetchIn;
224 type FetchOut = T::FetchOut;
225
226 fn fetch(&mut self, request: &Self::FetchIn) -> Result<Self::FetchOut, Error> {
227 self.0
228 .try_lock()
229 .map(|mut s| s.fetch(request))
230 .unwrap_or(Err(Error::service_unavailable()))
231 }
232}
233
234#[cfg(feature = "std")]
235impl<T: IPatchRenderable> IPatchRenderable for TryingThroughMutex<T> {
236 type IPatch = T::IPatch;
237
238 fn ipatch(&mut self, new: &Self::IPatch) -> Result<(), Error> {
239 self.0
240 .try_lock()
241 .map(|mut s| s.ipatch(new))
242 .unwrap_or(Err(Error::service_unavailable()))
243 }
244}