bluejay_parser/ast/executable/
selection.rs

1use crate::ast::executable::{Field, FragmentSpread, InlineFragment};
2use crate::ast::{DepthLimiter, FromTokens, IsMatch, ParseError, Tokens};
3use crate::lexical_token::PunctuatorType;
4use bluejay_core::executable::{Selection as CoreSelection, SelectionReference};
5
6#[derive(Debug)]
7pub enum Selection<'a> {
8    Field(Field<'a>),
9    FragmentSpread(FragmentSpread<'a>),
10    InlineFragment(InlineFragment<'a>),
11}
12
13impl<'a> CoreSelection for Selection<'a> {
14    type Field = Field<'a>;
15    type FragmentSpread = FragmentSpread<'a>;
16    type InlineFragment = InlineFragment<'a>;
17
18    fn as_ref(&self) -> SelectionReference<'_, Self> {
19        match self {
20            Self::Field(f) => SelectionReference::Field(f),
21            Self::FragmentSpread(fs) => SelectionReference::FragmentSpread(fs),
22            Self::InlineFragment(i) => SelectionReference::InlineFragment(i),
23        }
24    }
25}
26
27impl<'a> FromTokens<'a> for Selection<'a> {
28    #[inline]
29    fn from_tokens(
30        tokens: &mut impl Tokens<'a>,
31        depth_limiter: DepthLimiter,
32    ) -> Result<Self, ParseError> {
33        // don't bump depth limiters because this is just a thin wrapper in the AST
34        if Field::is_match(tokens) {
35            Field::from_tokens(tokens, depth_limiter).map(Self::Field)
36        } else if FragmentSpread::is_match(tokens) {
37            FragmentSpread::from_tokens(tokens, depth_limiter).map(Self::FragmentSpread)
38        } else if InlineFragment::is_match(tokens) {
39            InlineFragment::from_tokens(tokens, depth_limiter).map(Self::InlineFragment)
40        } else {
41            Err(tokens.unexpected_token())
42        }
43    }
44}
45
46impl<'a> IsMatch<'a> for Selection<'a> {
47    #[inline]
48    fn is_match(tokens: &mut impl Tokens<'a>) -> bool {
49        Field::is_match(tokens) || tokens.peek_punctuator_matches(0, PunctuatorType::Ellipse)
50    }
51}