use serde::{Deserialize, Serialize};
use super::argument::ArgumentDefinition;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DirectiveDefinition {
pub name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub locations: Vec<DirectiveLocationKind>,
#[serde(default)]
pub arguments: Vec<ArgumentDefinition>,
#[serde(default)]
pub is_repeatable: bool,
}
impl DirectiveDefinition {
#[must_use]
pub fn new(name: impl Into<String>, locations: Vec<DirectiveLocationKind>) -> Self {
Self {
name: name.into(),
description: None,
locations,
arguments: Vec::new(),
is_repeatable: false,
}
}
#[must_use]
pub fn with_description(mut self, description: impl Into<String>) -> Self {
self.description = Some(description.into());
self
}
#[must_use]
pub fn with_argument(mut self, arg: ArgumentDefinition) -> Self {
self.arguments.push(arg);
self
}
#[must_use]
pub fn with_arguments(mut self, args: Vec<ArgumentDefinition>) -> Self {
self.arguments = args;
self
}
#[must_use]
pub const fn repeatable(mut self) -> Self {
self.is_repeatable = true;
self
}
#[must_use]
pub fn valid_at(&self, location: DirectiveLocationKind) -> bool {
self.locations.contains(&location)
}
#[must_use]
pub fn find_argument(&self, name: &str) -> Option<&ArgumentDefinition> {
self.arguments.iter().find(|a| a.name == name)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
#[non_exhaustive]
pub enum DirectiveLocationKind {
Query,
Mutation,
Subscription,
Field,
FragmentDefinition,
FragmentSpread,
InlineFragment,
VariableDefinition,
Schema,
Scalar,
Object,
FieldDefinition,
ArgumentDefinition,
Interface,
Union,
Enum,
EnumValue,
InputObject,
InputFieldDefinition,
}
impl DirectiveLocationKind {
#[must_use]
pub const fn is_executable(&self) -> bool {
matches!(
self,
Self::Query
| Self::Mutation
| Self::Subscription
| Self::Field
| Self::FragmentDefinition
| Self::FragmentSpread
| Self::InlineFragment
| Self::VariableDefinition
)
}
#[must_use]
pub const fn is_type_system(&self) -> bool {
!self.is_executable()
}
}