use std::marker::PhantomData; use serde::{ ser::Serialize, de::DeserializeOwned, }; use serde_json; use drop_bomb::DropBomb; use ::{ Result, req::{ClientRequest, Notification}, io::{Io, RawMsg, RawResponse, RawRequest, RawNotification}, }; pub struct Responder { id: u64, bomb: DropBomb, ph: PhantomData, } impl Responder { pub fn response(self, io: &mut Io, resp: Result) -> Result<()> { match resp { Ok(res) => self.result(io, res)?, Err(e) => { self.error(io)?; return Err(e); } } Ok(()) } pub fn result(mut self, io: &mut Io, result: R::Result) -> Result<()> { self.bomb.defuse(); io.send(RawMsg::Response(RawResponse { id: Some(self.id), result: serde_json::to_value(result)?, error: serde_json::Value::Null, })); Ok(()) } pub fn error(mut self, io: &mut Io) -> Result<()> { self.bomb.defuse(); error(io, self.id, ErrorCode::InternalError, "internal error") } } fn parse_request_as(raw: RawRequest) -> Result<::std::result::Result<(R::Params, Responder), RawRequest>> { if raw.method != R::METHOD { return Ok(Err(raw)); } let params: R::Params = serde_json::from_value(raw.params)?; let responder = Responder { id: raw.id, bomb: DropBomb::new("dropped request"), ph: PhantomData, }; Ok(Ok((params, responder))) } pub fn handle_request(req: &mut Option, f: F) -> Result<()> where R: ClientRequest, F: FnOnce(R::Params, Responder) -> Result<()> { match req.take() { None => Ok(()), Some(r) => match parse_request_as::(r)? { Ok((params, responder)) => f(params, responder), Err(r) => { *req = Some(r); Ok(()) }, } } } pub fn expect_request(io: &mut Io, raw: RawRequest) -> Result)>> { let ret = match parse_request_as::(raw)? { Ok(x) => Some(x), Err(raw) => { unknown_method(io, raw)?; None } }; Ok(ret) } fn parse_notification_as(raw: RawNotification) -> Result<::std::result::Result> where N: Notification, N::Params: DeserializeOwned, { if raw.method != N::METHOD { return Ok(Err(raw)); } let params: N::Params = serde_json::from_value(raw.params)?; Ok(Ok(params)) } pub fn handle_notification(not: &mut Option, f: F) -> Result<()> where N: Notification, N::Params: DeserializeOwned, F: FnOnce(N::Params) -> Result<()> { match not.take() { None => Ok(()), Some(n) => match parse_notification_as::(n)? { Ok(params) => f(params), Err(n) => { *not = Some(n); Ok(()) }, } } } pub fn send_notification(io: &mut Io, params: N::Params) -> Result<()> where N: Notification, N::Params: Serialize { io.send(RawMsg::Notification(RawNotification { method: N::METHOD.to_string(), params: serde_json::to_value(params)?, })); Ok(()) } pub fn unknown_method(io: &mut Io, raw: RawRequest) -> Result<()> { error(io, raw.id, ErrorCode::MethodNotFound, "unknown method") } fn error(io: &mut Io, id: u64, code: ErrorCode, message: &'static str) -> Result<()> { #[derive(Serialize)] struct Error { code: i32, message: &'static str, } io.send(RawMsg::Response(RawResponse { id: Some(id), result: serde_json::Value::Null, error: serde_json::to_value(Error { code: code as i32, message, })?, })); Ok(()) } #[allow(unused)] enum ErrorCode { ParseError = -32700, InvalidRequest = -32600, MethodNotFound = -32601, InvalidParams = -32602, InternalError = -32603, ServerErrorStart = -32099, ServerErrorEnd = -32000, ServerNotInitialized = -32002, UnknownErrorCode = -32001, RequestCancelled = -32800, }