grafbase_sdk/types/
elements.rs

1use crate::{types::DirectiveSite, wit, SdkError};
2use serde::Deserialize;
3
4/// A list of elements present in the query on which one of the extension's directive was applied on their definition.
5#[derive(Clone, Copy)]
6pub struct QueryElements<'a>(&'a wit::QueryElements);
7
8impl<'a> From<&'a wit::QueryElements> for QueryElements<'a> {
9    fn from(value: &'a wit::QueryElements) -> Self {
10        Self(value)
11    }
12}
13
14// is never empty, otherwise we wouldn't call the extension at all
15#[allow(clippy::len_without_is_empty)]
16impl<'a> QueryElements<'a> {
17    /// Number of elements within the query
18    pub fn len(&self) -> usize {
19        self.0.elements.len()
20    }
21
22    /// Iterate over all elements, regardless of the directive they're associated with. Useful if
23    /// expect only one directive to be used.
24    pub fn iter(&self) -> impl ExactSizeIterator<Item = QueryElement<'a>> + 'a {
25        self.0
26            .elements
27            .iter()
28            .enumerate()
29            .map(move |(ix, element)| QueryElement { element, ix: ix as u32 })
30    }
31
32    /// Iterate over all elements grouped by the directive name.
33    pub fn iter_grouped_by_directive_name(
34        &self,
35    ) -> impl ExactSizeIterator<Item = (&'a str, impl ExactSizeIterator<Item = QueryElement<'a>> + 'a)> + 'a {
36        let query = self.0;
37        self.0.directive_names.iter().map(|(name, start, end)| {
38            let start = *start;
39            (
40                name.as_str(),
41                query.elements[start as usize..*end as usize]
42                    .iter()
43                    .enumerate()
44                    .map(move |(i, element)| QueryElement {
45                        element,
46                        ix: start + i as u32,
47                    }),
48            )
49        })
50    }
51}
52
53/// An element of the query on which a directive was applied.
54#[derive(Clone, Copy)]
55pub struct QueryElement<'a> {
56    element: &'a wit::QueryElement,
57    pub(super) ix: u32,
58}
59
60impl<'a> QueryElement<'a> {
61    /// Site, where and with which arguments, of the directive associated with this element.
62    /// The provided arguments will exclude anything that depend on response data such as
63    /// `FieldSet`.
64    pub fn site(&self) -> DirectiveSite<'a> {
65        (&self.element.site).into()
66    }
67
68    /// Arguments of the directive with any query data injected. Any argument that depends on
69    /// response data will not be present here and be provided separately.
70    pub fn arguments<T>(&self) -> Result<T, SdkError>
71    where
72        T: Deserialize<'a>,
73    {
74        minicbor_serde::from_slice(&self.element.arguments).map_err(Into::into)
75    }
76}