pub mod methods;
#[cfg(feature = "defmt")]
use defmt::*;
#[cfg(feature = "tokio")]
pub mod tokio;
#[cfg(feature = "embassy")]
pub mod embassy;
use nimbi_protocol::{microdot::MicrodotError, types::response::Error as ResponseError};
use core::{future::Future, marker::PhantomData};
pub struct Client<T, E>
where
T: ClientConnection<E>,
{
pub connection: T,
error: PhantomData<E>,
}
impl<T, E> Client<T, E>
where
T: ClientConnection<E>,
{
pub fn new(connection: T) -> Self {
Self {
connection,
error: PhantomData,
}
}
pub async fn close(&mut self) {
self.connection.close().await;
}
}
#[derive(Debug)]
pub enum ClientError<E> {
ConnectionError(E),
Microdot(MicrodotError),
Response(ResponseError),
IncompleteMessage,
Other(&'static str),
}
impl<E> ClientError<E> {
pub fn client_connection(err: E) -> Self {
ClientError::ConnectionError(err)
}
pub fn microdot(err: MicrodotError) -> Self {
ClientError::Microdot(err)
}
pub fn response(err: ResponseError) -> Self {
ClientError::Response(err)
}
pub fn other(err: &'static str) -> Self {
ClientError::Other(err)
}
}
impl<E> From<E> for ClientError<E> {
fn from(err: E) -> Self {
ClientError::ConnectionError(err)
}
}
#[cfg(feature = "defmt")]
impl<E> defmt::Format for ClientError<E> {
fn format(&self, f: defmt::Formatter) {
let msg = match self {
ClientError::ConnectionError(_) => "connection error",
ClientError::Microdot(error) => {
"microdot"
}
ClientError::Response(error) => "response",
ClientError::IncompleteMessage => "incomplete message",
ClientError::Other(_) => "other",
};
defmt::write!(f, "ClientError: {}", msg,)
}
}
pub trait ClientConnection<E> {
fn send(&mut self, buf: &[u8]) -> impl Future<Output = Result<usize, ClientError<E>>>;
fn recv(&mut self, buf: &mut [u8]) -> impl Future<Output = Result<usize, ClientError<E>>>;
fn close(&mut self) -> impl Future<Output = ()>;
}