time/client/
mod.rs

1//! # Client
2//!
3//! The client connects to the server, sends requests in order to
4//! control the timer and receive responses.
5//!
6//! The client must implement the [`Client`] trait.
7
8#[cfg(feature = "tcp-client")]
9pub mod tcp;
10
11use async_trait::async_trait;
12use log::{info, trace};
13use std::io::{Error, ErrorKind, Result};
14
15use crate::{
16    request::{Request, RequestWriter},
17    response::{Response, ResponseReader},
18    timer::Timer,
19};
20
21/// The client trait.
22///
23/// Clients must implement this trait. Only the [`Client::send`]
24/// function needs to be implemented: it should describe how to
25/// connect and send requests to the server.
26#[async_trait]
27pub trait Client: Send + Sync {
28    /// Send the given request and returns the associated response.
29    async fn send(&self, req: Request) -> Result<Response>;
30
31    /// Send the start timer request.
32    async fn start(&self) -> Result<()> {
33        info!("sending request to start timer");
34
35        match self.send(Request::Start).await {
36            Ok(Response::Ok) => Ok(()),
37            Ok(res) => Err(Error::new(
38                ErrorKind::InvalidData,
39                format!("invalid response: {res:?}"),
40            )),
41            Err(err) => Err(Error::new(ErrorKind::Other, err)),
42        }
43    }
44
45    /// Send the get timer request.
46    async fn get(&self) -> Result<Timer> {
47        info!("sending request to get timer");
48
49        match self.send(Request::Get).await {
50            Ok(Response::Timer(timer)) => {
51                trace!("timer: {timer:#?}");
52                Ok(timer)
53            }
54            Ok(res) => Err(Error::new(
55                ErrorKind::InvalidData,
56                format!("invalid response: {res:?}"),
57            )),
58            Err(err) => Err(Error::new(ErrorKind::Other, err)),
59        }
60    }
61
62    /// Send the set timer request.
63    async fn set(&self, duration: usize) -> Result<()> {
64        info!("sending request to set timer duration");
65
66        match self.send(Request::Set(duration)).await {
67            Ok(Response::Ok) => Ok(()),
68            Ok(res) => Err(Error::new(
69                ErrorKind::InvalidData,
70                format!("invalid response: {res:?}"),
71            )),
72            Err(err) => Err(Error::new(ErrorKind::Other, err)),
73        }
74    }
75
76    /// Send the pause timer request.
77    async fn pause(&self) -> Result<()> {
78        info!("sending request to pause timer");
79
80        match self.send(Request::Pause).await {
81            Ok(Response::Ok) => Ok(()),
82            Ok(res) => Err(Error::new(
83                ErrorKind::InvalidData,
84                format!("invalid response: {res:?}"),
85            )),
86            Err(err) => Err(Error::new(ErrorKind::Other, err)),
87        }
88    }
89
90    /// Send the resume timer request.
91    async fn resume(&self) -> Result<()> {
92        info!("sending request to resume timer");
93
94        match self.send(Request::Resume).await {
95            Ok(Response::Ok) => Ok(()),
96            Ok(res) => Err(Error::new(
97                ErrorKind::InvalidData,
98                format!("invalid response: {res:?}"),
99            )),
100            Err(err) => Err(Error::new(ErrorKind::Other, err)),
101        }
102    }
103
104    /// Send the stop timer request.
105    async fn stop(&self) -> Result<()> {
106        info!("sending request to stop timer");
107
108        match self.send(Request::Stop).await {
109            Ok(Response::Ok) => Ok(()),
110            Ok(res) => Err(Error::new(
111                ErrorKind::InvalidData,
112                format!("invalid response: {res:?}"),
113            )),
114            Err(err) => Err(Error::new(ErrorKind::Other, err)),
115        }
116    }
117}
118
119/// The client stream trait.
120#[async_trait]
121pub trait ClientStream: RequestWriter + ResponseReader {
122    async fn handle(&mut self, req: Request) -> Result<Response> {
123        self.write(req).await?;
124        self.read().await
125    }
126}
127
128impl<T: RequestWriter + ResponseReader> ClientStream for T {}