edgedb_composable_query/
prim.rs

1use crate::value::EdgedbValue;
2use crate::Result;
3use edgedb_protocol::model::{Json, Uuid};
4use edgedb_protocol::value::{self, Value};
5use serde::de::DeserializeOwned;
6use serde::{Deserialize, Serialize};
7
8/// One of the primitive EdgeDB types, including JSON (see [`EdgedbJson`]). Implement this for your types if they are primitive-convertible.
9pub trait EdgedbPrim: Sized {
10    const TYPE_CAST: &'static str;
11
12    fn from_edgedb_val(value: Value) -> Result<Self>;
13
14    fn to_edgedb_val(self) -> Result<Value>;
15}
16
17macro_rules! impl_prim {
18    ($($t:ty => $v:ident $name:literal),*) => {
19        $(
20            impl EdgedbPrim for $t {
21                const TYPE_CAST: &'static str = $name;
22
23                fn from_edgedb_val(value: Value) -> Result<Self> {
24                    match value {
25                        Value::$v(v) => Ok(v),
26                        v => Err(anyhow::anyhow!("expected {}, got {:?}", stringify!($v), v)),
27                    }
28                }
29
30                fn to_edgedb_val(self) -> Result<Value> {
31                    Ok(Value::$v(self))
32                }
33            }
34
35            impl EdgedbValue for $t {
36                type NativeArgType = $t;
37
38                fn from_edgedb_value(value: Value) -> Result<Self> {
39                    <$t>::from_edgedb_val(value)
40                }
41
42                // fn to_edgedb_value(self) -> Result<Value> {
43                //     <$t>::to_edgedb_val(self)
44                // }
45            }
46        )*
47    };
48    () => {
49
50    };
51}
52
53impl_prim! {
54    i16 => Int16 "int16",
55    i32 => Int32 "int32",
56    i64 => Int64 "int64",
57    f32 => Float32 "float32",
58    f64 => Float64 "float64",
59    bool => Bool "bool",
60    String => Str "str",
61    Uuid => Uuid "uuid"
62}
63
64/// Wrapper around your serializable types to pass them as JSON query arguments
65pub struct EdgedbJson<T: DeserializeOwned + Serialize>(pub T);
66
67impl<T: DeserializeOwned + Serialize> EdgedbPrim for EdgedbJson<T> {
68    const TYPE_CAST: &'static str = "json";
69
70    fn from_edgedb_val(value: Value) -> Result<Self> {
71        if let Value::Json(s) = value {
72            Ok(Self(serde_json::from_str(&s)?))
73        } else {
74            Err(anyhow::anyhow!("expected: {:?}", value))
75        }
76    }
77
78    fn to_edgedb_val(self) -> Result<Value> {
79        let val = serde_json::to_string(&self.0)?;
80
81        // safety: we just serialized this value
82        Ok(Value::Json(unsafe { Json::new_unchecked(val) }))
83    }
84}