gel_protocol/
query_result.rs

1/*!
2Contains the [QueryResult](crate::query_result::QueryResult) trait.
3*/
4
5use std::sync::Arc;
6
7use bytes::Bytes;
8
9use gel_errors::{DescriptorMismatch, ProtocolEncodingError};
10use gel_errors::{Error, ErrorKind};
11
12use crate::codec::Codec;
13use crate::descriptors::TypePos;
14use crate::queryable::{Decoder, DescriptorContext, Queryable};
15use crate::value::Value;
16
17pub trait Sealed: Sized {}
18
19/// A trait representing single result from a query.
20///
21/// This is implemented for scalars and tuples. To receive a shape from Gel
22/// derive [`Queryable`](Queryable) for a structure. This will automatically
23/// implement `QueryResult` for you.
24pub trait QueryResult: Sealed {
25    type State;
26    fn prepare(ctx: &DescriptorContext, root_pos: TypePos) -> Result<Self::State, Error>;
27    fn decode(state: &mut Self::State, msg: &Bytes) -> Result<Self, Error>;
28}
29
30impl<T: Queryable> Sealed for T {}
31
32impl Sealed for Value {}
33
34impl<T: Queryable> QueryResult for T {
35    type State = (Decoder, T::Args);
36    fn prepare(ctx: &DescriptorContext, root_pos: TypePos) -> Result<Self::State, Error> {
37        let args = T::check_descriptor(ctx, root_pos).map_err(DescriptorMismatch::with_source)?;
38        let decoder = Decoder {
39            has_implicit_id: ctx.has_implicit_id,
40            has_implicit_tid: ctx.has_implicit_tid,
41            has_implicit_tname: ctx.has_implicit_tname,
42        };
43        Ok((decoder, args))
44    }
45    fn decode((decoder, args): &mut Self::State, msg: &Bytes) -> Result<Self, Error> {
46        Queryable::decode(decoder, args, msg).map_err(ProtocolEncodingError::with_source)
47    }
48}
49
50impl QueryResult for Value {
51    type State = Arc<dyn Codec>;
52    fn prepare(ctx: &DescriptorContext, root_pos: TypePos) -> Result<Arc<dyn Codec>, Error> {
53        ctx.build_codec(root_pos)
54    }
55    fn decode(codec: &mut Arc<dyn Codec>, msg: &Bytes) -> Result<Self, Error> {
56        let res = codec.decode(msg);
57
58        match res {
59            Ok(v) => Ok(v),
60            Err(e) => {
61                if let Some(bt) = snafu::ErrorCompat::backtrace(&e) {
62                    eprintln!("{bt}");
63                }
64                Err(ProtocolEncodingError::with_source(e))
65            }
66        }
67    }
68}