#[derive(Debug, Clone)]
pub struct CoAPWSMessageW {
data: Vec<u8>,
option_base: u16,
}
use coap_message_utils::option_extension::push_extensions;
impl CoAPWSMessageW {
pub fn new(token: &[u8]) -> Self {
assert!(token.len() <= 8);
let mut data = Vec::with_capacity(token.len() + 2);
data.push(token.len() as u8);
data.push(0); data.extend_from_slice(&token);
Self { data, option_base: 0 }
}
pub fn serialize(self) -> Vec<u8> {
self.data
}
}
impl coap_message::MinimalWritableMessage for CoAPWSMessageW {
type Code = u8;
type OptionNumber = u16;
fn set_code(&mut self, code: u8) {
self.data[1] = code;
}
fn add_option(&mut self, optnum: u16, value: &[u8]) {
assert!(value.len() <= u16::MAX.into());
let delta = optnum - self.option_base;
self.option_base = optnum;
let len = value.len() as u16;
let startindex = self.data.len();
self.data.push(0); self.data[startindex] += push_extensions(&mut self.data, delta) << 4;
self.data[startindex] += push_extensions(&mut self.data, len);
self.data.extend_from_slice(value);
}
fn set_payload(&mut self, payload: &[u8]) {
if payload.len() > 0 {
self.data.push(0xff);
self.data.extend_from_slice(payload);
}
}
}
#[derive(Debug, Clone)]
pub struct CoAPWSMessageR<B: AsRef<[u8]>> {
data: B,
}
use coap_message_utils::{inmemory::{MessageOption, OptionsIter}, option_iteration::{OptPayloadReader, OptItem}};
impl<B: AsRef<[u8]>> CoAPWSMessageR<B> {
pub fn new(data: B) -> Result<Self, &'static str> {
let len_tkl = *data.as_ref().get(0).ok_or("Zero message")?;
if len_tkl > 8 {
return Err("Invalid first byte");
}
let tkl = len_tkl;
if data.as_ref().len() < 2 + (tkl as usize) {
return Err("Message too short for token");
}
Ok(Self { data })
}
pub fn token(&self) -> &[u8] {
&self.data.as_ref()[2..2 + (self.data.as_ref()[0] as usize)]
}
fn options_and_payload(&self) -> &[u8] {
&self.data.as_ref()[(self.data.as_ref()[0] as usize) + 2..]
}
}
impl<'m, B> coap_message::ReadableMessage<'m> for CoAPWSMessageR<B>
where B: AsRef<[u8]> + 'm
{
type Code = u8;
type MessageOption = MessageOption<'m>;
type OptionsIter = OptionsIter<'m>;
fn code(&self) -> u8 {
self.data.as_ref()[1]
}
fn payload(&self) -> &[u8] {
let empty: &[u8] = &[];
let optpayload = self.options_and_payload();
OptPayloadReader::new(optpayload)
.filter(|x| !matches!(x, OptItem::Option { .. }))
.next()
.map(|x| if let OptItem::Payload(data) = x {
let offset = data.as_ptr() as usize - optpayload.as_ptr() as usize;
&optpayload[offset..]
} else { panic!("Error before payload") })
.unwrap_or(&empty)
}
fn options(&'m self) -> OptionsIter<'m> {
OptionsIter(OptPayloadReader::new(self.options_and_payload()))
}
}