1#![no_std]
8#![allow(non_camel_case_types)]
9
10#[cfg(feature = "alloc")]
11extern crate alloc;
12
13use core::mem::MaybeUninit;
14
15use coap_message::{
16 error::RenderableOnMinimal, MessageOption as _, MinimalWritableMessage, MutableWritableMessage,
17 ReadableMessage,
18};
19
20#[allow(non_camel_case_types)]
22pub enum c_void {}
23
24struct Message<'a> {
25 data: MessageVariant<'a>,
26 payload_length: Option<usize>,
37}
38
39enum MessageVariant<'a> {
40 #[cfg(feature = "alloc")]
41 Heap(coap_message_implementations::heap::HeapMessage),
42 InMemory(&'a mut coap_message_implementations::inmemory_write::Message<'a>),
43 }
46
47impl<'a> Message<'a> {
48 unsafe fn from_ptr(ptr: oscore_msg_native_t) -> &'a mut Self {
49 unsafe { &mut *(ptr.0 as *mut Message<'a>) }
50 }
51}
52
53impl<'a> ReadableMessage for Message<'a> {
54 type Code = u8;
55 type MessageOption<'b>
56 = MessageOption<'b>
57 where
58 Self: 'b;
59 type OptionsIter<'b>
60 = OptionsIter<'b>
61 where
62 Self: 'b;
63 fn code(&self) -> u8 {
64 match &self.data {
65 #[cfg(feature = "alloc")]
66 MessageVariant::Heap(m) => m.code(),
67 MessageVariant::InMemory(m) => m.code(),
68 }
69 }
70 fn payload(&self) -> &[u8] {
71 panic!("This function is not used by the oscore_msg_native implementation");
73 }
74 fn options(&self) -> Self::OptionsIter<'_> {
75 match &self.data {
76 #[cfg(feature = "alloc")]
77 MessageVariant::Heap(m) => OptionsIter::Heap(m.options()),
78 MessageVariant::InMemory(m) => OptionsIter::InMemory(m.options()),
79 }
80 }
81}
82
83impl<'a> MinimalWritableMessage for Message<'a> {
84 type AddOptionError = oscore_msgerr_native_t;
87 type SetPayloadError = oscore_msgerr_native_t;
88 type UnionError = oscore_msgerr_native_t;
89
90 type Code = u8;
91 type OptionNumber = u16;
92
93 fn set_code(&mut self, code: u8) {
94 match &mut self.data {
95 #[cfg(feature = "alloc")]
96 MessageVariant::Heap(m) => m.set_code(code),
97 MessageVariant::InMemory(m) => m.set_code(code),
98 }
99 }
100 fn add_option(&mut self, option: u16, data: &[u8]) -> Result<(), oscore_msgerr_native_t> {
101 match &mut self.data {
102 #[cfg(feature = "alloc")]
103 MessageVariant::Heap(m) => map_internal_error(m.add_option(option, data)),
104 MessageVariant::InMemory(m) => map_internal_error(m.add_option(option, data)),
105 }
106 }
107 fn set_payload(&mut self, _: &[u8]) -> Result<(), oscore_msgerr_native_t> {
108 panic!("This function is not used by the oscore_msg_native implementation");
110 }
111}
112
113impl<'a> MutableWritableMessage for Message<'a> {
114 fn available_space(&self) -> usize {
115 match &self.data {
116 #[cfg(feature = "alloc")]
117 MessageVariant::Heap(m) => m.available_space(),
118 MessageVariant::InMemory(m) => m.available_space(),
119 }
120 }
121 fn payload_mut_with_len(&mut self, len: usize) -> Result<&mut [u8], oscore_msgerr_native_t> {
122 match &mut self.data {
123 #[cfg(feature = "alloc")]
124 MessageVariant::Heap(m) => map_internal_error(m.payload_mut_with_len(len)),
125 MessageVariant::InMemory(m) => map_internal_error(m.payload_mut_with_len(len)),
126 }
127 }
128 fn truncate(&mut self, len: usize) -> Result<(), oscore_msgerr_native_t> {
129 self.payload_length = Some(len);
130
131 match &mut self.data {
132 #[cfg(feature = "alloc")]
133 MessageVariant::Heap(m) => map_internal_error(m.truncate(len)),
134 MessageVariant::InMemory(m) => map_internal_error(m.truncate(len)),
135 }
136 }
137 fn mutate_options<F: FnMut(u16, &mut [u8])>(&mut self, f: F) {
138 match &mut self.data {
139 #[cfg(feature = "alloc")]
140 MessageVariant::Heap(m) => m.mutate_options(f),
141 MessageVariant::InMemory(m) => m.mutate_options(f),
142 }
143 }
144}
145
146enum OptionsIter<'a> {
147 #[cfg(feature = "alloc")]
148 Heap(<coap_message_implementations::heap::HeapMessage as ReadableMessage>::OptionsIter<'a>),
149 InMemory(<coap_message_implementations::inmemory_write::Message<'a> as ReadableMessage>::OptionsIter<'a>),
150}
151
152impl<'a> core::iter::Iterator for OptionsIter<'a> {
153 type Item = MessageOption<'a>;
154
155 fn next(&mut self) -> Option<MessageOption<'a>> {
156 match self {
157 #[cfg(feature = "alloc")]
158 OptionsIter::Heap(i) => i.next().map(MessageOption::Heap),
159 OptionsIter::InMemory(i) => i.next().map(MessageOption::InMemory),
160 }
161 }
162}
163
164enum MessageOption<'a> {
165 #[cfg(feature = "alloc")]
166 Heap(<coap_message_implementations::heap::HeapMessage as ReadableMessage>::MessageOption<'a>),
167 InMemory(
168 <coap_message_implementations::inmemory_write::Message<'a> as ReadableMessage>::MessageOption<'a>,
169 ),
170}
171
172impl<'a> coap_message::MessageOption for MessageOption<'a> {
173 fn number(&self) -> u16 {
174 match self {
175 #[cfg(feature = "alloc")]
176 MessageOption::Heap(m) => m.number(),
177 MessageOption::InMemory(m) => m.number(),
178 }
179 }
180
181 fn value(&self) -> &[u8] {
182 match self {
183 #[cfg(feature = "alloc")]
184 MessageOption::Heap(m) => m.value(),
185 MessageOption::InMemory(m) => m.value(),
186 }
187 }
188}
189
190#[repr(C)]
206pub struct oscore_msg_native_t(*mut c_void);
207
208#[repr(C)]
209pub struct oscore_msg_native_optiter_t([u64; 12]);
210
211#[derive(Debug, PartialEq)]
218#[repr(u8)]
219pub enum oscore_msgerr_native_t {
220 ResultOk,
221 UpdateOptionWrongLength,
222 UpdateOptionNotFound,
223 InternalMessageError,
228}
229
230fn map_internal_error<T, E>(r: Result<T, E>) -> Result<T, oscore_msgerr_native_t> {
231 r.map_err(|_| oscore_msgerr_native_t::InternalMessageError)
232}
233
234impl RenderableOnMinimal for oscore_msgerr_native_t {
235 type Error<IE: RenderableOnMinimal + core::fmt::Debug> = IE;
236 fn render<M: MinimalWritableMessage>(
237 self,
238 msg: &mut M,
239 ) -> Result<(), Self::Error<M::UnionError>> {
240 use coap_message::Code;
241 msg.set_code(Code::new(coap_numbers::code::INTERNAL_SERVER_ERROR)?);
242 Ok(())
243 }
244}
245
246impl From<core::convert::Infallible> for oscore_msgerr_native_t {
247 fn from(other: core::convert::Infallible) -> Self {
248 match other {}
249 }
250}
251
252#[no_mangle]
253pub extern "C" fn oscore_msg_native_get_code(msg: oscore_msg_native_t) -> u8 {
254 unsafe { Message::from_ptr(msg) }.code()
255}
256
257#[no_mangle]
258pub extern "C" fn oscore_msg_native_set_code(msg: oscore_msg_native_t, code: u8) {
259 unsafe { Message::from_ptr(msg) }.set_code(code)
260}
261
262#[no_mangle]
263pub extern "C" fn oscore_msg_native_append_option(
264 msg: oscore_msg_native_t,
265 option_number: u16,
266 value: *const u8,
267 value_len: usize,
268) -> oscore_msgerr_native_t {
269 let value = unsafe { core::slice::from_raw_parts(value, value_len) };
270 match unsafe { Message::from_ptr(msg) }.add_option(option_number, value) {
271 Ok(()) => oscore_msgerr_native_t::ResultOk,
272 Err(e) => e,
273 }
274}
275
276#[no_mangle]
277pub extern "C" fn oscore_msg_native_update_option(
278 msg: oscore_msg_native_t,
279 option_number: u16,
280 option_occurrence: usize,
281 value: *const u8,
282 value_len: usize,
283) -> oscore_msgerr_native_t {
284 let msg = unsafe { Message::from_ptr(msg) };
285 let value = unsafe { core::slice::from_raw_parts(value, value_len) };
286
287 let mut result = oscore_msgerr_native_t::ResultOk;
288 let mut occurrence = Some(option_occurrence);
289 msg.mutate_options(|onum, oval| {
290 if onum == option_number {
291 occurrence = match occurrence {
292 Some(0) => {
293 if oval.len() == value.len() {
294 oval[..].copy_from_slice(value);
295 } else {
296 result = oscore_msgerr_native_t::UpdateOptionWrongLength;
297 }
298 None
299 }
300 Some(i) => Some(i - 1),
301 None => None,
302 }
303 }
304 });
305 if occurrence.is_some() {
306 result = oscore_msgerr_native_t::UpdateOptionNotFound;
307 }
308 result
309}
310
311#[no_mangle]
312pub extern "C" fn oscore_msg_native_optiter_init(
313 msg: oscore_msg_native_t,
314 iter: &mut MaybeUninit<oscore_msg_native_optiter_t>,
315) {
316 let msg = unsafe { Message::from_ptr(msg) };
317 assert!(
318 core::mem::size_of::<oscore_msg_native_optiter_t>()
319 >= core::mem::size_of::<OptionsIter<'static>>(),
320 "OptionsIter doesn't fit in oscore_msg_native_optiter_t"
321 );
322 assert!(
323 core::mem::align_of::<oscore_msg_native_optiter_t>()
324 >= core::mem::align_of::<OptionsIter<'static>>(),
325 "oscore_msg_native_optiter_t is insufficiently aligned for OptionsIter"
326 );
327 let iter: &mut MaybeUninit<OptionsIter> = unsafe { core::mem::transmute(iter) };
328 iter.write(msg.options());
329}
330
331#[no_mangle]
332pub extern "C" fn oscore_msg_native_map_payload(
333 msg: oscore_msg_native_t,
334 payload: &mut *mut u8,
335 payload_len: &mut usize,
336) -> oscore_msgerr_native_t {
337 let msg = unsafe { Message::from_ptr(msg) };
338 if let Some(len) = msg.payload_length {
339 *payload_len = len;
340 } else {
341 let original_space = msg.available_space();
342 let available_space = original_space.clamp(0, 4097);
345 *payload_len = available_space.saturating_sub(1);
346 }
347 match msg.payload_mut_with_len(*payload_len) {
348 Ok(result) => {
349 *payload = result.as_mut_ptr();
350 oscore_msgerr_native_t::ResultOk
351 }
352 Err(e) => e,
353 }
354}
355
356#[no_mangle]
357pub extern "C" fn oscore_msgerr_native_is_error(msgerr: oscore_msgerr_native_t) -> bool {
358 msgerr != oscore_msgerr_native_t::ResultOk
359}
360
361#[no_mangle]
362pub extern "C" fn oscore_msg_native_trim_payload(
363 msg: oscore_msg_native_t,
364 payload_len: usize,
365) -> oscore_msgerr_native_t {
366 match unsafe { Message::from_ptr(msg) }.truncate(payload_len) {
367 Ok(()) => oscore_msgerr_native_t::ResultOk,
368 Err(e) => e,
369 }
370}
371
372#[no_mangle]
373pub extern "C" fn oscore_msg_native_optiter_next(
374 _: oscore_msg_native_t,
375 iter: &mut oscore_msg_native_optiter_t,
376 option_number: &mut u16,
377 value: &mut *const u8,
378 value_len: &mut usize,
379) -> bool {
380 let iter: &mut OptionsIter = unsafe { core::mem::transmute(iter) };
381 if let Some(o) = iter.next() {
382 *option_number = o.number();
383 let value_slice = o.value();
384 *value = value_slice.as_ptr();
385 *value_len = value_slice.len();
386 true
387 } else {
388 false
389 }
390}
391
392#[no_mangle]
393pub extern "C" fn oscore_msg_native_optiter_finish(
394 _: oscore_msg_native_t,
395 iter: &mut MaybeUninit<oscore_msg_native_optiter_t>,
396) -> oscore_msgerr_native_t {
397 let iter: &mut MaybeUninit<OptionsIter> = unsafe { core::mem::transmute(iter) };
398 unsafe { iter.assume_init_drop() };
399 oscore_msgerr_native_t::ResultOk
403}
404
405#[cfg(feature = "alloc")]
406#[no_mangle]
407pub extern "C" fn oscore_test_msg_create() -> oscore_msg_native_t {
408 let msg = alloc::boxed::Box::new(Message {
409 data: MessageVariant::Heap(coap_message_implementations::heap::HeapMessage::new()),
410 payload_length: None,
411 });
412
413 oscore_msg_native_t(alloc::boxed::Box::into_raw(msg) as *mut _)
414}
415
416#[cfg(feature = "alloc")]
417#[no_mangle]
418pub extern "C" fn oscore_test_msg_destroy(msg: oscore_msg_native_t) {
419 let boxed = unsafe { alloc::boxed::Box::from_raw(msg.0) };
420 drop(boxed);
421}
422
423#[cfg(feature = "alloc")]
429pub fn with_heapmessage_as_msg_native<F, R>(
432 msg: coap_message_implementations::heap::HeapMessage,
433 f: F,
434) -> R
435where
436 F: FnOnce(oscore_msg_native_t) -> R,
437{
438 let payload_len = msg.payload().len();
440 let mut wrapped_message = Message {
441 data: MessageVariant::Heap(msg),
442 payload_length: Some(payload_len),
443 };
444 f(oscore_msg_native_t(
445 &mut wrapped_message as *mut _ as *mut _,
446 ))
447}
448
449pub fn with_inmemory_as_msg_native<'a, 'b: 'a, F, R>(
453 msg: &'a mut coap_message_implementations::inmemory_write::Message<'b>,
454 f: F,
455) -> R
456where
457 F: FnOnce(oscore_msg_native_t) -> R,
458{
459 let msg: &'a mut coap_message_implementations::inmemory_write::Message<'a> =
463 unsafe { core::mem::transmute(msg) };
464
465 let read_payload_len = msg.payload().len();
473 let mut wrapped_message = Message {
474 data: MessageVariant::InMemory(msg),
475 payload_length: if read_payload_len == 0 {
476 None
479 } else {
480 Some(read_payload_len)
481 },
482 };
483 f(oscore_msg_native_t(
484 &mut wrapped_message as *mut _ as *mut _,
485 ))
486}
487
488pub trait WithMsgNative: sealed::Sealed {
490 fn with_msg_native<F: FnOnce(oscore_msg_native_t) -> R, R>(self, f: F) -> R;
491}
492
493impl<'a, 'b> WithMsgNative for &'a mut coap_message_implementations::inmemory_write::Message<'b> {
494 fn with_msg_native<F: FnOnce(oscore_msg_native_t) -> R, R>(self, f: F) -> R {
495 with_inmemory_as_msg_native(self, f)
496 }
497}
498#[cfg(feature = "alloc")]
499impl WithMsgNative for coap_message_implementations::heap::HeapMessage {
500 fn with_msg_native<F: FnOnce(oscore_msg_native_t) -> R, R>(self, f: F) -> R {
501 with_heapmessage_as_msg_native(self, f)
502 }
503}
504
505mod sealed {
506 pub trait Sealed {}
507
508 impl<'a, 'b> Sealed for &'a mut coap_message_implementations::inmemory_write::Message<'b> {}
509 #[cfg(feature = "alloc")]
510 impl Sealed for coap_message_implementations::heap::HeapMessage {}
511}