use super::*;
#[derive(Debug, Clone)]
pub struct ExecutableDocument {
pub definitions: Vec<ExecutableDefinition>,
}
impl ExecutableDocument {
#[must_use]
pub fn into_data(self, operation_name: Option<&str>) -> Option<ExecutableDocumentData> {
let mut operation = None;
let mut fragments = HashMap::new();
for definition in self.definitions {
match definition {
ExecutableDefinition::Operation(op)
if operation_name
.zip(op.node.name.as_ref())
.map_or(false, |(required_name, op_name)| {
required_name != op_name.node
}) => {}
ExecutableDefinition::Operation(op) => {
operation.get_or_insert(op);
}
ExecutableDefinition::Fragment(fragment) => {
fragments.insert(fragment.node.name.node.clone(), fragment);
}
}
}
operation.map(|operation| ExecutableDocumentData {
operation,
fragments,
})
}
}
#[derive(Debug, Clone)]
pub struct ExecutableDocumentData {
pub operation: Positioned<OperationDefinition>,
pub fragments: HashMap<Name, Positioned<FragmentDefinition>>,
}
#[derive(Debug, Clone)]
pub enum ExecutableDefinition {
Operation(Positioned<OperationDefinition>),
Fragment(Positioned<FragmentDefinition>),
}
impl ExecutableDefinition {
#[must_use]
pub fn pos(&self) -> Pos {
match self {
Self::Operation(op) => op.pos,
Self::Fragment(frag) => frag.pos,
}
}
#[must_use]
pub fn directives(&self) -> &Vec<Positioned<Directive>> {
match self {
Self::Operation(op) => &op.node.directives,
Self::Fragment(frag) => &frag.node.directives,
}
}
#[must_use]
pub fn directives_mut(&mut self) -> &mut Vec<Positioned<Directive>> {
match self {
Self::Operation(op) => &mut op.node.directives,
Self::Fragment(frag) => &mut frag.node.directives,
}
}
}
#[derive(Debug, Clone)]
pub struct OperationDefinition {
pub ty: OperationType,
pub name: Option<Positioned<Name>>,
pub variable_definitions: Vec<Positioned<VariableDefinition>>,
pub directives: Vec<Positioned<Directive>>,
pub selection_set: Positioned<SelectionSet>,
}
#[derive(Debug, Clone)]
pub struct VariableDefinition {
pub name: Positioned<Name>,
pub var_type: Positioned<Type>,
pub default_value: Option<Positioned<ConstValue>>,
}
impl VariableDefinition {
#[must_use]
pub fn default_value(&self) -> Option<&ConstValue> {
self.default_value
.as_ref()
.map(|value| &value.node)
.or_else(|| {
if self.var_type.node.nullable {
Some(&ConstValue::Null)
} else {
None
}
})
}
}
#[derive(Debug, Default, Clone)]
pub struct SelectionSet {
pub items: Vec<Positioned<Selection>>,
}
#[derive(Debug, Clone)]
pub enum Selection {
Field(Positioned<Field>),
FragmentSpread(Positioned<FragmentSpread>),
InlineFragment(Positioned<InlineFragment>),
}
impl Selection {
#[must_use]
pub fn directives(&self) -> &Vec<Positioned<Directive>> {
match self {
Self::Field(field) => &field.node.directives,
Self::FragmentSpread(spread) => &spread.node.directives,
Self::InlineFragment(fragment) => &fragment.node.directives,
}
}
#[must_use]
pub fn directives_mut(&mut self) -> &mut Vec<Positioned<Directive>> {
match self {
Self::Field(field) => &mut field.node.directives,
Self::FragmentSpread(spread) => &mut spread.node.directives,
Self::InlineFragment(fragment) => &mut fragment.node.directives,
}
}
}
#[derive(Debug, Clone)]
pub struct Field {
pub alias: Option<Positioned<Name>>,
pub name: Positioned<Name>,
pub arguments: Vec<(Positioned<Name>, Positioned<Value>)>,
pub directives: Vec<Positioned<Directive>>,
pub selection_set: Positioned<SelectionSet>,
}
impl Field {
#[must_use]
pub fn response_key(&self) -> &Positioned<Name> {
self.alias.as_ref().unwrap_or(&self.name)
}
#[must_use]
pub fn get_argument(&self, name: &str) -> Option<&Positioned<Value>> {
self.arguments
.iter()
.find(|item| item.0.node == name)
.map(|item| &item.1)
}
}
#[derive(Debug, Clone)]
pub struct FragmentSpread {
pub fragment_name: Positioned<Name>,
pub directives: Vec<Positioned<Directive>>,
}
#[derive(Debug, Clone)]
pub struct InlineFragment {
pub type_condition: Option<Positioned<TypeCondition>>,
pub directives: Vec<Positioned<Directive>>,
pub selection_set: Positioned<SelectionSet>,
}
#[derive(Debug, Clone)]
pub struct FragmentDefinition {
pub name: Positioned<Name>,
pub type_condition: Positioned<TypeCondition>,
pub directives: Vec<Positioned<Directive>>,
pub selection_set: Positioned<SelectionSet>,
}
#[derive(Debug, Clone)]
pub struct TypeCondition {
pub on: Positioned<Name>,
}