Crate apdu_derive

source ·
Expand description

Implementation of procedural macro for apdu crate. By deriving apdu_derive::Response, you can convert from APDU raw response to an Enum easily. Macro interface is inspired by thiserror crate.

Examples

Here is a simple example to derive Response:

#[derive(apdu_derive::Response)]
enum Response<'a> {
    #[apdu(0x90, 0x00)]
    Ok(&'a [u8]),

    #[apdu(0x60..=0x69, _)]
    #[apdu(0x12, 0x34)]
    NotOk,

    #[apdu(_, _)]
    Unknown(u8, u8),
}

This is equivalent to implementing this:

enum Response<'a> {
    Ok(&'a [u8]),
    NotOk,
    Unknown(u8, u8),
}

impl<'a> From<apdu_core::Response<'a>> for Response<'a> {
    fn from(response: apdu_core::Response<'a>) -> Self {
        match response.trailer {
            (0x90, 0x00) => Self::Ok(response.payload),
            (0x60..=0x69, _) => Self::NotOk,
            (_, _) => Self::Unknown(response.trailer.0, response.trailer.1),
        }
    }
}

Also you can combine them with thiserror derive:

#[derive(Debug, apdu_derive::Response, thiserror::Error)]
enum Response {
    #[apdu(0x60..=0x69, _)]
    #[error("not ok!")]
    NotOk,

    #[apdu(_, _)]
    #[error("unknown: {0:#X} {1:#X}")]
    Unknown(u8, u8),
}

Optionally you can select what to inject to the fields:

#[derive(Debug, apdu_derive::Response, thiserror::Error)]
enum Response {
    #[apdu(0x63, 0xC0..=0xCF)]
    #[error("verify failed: {0} tries left")]
    VerifyFailed(#[sw2] #[mask(0x0F)] u8),

    #[apdu(_, _)]
    #[error("unknown: {0:#X} {1:#X}")]
    Unknown(u8, u8),
}

Derive Macros