From 4a4d7407aaa7beca955c8863cda704e03d9f5336 Mon Sep 17 00:00:00 2001
From: Christoph Herzog <chris@theduke.at>
Date: Wed, 21 Aug 2019 15:20:01 +0200
Subject: [PATCH] Use Custom BoxFuture type + prepare new resolve result value

---
 juniper/src/executor/mod.rs      | 14 ++++++++++++++
 juniper/src/lib.rs               |  5 ++++-
 juniper/src/schema/schema.rs     |  2 +-
 juniper/src/types/async_await.rs |  9 +++------
 juniper/src/types/containers.rs  |  6 +++---
 juniper/src/types/pointers.rs    |  4 ++--
 juniper/src/types/scalars.rs     |  2 +-
 juniper/src/value/mod.rs         |  3 +++
 juniper/src/value/object.rs      |  1 +
 9 files changed, 32 insertions(+), 14 deletions(-)

diff --git a/juniper/src/executor/mod.rs b/juniper/src/executor/mod.rs
index 8b96b9ac..937376fc 100644
--- a/juniper/src/executor/mod.rs
+++ b/juniper/src/executor/mod.rs
@@ -210,6 +210,20 @@ impl<S> FieldError<S> {
 /// The result of resolving the value of a field of type `T`
 pub type FieldResult<T, S = DefaultScalarValue> = Result<T, FieldError<S>>;
 
+/*
+pub enum ResolvedValue<'a, S = DefaultScalarValue> {
+    Value(Value<S>),
+    Future(crate::BoxFuture<'a, Value<S>>),
+}
+
+impl<'a, S> From<Value<S>> for ResolvedValue<'a, S> {
+    #[inline]
+    fn from(value: Value<S>) -> Self {
+        ResolvedValue::Value(value)
+    }
+}
+*/
+
 /// The result of resolving an unspecified field
 pub type ExecutionResult<S = DefaultScalarValue> = Result<Value<S>, FieldError<S>>;
 
diff --git a/juniper/src/lib.rs b/juniper/src/lib.rs
index 95ce987b..6317f4c6 100644
--- a/juniper/src/lib.rs
+++ b/juniper/src/lib.rs
@@ -176,8 +176,11 @@ pub use crate::{
     },
 };
 
+/// A pinned, boxed future that can be polled.
+pub type BoxFuture<'a, T> = std::pin::Pin<Box<dyn std::future::Future<Output = T> + 'a + Send>>;
+
 #[cfg(feature = "async")]
-pub use crate::types::async_await::GraphQLTypeAsync;
+pub use crate::types::async_await::{GraphQLTypeAsync};
 
 /// An error that prevented query execution
 #[derive(Debug, PartialEq)]
diff --git a/juniper/src/schema/schema.rs b/juniper/src/schema/schema.rs
index 49b6940d..f71e9b18 100644
--- a/juniper/src/schema/schema.rs
+++ b/juniper/src/schema/schema.rs
@@ -94,7 +94,7 @@ where
         field_name: &'b str,
         arguments: &'b Arguments<S>,
         executor: &'b Executor<Self::Context, S>,
-    ) -> futures::future::BoxFuture<'b, ExecutionResult<S>> {
+    ) -> crate::BoxFuture<'b, ExecutionResult<S>> {
         use futures::future::{ready, FutureExt};
         match field_name {
             "__schema" | "__type" => {
diff --git a/juniper/src/types/async_await.rs b/juniper/src/types/async_await.rs
index 05fb502c..12369bef 100644
--- a/juniper/src/types/async_await.rs
+++ b/juniper/src/types/async_await.rs
@@ -1,4 +1,3 @@
-use futures::future::BoxFuture;
 
 use crate::ast::{Directive, FromInputValue, InputValue, Selection};
 use crate::value::{Object, ScalarRefValue, ScalarValue, Value};
@@ -21,7 +20,7 @@ where
         field_name: &'a str,
         arguments: &'a Arguments<S>,
         executor: &'a Executor<Self::Context, S>,
-    ) -> futures::future::BoxFuture<'a, ExecutionResult<S>> {
+    ) -> BoxFuture<'a, ExecutionResult<S>> {
         panic!("resolve_field must be implemented by object types");
     }
 
@@ -30,7 +29,7 @@ where
         info: &'a Self::TypeInfo,
         selection_set: Option<&'a [Selection<S>]>,
         executor: &'a Executor<Self::Context, S>,
-    ) -> futures::future::BoxFuture<'a, Value<S>> {
+    ) -> BoxFuture<'a, Value<S>> {
         if let Some(selection_set) = selection_set {
             resolve_selection_set_into_async(self, info, selection_set, executor)
         } else {
@@ -47,7 +46,7 @@ pub(crate) fn resolve_selection_set_into_async<'a, 'e, T, CtxT, S>(
     info: &'a T::TypeInfo,
     selection_set: &'e [Selection<'e, S>],
     executor: &'e Executor<'e, CtxT, S>,
-) -> futures::future::BoxFuture<'a, Value<S>>
+) -> BoxFuture<'a, Value<S>>
 where
     T: GraphQLTypeAsync<S, Context = CtxT>,
     T::TypeInfo: Send + Sync,
