edgedb_composable_query/
value.rs

1pub use crate::Result;
2use crate::{args::EdgedbQueryArgs, EdgedbObject};
3use edgedb_tokio::Client;
4pub use nonempty::{nonempty, NonEmpty};
5
6use edgedb_protocol::value::Value;
7
8/// An object or a primitive. For sets, see [`EdgedbSetValue`]. Provided automatically in most cases.
9pub trait EdgedbValue: Sized {
10    /// use Value by default
11    type NativeArgType;
12
13    fn from_edgedb_value(value: Value) -> Result<Self>;
14    // fn to_edgedb_value(self) -> Result<Value>;
15}
16
17/// A value of a particular cardinality (typically it's provided automatically for `T`, `Option<T>`, `Vec<T>` or [`NonEmpty<T>`])
18pub trait EdgedbSetValue: Sized {
19    const EXPECTED_CARDINALITY: edgedb_protocol::server_message::Cardinality;
20
21    fn from_edgedb_set_value(value: Value) -> Result<Self>;
22    // fn to_edgedb_set_value(self) -> Result<Value>;
23
24    fn interpret_possibly_missing_required_value(val: Option<Self>) -> Result<Self>;
25
26    fn query_direct<Args: EdgedbQueryArgs + Send>(
27        client: &Client,
28        q: &str,
29        args: Args,
30    ) -> impl std::future::Future<Output = Result<Self>> + Send;
31}
32
33impl<T: EdgedbObject> EdgedbValue for T {
34    type NativeArgType = Value;
35
36    fn from_edgedb_value(value: Value) -> Result<Self> {
37        let (shape, fields) = match value {
38            Value::Object { shape, fields } => (shape, fields),
39            _ => return Err(anyhow::anyhow!("expected object")),
40        };
41        Self::from_edgedb_object(shape, fields)
42    }
43
44    // fn to_edgedb_value(self) -> Result<Value> {
45    //     let (shape, fields) = self.to_edgedb_object()?;
46    //     Ok(Value::Object { shape, fields })
47    // }
48}
49
50impl<T: EdgedbValue> EdgedbSetValue for T {
51    const EXPECTED_CARDINALITY: edgedb_protocol::server_message::Cardinality =
52        edgedb_protocol::server_message::Cardinality::One;
53
54    async fn query_direct<Args: EdgedbQueryArgs + Send>(
55        client: &Client,
56        q: &str,
57        args: Args,
58    ) -> Result<Self> {
59        let val = client
60            .query_required_single::<Value, _>(q, &args.to_query_args()?)
61            .await?;
62        let val = Self::from_edgedb_value(val)?;
63        Ok(val)
64    }
65
66    fn from_edgedb_set_value(value: Value) -> Result<Self> {
67        T::from_edgedb_value(value)
68    }
69
70    // fn to_edgedb_set_value(self) -> Result<Value> {
71    //     T::to_edgedb_value(self)
72    // }
73
74    fn interpret_possibly_missing_required_value(val: Option<Self>) -> Result<Self> {
75        match val {
76            Some(val) => Ok(val),
77            None => Err(anyhow::anyhow!("expected single value")),
78        }
79    }
80}
81
82impl<T: EdgedbValue> EdgedbSetValue for Option<T> {
83    const EXPECTED_CARDINALITY: edgedb_protocol::server_message::Cardinality =
84        edgedb_protocol::server_message::Cardinality::AtMostOne;
85
86    async fn query_direct<Args: EdgedbQueryArgs + Send>(
87        client: &Client,
88        q: &str,
89        args: Args,
90    ) -> Result<Self> {
91        let val = client
92            .query_single::<Value, _>(q, &args.to_query_args()?)
93            .await?;
94        let val = val.map(|val| T::from_edgedb_value(val)).transpose()?;
95        Ok(val)
96    }
97
98    fn from_edgedb_set_value(value: Value) -> Result<Self> {
99        match value {
100            Value::Nothing => Ok(None),
101            _ => Ok(Some(T::from_edgedb_value(value)?)),
102        }
103    }
104
105    // fn to_edgedb_set_value(self) -> Result<Value> {
106    //     match self {
107    //         Some(v) => T::to_edgedb_value(v),
108    //         None => Ok(Value::Nothing),
109    //     }
110    // }
111
112    fn interpret_possibly_missing_required_value(val: Option<Self>) -> Result<Self> {
113        Ok(val.flatten())
114    }
115}
116
117impl<T: EdgedbValue> EdgedbSetValue for Vec<T> {
118    const EXPECTED_CARDINALITY: edgedb_protocol::server_message::Cardinality =
119        edgedb_protocol::server_message::Cardinality::Many;
120
121    fn from_edgedb_set_value(value: Value) -> Result<Self> {
122        match value {
123            Value::Nothing => {
124                // Ok(Vec::new())
125                todo!("Wrong cardinality/type (nothing), or just fine?..")
126            }
127            Value::Set(vals) => vals
128                .into_iter()
129                .map(|val| T::from_edgedb_value(val))
130                .collect(),
131            Value::Array(_vals) => {
132                todo!("Wrong cardinality/type (array), or just fine?..")
133            }
134            Value::Object {
135                shape: _,
136                fields: _,
137            } => {
138                todo!("Wrong cardinality/type (object), or just fine?..")
139            }
140            _ => Err(anyhow::anyhow!("expected object")),
141        }
142    }
143
144    // fn to_edgedb_set_value(self) -> Result<Value> {
145    //     let vs = self
146    //         .into_iter()
147    //         .map(|v| v.to_edgedb_value())
148    //         .collect::<Result<_>>()?;
149
150    //     Ok(Value::Set(vs))
151    // }
152
153    async fn query_direct<Args: EdgedbQueryArgs + Send>(
154        client: &Client,
155        q: &str,
156        args: Args,
157    ) -> Result<Self> {
158        let val = client.query::<Value, _>(q, &args.to_query_args()?).await?;
159
160        let val = val
161            .into_iter()
162            .map(|val| T::from_edgedb_value(val))
163            .collect::<Result<_>>()?;
164
165        Ok(val)
166    }
167
168    fn interpret_possibly_missing_required_value(val: Option<Self>) -> Result<Self> {
169        Ok(val.unwrap_or_default())
170    }
171}
172
173impl<T: EdgedbValue> EdgedbSetValue for NonEmpty<T> {
174    const EXPECTED_CARDINALITY: edgedb_protocol::server_message::Cardinality =
175        edgedb_protocol::server_message::Cardinality::AtLeastOne;
176
177    fn from_edgedb_set_value(value: Value) -> Result<Self> {
178        match value {
179            Value::Nothing => {
180                todo!("NonEmpty: Wrong cardinality/type (nothing), or just fine?..")
181            }
182            Value::Set(vals) => {
183                let vs = vals
184                    .into_iter()
185                    .map(|val| T::from_edgedb_value(val))
186                    .collect::<Result<_>>()?;
187
188                NonEmpty::from_vec(vs).ok_or_else(|| anyhow::anyhow!("expected non-empty set"))
189            }
190            Value::Array(_vals) => {
191                todo!("NonEmpty: Wrong cardinality/type (array), or just fine?..")
192            }
193            Value::Object {
194                shape: _,
195                fields: _,
196            } => {
197                todo!("NonEmpty: Wrong cardinality/type (object), or just fine?..")
198            }
199            _ => Err(anyhow::anyhow!("expected object")),
200        }
201    }
202
203    // fn to_edgedb_set_value(self) -> Result<Value> {
204    //     let vs = self
205    //         .into_iter()
206    //         .map(|v| v.to_edgedb_value())
207    //         .collect::<Result<_>>()?;
208
209    //     Ok(Value::Set(vs))
210    // }
211
212    async fn query_direct<Args: EdgedbQueryArgs + Send>(
213        client: &Client,
214        q: &str,
215        args: Args,
216    ) -> Result<Self> {
217        let val = client.query::<Value, _>(q, &args.to_query_args()?).await?;
218        let val = val
219            .into_iter()
220            .map(|val| T::from_edgedb_value(val))
221            .collect::<Result<_>>()?;
222        NonEmpty::from_vec(val).ok_or_else(|| anyhow::anyhow!("expected non-empty set"))
223    }
224
225    fn interpret_possibly_missing_required_value(val: Option<Self>) -> Result<Self> {
226        val.ok_or_else(|| anyhow::anyhow!("expected non-empty set"))
227    }
228}