edgedb_composable_query/
refs.rs1use edgedb_protocol::{model::Uuid, value::Value};
2use itertools::Itertools;
3
4use crate::{prim::EdgedbPrim, value::EdgedbValue, EdgedbObject};
5
6#[derive(Debug, PartialEq, Eq)]
8pub struct Ref<T: EdgedbObject> {
9 pub id: Uuid,
10 pub known_value: Option<T>,
11}
12
13impl<T: EdgedbObject> EdgedbValue for Ref<T> {
14 type NativeArgType = Value;
15
16 fn from_edgedb_value(value: edgedb_protocol::value::Value) -> anyhow::Result<Self> {
17 match value {
18 edgedb_protocol::value::Value::Object { shape, mut fields } => {
19 let uuid_i = shape
20 .elements
21 .iter()
22 .find_position(|e| e.name == "id")
23 .map(|(i, _)| i);
24
25 let id = uuid_i.and_then(|i| fields[i].take());
26 let id = Uuid::from_edgedb_val(id.ok_or_else(|| anyhow::anyhow!("Expected an object with an 'id' field when deserializing a Ref, got something else"))?)?;
27
28 if shape.elements.len() == 1 {
29 return Ok(Self {
30 id,
31 known_value: None,
32 });
33 }
34
35 let known_value = Some(T::from_edgedb_object(shape, fields)?);
55
56 Ok(Self { id, known_value })
57 }
58 edgedb_protocol::value::Value::Uuid(_) => {
59 anyhow::bail!("Expected an object when deserializing a Ref, got uuid (do we want to handle this?)")
60 }
61 edgedb_protocol::value::Value::SparseObject(_) => {
62 anyhow::bail!("Expected an object when deserializing a Ref, got sparse object (?)")
63 }
64 _ => {
65 anyhow::bail!("Expected an object when deserializing a Ref, got something else")
66 }
67 }
68 }
69
70 }
74
75#[cfg(test)]
76mod test {
77 use crate::{value::EdgedbSetValue, EdgedbObject};
78
79 #[derive(Debug, PartialEq)]
80 struct Inner {
81 req: String,
82 opt: Option<String>,
83 }
84
85 impl EdgedbObject for Inner {
86 fn from_edgedb_object(
87 shape: edgedb_protocol::codec::ObjectShape,
88 mut fields: Vec<Option<edgedb_protocol::value::Value>>,
89 ) -> anyhow::Result<Self> {
90 let mut req = None;
91 let mut opt = None;
92
93 for (i, s) in shape.elements.iter().enumerate() {
94 match s.name.as_str() {
95 "req" => {
96 req = fields[i]
97 .take()
98 .map(EdgedbSetValue::from_edgedb_set_value)
99 .transpose()?;
100 }
101 "opt" => {
102 opt = fields[i]
103 .take()
104 .map(EdgedbSetValue::from_edgedb_set_value)
105 .transpose()?;
106 }
107 _ => {}
108 }
109 }
110
111 Ok(Self {
112 req: EdgedbSetValue::interpret_possibly_missing_required_value(req)?,
113 opt: EdgedbSetValue::interpret_possibly_missing_required_value(opt)?,
114 })
115 }
116
117 }
126
127 #[tokio::test]
128 async fn some_queries() -> anyhow::Result<()> {
129 let _conn = edgedb_tokio::create_client().await?;
130
131 Ok(())
135 }
136}