tnnl 0.1.17

tnnl gives you full control over whether and when your IoT devices should be reachable from the internet
use std::{collections::HashMap, sync::atomic::AtomicU32};

use serde_json::Value;
use tokio::sync::{
    Mutex,
    oneshot::{Receiver, Sender, channel},
};

pub enum Response {
    Success(Value),
    Error(Value),
}

pub struct RpcHelper {
    max: AtomicU32,
    ongoing: Mutex<HashMap<u32, Sender<Response>>>,
}

impl RpcHelper {
    pub fn new() -> RpcHelper {
        RpcHelper {
            max: AtomicU32::new(1),
            ongoing: Mutex::new(HashMap::new()),
        }
    }

    pub async fn add(&self) -> (Receiver<Response>, u32) {
        let mut ongoing: tokio::sync::MutexGuard<'_, HashMap<u32, Sender<Response>>> =
            self.ongoing.lock().await;

        let id = self.max.fetch_add(1, std::sync::atomic::Ordering::SeqCst);

        let (tx, rx) = channel::<Response>();

        ongoing.insert(id, tx);

        (rx, id)
    }

    pub async fn complete(&self, id: u32, response: Response) -> bool {
        let mut ongoing: tokio::sync::MutexGuard<'_, HashMap<u32, Sender<Response>>> =
            self.ongoing.lock().await;

        let response_sender = ongoing.remove(&id);

        if let Some(sender) = response_sender {
            sender.send(response).is_ok()
        } else {
            false
        }
    }
}