use iso7816::Status;
use core::ops::{Deref, DerefMut};
#[derive(Debug)]
pub struct Reply<'v>(pub &'v mut heapless::VecView<u8>);
impl<'v> Deref for Reply<'v> {
type Target = &'v mut heapless::VecView<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Reply<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl Reply<'_> {
pub fn expand(&mut self, data: &[u8]) -> Result<(), Status> {
self.0.extend_from_slice(data).map_err(|_| {
error!("Buffer full");
Status::NotEnoughMemory
})
}
fn serialize_len(len: usize) -> Result<heapless::Vec<u8, 3>, Status> {
let mut buf = heapless::Vec::new();
if let Ok(len) = u8::try_from(len) {
if len <= 0x7f {
buf.extend_from_slice(&[len]).ok();
} else {
buf.extend_from_slice(&[0x81, len]).ok();
}
} else if let Ok(len) = u16::try_from(len) {
let arr = len.to_be_bytes();
buf.extend_from_slice(&[0x82, arr[0], arr[1]]).ok();
} else {
error!("Length too long to be encoded");
return Err(Status::UnspecifiedNonpersistentExecutionError);
}
Ok(buf)
}
pub fn prepend_len(&mut self, offset: usize) -> Result<(), Status> {
if self.len() < offset {
error!("`prepend_len` called with offset lower than buffer length");
return Err(Status::UnspecifiedNonpersistentExecutionError);
}
let len = self.len() - offset;
let encoded = Self::serialize_len(len)?;
self.extend_from_slice(&encoded).map_err(|_| {
error!("Buffer full");
Status::UnspecifiedNonpersistentExecutionError
})?;
self[offset..].rotate_right(encoded.len());
Ok(())
}
pub fn append_len(&mut self, len: usize) -> Result<(), Status> {
let encoded = Self::serialize_len(len)?;
self.extend_from_slice(&encoded).map_err(|_| {
error!("Buffer full");
Status::UnspecifiedNonpersistentExecutionError
})
}
pub fn lend(&mut self) -> Reply<'_> {
Reply(self.0)
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used, clippy::expect_used)]
use super::*;
#[test]
fn prep_length() {
let mut tmp = heapless::Vec::<u8, 1000>::new();
let mut buf = Reply(&mut tmp);
let offset = buf.len();
buf.extend_from_slice(&[0; 0]).unwrap();
buf.prepend_len(offset).unwrap();
assert_eq!(&buf[offset..], [0]);
let offset = buf.len();
buf.extend_from_slice(&[0; 20]).unwrap();
buf.prepend_len(offset).unwrap();
let mut expected = vec![20];
expected.extend_from_slice(&[0; 20]);
assert_eq!(&buf[offset..], expected,);
let offset = buf.len();
buf.extend_from_slice(&[1; 127]).unwrap();
buf.prepend_len(offset).unwrap();
let mut expected = vec![127];
expected.extend_from_slice(&[1; 127]);
assert_eq!(&buf[offset..], expected);
let offset = buf.len();
buf.extend_from_slice(&[2; 128]).unwrap();
buf.prepend_len(offset).unwrap();
let mut expected = vec![0x81, 128];
expected.extend_from_slice(&[2; 128]);
assert_eq!(&buf[offset..], expected);
let offset = buf.len();
buf.extend_from_slice(&[3; 256]).unwrap();
buf.prepend_len(offset).unwrap();
let mut expected = vec![0x82, 0x01, 0x00];
expected.extend_from_slice(&[3; 256]);
assert_eq!(&buf[offset..], expected);
}
}