use core::future::Future;
use std::num::NonZero;
use le_stream::ToLeStream;
use log::{info, trace, warn};
use crate::frame::{Parameter, RespondsWith};
use crate::parameters::configuration::version;
use crate::{Connection, Error, Parameters};
pub trait Transport: Send {
fn connect(&mut self) -> impl Future<Output = Result<version::Response, Error>> + Send;
fn state(&self) -> Connection;
fn negotiated_version(&self) -> Option<NonZero<u8>>;
fn send<T>(&mut self, command: T) -> impl Future<Output = Result<u16, Error>> + Send
where
T: Parameter + ToLeStream;
fn receive<T>(&mut self) -> impl Future<Output = Result<T, Error>> + Send
where
T: TryFrom<Parameters> + Send,
<T as TryFrom<Parameters>>::Error: Into<Parameters> + Send;
fn ensure_connection(&mut self) -> impl Future<Output = Result<(), Error>> + Send {
async {
match self.state() {
Connection::Disconnected => {
info!("Initializing UART connection");
self.connect().await.map(drop)
}
Connection::Connected => {
trace!("UART is connected");
Ok(())
}
Connection::Failed => {
warn!("UART connection failed, reinitializing");
self.connect().await.map(drop)
}
}
}
}
fn communicate<T>(
&mut self,
command: T,
) -> impl Future<Output = Result<T::Response, Error>> + Send
where
T: Parameter + RespondsWith + ToLeStream,
{
async {
self.ensure_connection().await?;
self.send(command).await?;
self.receive().await
}
}
}