use super::{Authenticated, AuthenticationState, Card, CardIoDefault, Unauthenticated, command};
use crate::{ApplicationId, Error, Instruction, KeyCount, KeySettings, StatusCode, io};
impl<'card, IoBackendT, AuthenticationStateT> Card<'card, IoBackendT, AuthenticationStateT>
where
AuthenticationStateT: AuthenticationState,
IoBackendT: io::Backend,
Self: CardIoDefault<IoBackendT>,
{
pub async fn list_applications<'a>(
&mut self,
out: &'a mut [u8],
) -> Result<&'a [ApplicationId], Error<IoBackendT::Error>> {
let (status_code, response) = self
.default_exchange(out, &[Instruction::GetApplicationIdList as u8])
.await?;
if status_code != StatusCode::Ack {
return Err(Error::BadStatusCode);
}
let (application_ids, &[]) = response.as_chunks::<3>() else {
return Err(Error::BadSize);
};
Ok(application_ids)
}
}
impl<'card, IoBackendT> Card<'card, IoBackendT, Authenticated>
where
IoBackendT: io::Backend,
{
pub async fn select_application<'a>(
self,
out: &'a mut [u8],
application_id: ApplicationId,
) -> Result<Card<'card, IoBackendT, Unauthenticated>, Error<IoBackendT::Error>> {
let card = self.to_unauthenticated();
card.select_application(out, application_id).await
}
pub async fn create_application(
&mut self,
out: &mut [u8],
application_id: ApplicationId,
key_settings: KeySettings,
key_number: KeyCount,
) -> Result<(), Error<IoBackendT::Error>> {
let (status_code, response) = command!(self, out, {
instruction: Instruction = Instruction::CreateApplication,
application_id: ApplicationId = application_id,
key_settings: u8 = key_settings.as_u8()?,
key_number: u8 = key_number.as_u8()?
}, []);
if !response.is_empty() {
return Err(Error::BadSize);
};
if status_code != StatusCode::Ack {
return Err(Error::BadStatusCode);
}
Ok(())
}
pub async fn delete_application(
&mut self,
out: &mut [u8],
application_id: ApplicationId,
) -> Result<(), Error<IoBackendT::Error>> {
let (status_code, response) = command!(self, out, {
instruction: Instruction = Instruction::DeleteApplication,
application_id: ApplicationId = application_id
}, []);
if !response.is_empty() {
return Err(Error::BadSize);
};
if status_code != StatusCode::Ack {
return Err(Error::BadStatusCode);
}
Ok(())
}
}
impl<'card, IoBackendT> Card<'card, IoBackendT, Unauthenticated>
where
IoBackendT: io::Backend,
{
pub async fn select_application(
mut self,
out: &mut [u8],
application_id: ApplicationId,
) -> Result<Self, Error<IoBackendT::Error>> {
let (status_code, response) = command!((&mut self), out, {
instruction: Instruction = Instruction::SelectApplication,
application_id: ApplicationId = application_id
}, []);
if !response.is_empty() {
return Err(Error::BadSize);
};
if status_code != StatusCode::Ack {
return Err(Error::BadStatusCode);
}
Ok(self)
}
}