jsonrpc2 0.1.1

JsonRPC2 Library

use std::collections::BTreeMap;
use std::str::FromStr;
use std::string::ToString;
use ::{Json, ToJson, Object, Error, Request};

#[derive(Debug, Clone)]
pub enum Response {
    Success{jsonrpc: String, result: Option<Json>, id: Option<i64>},
    Error  {jsonrpc: String, error : Error,        id: Option<i64>}
}

impl ToJson for Response {
    fn to_json(&self) -> Json {
        match *self {
            Response::Success{
                jsonrpc: ref jsonrpc,
                result : ref result,
                id     : ref id } => {
                    let mut json = BTreeMap::new();
                    json.insert("jsonrpc".to_string(), jsonrpc.to_json() );
                    json.insert("result".to_string(),  result.to_json()  );
                    json.insert("id".to_string(),      id.to_json()      );
                    Json::Object(json)
            },
            Response::Error{
                jsonrpc: ref jsonrpc,
                error  : ref error,
                id     : ref id } => {
                    let mut json = BTreeMap::new();
                    json.insert("jsonrpc".to_string(), jsonrpc.to_json() );
                    json.insert("error".to_string(),   error.to_json()   );
                    json.insert("id".to_string(),      id.to_json()      );
                    Json::Object(json)
            }
        }
    }
}

impl ToString for Response {
    fn to_string(&self) -> String {
        self.to_json().to_string()
    }
}

impl FromStr for Response {
    type Err = Error;
    fn from_str(s: &str) -> Result<Response, Error> {
        match Json::from_str(s) {
            Ok(json) => {
                match Response::parse(json) {
                    Ok(response) => Ok(response),
                    Err(err)    => Err(err)
                }
            },
            Err(_)  => Err(Error::ParseError)
        }
    }
}

impl Response {
    pub fn parse(j: Json) -> Result<Response, Error> {
        if !j.is_object() {
            return Err(Error::ParseError);
        }
        let obj = j.as_object().unwrap();

        let version = Request::_parse_version(&obj);
        let id      = Request::_parse_id(&obj);

        let result  = Response::_parse_result(&obj);
        let error   = Error::_parse_error(&obj);
        

        if version.is_err() && id.is_err() {
            return Err(Error::InternalError);
        }

        if result.is_err() && error.is_err() {
            return Err(Error::InternalError);
        }
        if result.is_err() && error.is_ok() {
            let (code, message, data) = error.ok().unwrap();
            let mut error = Error::from_i64(code).unwrap();
            error.set_message(message);
            error.set_data(data);
            
            return Ok(Response::Error{
                jsonrpc: version.ok().unwrap(),
                error  : error,
                id     : id.ok().unwrap()
            })
        }
        if result.is_ok() && error.is_err() {
            return Ok(Response::Success{
                jsonrpc: version.ok().unwrap(),
                result : result.ok().unwrap(),
                id     : id.ok().unwrap()
            })
        } else {
            return Err(Error::InternalError);
        }
        
    }
    pub fn _parse_result(obj: &Object) -> Result<Option<Json>, ()> {
        match obj.get("result") {
            Some(result) => {
                if result.is_array() || result.is_object() {
                    Ok(Some(result.clone()))
                } else if result.is_i64() 
                    || result.is_u64() 
                    || result.is_f64()
                    || result.is_boolean()
                    || result.is_string() {
                        Ok(Some(result.clone()))
                } else if result.is_null() {
                    Ok(None)
                } else {
                    Err(())
                }
            },
            None => Err(())
        }
    }

}