@@ -71,8 +70,6 @@ enum AsyncValue<S> {
     Nested(Value<S>),
 }
 
-// type ResolveFuture<'a, S> = BoxFuture<'a, AsyncResolve<S>>;
-
 #[cfg(feature = "async")]
 pub(crate) async fn resolve_selection_set_into_async_recursive<'a, T, CtxT, S>(
     instance: &'a T,
diff --git a/juniper/src/types/containers.rs b/juniper/src/types/containers.rs
index caa0e453..8004dbaf 100644
--- a/juniper/src/types/containers.rs
+++ b/juniper/src/types/containers.rs
@@ -270,7 +270,7 @@ where
         info: &'a Self::TypeInfo,
         selection_set: Option<&'a [Selection<S>]>,
         executor: &'a Executor<Self::Context, S>,
-    ) -> futures::future::BoxFuture<'a, Value<S>> {
+    ) -> crate::BoxFuture<'a, Value<S>> {
         let f = resolve_into_list_async(executor, info, self.iter());
         futures::future::FutureExt::boxed(f)
     }
@@ -290,7 +290,7 @@ where
         info: &'a Self::TypeInfo,
         selection_set: Option<&'a [Selection<S>]>,
         executor: &'a Executor<Self::Context, S>,
-    ) -> futures::future::BoxFuture<'a, Value<S>> {
+    ) -> crate::BoxFuture<'a, Value<S>> {
         let f = resolve_into_list_async(executor, info, self.iter());
         futures::future::FutureExt::boxed(f)
     }
@@ -310,7 +310,7 @@ where
         info: &'a Self::TypeInfo,
         selection_set: Option<&'a [Selection<S>]>,
         executor: &'a Executor<Self::Context, S>,
-    ) -> futures::future::BoxFuture<'a, Value<S>> {
+    ) -> crate::BoxFuture<'a, Value<S>> {
         let f = async move {
             match *self {
                 Some(ref obj) => executor.resolve_into_value_async(info, obj).await,
diff --git a/juniper/src/types/pointers.rs b/juniper/src/types/pointers.rs
index 118f9fcc..1e8478a1 100644
--- a/juniper/src/types/pointers.rs
+++ b/juniper/src/types/pointers.rs
@@ -151,7 +151,7 @@ where
         field_name: &'b str,
         arguments: &'b Arguments<S>,
         executor: &'b Executor<Self::Context, S>,
-    ) -> futures::future::BoxFuture<'b, ExecutionResult<S>> {
+    ) -> crate::BoxFuture<'b, ExecutionResult<S>> {
         crate::GraphQLTypeAsync::resolve_field_async(&**self, info, field_name, arguments, executor)
     }
 
@@ -160,7 +160,7 @@ where
         info: &'a Self::TypeInfo,
         selection_set: Option<&'a [Selection<S>]>,
         executor: &'a Executor<Self::Context, S>,
-    ) -> futures::future::BoxFuture<'a, Value<S>> {
+    ) -> crate::BoxFuture<'a, Value<S>> {
         crate::GraphQLTypeAsync::resolve_async(&**self, info, selection_set, executor)
     }
 }
diff --git a/juniper/src/types/scalars.rs b/juniper/src/types/scalars.rs
index a2df7eb3..dba13834 100644
--- a/juniper/src/types/scalars.rs
+++ b/juniper/src/types/scalars.rs
@@ -207,7 +207,7 @@ where
         info: &'a Self::TypeInfo,
         selection_set: Option<&'a [Selection<S>]>,
         executor: &'a Executor<Self::Context, S>,
-    ) -> futures::future::BoxFuture<'a, crate::Value<S>> {
+    ) -> crate::BoxFuture<'a, crate::Value<S>> {
         use futures::future;
         future::FutureExt::boxed(future::ready(self.resolve(info, selection_set, executor)))
     }
diff --git a/juniper/src/value/mod.rs b/juniper/src/value/mod.rs
index 6faa8904..dc84256d 100644
--- a/juniper/src/value/mod.rs
+++ b/juniper/src/value/mod.rs
@@ -120,6 +120,9 @@ where
         }
     }
 
+    /// Convert this value into an Object.
+    ///
+    /// Returns None if value is not an Object.
     pub fn into_object(self) -> Option<Object<S>> {
         match self {
             Value::Object(o) => Some(o),
diff --git a/juniper/src/value/object.rs b/juniper/src/value/object.rs
index 1e8ee25d..72cea251 100644
--- a/juniper/src/value/object.rs
+++ b/juniper/src/value/object.rs
@@ -77,6 +77,7 @@ impl<S> Object<S> {
             .map(|&(_, ref value)| value)
     }
 
+    /// Recursively sort all keys by field.
     pub fn sort_by_field(&mut self) {
         self.key_value_list
             .sort_by(|(key1, _), (key2, _)| key1.cmp(key2));