use crate::{
SdkError,
types::{FieldDefinition, SubgraphSchema},
wit,
};
use serde::{Deserialize, de::DeserializeSeed};
use super::DefinitionId;
#[derive(Clone, Copy)]
pub struct Field<'a> {
pub(crate) fields: &'a [wit::Field],
pub(crate) field: &'a wit::Field,
}
impl<'a> Field<'a> {
pub fn alias(&self) -> Option<&'a str> {
self.field.alias.as_deref()
}
pub fn arguments_id(&self) -> Option<ArgumentsId> {
self.field.arguments.map(ArgumentsId)
}
pub fn definition<'s>(&self, schema: &'s SubgraphSchema) -> FieldDefinition<'s> {
schema
.field_definition(self.definition_id())
.expect("Field definition not found, the wrong subgraph may have been used.")
}
pub fn definition_id(&self) -> DefinitionId {
DefinitionId(self.field.definition_id)
}
pub fn arguments<'de, T>(&self, variables: &'de Variables) -> Result<T, SdkError>
where
T: Deserialize<'de>,
{
match self.field.arguments {
Some(id) => variables.get(id.into()),
None => Ok(T::deserialize(serde_json::json!({}))?),
}
}
pub fn arguments_seed<'de, Seed>(&self, variables: &'de Variables, seed: Seed) -> Result<Seed::Value, SdkError>
where
Seed: DeserializeSeed<'de>,
{
match self.field.arguments {
Some(id) => variables.get_seed(id.into(), seed),
None => Ok(seed.deserialize(serde_json::json!({}))?),
}
}
pub fn selection_set(&self) -> SelectionSet<'a> {
self.field
.selection_set
.map(|selection_set| SelectionSet {
fields: self.fields,
selection_set,
})
.unwrap_or_else(|| SelectionSet {
fields: &[],
selection_set: wit::SelectionSet {
fields_ordered_by_parent_entity: (0, 0),
requires_typename: false,
},
})
}
}
#[derive(Clone, Copy)]
pub struct SelectionSet<'a> {
fields: &'a [wit::Field],
selection_set: wit::SelectionSet,
}
impl<'a> SelectionSet<'a> {
pub fn is_empty(&self) -> bool {
self.fields().len() == 0
}
pub fn fields(&self) -> impl ExactSizeIterator<Item = Field<'a>> + 'a {
self.fields_ordered_by_parent_entity()
}
pub fn fields_ordered_by_parent_entity(&self) -> impl ExactSizeIterator<Item = Field<'a>> + 'a {
let (start, end) = self.selection_set.fields_ordered_by_parent_entity;
let fields = self.fields;
fields[usize::from(start)..usize::from(end)]
.iter()
.map(move |field| Field { fields, field })
}
pub fn requires_typename(&self) -> bool {
self.selection_set.requires_typename
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ArgumentsId(wit::ArgumentsId);
impl From<wit::ArgumentsId> for ArgumentsId {
fn from(id: wit::ArgumentsId) -> Self {
Self(id)
}
}
pub struct Variables(Vec<(wit::ArgumentsId, Vec<u8>)>);
impl std::fmt::Debug for Variables {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Variables").finish_non_exhaustive()
}
}
impl From<Vec<(wit::ArgumentsId, Vec<u8>)>> for Variables {
fn from(values: Vec<(wit::ArgumentsId, Vec<u8>)>) -> Self {
Self(values)
}
}
impl Variables {
pub fn get<'de, T>(&'de self, id: ArgumentsId) -> Result<T, SdkError>
where
T: Deserialize<'de>,
{
let bytes = self.get_bytes(id);
crate::cbor::from_slice(bytes).map_err(Into::into)
}
pub fn get_seed<'de, Seed>(&'de self, id: ArgumentsId, seed: Seed) -> Result<Seed::Value, SdkError>
where
Seed: DeserializeSeed<'de>,
{
let bytes = self.get_bytes(id);
crate::cbor::from_slice_with_seed(bytes, seed).map_err(Into::into)
}
fn get_bytes(&self, id: ArgumentsId) -> &[u8] {
self.0
.iter()
.find_map(|(args_id, args)| if *args_id == id.0 { Some(args.as_slice()) } else { None })
.unwrap()
}
}