use serde::Serialize; use serde_json::Value as Json; use std::borrow::Cow; use surrealdb::channel::Sender; use surrealdb::sql; use surrealdb::sql::Value; use warp::ws::Message; #[derive(Clone)] pub enum Output { Json, // JSON Cbor, // CBOR Pack, // MessagePack Full, // Full type serialization } #[derive(Serialize)] pub struct Response { #[serde(skip_serializing_if = "Option::is_none")] id: Option, #[serde(flatten)] content: Content, } #[derive(Serialize)] enum Content { #[serde(rename = "result")] Success(T), #[serde(rename = "error")] Failure(Failure), } impl Response { /// Convert and simplify the value into JSON #[inline] fn simplify(self) -> Json { sql::to_value(self).unwrap().into() } /// Send the response to the WebSocket channel pub async fn send(self, out: Output, chn: Sender) { match out { Output::Json => { let res = serde_json::to_string(&self.simplify()).unwrap(); let res = Message::text(res); let _ = chn.send(res).await; } Output::Cbor => { let res = serde_cbor::to_vec(&self.simplify()).unwrap(); let res = Message::binary(res); let _ = chn.send(res).await; } Output::Pack => { let res = serde_pack::to_vec(&self.simplify()).unwrap(); let res = Message::binary(res); let _ = chn.send(res).await; } Output::Full => { let res = bung::to_vec(&self).unwrap(); let res = Message::binary(res); let _ = chn.send(res).await; } } } } #[derive(Clone, Debug, Serialize)] pub struct Failure { code: i64, message: Cow<'static, str>, } impl Failure { pub const PARSE_ERROR: Failure = Failure { code: -32700, message: Cow::Borrowed("Parse error"), }; pub const INVALID_REQUEST: Failure = Failure { code: -32600, message: Cow::Borrowed("Invalid Request"), }; pub const METHOD_NOT_FOUND: Failure = Failure { code: -32601, message: Cow::Borrowed("Method not found"), }; pub const INVALID_PARAMS: Failure = Failure { code: -32602, message: Cow::Borrowed("Invalid params"), }; pub const INTERNAL_ERROR: Failure = Failure { code: -32603, message: Cow::Borrowed("Internal error"), }; pub fn custom(message: S) -> Failure where Cow<'static, str>: From, { Failure { code: -32000, message: message.into(), } } } /// Create a JSON RPC result response pub fn success(id: Option, val: S) -> Response { Response { id, content: Content::Success(val), } } /// Create a JSON RPC failure response pub fn failure(id: Option, err: Failure) -> Response { Response { id, content: Content::Failure(err), } }