1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use arbitrary::Result;
use crate::{
field::Field,
fragment::{FragmentSpread, InlineFragment},
name::Name,
DocumentBuilder,
};
#[derive(Debug)]
pub struct SelectionSet {
selections: Vec<Selection>,
}
impl From<SelectionSet> for apollo_encoder::SelectionSet {
fn from(sel_set: SelectionSet) -> Self {
let mut new_sel_set = Self::new();
sel_set
.selections
.into_iter()
.for_each(|selection| new_sel_set.selection(selection.into()));
new_sel_set
}
}
#[cfg(feature = "parser-impl")]
impl TryFrom<apollo_parser::ast::SelectionSet> for SelectionSet {
type Error = crate::FromError;
fn try_from(selection_set: apollo_parser::ast::SelectionSet) -> Result<Self, Self::Error> {
Ok(Self {
selections: selection_set
.selections()
.map(Selection::try_from)
.collect::<Result<_, _>>()?,
})
}
}
#[derive(Debug)]
pub enum Selection {
Field(Field),
FragmentSpread(FragmentSpread),
InlineFragment(InlineFragment),
}
impl From<Selection> for apollo_encoder::Selection {
fn from(selection: Selection) -> Self {
match selection {
Selection::Field(field) => Self::Field(field.into()),
Selection::FragmentSpread(fragment_spread) => {
Self::FragmentSpread(fragment_spread.into())
}
Selection::InlineFragment(inline_fragment) => {
Self::InlineFragment(inline_fragment.into())
}
}
}
}
#[cfg(feature = "parser-impl")]
impl TryFrom<apollo_parser::ast::Selection> for Selection {
type Error = crate::FromError;
fn try_from(selection: apollo_parser::ast::Selection) -> Result<Self, Self::Error> {
match selection {
apollo_parser::ast::Selection::Field(field) => field.try_into().map(Self::Field),
apollo_parser::ast::Selection::FragmentSpread(fragment_spread) => {
fragment_spread.try_into().map(Self::FragmentSpread)
}
apollo_parser::ast::Selection::InlineFragment(inline_fragment) => {
inline_fragment.try_into().map(Self::InlineFragment)
}
}
}
}
impl<'a> DocumentBuilder<'a> {
pub fn selection_set(&mut self) -> Result<SelectionSet> {
let mut exclude_names = Vec::new();
let selection_nb = std::cmp::max(
self.stack.last().map(|o| o.fields_def().len()).unwrap_or(7),
3,
);
let selections = (0..self.u.int_in_range(2..=selection_nb)?)
.map(|index| self.selection(index, &mut exclude_names)) .collect::<Result<Vec<_>>>()?;
Ok(SelectionSet { selections })
}
pub fn selection(&mut self, index: usize, excludes: &mut Vec<Name>) -> Result<Selection> {
let selection = match self.u.int_in_range(0..=2usize)? {
0 => Selection::Field(self.field(index)?),
1 => match self.fragment_spread(excludes)? {
Some(frag_spread) => Selection::FragmentSpread(frag_spread),
None => Selection::Field(self.field(index)?),
},
2 => Selection::InlineFragment(self.inline_fragment()?),
_ => unreachable!(),
};
Ok(selection)
}
}