extern crate alloc;
use alloc::{vec, vec::Vec};
use core::convert::Infallible;
use coap_message::{
MinimalWritableMessage, MutableWritableMessage, ReadableMessage, SeekWritableMessage,
WithSortedOptions,
};
#[derive(Debug, Clone)]
pub struct HeapMessage {
code: u8,
options: alloc::collections::BTreeMap<u16, Vec<Vec<u8>>>,
payload: Vec<u8>,
}
impl Default for HeapMessage {
fn default() -> Self {
Self::new()
}
}
impl HeapMessage {
pub fn new() -> Self {
Self {
code: 0,
options: alloc::collections::BTreeMap::new(),
payload: vec![],
}
}
pub fn change_option(&mut self, optnum: u16, occurrence: usize, value: impl Into<Vec<u8>>) {
self.options.get_mut(&optnum).unwrap()[occurrence] = value.into();
}
pub fn remove_option(&mut self, optnum: u16, occurrence: usize) {
let vec = self.options.get_mut(&optnum).unwrap();
vec.remove(occurrence);
if vec.is_empty() {
self.options.remove(&optnum);
}
}
}
impl MinimalWritableMessage for HeapMessage {
type AddOptionError = Infallible;
type SetPayloadError = Infallible;
type UnionError = Infallible;
type Code = u8;
type OptionNumber = u16;
fn set_code(&mut self, code: u8) {
self.code = code;
}
fn add_option(&mut self, optnum: u16, data: &[u8]) -> Result<(), Infallible> {
self.options.entry(optnum).or_default().push(data.to_vec());
Ok(())
}
fn set_payload(&mut self, payload: &[u8]) -> Result<(), Infallible> {
self.payload = payload.to_vec();
Ok(())
}
}
impl MutableWritableMessage for HeapMessage {
fn available_space(&self) -> usize {
usize::MAX
}
fn payload_mut_with_len(&mut self, len: usize) -> Result<&mut [u8], Infallible> {
self.payload.resize(len, 0);
Ok(&mut self.payload)
}
fn truncate(&mut self, len: usize) -> Result<(), Infallible> {
self.payload.truncate(len);
Ok(())
}
fn mutate_options<F>(&mut self, mut callback: F)
where
F: FnMut(Self::OptionNumber, &mut [u8]),
{
for (&number, ref mut values) in self.options.iter_mut() {
for v in values.iter_mut() {
callback(number, v);
}
}
}
}
impl SeekWritableMessage for HeapMessage {}
pub struct MessageOption<'a> {
number: u16,
value: &'a [u8],
}
impl coap_message::MessageOption for MessageOption<'_> {
fn number(&self) -> u16 {
self.number
}
fn value(&self) -> &[u8] {
self.value
}
}
pub struct ReadCursor<'a> {
iter: alloc::collections::btree_map::Iter<'a, u16, Vec<Vec<u8>>>,
popped: (u16, &'a [Vec<u8>]),
}
impl<'a> Iterator for ReadCursor<'a> {
type Item = MessageOption<'a>;
fn next(&mut self) -> Option<MessageOption<'a>> {
if self.popped.1.is_empty() {
self.popped = self.iter.next().map(|(k, v)| (*k, v.as_slice()))?;
debug_assert!(
!self.popped.1.is_empty(),
"HeapMessage had present but empty option"
);
}
let (first, rest) = self.popped.1.split_at(1);
self.popped.1 = rest;
Some(MessageOption {
number: self.popped.0,
value: first[0].as_slice(),
})
}
}
impl WithSortedOptions for HeapMessage {
}
impl ReadableMessage for HeapMessage {
type Code = u8;
type MessageOption<'a> = MessageOption<'a>;
type OptionsIter<'a> = ReadCursor<'a>;
fn code(&self) -> u8 {
self.code
}
fn payload(&self) -> &[u8] {
&self.payload
}
fn options(&self) -> ReadCursor<'_> {
ReadCursor {
iter: self.options.iter(),
popped: (0, &[]),
}
}
}