#[derive(Clone, Copy)]
pub enum Expect {
Empty,
Some,
Short(u8),
}
#[derive(Clone, Debug)]
pub(crate) struct Command {
cla: u8,
ins: u8,
p1: u8,
p2: u8,
data: Vec<u8>,
}
impl Command {
pub fn new(cla: u8, ins: u8, p1: u8, p2: u8, data: Vec<u8>) -> Self {
if data.len() > u16::MAX as usize {
panic!("'data' too big, must be <64 kbyte");
}
Command {
cla,
ins,
p1,
p2,
data,
}
}
pub(crate) fn ins(&self) -> u8 {
self.ins
}
pub(crate) fn p1(&self) -> u8 {
self.p1
}
pub(crate) fn p2(&self) -> u8 {
self.p2
}
pub(crate) fn data(&self) -> &[u8] {
&self.data
}
pub(crate) fn serialize(
&self,
ext_len: bool,
expect_response: Expect,
) -> Result<Vec<u8>, crate::Error> {
assert!(self.data.len() <= u16::MAX as usize);
let nc = self.data.len() as u16;
let mut buf = vec![self.cla, self.ins, self.p1, self.p2];
buf.extend(Self::make_lc(nc, ext_len)?);
buf.extend(&self.data);
buf.extend(Self::make_le(nc, ext_len, expect_response));
Ok(buf)
}
fn make_lc(len: u16, ext_len: bool) -> Result<Vec<u8>, crate::Error> {
if !ext_len && len > 0xff {
return Err(crate::Error::InternalError(format!(
"Command len = {len:x?}, but extended length is unsupported by backend"
)));
}
if len == 0 {
Ok(vec![])
} else if !ext_len {
Ok(vec![len as u8])
} else {
Ok(vec![0, (len >> 8) as u8, (len & 255) as u8])
}
}
fn make_le(nc: u16, ext_len: bool, expect_response: Expect) -> Vec<u8> {
match (ext_len, expect_response) {
(_, Expect::Empty) => {
vec![]
}
(false, Expect::Some) => {
vec![0]
}
(false, Expect::Short(size)) => {
vec![size]
}
(true, Expect::Some) => {
if nc == 0 {
vec![0, 0, 0]
} else {
vec![0, 0]
}
}
_ => {
unreachable!("This should not happen")
}
}
}
}