1use std::future;
2
3use auto_enums::enum_derive;
4
5use crate::{
6 ast::Selection,
7 executor::{ExecutionResult, Executor},
8 parser::Spanning,
9 value::{DefaultScalarValue, Object, ScalarValue, Value},
10};
11
12use crate::BoxFuture;
13
14use super::base::{Arguments, GraphQLType, GraphQLValue, is_excluded, merge_key_into};
15
16pub trait GraphQLValueAsync<S = DefaultScalarValue>: GraphQLValue<S> + Sync
21where
22 Self::TypeInfo: Sync,
23 Self::Context: Sync,
24 S: ScalarValue + Send + Sync,
25{
26 fn resolve_field_async<'a>(
39 &'a self,
40 _info: &'a Self::TypeInfo,
41 _field_name: &'a str,
42 _arguments: &'a Arguments<S>,
43 _executor: &'a Executor<Self::Context, S>,
44 ) -> BoxFuture<'a, ExecutionResult<S>> {
45 panic!(
46 "GraphQLValueAsync::resolve_field_async() must be implemented by objects and \
47 interfaces",
48 );
49 }
50
51 fn resolve_into_type_async<'a>(
65 &'a self,
66 info: &'a Self::TypeInfo,
67 type_name: &str,
68 selection_set: Option<&'a [Selection<'a, S>]>,
69 executor: &'a Executor<'a, 'a, Self::Context, S>,
70 ) -> BoxFuture<'a, ExecutionResult<S>> {
71 if self.type_name(info).unwrap() == type_name {
72 self.resolve_async(info, selection_set, executor)
73 } else {
74 panic!(
75 "GraphQLValueAsync::resolve_into_type_async() must be implemented by unions and \
76 interfaces",
77 );
78 }
79 }
80
81 fn resolve_async<'a>(
101 &'a self,
102 info: &'a Self::TypeInfo,
103 selection_set: Option<&'a [Selection<S>]>,
104 executor: &'a Executor<Self::Context, S>,
105 ) -> BoxFuture<'a, ExecutionResult<S>> {
106 if let Some(sel) = selection_set {
107 Box::pin(async move {
108 Ok(resolve_selection_set_into_async(self, info, sel, executor).await)
109 })
110 } else {
111 panic!(
112 "GraphQLValueAsync::resolve_async() must be implemented by non-object output types",
113 );
114 }
115 }
116}
117
118pub trait GraphQLTypeAsync<S = DefaultScalarValue>: GraphQLValueAsync<S> + GraphQLType<S>
123where
124 Self::Context: Sync,
125 Self::TypeInfo: Sync,
126 S: ScalarValue + Send + Sync,
127{
128}
129
130impl<S, T> GraphQLTypeAsync<S> for T
131where
132 T: GraphQLValueAsync<S> + GraphQLType<S> + ?Sized,
133 T::Context: Sync,
134 T::TypeInfo: Sync,
135 S: ScalarValue + Send + Sync,
136{
137}
138
139fn resolve_selection_set_into_async<'a, 'e, T, S>(
142 instance: &'a T,
143 info: &'a T::TypeInfo,
144 selection_set: &'e [Selection<'e, S>],
145 executor: &'e Executor<'e, 'e, T::Context, S>,
146) -> BoxFuture<'a, Value<S>>
147where
148 T: GraphQLValueAsync<S> + ?Sized,
149 T::TypeInfo: Sync,
150 T::Context: Sync,
151 S: ScalarValue + Send + Sync,
152 'e: 'a,
153{
154 Box::pin(resolve_selection_set_into_async_recursive(
155 instance,
156 info,
157 selection_set,
158 executor,
159 ))
160}
161
162#[derive(Debug)]
163struct AsyncField<S> {
164 name: String,
165 value: Option<Value<S>>,
166}
167
168#[derive(Debug)]
169enum AsyncValue<S> {
170 Field(AsyncField<S>),
171 Nested(Value<S>),
172}
173
174pub(crate) async fn resolve_selection_set_into_async_recursive<'a, T, S>(
175 instance: &'a T,
176 info: &'a T::TypeInfo,
177 selection_set: &'a [Selection<'a, S>],
178 executor: &'a Executor<'a, 'a, T::Context, S>,
179) -> Value<S>
180where
181 T: GraphQLValueAsync<S> + ?Sized,
182 T::TypeInfo: Sync,
183 T::Context: Sync,
184 S: ScalarValue + Send + Sync,
185{
186 use futures::stream::{FuturesOrdered, StreamExt as _};
187
188 #[enum_derive(Future)]
189 enum AsyncValueFuture<F1, F2, FS, IF1, IF2> {
190 Field1(F1),
191 Field2(F2),
192 FragmentSpread(FS),
193 InlineFragment1(IF1),
194 InlineFragment2(IF2),
195 }
196
197 let mut object = Object::with_capacity(selection_set.len());
198
199 let mut async_values = FuturesOrdered::<AsyncValueFuture<_, _, _, _, _>>::new();
200
201 let meta_type = executor
202 .schema()
203 .concrete_type_by_name(
204 instance
205 .type_name(info)
206 .expect("Resolving named type's selection set"),
207 )
208 .expect("Type not found in schema");
209
210 for selection in selection_set {
211 match *selection {
212 Selection::Field(Spanning {
213 item: ref f,
214 ref span,
215 }) => {
216 if is_excluded(&f.directives, executor.variables()) {
217 continue;
218 }
219
220 let response_name = f.alias.as_ref().unwrap_or(&f.name).item;
221
222 if f.name.item == "__typename" {
223 object.add_field(
224 response_name,
225 Value::Scalar(instance.concrete_type_name(executor.context(), info).into()),
226 );
227 continue;
228 }
229
230 let meta_field = meta_type.field_by_name(f.name.item).unwrap_or_else(|| {
231 panic!(
232 "Field {} not found on type {:?}",
233 f.name.item,
234 meta_type.name(),
235 )
236 });
237
238 let exec_vars = executor.variables();
239
240 let sub_exec = executor.field_sub_executor(
241 response_name,
242 f.name.item,
243 span.start,
244 f.selection_set.as_ref().map(|v| &v[..]),
245 );
246 let args = Arguments::new(
247 f.arguments.as_ref().map(|m| {
248 m.item
249 .iter()
250 .filter_map(|(k, v)| {
251 let val = v.item.clone().into_const(exec_vars)?;
252 Some((k.item, Spanning::new(v.span, val)))
253 })
254 .collect()
255 }),
256 &meta_field.arguments,
257 );
258
259 let pos = span.start;
260 let is_non_null = meta_field.field_type.is_non_null();
261
262 let response_name = response_name.to_string();
263 async_values.push_back(AsyncValueFuture::Field1(async move {
264 let res = instance
267 .resolve_field_async(info, f.name.item, &args, &sub_exec)
268 .await;
269
270 let value = match res {
271 Ok(Value::Null) if is_non_null => None,
272 Ok(v) => Some(v),
273 Err(e) => {
274 sub_exec.push_error_at(e, pos);
275
276 if is_non_null {
277 None
278 } else {
279 Some(Value::null())
280 }
281 }
282 };
283 AsyncValue::Field(AsyncField {
284 name: response_name,
285 value,
286 })
287 }));
288 }
289
290 Selection::FragmentSpread(Spanning {
291 item: ref spread,
292 ref span,
293 }) => {
294 if is_excluded(&spread.directives, executor.variables()) {
295 continue;
296 }
297
298 let fragment = &executor
299 .fragment_by_name(spread.name.item)
300 .expect("Fragment could not be found");
301
302 let sub_exec = executor.type_sub_executor(
303 Some(fragment.type_condition.item),
304 Some(&fragment.selection_set[..]),
305 );
306
307 let concrete_type_name = instance.concrete_type_name(sub_exec.context(), info);
308 let type_name = instance.type_name(info);
309 if executor
310 .schema()
311 .is_named_subtype(&concrete_type_name, fragment.type_condition.item)
312 || Some(fragment.type_condition.item) == type_name.as_deref()
313 {
314 let sub_result = instance
315 .resolve_into_type_async(
316 info,
317 &concrete_type_name,
318 Some(&fragment.selection_set[..]),
319 &sub_exec,
320 )
321 .await;
322
323 if let Ok(Value::Object(obj)) = sub_result {
324 for (k, v) in obj {
325 async_values.push_back(AsyncValueFuture::FragmentSpread(
326 future::ready(AsyncValue::Field(AsyncField {
327 name: k,
328 value: Some(v),
329 })),
330 ));
331 }
332 } else {
333 if let Err(e) = sub_result {
334 sub_exec.push_error_at(e, span.start);
335 }
336 async_values.push_back(AsyncValueFuture::Field2(future::ready(
344 AsyncValue::Field(AsyncField {
345 name: String::new(), value: None,
347 }),
348 )));
349 }
350 }
351 }
352
353 Selection::InlineFragment(Spanning {
354 item: ref fragment,
355 ref span,
356 }) => {
357 if is_excluded(&fragment.directives, executor.variables()) {
358 continue;
359 }
360
361 let sub_exec = executor.type_sub_executor(
362 fragment.type_condition.as_ref().map(|c| c.item),
363 Some(&fragment.selection_set[..]),
364 );
365
366 if let Some(ref type_condition) = fragment.type_condition {
367 let concrete_type_name = instance.concrete_type_name(sub_exec.context(), info);
369 if executor
370 .schema()
371 .is_named_subtype(&concrete_type_name, type_condition.item)
372 {
373 let sub_result = instance
374 .resolve_into_type_async(
375 info,
376 &concrete_type_name,
377 Some(&fragment.selection_set[..]),
378 &sub_exec,
379 )
380 .await;
381
382 if let Ok(Value::Object(obj)) = sub_result {
383 for (k, v) in obj {
384 async_values.push_back(AsyncValueFuture::InlineFragment1(
385 future::ready(AsyncValue::Field(AsyncField {
386 name: k,
387 value: Some(v),
388 })),
389 ));
390 }
391 } else {
392 if let Err(e) = sub_result {
393 sub_exec.push_error_at(e, span.start);
394 }
395 async_values.push_back(AsyncValueFuture::Field2(future::ready(
403 AsyncValue::Field(AsyncField {
404 name: String::new(), value: None,
406 }),
407 )));
408 }
409 }
410 } else {
411 async_values.push_back(AsyncValueFuture::InlineFragment2(async move {
412 let value = resolve_selection_set_into_async(
413 instance,
414 info,
415 &fragment.selection_set[..],
416 &sub_exec,
417 )
418 .await;
419 AsyncValue::Nested(value)
420 }));
421 }
422 }
423 }
424 }
425
426 while let Some(item) = async_values.next().await {
427 match item {
428 AsyncValue::Field(AsyncField { name, value }) => {
429 if let Some(value) = value {
430 merge_key_into(&mut object, &name, value);
431 } else {
432 return Value::null();
433 }
434 }
435 AsyncValue::Nested(obj) => match obj {
436 v @ Value::Null => {
437 return v;
438 }
439 Value::Object(obj) => {
440 for (k, v) in obj {
441 merge_key_into(&mut object, &k, v);
442 }
443 }
444 _ => unreachable!(),
445 },
446 }
447 }
448
449 Value::Object(object)
450}