psdk_fruit_emapi/
connection.rs1use std::{
2 collections::VecDeque,
3 sync::{Arc, Mutex},
4 time::Duration,
5};
6
7use crate::error::{EmapiError, Result};
8
9pub trait EmapiConnection {
10 fn write(&mut self, data: &[u8]) -> Result<()>;
11 fn read(&mut self, timeout: Duration) -> Result<Vec<u8>>;
12}
13
14#[derive(Debug, Clone)]
15pub struct ScriptedEmapiConnection {
16 state: Arc<Mutex<ScriptedEmapiConnectionState>>,
17}
18
19#[derive(Debug, Default)]
20struct ScriptedEmapiConnectionState {
21 responses: VecDeque<Option<Vec<u8>>>,
22 writes: Vec<Vec<u8>>,
23 reads: usize,
24}
25
26impl ScriptedEmapiConnection {
27 pub fn new(responses: Vec<Option<Vec<u8>>>) -> Self {
28 Self {
29 state: Arc::new(Mutex::new(ScriptedEmapiConnectionState {
30 responses: responses.into(),
31 writes: Vec::new(),
32 reads: 0,
33 })),
34 }
35 }
36
37 pub fn writes(&self) -> Vec<Vec<u8>> {
38 self.state.lock().unwrap().writes.clone()
39 }
40
41 pub fn reads(&self) -> usize {
42 self.state.lock().unwrap().reads
43 }
44}
45
46impl EmapiConnection for ScriptedEmapiConnection {
47 fn write(&mut self, data: &[u8]) -> Result<()> {
48 self.state.lock().unwrap().writes.push(data.to_vec());
49 Ok(())
50 }
51
52 fn read(&mut self, timeout: Duration) -> Result<Vec<u8>> {
53 let mut state = self.state.lock().unwrap();
54 state.reads += 1;
55 match state.responses.pop_front() {
56 Some(Some(response)) => Ok(response),
57 Some(None) => Err(EmapiError::Timeout {
58 message: format!("timeout waiting for response after {timeout:?}"),
59 }),
60 None => Err(EmapiError::Timeout {
61 message: format!("no response after {timeout:?}"),
62 }),
63 }
64 }
65}