juniper/macros/helper/
subscription.rs

1//! Helper types for converting types to `Result<T, FieldError<E>>`.
2//!
3//! Used in `#[graphql_subscription]` macros to convert result type aliases on
4//! subscription handlers to a concrete return type.
5
6use futures::Stream;
7
8use crate::{FieldError, GraphQLValue, IntoFieldError, ScalarValue};
9
10/// Trait for wrapping [`Stream`] into [`Ok`] if it's not [`Result`].
11///
12/// Used in subscription macros when user can provide type alias for [`Stream`] or
13/// `Result<Stream, _>` and then a function on [`Stream`] should be called.
14pub trait IntoFieldResult<T, S> {
15    /// Type of items yielded by this [`Stream`].
16    type Item;
17
18    /// Turns current [`Stream`] type into a generic [`Result`].
19    fn into_result(self) -> Result<T, FieldError<S>>;
20}
21
22impl<T, E, S> IntoFieldResult<T, S> for Result<T, E>
23where
24    T: IntoFieldResult<T, S>,
25    E: IntoFieldError<S>,
26{
27    type Item = T::Item;
28
29    fn into_result(self) -> Result<T, FieldError<S>> {
30        self.map_err(E::into_field_error)
31    }
32}
33
34impl<T, S> IntoFieldResult<T, S> for T
35where
36    T: Stream,
37{
38    type Item = T::Item;
39
40    fn into_result(self) -> Result<T, FieldError<S>> {
41        Ok(self)
42    }
43}
44
45/// This struct is used in `ExtractTypeFromStream` implementation for streams
46/// of values.
47pub struct StreamItem;
48
49/// This struct is used in `ExtractTypeFromStream` implementation for results
50/// with streams of values inside.
51pub struct StreamResult;
52
53/// This struct is used in `ExtractTypeFromStream` implementation for streams
54/// of results of values inside.
55pub struct ResultStreamItem;
56
57/// This struct is used in `ExtractTypeFromStream` implementation for results
58/// with streams of results of values inside.
59pub struct ResultStreamResult;
60
61/// This trait is used in `juniper::graphql_subscription` macro to get stream's
62/// item type that implements `GraphQLValue` from type alias provided
63/// by user.
64pub trait ExtractTypeFromStream<T, S>
65where
66    S: ScalarValue,
67{
68    /// Stream's return Value that will be returned if
69    /// no errors occured. Is used to determine field type in
70    /// `#[juniper::graphql_subscription]`
71    type Item: GraphQLValue<S>;
72}
73
74impl<T, I, S> ExtractTypeFromStream<StreamItem, S> for T
75where
76    T: futures::Stream<Item = I>,
77    I: GraphQLValue<S>,
78    S: ScalarValue,
79{
80    type Item = I;
81}
82
83impl<Ty, T, E, S> ExtractTypeFromStream<StreamResult, S> for Ty
84where
85    Ty: futures::Stream<Item = Result<T, E>>,
86    T: GraphQLValue<S>,
87    S: ScalarValue,
88{
89    type Item = T;
90}
91
92impl<T, I, E, S> ExtractTypeFromStream<ResultStreamItem, S> for Result<T, E>
93where
94    T: futures::Stream<Item = I>,
95    I: GraphQLValue<S>,
96    S: ScalarValue,
97{
98    type Item = I;
99}
100
101impl<T, E, I, ER, S> ExtractTypeFromStream<ResultStreamResult, S> for Result<T, E>
102where
103    T: futures::Stream<Item = Result<I, ER>>,
104    I: GraphQLValue<S>,
105    S: ScalarValue,
106{
107    type Item = I;
108}