#[cfg(feature = "tcp-client")]
pub mod tcp;
use async_trait::async_trait;
use log::{info, trace};
use std::io::{Error, ErrorKind, Result};
use crate::{
request::{Request, RequestWriter},
response::{Response, ResponseReader},
timer::Timer,
};
#[async_trait]
pub trait Client: Send + Sync {
async fn send(&self, req: Request) -> Result<Response>;
async fn start(&self) -> Result<()> {
info!("sending request to start timer");
match self.send(Request::Start).await {
Ok(Response::Ok) => Ok(()),
Ok(res) => Err(Error::new(
ErrorKind::InvalidData,
format!("invalid response: {res:?}"),
)),
Err(err) => Err(Error::new(ErrorKind::Other, err)),
}
}
async fn get(&self) -> Result<Timer> {
info!("sending request to get timer");
match self.send(Request::Get).await {
Ok(Response::Timer(timer)) => {
trace!("timer: {timer:#?}");
Ok(timer)
}
Ok(res) => Err(Error::new(
ErrorKind::InvalidData,
format!("invalid response: {res:?}"),
)),
Err(err) => Err(Error::new(ErrorKind::Other, err)),
}
}
async fn set(&self, duration: usize) -> Result<()> {
info!("sending request to set timer duration");
match self.send(Request::Set(duration)).await {
Ok(Response::Ok) => Ok(()),
Ok(res) => Err(Error::new(
ErrorKind::InvalidData,
format!("invalid response: {res:?}"),
)),
Err(err) => Err(Error::new(ErrorKind::Other, err)),
}
}
async fn pause(&self) -> Result<()> {
info!("sending request to pause timer");
match self.send(Request::Pause).await {
Ok(Response::Ok) => Ok(()),
Ok(res) => Err(Error::new(
ErrorKind::InvalidData,
format!("invalid response: {res:?}"),
)),
Err(err) => Err(Error::new(ErrorKind::Other, err)),
}
}
async fn resume(&self) -> Result<()> {
info!("sending request to resume timer");
match self.send(Request::Resume).await {
Ok(Response::Ok) => Ok(()),
Ok(res) => Err(Error::new(
ErrorKind::InvalidData,
format!("invalid response: {res:?}"),
)),
Err(err) => Err(Error::new(ErrorKind::Other, err)),
}
}
async fn stop(&self) -> Result<()> {
info!("sending request to stop timer");
match self.send(Request::Stop).await {
Ok(Response::Ok) => Ok(()),
Ok(res) => Err(Error::new(
ErrorKind::InvalidData,
format!("invalid response: {res:?}"),
)),
Err(err) => Err(Error::new(ErrorKind::Other, err)),
}
}
}
#[async_trait]
pub trait ClientStream: RequestWriter + ResponseReader {
async fn handle(&mut self, req: Request) -> Result<Response> {
self.write(req).await?;
self.read().await
}
}
impl<T: RequestWriter + ResponseReader> ClientStream for T {}