dynamic_graphql/
resolve.rs

1use std::borrow::Cow;
2
3use crate::Context;
4use crate::Error;
5use crate::FieldValue;
6use crate::ID;
7use crate::Result;
8
9pub trait ResolveRef<'a> {
10    fn resolve_ref(&'a self, ctx: &Context) -> Result<Option<FieldValue<'a>>>;
11}
12
13pub trait ResolveOwned<'a> {
14    fn resolve_owned(self, ctx: &Context) -> Result<Option<FieldValue<'a>>>;
15}
16
17pub trait Resolve<'a> {
18    fn resolve(self, ctx: &Context) -> Result<Option<FieldValue<'a>>>;
19}
20
21mod resolve_ref {
22    use super::*;
23    // &Option<T>
24    impl<'a, T> ResolveRef<'a> for Option<T>
25    where
26        &'a T: Resolve<'a> + 'a,
27    {
28        #[inline]
29        fn resolve_ref(&'a self, ctx: &Context) -> Result<Option<FieldValue<'a>>> {
30            match self {
31                None => Ok(None),
32                Some(value) => value.resolve(ctx),
33            }
34        }
35    }
36
37    // &Vec<T>
38    impl<'a, T> ResolveRef<'a> for Vec<T>
39    where
40        &'a T: Resolve<'a> + 'a,
41    {
42        fn resolve_ref(&'a self, ctx: &Context) -> Result<Option<FieldValue<'a>>> {
43            let iter = self.iter();
44            let items = iter.enumerate().map(|(index, item)| {
45                let ctx_idx = ctx.with_index(index);
46                match item.resolve(&ctx_idx) {
47                    Ok(Some(value)) => value,
48                    _ => FieldValue::NULL,
49                }
50            });
51            Ok(Some(FieldValue::list(items)))
52        }
53    }
54    // &ID
55    impl<'a> ResolveRef<'a> for ID {
56        #[inline]
57        fn resolve_ref(&self, _ctx: &Context) -> Result<Option<FieldValue<'a>>> {
58            Ok(Some(FieldValue::value(self.0.to_owned())))
59        }
60    }
61    // &str
62    impl<'a> ResolveRef<'a> for &str {
63        #[inline]
64        fn resolve_ref(&'a self, _ctx: &Context) -> Result<Option<FieldValue<'a>>> {
65            Ok(Some(FieldValue::value(self.to_string())))
66        }
67    }
68}
69mod resolve_own {
70    use super::*;
71    // &T
72    impl<'a, T> ResolveOwned<'a> for &'a T
73    where
74        T: ResolveRef<'a>,
75    {
76        #[inline]
77        fn resolve_owned(self, ctx: &Context) -> Result<Option<FieldValue<'a>>> {
78            self.resolve_ref(ctx)
79        }
80    }
81    // Cow<'a, T>
82    impl<'a, T> ResolveOwned<'a> for Cow<'a, T>
83    where
84        T: Clone + Resolve<'a>,
85        &'a T: Resolve<'a>,
86    {
87        #[inline]
88        fn resolve_owned(self, ctx: &Context) -> Result<Option<FieldValue<'a>>> {
89            match self {
90                Cow::Owned(value) => value.resolve(ctx),
91                Cow::Borrowed(value) => value.resolve(ctx),
92            }
93        }
94    }
95    // Option<T>
96    impl<'a, T> ResolveOwned<'a> for Option<T>
97    where
98        T: Resolve<'a>,
99    {
100        #[inline]
101        fn resolve_owned(self, ctx: &Context) -> Result<Option<FieldValue<'a>>> {
102            match self {
103                None => Ok(None),
104                Some(value) => value.resolve(ctx),
105            }
106        }
107    }
108
109    // Result<T, E>
110    impl<'a, T, E> ResolveOwned<'a> for Result<T, E>
111    where
112        T: Resolve<'a>,
113        E: Into<Error>,
114    {
115        #[inline]
116        fn resolve_owned(self, ctx: &Context) -> Result<Option<FieldValue<'a>>> {
117            match self {
118                Ok(value) => value.resolve(ctx),
119                Err(err) => Err(err.into()),
120            }
121        }
122    }
123
124    // Vec<T>
125    impl<'a, T> ResolveOwned<'a> for Vec<T>
126    where
127        T: Resolve<'a>,
128    {
129        fn resolve_owned(self, ctx: &Context) -> Result<Option<FieldValue<'a>>> {
130            let iter = self.into_iter();
131            let items = iter.enumerate().map(|(index, item)| {
132                let ctx_idx = ctx.with_index(index);
133                match item.resolve(&ctx_idx) {
134                    Ok(Some(value)) => value,
135                    _ => FieldValue::NULL,
136                }
137            });
138            Ok(Some(FieldValue::list(items)))
139        }
140    }
141
142    // &[T]
143    impl<'a, T> ResolveOwned<'a> for &'a [T]
144    where
145        &'a T: Resolve<'a>,
146    {
147        fn resolve_owned(self, ctx: &Context) -> Result<Option<FieldValue<'a>>> {
148            let iter = self.iter();
149            let items = iter.enumerate().map(|(index, item)| {
150                let ctx_idx = ctx.with_index(index);
151                match item.resolve(&ctx_idx) {
152                    Ok(Some(value)) => value,
153                    _ => FieldValue::NULL,
154                }
155            });
156            Ok(Some(FieldValue::list(items)))
157        }
158    }
159
160    // ID
161    impl<'a> ResolveOwned<'a> for ID {
162        #[inline]
163        fn resolve_owned(self, _ctx: &Context) -> Result<Option<FieldValue<'a>>> {
164            Ok(Some(FieldValue::value(self.0)))
165        }
166    }
167
168    // &str
169    impl<'a> ResolveOwned<'a> for &str {
170        #[inline]
171        fn resolve_owned(self, _ctx: &Context) -> Result<Option<FieldValue<'a>>> {
172            Ok(Some(FieldValue::value(self.to_string())))
173        }
174    }
175}
176
177// T
178impl<'a, T: ResolveOwned<'a>> Resolve<'a> for T {
179    #[inline]
180    fn resolve(self, ctx: &Context) -> Result<Option<FieldValue<'a>>> {
181        self.resolve_owned(ctx)
182    }
183}
184
185macro_rules! resolves {
186    ($($ty:ident),*) => {
187        $(
188            impl <'a> ResolveOwned<'a> for $ty {
189                #[inline]
190                fn resolve_owned(self, _ctx: &Context) -> Result<Option<FieldValue<'a>>> {
191                    Ok(Some(FieldValue::value(self)))
192                }
193            }
194            impl <'a> ResolveRef<'a> for $ty {
195                #[inline]
196                fn resolve_ref(&self, _ctx: &Context) -> Result<Option<FieldValue<'a>>> {
197                    Ok(Some(FieldValue::value(self.to_owned())))
198                }
199            }
200        )*
201    };
202}
203
204resolves!(
205    String, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, bool, f32, f64
206);