nimbi-rs 0.1.0

A client for interacting with nimbi-api
Documentation
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) => {
                // info!("microdot error: {:?}", 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 = ()>;
}