mod serializer;
mod storage;
pub use self::storage::{Slice, Storage};
#[cfg(feature = "heapless")]
pub use self::storage::HVec;
use self::serializer::Serializer;
use crate::{
command::{Command, Write},
Result, CRC, HEADER,
};
use core::marker::PhantomData;
use serde::Serialize;
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Request<C, S: Storage> {
serializer: Serializer<S>,
cmd: PhantomData<C>,
}
impl<'a, C> Request<C, Slice<'a>> {
pub fn with_slice(buf: &'a mut [u8], cmd: impl Command) -> Result<Self> {
Self::new(Slice::new(buf), cmd)
}
}
#[cfg(feature = "heapless")]
impl<C, const N: usize> Request<C, HVec<N>> {
pub fn with_hvec(cmd: impl Command) -> Result<Self> {
Self::new(HVec::new(), cmd)
}
}
impl<S, O> Request<Write, S>
where
S: Storage<Output = O>,
{
pub fn push<T: Serialize>(&mut self, value: &T) -> Result<()> {
value.serialize(&mut self.serializer)
}
}
impl<RW, S, O> Request<RW, S>
where
S: Storage<Output = O>,
{
pub fn new<C: Command>(output: S, cmd: C) -> Result<Self> {
let mut serializer = Serializer { output };
HEADER.serialize(&mut serializer)?;
0u8.serialize(&mut serializer)?;
C::CMD.serialize(&mut serializer)?;
cmd.serialize(&mut serializer)?;
Ok(Self {
serializer,
cmd: PhantomData,
})
}
pub fn finalize(mut self, crc: bool) -> Result<O> {
if crc {
let crc = CRC.checksum(&self.serializer.output[3..]).swap_bytes();
crc.serialize(&mut self.serializer)?;
}
self.serializer.output[2] = self.serializer.output.len() as u8 - 3;
Ok(self.serializer.output.finalize())
}
}
#[cfg(feature = "heapless")]
#[cfg(test)]
mod tests {
use super::*;
use crate::command::{Word, Write};
use heapless::Vec;
#[derive(Serialize)]
struct TestTuple(u16, u16);
impl TestTuple {
fn new() -> Self {
Self(0x5A00, 0x1234)
}
}
#[test]
fn tuple_to_slice_crc() {
let buf = &mut [0u8; 20];
let expected = &[
0x5A, 0xA5, 9, 0x82, 0x00, 0xDE, 0x5A, 0x00, 0x12, 0x34, 0x0E, 0xB4,
];
let data = TestTuple::new();
let mut frame = Request::with_slice(
buf,
Word {
addr: 0x00DE,
cmd: Write,
},
)
.unwrap();
frame.push(&data).unwrap();
let output = frame.finalize(true).unwrap();
assert_eq!(output, expected);
}
#[test]
fn tuple_to_slice_nocrc() {
let buf = &mut [0u8; 20];
let expected = &[0x5A, 0xA5, 7, 0x82, 0x00, 0xDE, 0x5A, 0x00, 0x12, 0x34];
let data = TestTuple::new();
let mut frame = Request::with_slice(
buf,
Word {
addr: 0x00DE,
cmd: Write,
},
)
.unwrap();
frame.push(&data).unwrap();
let output = frame.finalize(false).unwrap();
assert_eq!(output, expected);
}
#[test]
fn tuple_to_hvec() {
let expected: Vec<u8, 12> = Vec::from_slice(&[
0x5A, 0xA5, 9, 0x82, 0x00, 0xDE, 0x5A, 0x00, 0x12, 0x34, 0x0E, 0xB4,
])
.unwrap();
let data = TestTuple::new();
let mut frame = Request::with_hvec(Word {
addr: 0x00DE,
cmd: Write,
})
.unwrap();
frame.push(&data).unwrap();
let output: Vec<u8, 12> = frame.finalize(true).unwrap();
assert_eq!(output, expected);
}
#[test]
fn tuple_to_hvec_nocrc() {
let expected: Vec<u8, 10> =
Vec::from_slice(&[0x5A, 0xA5, 7, 0x82, 0x00, 0xDE, 0x5A, 0x00, 0x12, 0x34]).unwrap();
let data = TestTuple::new();
let mut frame = Request::with_hvec(Word {
addr: 0x00DE,
cmd: Write,
})
.unwrap();
frame.push(&data).unwrap();
let output: Vec<u8, 10> = frame.finalize(false).unwrap();
assert_eq!(output, expected);
}
}