use crate::ledger::comm::LedgerTransport;
use crate::errors::HWKeyError;
use crate::ledger::connect::{LedgerKey, direct::AppDetails};
use std::sync::{Arc, Mutex};
pub struct MockTransport {
pub call_count: std::cell::RefCell<usize>,
pub last_command: std::cell::RefCell<Option<u8>>,
pub last_p1: std::cell::RefCell<Option<u8>>,
pub response: Vec<u8>,
}
impl Default for MockTransport {
fn default() -> Self {
Self::new()
}
}
impl MockTransport {
pub fn new() -> Self {
MockTransport {
call_count: std::cell::RefCell::new(0),
last_command: std::cell::RefCell::new(None),
last_p1: std::cell::RefCell::new(None),
response: vec![0x90, 0x00], }
}
pub fn with_response(response: Vec<u8>) -> Self {
MockTransport {
call_count: std::cell::RefCell::new(0),
last_command: std::cell::RefCell::new(None),
last_p1: std::cell::RefCell::new(None),
response,
}
}
}
impl LedgerTransport for MockTransport {
fn write(&self, data: &[u8]) -> Result<usize, HWKeyError> {
*self.call_count.borrow_mut() += 1;
if data.len() >= 8 {
let apdu_start = 7;
if data.len() > apdu_start + 1 {
*self.last_command.borrow_mut() = Some(data[apdu_start + 1]);
*self.last_p1.borrow_mut() = Some(data[apdu_start + 2]);
}
}
Ok(data.len())
}
fn read(&self, buf: &mut [u8]) -> Result<usize, HWKeyError> {
let copy_len = std::cmp::min(buf.len(), self.response.len());
buf[..copy_len].copy_from_slice(&self.response[..copy_len]);
Ok(copy_len)
}
fn read_timeout(&self, buf: &mut [u8], _timeout_ms: i32) -> Result<usize, HWKeyError> {
self.read(buf)
}
}
pub struct MockLedgerKey {
pub connected: std::cell::RefCell<bool>,
pub error: Option<HWKeyError>,
}
impl MockLedgerKey {
pub fn new() -> Self {
Self {
connected: std::cell::RefCell::new(false),
error: None,
}
}
pub fn new_disconnected() -> Self {
Self {
connected: std::cell::RefCell::new(false),
error: Some(HWKeyError::Unavailable),
}
}
}
impl LedgerKey for MockLedgerKey {
type Transport = MockTransport;
fn create() -> Result<Self, HWKeyError> {
Ok(Self::new())
}
fn connect(&mut self) -> Result<(), HWKeyError> {
if let Some(err) = &self.error {
return Err(err.clone());
}
*self.connected.borrow_mut() = true;
Ok(())
}
fn get_app_details(&self) -> Result<AppDetails, HWKeyError> {
if !*self.connected.borrow() {
return Err(HWKeyError::Unavailable);
}
Ok(AppDetails::default())
}
fn open_exclusive(&self) -> Result<Arc<Mutex<Self::Transport>>, HWKeyError> {
if !*self.connected.borrow() {
return Err(HWKeyError::Unavailable);
}
Ok(Arc::new(Mutex::new(MockTransport::new())))
}
}