1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/*!
Contains the [QueryResult](crate::query_result::QueryResult) trait.
*/

use std::sync::Arc;

use bytes::Bytes;

use edgedb_errors::{DescriptorMismatch, ProtocolEncodingError};
use edgedb_errors::{Error, ErrorKind};

use crate::codec::Codec;
use crate::descriptors::TypePos;
use crate::queryable::{Decoder, DescriptorContext, Queryable};
use crate::value::Value;

pub trait Sealed: Sized {}

/// A trait representing single result from a query.
///
/// This is implemented for scalars and tuples. To receive a shape from EdgeDB
/// derive [`Queryable`](Queryable) for a structure. This will automatically
/// implement `QueryResult` for you.
pub trait QueryResult: Sealed {
    type State;
    fn prepare(ctx: &DescriptorContext, root_pos: TypePos) -> Result<Self::State, Error>;
    fn decode(state: &mut Self::State, msg: &Bytes) -> Result<Self, Error>;
}

impl<T: Queryable> Sealed for T {}

impl Sealed for Value {}

impl<T: Queryable> QueryResult for T {
    type State = Decoder;
    fn prepare(ctx: &DescriptorContext, root_pos: TypePos) -> Result<Decoder, Error> {
        T::check_descriptor(ctx, root_pos).map_err(DescriptorMismatch::with_source)?;
        Ok(Decoder {
            has_implicit_id: ctx.has_implicit_id,
            has_implicit_tid: ctx.has_implicit_tid,
            has_implicit_tname: ctx.has_implicit_tname,
        })
    }
    fn decode(decoder: &mut Decoder, msg: &Bytes) -> Result<Self, Error> {
        Queryable::decode(decoder, msg).map_err(ProtocolEncodingError::with_source)
    }
}

impl QueryResult for Value {
    type State = Arc<dyn Codec>;
    fn prepare(ctx: &DescriptorContext, root_pos: TypePos) -> Result<Arc<dyn Codec>, Error> {
        ctx.build_codec(root_pos)
    }
    fn decode(codec: &mut Arc<dyn Codec>, msg: &Bytes) -> Result<Self, Error> {
        codec
            .decode(msg)
            .map_err(ProtocolEncodingError::with_source)
    }
}