surrealdb_core/rpc/
request.rs

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
use crate::rpc::format::cbor::Cbor;
use crate::rpc::format::msgpack::Pack;
use crate::rpc::RpcError;
use crate::sql::Part;
use crate::sql::{Array, Value};
use std::sync::LazyLock;

pub static ID: LazyLock<[Part; 1]> = LazyLock::new(|| [Part::from("id")]);
pub static METHOD: LazyLock<[Part; 1]> = LazyLock::new(|| [Part::from("method")]);
pub static PARAMS: LazyLock<[Part; 1]> = LazyLock::new(|| [Part::from("params")]);

#[derive(Debug)]
pub struct Request {
	pub id: Option<Value>,
	pub method: String,
	pub params: Array,
}

impl TryFrom<Cbor> for Request {
	type Error = RpcError;
	fn try_from(val: Cbor) -> Result<Self, RpcError> {
		<Cbor as TryInto<Value>>::try_into(val).map_err(|_| RpcError::InvalidRequest)?.try_into()
	}
}

impl TryFrom<Pack> for Request {
	type Error = RpcError;
	fn try_from(val: Pack) -> Result<Self, RpcError> {
		<Pack as TryInto<Value>>::try_into(val).map_err(|_| RpcError::InvalidRequest)?.try_into()
	}
}

impl TryFrom<Value> for Request {
	type Error = RpcError;
	fn try_from(val: Value) -> Result<Self, RpcError> {
		// Fetch the 'id' argument
		let id = match val.pick(&*ID) {
			v if v.is_none() => None,
			v if v.is_null() => Some(v),
			v if v.is_uuid() => Some(v),
			v if v.is_number() => Some(v),
			v if v.is_strand() => Some(v),
			v if v.is_datetime() => Some(v),
			_ => return Err(RpcError::InvalidRequest),
		};
		// Fetch the 'method' argument
		let method = match val.pick(&*METHOD) {
			Value::Strand(v) => v.to_raw(),
			_ => return Err(RpcError::InvalidRequest),
		};
		// Fetch the 'params' argument
		let params = match val.pick(&*PARAMS) {
			Value::Array(v) => v,
			_ => Array::new(),
		};
		// Return the parsed request
		Ok(Request {
			id,
			method,
			params,
		})
	}
}