Skip to main content

psdk_fruit_emapi/
connection.rs

1use 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}