tf_embedded_hal/
adapters.rs1use core::convert::TryInto;
6
7use ed25519_compact::{KeyPair, PublicKey, Seed, Signature};
8use heapless::spsc::Queue;
9
10use crate::{BleAdvertiser, Entropy, LoraRadio, NfcReader, SecureElement};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum MockError {
15 Empty,
17 BufferTooSmall,
19 OutboxFull,
21 BadSeed,
23 Rng,
26}
27
28pub const MOCK_FRAME_CAP: usize = 1024;
30pub const MOCK_QUEUE_CAP: usize = 16;
32
33#[derive(Debug)]
37pub struct MockLoraRadio {
38 pub inbox: heapless::Vec<heapless::Vec<u8, MOCK_FRAME_CAP>, MOCK_QUEUE_CAP>,
39 pub outbox: heapless::Vec<heapless::Vec<u8, MOCK_FRAME_CAP>, MOCK_QUEUE_CAP>,
40}
41
42impl Default for MockLoraRadio {
43 fn default() -> Self {
44 Self::new()
45 }
46}
47
48impl MockLoraRadio {
49 pub fn new() -> Self {
50 MockLoraRadio {
51 inbox: heapless::Vec::new(),
52 outbox: heapless::Vec::new(),
53 }
54 }
55
56 pub fn enqueue_inbox(&mut self, frame: &[u8]) -> Result<(), MockError> {
58 let mut v: heapless::Vec<u8, MOCK_FRAME_CAP> = heapless::Vec::new();
59 v.extend_from_slice(frame)
60 .map_err(|_| MockError::BufferTooSmall)?;
61 self.inbox.push(v).map_err(|_| MockError::OutboxFull)?;
62 Ok(())
63 }
64}
65
66impl LoraRadio for MockLoraRadio {
67 type Error = MockError;
68
69 fn send(&mut self, payload: &[u8]) -> Result<(), Self::Error> {
70 let mut v: heapless::Vec<u8, MOCK_FRAME_CAP> = heapless::Vec::new();
71 v.extend_from_slice(payload)
72 .map_err(|_| MockError::BufferTooSmall)?;
73 self.outbox.push(v).map_err(|_| MockError::OutboxFull)?;
74 Ok(())
75 }
76
77 fn recv(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
78 if self.inbox.is_empty() {
79 return Err(MockError::Empty);
80 }
81 let frame = self.inbox.remove(0);
84 if frame.len() > buf.len() {
85 return Err(MockError::BufferTooSmall);
86 }
87 buf[..frame.len()].copy_from_slice(&frame);
88 Ok(frame.len())
89 }
90}
91
92#[derive(Debug)]
94pub struct MockBleAdvertiser {
95 pub last: Option<heapless::Vec<u8, MOCK_FRAME_CAP>>,
96 pub advertise_count: u32,
97}
98
99impl Default for MockBleAdvertiser {
100 fn default() -> Self {
101 Self::new()
102 }
103}
104
105impl MockBleAdvertiser {
106 pub fn new() -> Self {
107 MockBleAdvertiser {
108 last: None,
109 advertise_count: 0,
110 }
111 }
112}
113
114impl BleAdvertiser for MockBleAdvertiser {
115 type Error = MockError;
116 fn advertise(&mut self, payload: &[u8]) -> Result<(), Self::Error> {
117 let mut v: heapless::Vec<u8, MOCK_FRAME_CAP> = heapless::Vec::new();
118 v.extend_from_slice(payload)
119 .map_err(|_| MockError::BufferTooSmall)?;
120 self.last = Some(v);
121 self.advertise_count += 1;
122 Ok(())
123 }
124}
125
126#[derive(Debug)]
129pub struct MockNfcReader {
130 pub queue: heapless::Vec<heapless::Vec<u8, MOCK_FRAME_CAP>, MOCK_QUEUE_CAP>,
131}
132
133impl Default for MockNfcReader {
134 fn default() -> Self {
135 Self::new()
136 }
137}
138
139impl MockNfcReader {
140 pub fn new() -> Self {
141 MockNfcReader {
142 queue: heapless::Vec::new(),
143 }
144 }
145 pub fn enqueue(&mut self, frame: &[u8]) -> Result<(), MockError> {
146 let mut v: heapless::Vec<u8, MOCK_FRAME_CAP> = heapless::Vec::new();
147 v.extend_from_slice(frame)
148 .map_err(|_| MockError::BufferTooSmall)?;
149 self.queue.push(v).map_err(|_| MockError::OutboxFull)?;
150 Ok(())
151 }
152}
153
154impl NfcReader for MockNfcReader {
155 type Error = MockError;
156 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
157 if self.queue.is_empty() {
158 return Err(MockError::Empty);
159 }
160 let frame = self.queue.remove(0);
161 if frame.len() > buf.len() {
162 return Err(MockError::BufferTooSmall);
163 }
164 buf[..frame.len()].copy_from_slice(&frame);
165 Ok(frame.len())
166 }
167}
168
169#[derive(Debug)]
173pub struct MockSecureElement {
174 keypair: KeyPair,
175 pub_bytes: [u8; 32],
176}
177
178impl MockSecureElement {
179 pub fn from_seed(seed_bytes: [u8; 32]) -> Result<Self, MockError> {
181 let seed = Seed::from_slice(&seed_bytes).map_err(|_| MockError::BadSeed)?;
182 let keypair = KeyPair::from_seed(seed);
183 let pub_bytes: [u8; 32] = keypair
184 .pk
185 .as_ref()
186 .try_into()
187 .map_err(|_| MockError::BadSeed)?;
188 Ok(MockSecureElement { keypair, pub_bytes })
189 }
190
191 pub fn verify(&self, msg: &[u8], sig: &[u8; 64]) -> bool {
194 let sig = match Signature::from_slice(sig) {
195 Ok(s) => s,
196 Err(_) => return false,
197 };
198 let pk = match PublicKey::from_slice(&self.pub_bytes) {
199 Ok(p) => p,
200 Err(_) => return false,
201 };
202 pk.verify(msg, &sig).is_ok()
203 }
204}
205
206impl SecureElement for MockSecureElement {
207 type Error = MockError;
208
209 fn sign(&mut self, msg: &[u8]) -> Result<[u8; 64], Self::Error> {
210 let sig = self.keypair.sk.sign(msg, None);
211 let bytes: [u8; 64] = sig.as_ref().try_into().expect("ed25519 sig is 64 bytes");
212 Ok(bytes)
213 }
214
215 fn pubkey(&self) -> [u8; 32] {
216 self.pub_bytes
217 }
218}
219
220#[derive(Debug)]
224pub struct MockEntropy {
225 state: u64,
226}
227
228impl MockEntropy {
229 pub fn new(seed: u64) -> Self {
230 let s = if seed == 0 {
232 0xdead_beef_dead_beef
233 } else {
234 seed
235 };
236 MockEntropy { state: s }
237 }
238}
239
240impl Entropy for MockEntropy {
241 type Error = MockError;
242 fn fill(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
243 for chunk in buf.chunks_mut(8) {
244 self.state ^= self.state << 13;
245 self.state ^= self.state >> 7;
246 self.state ^= self.state << 17;
247 let v = self.state.wrapping_mul(0x2545_F491_4F6C_DD1Du64);
248 let bytes = v.to_le_bytes();
249 chunk.copy_from_slice(&bytes[..chunk.len()]);
250 }
251 Ok(())
252 }
253}
254
255#[doc(hidden)]
258pub type _UnusedQueueImport<T, const N: usize> = Queue<T, N>;