surrealdb_core/rpc/
request.rs

1use crate::rpc::format::cbor::Cbor;
2use crate::rpc::format::msgpack::Pack;
3use crate::rpc::Method;
4use crate::rpc::RpcError;
5use crate::sql::Array;
6use crate::sql::Number;
7use crate::sql::Part;
8use crate::sql::Value;
9use std::sync::LazyLock;
10
11pub static ID: LazyLock<[Part; 1]> = LazyLock::new(|| [Part::from("id")]);
12pub static METHOD: LazyLock<[Part; 1]> = LazyLock::new(|| [Part::from("method")]);
13pub static PARAMS: LazyLock<[Part; 1]> = LazyLock::new(|| [Part::from("params")]);
14pub static VERSION: LazyLock<[Part; 1]> = LazyLock::new(|| [Part::from("version")]);
15
16#[derive(Debug)]
17pub struct Request {
18	pub id: Option<Value>,
19	pub version: Option<u8>,
20	pub method: Method,
21	pub params: Array,
22}
23
24impl TryFrom<Cbor> for Request {
25	type Error = RpcError;
26	fn try_from(val: Cbor) -> Result<Self, RpcError> {
27		<Cbor as TryInto<Value>>::try_into(val).map_err(|_| RpcError::InvalidRequest)?.try_into()
28	}
29}
30
31impl TryFrom<Pack> for Request {
32	type Error = RpcError;
33	fn try_from(val: Pack) -> Result<Self, RpcError> {
34		<Pack as TryInto<Value>>::try_into(val).map_err(|_| RpcError::InvalidRequest)?.try_into()
35	}
36}
37
38impl TryFrom<Value> for Request {
39	type Error = RpcError;
40	fn try_from(val: Value) -> Result<Self, RpcError> {
41		// Fetch the 'id' argument
42		let id = match val.pick(&*ID) {
43			v if v.is_none() => None,
44			v if v.is_null() => Some(v),
45			v if v.is_uuid() => Some(v),
46			v if v.is_number() => Some(v),
47			v if v.is_strand() => Some(v),
48			v if v.is_datetime() => Some(v),
49			_ => return Err(RpcError::InvalidRequest),
50		};
51		// Fetch the 'version' argument
52		let version = match val.pick(&*VERSION) {
53			v if v.is_none() => None,
54			v if v.is_null() => None,
55			Value::Number(v) => match v {
56				Number::Int(1) => Some(1),
57				Number::Int(2) => Some(2),
58				_ => return Err(RpcError::InvalidRequest),
59			},
60			_ => return Err(RpcError::InvalidRequest),
61		};
62		// Fetch the 'method' argument
63		let method = match val.pick(&*METHOD) {
64			Value::Strand(v) => v.to_raw(),
65			_ => return Err(RpcError::InvalidRequest),
66		};
67		// Fetch the 'params' argument
68		let params = match val.pick(&*PARAMS) {
69			Value::Array(v) => v,
70			_ => Array::new(),
71		};
72		// Parse the specified method
73		let method = Method::parse_case_sensitive(&method);
74		// Return the parsed request
75		Ok(Request {
76			id,
77			method,
78			params,
79			version,
80		})
81	}
82}