apdu_core/
lib.rs

1//! Core library for composing APDU commands and parsing their responses.
2
3#![deny(missing_debug_implementations)]
4#![cfg_attr(not(feature = "std"), no_std)]
5
6mod command;
7mod error;
8mod response;
9
10pub use command::*;
11pub use error::*;
12pub use response::*;
13
14use core::fmt::{Debug, Display, Formatter};
15
16pub enum HandleError {
17    /// The buffer is too small to write the response.
18    /// Reallocate with the capacity and retry.
19    NotEnoughBuffer(usize),
20
21    /// Failed to communicate through physical NFC layer.
22    /// Hardware or OS API error?
23    Nfc(Box<dyn Display>),
24}
25
26impl HandleError {
27    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
28        use HandleError::*;
29        match self {
30            NotEnoughBuffer(size) => write!(
31                f,
32                "The buffer is too small to write the response. (needs {size} bytes)",
33            ),
34            Nfc(e) => e.fmt(f),
35        }
36    }
37}
38
39impl Debug for HandleError {
40    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
41        Self::fmt(self, f)
42    }
43}
44
45impl Display for HandleError {
46    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
47        Self::fmt(self, f)
48    }
49}
50
51#[cfg(feature = "std")]
52impl std::error::Error for HandleError {}
53
54pub type Result = std::result::Result<usize, HandleError>;
55
56/// An handler to handle an APDU command and receive a response in a specific context.
57pub trait HandlerInCtx<Ctx = ()> {
58    /// Handles the APDU command in a specific context.
59    /// Implementations must transmit the command to the card through a reader,
60    /// then receive the response from them, returning length of the data written.
61    fn handle_in_ctx(&self, ctx: Ctx, command: &[u8], response: &mut [u8]) -> Result;
62}
63
64/// An handler to handle an APDU command and receive a response
65pub trait Handler: HandlerInCtx<()> {
66    /// Handles the APDU command.
67    /// Implementations must transmit the command to the card through a reader,
68    /// then receive the response from them, returning length of the data written.
69    fn handle(&self, command: &[u8], response: &mut [u8]) -> Result {
70        self.handle_in_ctx((), command, response)
71    }
72}