1use std::{
2 collections::HashMap,
3 sync::{Arc, RwLock},
4};
5
6use crate::{
7 ExecutionError, Executor, Selection, Variables,
8 ast::Fragment,
9 executor::FieldPath,
10 parser::SourcePosition,
11 schema::model::{SchemaType, TypeType},
12};
13
14pub struct OwnedExecutor<'a, CtxT, S> {
17 pub(super) fragments: HashMap<&'a str, Fragment<'a, S>>,
18 pub(super) variables: Variables<S>,
19 pub(super) current_selection_set: Option<Vec<Selection<'a, S>>>,
20 pub(super) parent_selection_set: Option<Vec<Selection<'a, S>>>,
21 pub(super) current_type: TypeType<'a, S>,
22 pub(super) schema: &'a SchemaType<S>,
23 pub(super) context: &'a CtxT,
24 pub(super) errors: RwLock<Vec<ExecutionError<S>>>,
25 pub(super) field_path: Arc<FieldPath<'a>>,
26}
27
28impl<CtxT, S> Clone for OwnedExecutor<'_, CtxT, S>
29where
30 S: Clone,
31{
32 fn clone(&self) -> Self {
33 Self {
34 fragments: self.fragments.clone(),
35 variables: self.variables.clone(),
36 current_selection_set: self.current_selection_set.clone(),
37 parent_selection_set: self.parent_selection_set.clone(),
38 current_type: self.current_type.clone(),
39 schema: self.schema,
40 context: self.context,
41 errors: RwLock::new(vec![]),
42 field_path: self.field_path.clone(),
43 }
44 }
45}
46
47impl<'a, CtxT, S> OwnedExecutor<'a, CtxT, S>
48where
49 S: Clone,
50{
51 #[doc(hidden)]
52 #[must_use]
53 pub fn type_sub_executor(
54 &self,
55 type_name: Option<&str>,
56 selection_set: Option<Vec<Selection<'a, S>>>,
57 ) -> OwnedExecutor<'a, CtxT, S> {
58 OwnedExecutor {
59 fragments: self.fragments.clone(),
60 variables: self.variables.clone(),
61 current_selection_set: selection_set,
62 parent_selection_set: self.current_selection_set.clone(),
63 current_type: match type_name {
64 Some(type_name) => self.schema.type_by_name(type_name).expect("Type not found"),
65 None => self.current_type.clone(),
66 },
67 schema: self.schema,
68 context: self.context,
69 errors: RwLock::new(vec![]),
70 field_path: self.field_path.clone(),
71 }
72 }
73
74 #[doc(hidden)]
75 pub fn variables(&self) -> Variables<S> {
76 self.variables.clone()
77 }
78
79 #[doc(hidden)]
80 #[must_use]
81 pub fn field_sub_executor(
82 &self,
83 field_alias: &'a str,
84 field_name: &'a str,
85 location: SourcePosition,
86 selection_set: Option<Vec<Selection<'a, S>>>,
87 ) -> OwnedExecutor<'a, CtxT, S> {
88 OwnedExecutor {
89 fragments: self.fragments.clone(),
90 variables: self.variables.clone(),
91 current_selection_set: selection_set,
92 parent_selection_set: self.current_selection_set.clone(),
93 current_type: self.schema.make_type(
94 &self
95 .current_type
96 .innermost_concrete()
97 .field_by_name(field_name)
98 .expect("Field not found on inner type")
99 .field_type,
100 ),
101 schema: self.schema,
102 context: self.context,
103 errors: RwLock::new(vec![]),
104 field_path: Arc::new(FieldPath::Field(
105 field_alias,
106 location,
107 Arc::clone(&self.field_path),
108 )),
109 }
110 }
111
112 #[doc(hidden)]
113 pub fn as_executor(&self) -> Executor<'_, '_, CtxT, S> {
114 Executor {
115 fragments: &self.fragments,
116 variables: &self.variables,
117 current_selection_set: self.current_selection_set.as_deref(),
118 parent_selection_set: self.parent_selection_set.as_deref(),
119 current_type: self.current_type.clone(),
120 schema: self.schema,
121 context: self.context,
122 errors: &self.errors,
123 field_path: Arc::clone(&self.field_path),
124 }
125 }
126}
127
128impl<'a, CtxT, S> OwnedExecutor<'a, CtxT, S> {
129 #[doc(hidden)]
130 pub fn fragment_by_name<'b>(&'b self, name: &str) -> Option<&'b Fragment<'a, S>> {
131 self.fragments.get(name)
132 }
133
134 #[doc(hidden)]
135 pub fn context(&self) -> &'a CtxT {
136 self.context
137 }
138
139 #[doc(hidden)]
140 pub fn schema(&self) -> &'a SchemaType<S> {
141 self.schema
142 }
143
144 #[doc(hidden)]
145 pub fn location(&self) -> &SourcePosition {
146 self.field_path.location()
147 }
148}