grafbase_sdk/types/
selection_set.rs1use std::borrow::Cow;
2
3use crate::{SdkError, wit::selection_set_resolver_types as wit};
4use serde::{Deserialize, de::DeserializeSeed};
5
6use super::DefinitionId;
7
8#[derive(Clone, Copy)]
10pub struct Field<'a> {
11 pub(crate) fields: &'a [wit::Field],
12 pub(crate) field: &'a wit::Field,
13}
14
15impl<'a> Field<'a> {
16 pub fn alias(&self) -> Option<&str> {
18 self.field.alias.as_deref()
19 }
20
21 pub fn arguments_id(&self) -> Option<ArgumentsId> {
23 self.field.arguments.map(ArgumentsId)
24 }
25
26 pub fn definition_id(&self) -> DefinitionId {
28 DefinitionId(self.field.definition_id)
29 }
30
31 pub fn arguments<'de, T>(&self, values: ArgumentValues<'de>) -> Result<T, SdkError>
33 where
34 T: Deserialize<'de>,
35 {
36 match self.field.arguments {
37 Some(id) => values.get(id.into()),
38 None => Err(SdkError::from("Field has no arguments".to_string())),
39 }
40 }
41
42 pub fn arguments_seed<'de, Seed>(&self, seed: Seed, values: ArgumentValues<'de>) -> Result<Seed::Value, SdkError>
44 where
45 Seed: DeserializeSeed<'de>,
46 {
47 match self.field.arguments {
48 Some(id) => values.get_seed(id.into(), seed),
49 None => Err(SdkError::from("Field has no arguments".to_string())),
50 }
51 }
52
53 pub fn selection_set(&self) -> SelectionSet<'a> {
55 self.field
56 .selection_set
57 .map(|selection_set| SelectionSet {
58 fields: self.fields,
59 selection_set,
60 })
61 .unwrap_or_else(|| SelectionSet {
62 fields: &[],
63 selection_set: wit::SelectionSet {
64 fields_ordered_by_parent_entity: (0, 0),
65 requires_typename: false,
66 },
67 })
68 }
69
70 pub fn into_bytes(&self) -> Vec<u8> {
72 postcard::to_stdvec(&Data {
73 fields: Cow::Borrowed(self.fields),
74 ix: element_offset(self.fields, self.field).unwrap(),
75 })
76 .unwrap()
77 }
78
79 pub fn with_bytes<T>(data: &[u8], f: impl FnOnce(Field<'_>) -> T) -> Result<T, SdkError> {
81 match postcard::from_bytes(data) {
82 Ok(Data { fields, ix }) => {
83 let field = fields.get(ix).ok_or("Field index out of bounds")?;
84 Ok(f(Field {
85 fields: fields.as_ref(),
86 field,
87 }))
88 }
89 Err(err) => Err(format!("Failed to deserialize field data: {err}").into()),
90 }
91 }
92}
93
94fn element_offset(slice: &[wit::Field], element: &wit::Field) -> Option<usize> {
96 let self_start = slice.as_ptr().addr();
97 let elem_start = std::ptr::from_ref(element).addr();
98
99 let byte_offset = elem_start.wrapping_sub(self_start);
100
101 if byte_offset % std::mem::size_of::<wit::Field>() != 0 {
102 return None;
103 }
104
105 let offset = byte_offset / std::mem::size_of::<wit::Field>();
106
107 if offset < slice.len() { Some(offset) } else { None }
108}
109
110#[derive(serde::Serialize, serde::Deserialize)]
111struct Data<'a> {
112 fields: Cow<'a, [wit::Field]>,
113 ix: usize,
114}
115
116#[derive(Clone, Copy)]
120pub struct SelectionSet<'a> {
121 fields: &'a [wit::Field],
122 selection_set: wit::SelectionSet,
123}
124
125impl<'a> SelectionSet<'a> {
126 pub fn is_empty(&self) -> bool {
128 self.fields().len() == 0
129 }
130
131 pub fn fields(&self) -> impl ExactSizeIterator<Item = Field<'a>> + 'a {
134 self.fields_ordered_by_parent_entity()
135 }
136
137 pub fn fields_ordered_by_parent_entity(&self) -> impl ExactSizeIterator<Item = Field<'a>> + 'a {
141 let (start, end) = self.selection_set.fields_ordered_by_parent_entity;
142 let fields = self.fields;
143 fields[usize::from(start)..usize::from(end)]
144 .iter()
145 .map(move |field| Field { fields, field })
146 }
147
148 pub fn requires_typename(&self) -> bool {
152 self.selection_set.requires_typename
153 }
154}
155
156#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
158pub struct ArgumentsId(wit::ArgumentsId);
159
160impl From<wit::ArgumentsId> for ArgumentsId {
161 fn from(id: wit::ArgumentsId) -> Self {
162 Self(id)
163 }
164}
165
166#[derive(Clone, Copy)]
168pub struct ArgumentValues<'a>(pub(crate) &'a [(wit::ArgumentsId, Vec<u8>)]);
169
170impl<'a> ArgumentValues<'a> {
171 pub fn get<T>(&self, id: ArgumentsId) -> Result<T, SdkError>
173 where
174 T: Deserialize<'a>,
175 {
176 let bytes = self.get_bytes(id);
177 crate::cbor::from_slice(bytes).map_err(Into::into)
178 }
179
180 pub fn get_seed<Seed>(&self, id: ArgumentsId, seed: Seed) -> Result<Seed::Value, SdkError>
182 where
183 Seed: DeserializeSeed<'a>,
184 {
185 let bytes = self.get_bytes(id);
186 crate::cbor::from_slice_with_seed(bytes, seed).map_err(Into::into)
187 }
188
189 fn get_bytes(&self, id: ArgumentsId) -> &'a [u8] {
190 self.0
191 .iter()
192 .find_map(|(args_id, args)| if *args_id == id.0 { Some(args.as_slice()) } else { None })
193 .unwrap()
194 }
195}