edgedb_composable_query/
value.rs1pub use crate::Result;
2use crate::{args::EdgedbQueryArgs, EdgedbObject};
3use edgedb_tokio::Client;
4pub use nonempty::{nonempty, NonEmpty};
5
6use edgedb_protocol::value::Value;
7
8pub trait EdgedbValue: Sized {
10 type NativeArgType;
12
13 fn from_edgedb_value(value: Value) -> Result<Self>;
14 }
16
17pub 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 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 }
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 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 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 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 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 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}