bluejay_parser/ast/definition/
field_definition.rs1use crate::ast::definition::{ArgumentsDefinition, Context, Directives, OutputType};
2use crate::ast::{
3 ConstDirectives, DepthLimiter, FromTokens, Parse, ParseError, Tokens, TryFromTokens,
4};
5use crate::lexical_token::{Name, PunctuatorType, StringValue};
6use bluejay_core::definition::{FieldDefinition as CoreFieldDefinition, HasDirectives};
7
8#[derive(Debug)]
9pub struct FieldDefinition<'a, C: Context> {
10 description: Option<StringValue<'a>>,
11 name: Name<'a>,
12 arguments_definition: Option<ArgumentsDefinition<'a, C>>,
13 r#type: OutputType<'a, C>,
14 directives: Option<Directives<'a, C>>,
15 is_builtin: bool,
16}
17
18impl<C: Context> FieldDefinition<'_, C> {
19 const __TYPENAME_DEFINITION: &'static str = "__typename: String!";
20 const __SCHEMA_DEFINITION: &'static str = "__schema: __Schema!";
21 const __TYPE_DEFINITION: &'static str = "__type(name: String!): __Type";
22
23 fn builtin(s: &'static str) -> Self {
24 let mut definition = Self::parse(s).unwrap();
25 definition.is_builtin = true;
26 definition
27 }
28
29 pub(crate) fn __typename() -> Self {
30 Self::builtin(Self::__TYPENAME_DEFINITION)
31 }
32
33 pub(crate) fn __schema() -> Self {
34 Self::builtin(Self::__SCHEMA_DEFINITION)
35 }
36
37 pub(crate) fn __type() -> Self {
38 Self::builtin(Self::__TYPE_DEFINITION)
39 }
40}
41
42impl<'a, C: Context> CoreFieldDefinition for FieldDefinition<'a, C> {
43 type ArgumentsDefinition = ArgumentsDefinition<'a, C>;
44 type OutputType = OutputType<'a, C>;
45
46 fn description(&self) -> Option<&str> {
47 self.description.as_ref().map(AsRef::as_ref)
48 }
49
50 fn name(&self) -> &str {
51 self.name.as_ref()
52 }
53
54 fn arguments_definition(&self) -> Option<&Self::ArgumentsDefinition> {
55 self.arguments_definition.as_ref()
56 }
57
58 fn r#type(&self) -> &Self::OutputType {
59 &self.r#type
60 }
61
62 fn is_builtin(&self) -> bool {
63 self.is_builtin
64 }
65}
66
67impl<'a, C: Context> FromTokens<'a> for FieldDefinition<'a, C> {
68 fn from_tokens(
69 tokens: &mut impl Tokens<'a>,
70 depth_limiter: DepthLimiter,
71 ) -> Result<Self, ParseError> {
72 let description = tokens.next_if_string_value();
73 let name = tokens.expect_name()?;
74 let arguments_definition =
75 ArgumentsDefinition::try_from_tokens(tokens, depth_limiter.bump()?).transpose()?;
76 tokens.expect_punctuator(PunctuatorType::Colon)?;
77 let r#type = OutputType::from_tokens(tokens, depth_limiter.bump()?)?;
78 let directives =
79 ConstDirectives::try_from_tokens(tokens, depth_limiter.bump()?).transpose()?;
80 Ok(Self {
81 description,
82 name,
83 arguments_definition,
84 r#type,
85 directives: directives.map(Directives::from),
86 is_builtin: false,
87 })
88 }
89}
90
91impl<'a, C: Context> HasDirectives for FieldDefinition<'a, C> {
92 type Directives = Directives<'a, C>;
93
94 fn directives(&self) -> Option<&Self::Directives> {
95 self.directives.as_ref()
96 }
97}