gel_protocol/
queryable.rs

1/*!
2Contains the [Queryable] trait.
3*/
4use snafu::{ensure, Snafu};
5use std::default::Default;
6use std::sync::Arc;
7
8use crate::codec::{build_codec, Codec};
9use crate::descriptors::{Descriptor, TypePos};
10use crate::errors::{self, DecodeError};
11use gel_errors::{Error, ErrorKind, ProtocolEncodingError};
12
13#[non_exhaustive]
14#[derive(Default)]
15pub struct Decoder {
16    pub has_implicit_id: bool,
17    pub has_implicit_tid: bool,
18    pub has_implicit_tname: bool,
19}
20
21pub trait Queryable: Sized {
22    /// Data returned by [Queryable::check_descriptor], that can be used during decoding.
23    /// For example, this is used to pass the order of object pointers (which is sent in
24    /// type descriptors) to decode function.
25    type Args;
26
27    fn decode(decoder: &Decoder, args: &Self::Args, buf: &[u8]) -> Result<Self, DecodeError>;
28    fn decode_optional(
29        decoder: &Decoder,
30        args: &Self::Args,
31        buf: Option<&[u8]>,
32    ) -> Result<Self, DecodeError> {
33        ensure!(buf.is_some(), errors::MissingRequiredElement);
34        Self::decode(decoder, args, buf.unwrap())
35    }
36    fn check_descriptor(
37        ctx: &DescriptorContext,
38        type_pos: TypePos,
39    ) -> Result<Self::Args, DescriptorMismatch>;
40}
41
42#[derive(Snafu, Debug)]
43#[non_exhaustive]
44pub enum DescriptorMismatch {
45    #[snafu(display("unexpected type {}, expected {}", unexpected, expected))]
46    WrongType {
47        unexpected: String,
48        expected: String,
49    },
50    #[snafu(display("unexpected field {}, expected {}", unexpected, expected))]
51    WrongField {
52        unexpected: String,
53        expected: String,
54    },
55    #[snafu(display("expected {} fields, got {}", expected, unexpected))]
56    FieldNumber { unexpected: usize, expected: usize },
57    #[snafu(display("expected {}", expected))]
58    Expected { expected: String },
59    #[snafu(display("invalid type descriptor"))]
60    InvalidDescriptor,
61}
62
63pub struct DescriptorContext<'a> {
64    pub has_implicit_id: bool,
65    pub has_implicit_tid: bool,
66    pub has_implicit_tname: bool,
67    descriptors: &'a [Descriptor],
68}
69
70impl DescriptorContext<'_> {
71    pub(crate) fn new(descriptors: &[Descriptor]) -> DescriptorContext {
72        DescriptorContext {
73            descriptors,
74            has_implicit_id: false,
75            has_implicit_tid: false,
76            has_implicit_tname: false,
77        }
78    }
79    pub fn build_codec(&self, root_pos: TypePos) -> Result<Arc<dyn Codec>, Error> {
80        build_codec(Some(root_pos), self.descriptors).map_err(ProtocolEncodingError::with_source)
81    }
82    pub fn get(&self, type_pos: TypePos) -> Result<&Descriptor, DescriptorMismatch> {
83        self.descriptors
84            .get(type_pos.0 as usize)
85            .ok_or(DescriptorMismatch::InvalidDescriptor)
86    }
87    pub fn wrong_type(&self, descriptor: &Descriptor, expected: &str) -> DescriptorMismatch {
88        DescriptorMismatch::WrongType {
89            unexpected: format!("{descriptor:?}"),
90            expected: expected.into(),
91        }
92    }
93    pub fn field_number(&self, expected: usize, unexpected: usize) -> DescriptorMismatch {
94        DescriptorMismatch::FieldNumber {
95            expected,
96            unexpected,
97        }
98    }
99    pub fn wrong_field(&self, expected: &str, unexpected: &str) -> DescriptorMismatch {
100        DescriptorMismatch::WrongField {
101            expected: expected.into(),
102            unexpected: unexpected.into(),
103        }
104    }
105    pub fn expected(&self, expected: &str) -> DescriptorMismatch {
106        DescriptorMismatch::Expected {
107            expected: expected.into(),
108        }
109    }
110}