futures-jsonrpc 0.2.1

Futures implementation for JSON-RPC
Documentation
use crate::futures::prelude::*;
use crate::{ErrorVariant, JrpcMethodTrait, JrpcRequest, JrpcResponse};
use std::collections::HashMap;
use std::sync::{Arc, RwLock};

pub struct JrpcHandler<'a> {
    hm_methods: Arc<RwLock<HashMap<String, Box<dyn JrpcMethodTrait<'a> + 'a>>>>,
}

impl<'a> JrpcHandler<'a> {
    pub fn new() -> Result<Self, ErrorVariant> {
        let hm_methods = Arc::new(RwLock::new(HashMap::new()));
        let handler = JrpcHandler { hm_methods };
        Ok(handler)
    }

    pub fn register_method<T: ToString, F: JrpcMethodTrait<'a> + 'a>(
        &self,
        signature: T,
        jrpc_method: F,
    ) -> Result<&Self, ErrorVariant> {
        let signature = signature.to_string();
        let jrpc_method = Box::new(jrpc_method);
        let log_message = format!("Signature {} registered as method", &signature);

        {
            self.hm_methods
                .try_write()
                .map_err(|_| ErrorVariant::RwLockPoisoned)
                .and_then(|mut hm| {
                    hm.insert(signature, jrpc_method);
                    Ok(())
                })?;
        }

        trace!("{}", log_message);
        Ok(self)
    }

    pub fn handle_message<T: ToString>(
        &self,
        message: T,
    ) -> Result<Box<'a + Future<Item = Option<JrpcResponse>, Error = ErrorVariant>>, ErrorVariant>
    {
        let message = message.to_string();
        let log_message = format!("Message {}", &message);
        let request = JrpcRequest::parse(message)?;
        let log_message = format!("{} generated response {:?}", &log_message, &request);

        let future = {
            self.hm_methods
                .try_read()
                .map_err(|_| ErrorVariant::RwLockPoisoned)
                .and_then(|hm| {
                    hm.get(request.get_method())
                        .map(|method| Ok(method))
                        .unwrap_or(Err(ErrorVariant::MethodSignatureNotFound(
                            request.get_method().clone(),
                        )))
                        .and_then(|method| method.generate_future(request))
                })?
        };

        trace!("{}", log_message);
        Ok(future)
    }
}