1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
use async_trait::async_trait; use hex::FromHex; use regex::Regex; use ledger_hw_transport::Transport; pub struct RecordStore { pub queue: Vec<(Vec<u8>, Vec<u8>)>, } impl RecordStore { pub fn new() -> RecordStore { RecordStore { queue: Vec::new() } } pub fn from_str(s: &str) -> Result<RecordStore, MockError> { let cmd_reg: Regex = Regex::new(r"^=>([0-9a-fA-F]+)$").unwrap(); let out_reg: Regex = Regex::new(r"^<=([0-9a-fA-F]+)$").unwrap(); let mut store = RecordStore::new(); let mut c: Vec<u8> = Vec::new(); for l in s.split('\n') { let line = l.replace(" ", ""); if let Some(cmd) = cmd_reg.find(&line) { c = Vec::from_hex(cmd.as_str().replace("=>", "")) .map_err(|_| MockError::ParseExchangeError)?; } if let Some(out) = out_reg.find(&line) { let o = Vec::from_hex(out.as_str().replace("<=", "")) .map_err(|_| MockError::ParseExchangeError)?; store.queue.push((c.clone(), o)); } } Ok(store) } } pub struct TransportReplayer { store: RecordStore, } impl TransportReplayer { pub fn new(store: RecordStore) -> TransportReplayer { TransportReplayer { store: store } } } #[async_trait] impl Transport for TransportReplayer { type Error = MockError; async fn exchange(&self, command: &[u8]) -> Result<Vec<u8>, Self::Error> { for exchange in &self.store.queue { if command == exchange.0.as_slice() { return Ok(exchange.1.clone()); } } Err(MockError::ExchangeNotFound(command.to_vec())) } } #[derive(Debug)] pub enum MockError { ParseExchangeError, ExchangeNotFound(Vec<u8>), }