aboutsummaryrefslogtreecommitdiff
path: root/codeless/server/src/dispatch.rs
blob: ee87fa6c3103cd8cdc8cd01ce806a60dde37c299 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use std::marker::PhantomData;

use serde::{
    ser::Serialize,
    de::DeserializeOwned,
};
use serde_json;
use drop_bomb::DropBomb;

use ::{
    Result,
    req::Request,
    io::{Io, RawMsg, RawResponse, RawRequest},
};

pub struct Responder<R: Request> {
    id: u64,
    bomb: DropBomb,
    ph: PhantomData<R>,
}

impl<R: Request> Responder<R>
    where
        R::Params: DeserializeOwned,
        R::Result: Serialize,
{
    pub fn response(self, io: &mut Io, resp: Result<R::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")
    }
}


pub fn parse_as<R>(raw: RawRequest) -> Result<::std::result::Result<(R::Params, Responder<R>), RawRequest>>
    where
        R: Request,
        R::Params: DeserializeOwned,
        R::Result: Serialize,
{
    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 expect<R>(io: &mut Io, raw: RawRequest) -> Result<Option<(R::Params, Responder<R>)>>
    where
        R: Request,
        R::Params: DeserializeOwned,
        R::Result: Serialize,
{
    let ret = match parse_as::<R>(raw)? {
        Ok(x) => Some(x),
        Err(raw) => {
            unknown_method(io, raw)?;
            None
        }
    };
    Ok(ret)
}

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,
}