mikrotik_api 0.3.0

Rust library & minimal client to connect and interact with Mikrotik RouterOS API, usually exposed on port 8728
Documentation
mod array;
mod one_shot;
mod streaming;

use std::{
    fmt::Debug,
    sync::{Arc, Mutex},
};

pub use array::ArrayListCall;
pub use one_shot::OneShotCall;
pub use streaming::StreamingCall;

use tokio::sync::OnceCell;

use super::de::DeserializerError;

pub type EmptyCall = OneShotCall<()>;

type ThreadSafeInnerCall<T> = Arc<Mutex<InnerCall<T>>>;

#[derive(Debug)]
pub enum CallError {
    DoneAlreadyHappened,
    DoneWithoutReply,
    BadLock,
    BadSentence(DeserializerError),
}

impl From<DeserializerError> for CallError {
    fn from(e: DeserializerError) -> Self {
        CallError::BadSentence(e)
    }
}

pub trait AsyncCall {
    fn push_reply(&mut self, sentence: Vec<String>) -> Result<(), CallError>;

    fn done(&mut self) -> Result<(), CallError>;
}

struct InnerCall<T> {
    inner: Option<T>,
    done: OnceCell<T>,
}

impl<T: Debug> InnerCall<T> {
    pub fn new(value: Option<T>) -> Self {
        Self {
            inner: value,
            done: OnceCell::new(),
        }
    }

    pub fn done(&mut self) -> Result<(), CallError> {
        if let Some(value) = self.inner.take() {
            self.done
                .set(value)
                .map_err(|_| CallError::DoneAlreadyHappened)?;

            return Ok(());
        }

        Err(CallError::DoneWithoutReply)
    }

    pub fn get_done(&mut self) -> Option<T> {
        self.done.take()
    }
}