1use std::{
2 any::Any,
3 borrow::Cow,
4 fmt::{self, Debug},
5 ops::Deref,
6};
7
8use futures_util::{future::BoxFuture, Future, FutureExt};
9use indexmap::IndexMap;
10
11use super::Directive;
12use crate::{
13 dynamic::{InputValue, ObjectAccessor, TypeRef},
14 registry::Deprecation,
15 Context, Error, Result, Value,
16};
17
18pub struct FieldValue<'a>(pub(crate) FieldValueInner<'a>);
20
21pub(crate) enum FieldValueInner<'a> {
22 Value(Value),
24 BorrowedAny(Cow<'static, str>, &'a (dyn Any + Send + Sync)),
28 OwnedAny(Cow<'static, str>, Box<dyn Any + Send + Sync>),
32 List(Vec<FieldValue<'a>>),
34 WithType {
36 value: Box<FieldValue<'a>>,
38 ty: Cow<'static, str>,
40 },
41}
42
43impl Debug for FieldValue<'_> {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 match &self.0 {
46 FieldValueInner::Value(v) => write!(f, "{}", v),
47 FieldValueInner::BorrowedAny(ty, _)
48 | FieldValueInner::OwnedAny(ty, _)
49 | FieldValueInner::WithType { ty, .. } => write!(f, "{}", ty),
50 FieldValueInner::List(list) => match list.first() {
51 Some(v) => {
52 write!(f, "[{:?}, ...]", v)
53 }
54 None => {
55 write!(f, "[()]")
56 }
57 },
58 }
59 }
60}
61
62impl From<()> for FieldValue<'_> {
63 #[inline]
64 fn from(_: ()) -> Self {
65 Self(FieldValueInner::Value(Value::Null))
66 }
67}
68
69impl From<Value> for FieldValue<'_> {
70 #[inline]
71 fn from(value: Value) -> Self {
72 Self(FieldValueInner::Value(value))
73 }
74}
75
76impl<'a, T: Into<FieldValue<'a>>> From<Vec<T>> for FieldValue<'a> {
77 fn from(values: Vec<T>) -> Self {
78 Self(FieldValueInner::List(
79 values.into_iter().map(Into::into).collect(),
80 ))
81 }
82}
83
84impl<'a> FieldValue<'a> {
85 pub const NULL: FieldValue<'a> = Self(FieldValueInner::Value(Value::Null));
87
88 pub const NONE: Option<FieldValue<'a>> = None;
103
104 pub const fn none() -> Option<FieldValue<'a>> {
106 None
107 }
108
109 #[inline]
111 pub fn value(value: impl Into<Value>) -> Self {
112 Self(FieldValueInner::Value(value.into()))
113 }
114
115 #[inline]
117 pub fn owned_any<T: Any + Send + Sync>(obj: T) -> Self {
118 Self(FieldValueInner::OwnedAny(
119 std::any::type_name::<T>().into(),
120 Box::new(obj),
121 ))
122 }
123
124 #[inline]
126 pub fn boxed_any(obj: Box<dyn Any + Send + Sync>) -> Self {
127 Self(FieldValueInner::OwnedAny("Any".into(), obj))
128 }
129
130 #[inline]
132 pub fn borrowed_any(obj: &'a (dyn Any + Send + Sync)) -> Self {
133 Self(FieldValueInner::BorrowedAny("Any".into(), obj))
134 }
135
136 #[inline]
138 pub fn list<I, T>(values: I) -> Self
139 where
140 I: IntoIterator<Item = T>,
141 T: Into<FieldValue<'a>>,
142 {
143 Self(FieldValueInner::List(
144 values.into_iter().map(Into::into).collect(),
145 ))
146 }
147
148 pub fn with_type(self, ty: impl Into<Cow<'static, str>>) -> Self {
201 Self(FieldValueInner::WithType {
202 value: Box::new(self),
203 ty: ty.into(),
204 })
205 }
206
207 #[inline]
210 pub fn as_value(&self) -> Option<&Value> {
211 match &self.0 {
212 FieldValueInner::Value(value) => Some(value),
213 _ => None,
214 }
215 }
216
217 #[inline]
219 pub fn try_to_value(&self) -> Result<&Value> {
220 self.as_value()
221 .ok_or_else(|| Error::new(format!("internal: \"{:?}\" not a Value", self)))
222 }
223
224 #[inline]
227 pub fn as_list(&self) -> Option<&[FieldValue]> {
228 match &self.0 {
229 FieldValueInner::List(values) => Some(values),
230 _ => None,
231 }
232 }
233
234 #[inline]
236 pub fn try_to_list(&self) -> Result<&[FieldValue]> {
237 self.as_list()
238 .ok_or_else(|| Error::new(format!("internal: \"{:?}\" not a List", self)))
239 }
240
241 #[inline]
244 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
245 match &self.0 {
246 FieldValueInner::BorrowedAny(_, value) => value.downcast_ref::<T>(),
247 FieldValueInner::OwnedAny(_, value) => value.downcast_ref::<T>(),
248 _ => None,
249 }
250 }
251
252 #[inline]
254 pub fn try_downcast_ref<T: Any>(&self) -> Result<&T> {
255 self.downcast_ref().ok_or_else(|| {
256 Error::new(format!(
257 "internal: \"{:?}\" is not of the expected type \"{}\"",
258 self,
259 std::any::type_name::<T>()
260 ))
261 })
262 }
263}
264
265type BoxResolveFut<'a> = BoxFuture<'a, Result<Option<FieldValue<'a>>>>;
266
267pub struct ResolverContext<'a> {
269 pub ctx: &'a Context<'a>,
271 pub args: ObjectAccessor<'a>,
273 pub parent_value: &'a FieldValue<'a>,
275}
276
277impl<'a> Deref for ResolverContext<'a> {
278 type Target = Context<'a>;
279
280 fn deref(&self) -> &Self::Target {
281 self.ctx
282 }
283}
284
285pub enum FieldFuture<'a> {
287 Value(Option<FieldValue<'a>>),
289
290 Future(BoxResolveFut<'a>),
292}
293
294impl<'a> FieldFuture<'a> {
295 pub fn new<Fut, R>(future: Fut) -> Self
297 where
298 Fut: Future<Output = Result<Option<R>>> + Send + 'a,
299 R: Into<FieldValue<'a>> + Send,
300 {
301 FieldFuture::Future(
302 async move {
303 let res = future.await?;
304 Ok(res.map(Into::into))
305 }
306 .boxed(),
307 )
308 }
309
310 pub fn from_value(value: Option<Value>) -> Self {
312 FieldFuture::Value(value.map(FieldValue::from))
313 }
314}
315
316pub(crate) type BoxResolverFn =
317 Box<(dyn for<'a> Fn(ResolverContext<'a>) -> FieldFuture<'a> + Send + Sync)>;
318
319pub struct Field {
321 pub(crate) name: String,
322 pub(crate) description: Option<String>,
323 pub(crate) arguments: IndexMap<String, InputValue>,
324 pub(crate) ty: TypeRef,
325 pub(crate) ty_str: String,
326 pub(crate) resolver_fn: BoxResolverFn,
327 pub(crate) deprecation: Deprecation,
328 pub(crate) external: bool,
329 pub(crate) requires: Option<String>,
330 pub(crate) provides: Option<String>,
331 pub(crate) shareable: bool,
332 pub(crate) inaccessible: bool,
333 pub(crate) tags: Vec<String>,
334 pub(crate) override_from: Option<String>,
335 pub(crate) directives: Vec<Directive>,
336}
337
338impl Debug for Field {
339 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
340 f.debug_struct("Field")
341 .field("name", &self.name)
342 .field("description", &self.description)
343 .field("arguments", &self.arguments)
344 .field("ty", &self.ty)
345 .field("deprecation", &self.deprecation)
346 .finish()
347 }
348}
349
350impl Field {
351 pub fn new<N, T, F>(name: N, ty: T, resolver_fn: F) -> Self
353 where
354 N: Into<String>,
355 T: Into<TypeRef>,
356 F: for<'a> Fn(ResolverContext<'a>) -> FieldFuture<'a> + Send + Sync + 'static,
357 {
358 let ty = ty.into();
359 Self {
360 name: name.into(),
361 description: None,
362 arguments: Default::default(),
363 ty_str: ty.to_string(),
364 ty,
365 resolver_fn: Box::new(resolver_fn),
366 deprecation: Deprecation::NoDeprecated,
367 external: false,
368 requires: None,
369 provides: None,
370 shareable: false,
371 inaccessible: false,
372 tags: Vec::new(),
373 override_from: None,
374 directives: Vec::new(),
375 }
376 }
377
378 impl_set_description!();
379 impl_set_deprecation!();
380 impl_set_external!();
381 impl_set_requires!();
382 impl_set_provides!();
383 impl_set_shareable!();
384 impl_set_inaccessible!();
385 impl_set_tags!();
386 impl_set_override_from!();
387 impl_directive!();
388
389 #[inline]
391 pub fn argument(mut self, input_value: InputValue) -> Self {
392 self.arguments.insert(input_value.name.clone(), input_value);
393 self
394 }
395}