use crate::message::*;
extern crate alloc;
use alloc::{vec, vec::Vec};
#[derive(Debug)]
pub struct HeapMessage {
code: u8,
options: alloc::collections::BTreeMap<u16, Vec<Vec<u8>>>,
payload: Vec<u8>,
}
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.len() == 0 {
self.options.remove(&optnum);
}
}
pub fn add_option(&mut self, optnum: u16, data: &[u8]) {
self.options
.entry(optnum)
.or_insert(vec![])
.push(data.to_vec());
}
}
impl MinimalWritableMessage for HeapMessage {
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]) {
debug_assert!(
&optnum >= self.options.keys().max().unwrap_or(&0),
"Option appended out-of-order");
self.add_option(optnum, data);
}
fn set_payload(&mut self, payload: &[u8]) {
self.payload = payload.to_vec();
}
}
pub struct MessageOption<'a> {
number: u16,
value: &'a [u8],
}
impl<'a> crate::message::MessageOption for MessageOption<'a> {
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.len() == 0 {
self.popped = self.iter.next()
.map(|(k, v)| (*k, v.as_slice()))
?;
debug_assert!(self.popped.1.len() > 0, "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<'a> WithSortedOptions<'a> for HeapMessage {
}
impl<'m> ReadableMessage<'m> for HeapMessage {
type Code = u8;
type MessageOption = MessageOption<'m>;
type OptionsIter = ReadCursor<'m>;
fn code(&self) -> u8 { self.code }
fn payload(&self) -> &[u8] { &self.payload }
fn options(&'m self) -> ReadCursor<'m> {
ReadCursor { iter: self.options.iter(), popped: (0, &[]) }
}
}