use super::{
super::apdu::ApduTag,
Resource,
ResourceContext,
ResourceId,
};
use crate::error::{
Error,
Result,
};
pub struct ResourceManager {
profile: Vec<u8>,
}
impl ResourceManager {
pub fn new(host_profile: &[ResourceId]) -> Self {
let mut profile = Vec::with_capacity(host_profile.len() * 4);
for resource_id in host_profile {
let raw = resource_id.raw();
profile.push((raw >> 24) as u8);
profile.push((raw >> 16) as u8);
profile.push((raw >> 8) as u8);
profile.push(raw as u8);
}
ResourceManager { profile }
}
}
impl Resource for ResourceManager {
fn resource_id(&self) -> ResourceId {
ResourceId::RESOURCE_MANAGER
}
fn on_open(&mut self, ctx: &mut ResourceContext<'_>) -> Result<()> {
ctx.send_apdu(ApduTag::PROFILE_ENQ, &[])
}
fn on_apdu(&mut self, ctx: &mut ResourceContext<'_>, tag: ApduTag, _body: &[u8]) -> Result<()> {
match tag {
ApduTag::PROFILE => ctx.send_apdu(ApduTag::PROFILE_CHANGE, &[]),
ApduTag::PROFILE_ENQ => ctx.send_apdu(ApduTag::PROFILE, &self.profile),
ApduTag::PROFILE_CHANGE => ctx.send_apdu(ApduTag::PROFILE_ENQ, &[]),
tag => Err(Error::InvalidData(format!(
"ca slot {}: unexpected resource manager apdu tag {:?}",
ctx.slot_id, tag
))),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_profile_coding() {
let rm = ResourceManager::new(&[ResourceId::RESOURCE_MANAGER, ResourceId::MMI]);
assert_eq!(
rm.profile,
vec![0x00, 0x01, 0x00, 0x41, 0x00, 0x40, 0x00, 0x41]
);
}
}