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();
}
}
impl MutableWritableMessage for HeapMessage {
fn available_space(&self) -> usize {
core::usize::MAX
}
fn payload_mut(&mut self) -> &mut [u8] {
&mut self.payload
}
fn payload_mut_with_len(&mut self, len: usize) -> &mut [u8] {
self.payload.resize(len, 0);
&mut self.payload
}
fn truncate(&mut self, len: usize) {
self.payload.truncate(len)
}
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.into(), v);
}
}
}
}
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 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<'m>(&'m self) -> ReadCursor<'m> {
ReadCursor {
iter: self.options.iter(),
popped: (0, &[]),
}
}
}