uds_client/uds_client/
response.rs

1use std::{cell::RefCell, time::Duration};
2use tokio::sync::{Mutex, Notify};
3
4use super::{
5    DiagError,
6    frame::{FrameError, UdsFrame},
7};
8
9#[derive(Debug, Clone, PartialEq)]
10pub enum Response {
11    Ok(UdsFrame),
12    Error,
13}
14
15/// The response slot for each UDS request
16pub struct ResponseSlot(pub Mutex<RefCell<Response>>, pub Notify);
17
18impl Default for ResponseSlot {
19    fn default() -> Self {
20        Self::new()
21    }
22}
23
24impl ResponseSlot {
25    // timeout in miliseconds
26    const TIMEOUT: u64 = 1000;
27
28    /// Create new response slot.
29    pub fn new() -> Self {
30        Self(Mutex::new(RefCell::new(Response::Error)), Notify::new())
31    }
32
33    /// Get a response with blocking forever method.
34    pub async fn get(&self) -> Result<Response, DiagError> {
35        self.1.notified().await;
36        let res = self.0.try_lock().unwrap().to_owned().into_inner();
37        Ok(res)
38    }
39
40    /// Get a response with a <TIMEOUT> in ms.
41    pub async fn wait_for_response(&self) -> Response {
42        tokio::select! {
43            _ = self.1.notified() => {
44                let data = self.0.lock().await;
45                data.borrow().clone()
46            }
47            _ = tokio::time::sleep(Duration::from_millis(Self::TIMEOUT)) => {
48                Response::Error
49            }
50        }
51    }
52
53    /// Update the response data into response slot and raise a notification.
54    pub async fn update_response(&self, new_data: Vec<u8>) -> Result<(), FrameError> {
55        let res = UdsFrame::from_vec(new_data)?;
56        self.0.lock().await.replace(Response::Ok(res)); // Lock and modify data
57        self.1.notify_one(); // Notify the waiting thread
58        Ok(())
59    }
60}