juniper/schema/
meta.rs

1//! Types used to describe a `GraphQL` schema
2
3use juniper::IntoFieldError;
4use std::{borrow::Cow, fmt};
5
6use crate::{
7    ast::{FromInputValue, InputValue, Type},
8    parser::{ParseError, ScalarToken},
9    schema::model::SchemaType,
10    types::base::TypeKind,
11    value::{DefaultScalarValue, ParseScalarValue},
12    FieldError,
13};
14
15/// Whether an item is deprecated, with context.
16#[derive(Clone, Debug, Eq, Hash, PartialEq)]
17pub enum DeprecationStatus {
18    /// The field/variant is not deprecated.
19    Current,
20    /// The field/variant is deprecated, with an optional reason
21    Deprecated(Option<String>),
22}
23
24impl DeprecationStatus {
25    /// If this deprecation status indicates the item is deprecated.
26    pub fn is_deprecated(&self) -> bool {
27        match self {
28            DeprecationStatus::Current => false,
29            DeprecationStatus::Deprecated(_) => true,
30        }
31    }
32
33    /// An optional reason for the deprecation, or none if `Current`.
34    pub fn reason(&self) -> Option<&str> {
35        match self {
36            DeprecationStatus::Current => None,
37            DeprecationStatus::Deprecated(rsn) => rsn.as_deref(),
38        }
39    }
40}
41
42/// Scalar type metadata
43pub struct ScalarMeta<'a, S> {
44    #[doc(hidden)]
45    pub name: Cow<'a, str>,
46    #[doc(hidden)]
47    pub description: Option<String>,
48    #[doc(hidden)]
49    pub specified_by_url: Option<Cow<'a, str>>,
50    pub(crate) try_parse_fn: InputValueParseFn<S>,
51    pub(crate) parse_fn: ScalarTokenParseFn<S>,
52}
53
54/// Shortcut for an [`InputValue`] parsing function.
55pub type InputValueParseFn<S> = for<'b> fn(&'b InputValue<S>) -> Result<(), FieldError<S>>;
56
57/// Shortcut for a [`ScalarToken`] parsing function.
58pub type ScalarTokenParseFn<S> = for<'b> fn(ScalarToken<'b>) -> Result<S, ParseError>;
59
60/// List type metadata
61#[derive(Debug)]
62pub struct ListMeta<'a> {
63    #[doc(hidden)]
64    pub of_type: Type<'a>,
65
66    #[doc(hidden)]
67    pub expected_size: Option<usize>,
68}
69
70/// Nullable type metadata
71#[derive(Debug)]
72pub struct NullableMeta<'a> {
73    #[doc(hidden)]
74    pub of_type: Type<'a>,
75}
76
77/// Object type metadata
78#[derive(Debug)]
79pub struct ObjectMeta<'a, S> {
80    #[doc(hidden)]
81    pub name: Cow<'a, str>,
82    #[doc(hidden)]
83    pub description: Option<String>,
84    #[doc(hidden)]
85    pub fields: Vec<Field<'a, S>>,
86    #[doc(hidden)]
87    pub interface_names: Vec<String>,
88}
89
90/// Enum type metadata
91pub struct EnumMeta<'a, S> {
92    #[doc(hidden)]
93    pub name: Cow<'a, str>,
94    #[doc(hidden)]
95    pub description: Option<String>,
96    #[doc(hidden)]
97    pub values: Vec<EnumValue>,
98    pub(crate) try_parse_fn: InputValueParseFn<S>,
99}
100
101/// Interface type metadata
102#[derive(Debug)]
103pub struct InterfaceMeta<'a, S> {
104    #[doc(hidden)]
105    pub name: Cow<'a, str>,
106    #[doc(hidden)]
107    pub description: Option<String>,
108    #[doc(hidden)]
109    pub fields: Vec<Field<'a, S>>,
110    #[doc(hidden)]
111    pub interface_names: Vec<String>,
112}
113
114/// Union type metadata
115#[derive(Debug)]
116pub struct UnionMeta<'a> {
117    #[doc(hidden)]
118    pub name: Cow<'a, str>,
119    #[doc(hidden)]
120    pub description: Option<String>,
121    #[doc(hidden)]
122    pub of_type_names: Vec<String>,
123}
124
125/// Input object metadata
126pub struct InputObjectMeta<'a, S> {
127    #[doc(hidden)]
128    pub name: Cow<'a, str>,
129    #[doc(hidden)]
130    pub description: Option<String>,
131    #[doc(hidden)]
132    pub input_fields: Vec<Argument<'a, S>>,
133    pub(crate) try_parse_fn: InputValueParseFn<S>,
134}
135
136/// A placeholder for not-yet-registered types
137///
138/// After a type's `meta` method has been called but before it has returned, a placeholder type
139/// is inserted into a registry to indicate existence.
140#[derive(Debug)]
141pub struct PlaceholderMeta<'a> {
142    #[doc(hidden)]
143    pub of_type: Type<'a>,
144}
145
146/// Generic type metadata
147#[derive(Debug)]
148pub enum MetaType<'a, S = DefaultScalarValue> {
149    #[doc(hidden)]
150    Scalar(ScalarMeta<'a, S>),
151    #[doc(hidden)]
152    List(ListMeta<'a>),
153    #[doc(hidden)]
154    Nullable(NullableMeta<'a>),
155    #[doc(hidden)]
156    Object(ObjectMeta<'a, S>),
157    #[doc(hidden)]
158    Enum(EnumMeta<'a, S>),
159    #[doc(hidden)]
160    Interface(InterfaceMeta<'a, S>),
161    #[doc(hidden)]
162    Union(UnionMeta<'a>),
163    #[doc(hidden)]
164    InputObject(InputObjectMeta<'a, S>),
165    #[doc(hidden)]
166    Placeholder(PlaceholderMeta<'a>),
167}
168
169/// Metadata for a field
170#[derive(Debug, Clone)]
171pub struct Field<'a, S> {
172    #[doc(hidden)]
173    pub name: smartstring::alias::String,
174    #[doc(hidden)]
175    pub description: Option<String>,
176    #[doc(hidden)]
177    pub arguments: Option<Vec<Argument<'a, S>>>,
178    #[doc(hidden)]
179    pub field_type: Type<'a>,
180    #[doc(hidden)]
181    pub deprecation_status: DeprecationStatus,
182}
183
184impl<'a, S> Field<'a, S> {
185    /// Returns true if the type is built-in to GraphQL.
186    pub fn is_builtin(&self) -> bool {
187        // "used exclusively by GraphQL’s introspection system"
188        self.name.starts_with("__")
189    }
190}
191
192/// Metadata for an argument to a field
193#[derive(Debug, Clone)]
194pub struct Argument<'a, S> {
195    #[doc(hidden)]
196    pub name: String,
197    #[doc(hidden)]
198    pub description: Option<String>,
199    #[doc(hidden)]
200    pub arg_type: Type<'a>,
201    #[doc(hidden)]
202    pub default_value: Option<InputValue<S>>,
203}
204
205impl<'a, S> Argument<'a, S> {
206    /// Returns true if the type is built-in to GraphQL.
207    pub fn is_builtin(&self) -> bool {
208        // "used exclusively by GraphQL’s introspection system"
209        self.name.starts_with("__")
210    }
211}
212
213/// Metadata for a single value in an enum
214#[derive(Debug, Clone)]
215pub struct EnumValue {
216    /// The name of the enum value
217    ///
218    /// This is the string literal representation of the enum in responses.
219    pub name: String,
220    /// The optional description of the enum value.
221    ///
222    /// Note: this is not the description of the enum itself; it's the
223    /// description of this enum _value_.
224    pub description: Option<String>,
225    /// Whether the field is deprecated or not, with an optional reason.
226    pub deprecation_status: DeprecationStatus,
227}
228
229impl<'a, S> MetaType<'a, S> {
230    /// Access the name of the type, if applicable
231    ///
232    /// Lists, non-null wrappers, and placeholders don't have names.
233    pub fn name(&self) -> Option<&str> {
234        match *self {
235            MetaType::Scalar(ScalarMeta { ref name, .. })
236            | MetaType::Object(ObjectMeta { ref name, .. })
237            | MetaType::Enum(EnumMeta { ref name, .. })
238            | MetaType::Interface(InterfaceMeta { ref name, .. })
239            | MetaType::Union(UnionMeta { ref name, .. })
240            | MetaType::InputObject(InputObjectMeta { ref name, .. }) => Some(name),
241            _ => None,
242        }
243    }
244
245    /// Access the description of the type, if applicable
246    ///
247    /// Lists, nullable wrappers, and placeholders don't have names.
248    pub fn description(&self) -> Option<&str> {
249        match self {
250            MetaType::Scalar(ScalarMeta { description, .. })
251            | MetaType::Object(ObjectMeta { description, .. })
252            | MetaType::Enum(EnumMeta { description, .. })
253            | MetaType::Interface(InterfaceMeta { description, .. })
254            | MetaType::Union(UnionMeta { description, .. })
255            | MetaType::InputObject(InputObjectMeta { description, .. }) => description.as_deref(),
256            _ => None,
257        }
258    }
259
260    /// Accesses the [specification URL][0], if applicable.
261    ///
262    /// Only custom GraphQL scalars can have a [specification URL][0].
263    ///
264    /// [0]: https://spec.graphql.org/October2021#sec--specifiedBy
265    pub fn specified_by_url(&self) -> Option<&str> {
266        match self {
267            Self::Scalar(ScalarMeta {
268                specified_by_url, ..
269            }) => specified_by_url.as_deref(),
270            _ => None,
271        }
272    }
273
274    /// Construct a `TypeKind` for a given type
275    ///
276    /// # Panics
277    ///
278    /// Panics if the type represents a placeholder or nullable type.
279    pub fn type_kind(&self) -> TypeKind {
280        match *self {
281            MetaType::Scalar(_) => TypeKind::Scalar,
282            MetaType::List(_) => TypeKind::List,
283            MetaType::Nullable(_) => panic!("Can't take type_kind of nullable meta type"),
284            MetaType::Object(_) => TypeKind::Object,
285            MetaType::Enum(_) => TypeKind::Enum,
286            MetaType::Interface(_) => TypeKind::Interface,
287            MetaType::Union(_) => TypeKind::Union,
288            MetaType::InputObject(_) => TypeKind::InputObject,
289            MetaType::Placeholder(_) => panic!("Can't take type_kind of placeholder meta type"),
290        }
291    }
292
293    /// Access a field's meta data given its name
294    ///
295    /// Only objects and interfaces have fields. This method always returns `None` for other types.
296    pub fn field_by_name(&self, name: &str) -> Option<&Field<S>> {
297        match *self {
298            MetaType::Object(ObjectMeta { ref fields, .. })
299            | MetaType::Interface(InterfaceMeta { ref fields, .. }) => {
300                fields.iter().find(|f| f.name == name)
301            }
302            _ => None,
303        }
304    }
305
306    /// Access an input field's meta data given its name
307    ///
308    /// Only input objects have input fields. This method always returns `None` for other types.
309    pub fn input_field_by_name(&self, name: &str) -> Option<&Argument<S>> {
310        match *self {
311            MetaType::InputObject(InputObjectMeta {
312                ref input_fields, ..
313            }) => input_fields.iter().find(|f| f.name == name),
314            _ => None,
315        }
316    }
317
318    /// Construct a `Type` literal instance based on the metadata
319    pub fn as_type(&self) -> Type<'a> {
320        match *self {
321            MetaType::Scalar(ScalarMeta { ref name, .. })
322            | MetaType::Object(ObjectMeta { ref name, .. })
323            | MetaType::Enum(EnumMeta { ref name, .. })
324            | MetaType::Interface(InterfaceMeta { ref name, .. })
325            | MetaType::Union(UnionMeta { ref name, .. })
326            | MetaType::InputObject(InputObjectMeta { ref name, .. }) => {
327                Type::NonNullNamed(name.clone())
328            }
329            MetaType::List(ListMeta {
330                ref of_type,
331                expected_size,
332            }) => Type::NonNullList(Box::new(of_type.clone()), expected_size),
333            MetaType::Nullable(NullableMeta { ref of_type }) => match *of_type {
334                Type::NonNullNamed(ref inner) => Type::Named(inner.clone()),
335                Type::NonNullList(ref inner, expected_size) => {
336                    Type::List(inner.clone(), expected_size)
337                }
338                ref t => t.clone(),
339            },
340            MetaType::Placeholder(PlaceholderMeta { ref of_type }) => of_type.clone(),
341        }
342    }
343
344    /// Access the input value parse function, if applicable
345    ///
346    /// An input value parse function is a function that takes an `InputValue` instance and returns
347    /// `true` if it can be parsed as the provided type.
348    ///
349    /// Only scalars, enums, and input objects have parse functions.
350    pub fn input_value_parse_fn(&self) -> Option<InputValueParseFn<S>> {
351        match *self {
352            MetaType::Scalar(ScalarMeta {
353                ref try_parse_fn, ..
354            })
355            | MetaType::Enum(EnumMeta {
356                ref try_parse_fn, ..
357            })
358            | MetaType::InputObject(InputObjectMeta {
359                ref try_parse_fn, ..
360            }) => Some(*try_parse_fn),
361            _ => None,
362        }
363    }
364
365    /// Returns true if the type is a composite type
366    ///
367    /// Objects, interfaces, and unions are composite.
368    pub fn is_composite(&self) -> bool {
369        matches!(
370            *self,
371            MetaType::Object(_) | MetaType::Interface(_) | MetaType::Union(_)
372        )
373    }
374
375    /// Returns true if the type can occur in leaf positions in queries
376    ///
377    /// Only enums and scalars are leaf types.
378    pub fn is_leaf(&self) -> bool {
379        matches!(*self, MetaType::Enum(_) | MetaType::Scalar(_))
380    }
381
382    /// Returns true if the type is abstract
383    ///
384    /// Only interfaces and unions are abstract types.
385    pub fn is_abstract(&self) -> bool {
386        matches!(*self, MetaType::Interface(_) | MetaType::Union(_))
387    }
388
389    /// Returns true if the type can be used in input positions, e.g. arguments or variables
390    ///
391    /// Only scalars, enums, and input objects are input types.
392    pub fn is_input(&self) -> bool {
393        matches!(
394            *self,
395            MetaType::Scalar(_) | MetaType::Enum(_) | MetaType::InputObject(_)
396        )
397    }
398
399    /// Returns true if the type is built-in to GraphQL.
400    pub fn is_builtin(&self) -> bool {
401        if let Some(name) = self.name() {
402            // "used exclusively by GraphQL’s introspection system"
403            {
404                name.starts_with("__") ||
405            // https://spec.graphql.org/October2021#sec-Scalars
406            name == "Boolean" || name == "String" || name == "Int" || name == "Float" || name == "ID" ||
407            // Our custom empty markers
408            name == "_EmptyMutation" || name == "_EmptySubscription"
409            }
410        } else {
411            false
412        }
413    }
414
415    pub(crate) fn fields<'b>(&self, schema: &'b SchemaType<S>) -> Option<Vec<&'b Field<'b, S>>> {
416        schema
417            .lookup_type(&self.as_type())
418            .and_then(|tpe| match *tpe {
419                MetaType::Interface(ref i) => Some(i.fields.iter().collect()),
420                MetaType::Object(ref o) => Some(o.fields.iter().collect()),
421                MetaType::Union(ref u) => Some(
422                    u.of_type_names
423                        .iter()
424                        .filter_map(|n| schema.concrete_type_by_name(n))
425                        .filter_map(|t| t.fields(schema))
426                        .flatten()
427                        .collect(),
428                ),
429                _ => None,
430            })
431    }
432}
433
434impl<'a, S> ScalarMeta<'a, S> {
435    /// Builds a new [`ScalarMeta`] type with the specified `name`.
436    pub fn new<T>(name: Cow<'a, str>) -> Self
437    where
438        T: FromInputValue<S> + ParseScalarValue<S>,
439        T::Error: IntoFieldError<S>,
440    {
441        Self {
442            name,
443            description: None,
444            specified_by_url: None,
445            try_parse_fn: try_parse_fn::<S, T>,
446            parse_fn: <T as ParseScalarValue<S>>::from_str,
447        }
448    }
449
450    /// Sets the `description` of this [`ScalarMeta`] type.
451    ///
452    /// Overwrites any previously set description.
453    #[must_use]
454    pub fn description(mut self, description: &str) -> Self {
455        self.description = Some(description.into());
456        self
457    }
458
459    /// Sets the [specification URL][0] for this [`ScalarMeta`] type.
460    ///
461    /// Overwrites any previously set [specification URL][0].
462    ///
463    /// [0]: https://spec.graphql.org/October2021#sec--specifiedBy
464    #[must_use]
465    pub fn specified_by_url(mut self, url: impl Into<Cow<'a, str>>) -> Self {
466        self.specified_by_url = Some(url.into());
467        self
468    }
469
470    /// Wraps this [`ScalarMeta`] type into a generic [`MetaType`].
471    pub fn into_meta(self) -> MetaType<'a, S> {
472        MetaType::Scalar(self)
473    }
474}
475
476impl<'a> ListMeta<'a> {
477    /// Build a new [`ListMeta`] type by wrapping the specified [`Type`].
478    ///
479    /// Specifying `expected_size` will be used to ensure that values of this
480    /// type will always match it.
481    pub fn new(of_type: Type<'a>, expected_size: Option<usize>) -> Self {
482        Self {
483            of_type,
484            expected_size,
485        }
486    }
487
488    /// Wraps this [`ListMeta`] type into a generic [`MetaType`].
489    pub fn into_meta<S>(self) -> MetaType<'a, S> {
490        MetaType::List(self)
491    }
492}
493
494impl<'a> NullableMeta<'a> {
495    /// Build a new [`NullableMeta`] type by wrapping the specified [`Type`].
496    pub fn new(of_type: Type<'a>) -> Self {
497        Self { of_type }
498    }
499
500    /// Wraps this [`NullableMeta`] type into a generic [`MetaType`].
501    pub fn into_meta<S>(self) -> MetaType<'a, S> {
502        MetaType::Nullable(self)
503    }
504}
505
506impl<'a, S> ObjectMeta<'a, S> {
507    /// Build a new [`ObjectMeta`] type with the specified `name` and `fields`.
508    pub fn new(name: Cow<'a, str>, fields: &[Field<'a, S>]) -> Self
509    where
510        S: Clone,
511    {
512        Self {
513            name,
514            description: None,
515            fields: fields.to_vec(),
516            interface_names: vec![],
517        }
518    }
519
520    /// Sets the `description` of this [`ObjectMeta`] type.
521    ///
522    /// Overwrites any previously set description.
523    #[must_use]
524    pub fn description(mut self, description: &str) -> Self {
525        self.description = Some(description.into());
526        self
527    }
528
529    /// Set the `interfaces` this [`ObjectMeta`] type implements.
530    ///
531    /// Overwrites any previously set list of interfaces.
532    #[must_use]
533    pub fn interfaces(mut self, interfaces: &[Type<'a>]) -> Self {
534        self.interface_names = interfaces
535            .iter()
536            .map(|t| t.innermost_name().into())
537            .collect();
538        self
539    }
540
541    /// Wraps this [`ObjectMeta`] type into a generic [`MetaType`].
542    pub fn into_meta(self) -> MetaType<'a, S> {
543        MetaType::Object(self)
544    }
545}
546
547impl<'a, S> EnumMeta<'a, S> {
548    /// Build a new [`EnumMeta`] type with the specified `name` and possible
549    /// `values`.
550    pub fn new<T>(name: Cow<'a, str>, values: &[EnumValue]) -> Self
551    where
552        T: FromInputValue<S>,
553        T::Error: IntoFieldError<S>,
554    {
555        Self {
556            name,
557            description: None,
558            values: values.to_owned(),
559            try_parse_fn: try_parse_fn::<S, T>,
560        }
561    }
562
563    /// Sets the `description` of this [`EnumMeta`] type.
564    ///
565    /// Overwrites any previously set description.
566    #[must_use]
567    pub fn description(mut self, description: &str) -> Self {
568        self.description = Some(description.into());
569        self
570    }
571
572    /// Wraps this [`EnumMeta`] type into a generic [`MetaType`].
573    pub fn into_meta(self) -> MetaType<'a, S> {
574        MetaType::Enum(self)
575    }
576}
577
578impl<'a, S> InterfaceMeta<'a, S> {
579    /// Builds a new [`InterfaceMeta`] type with the specified `name` and
580    /// `fields`.
581    pub fn new(name: Cow<'a, str>, fields: &[Field<'a, S>]) -> Self
582    where
583        S: Clone,
584    {
585        Self {
586            name,
587            description: None,
588            fields: fields.to_vec(),
589            interface_names: Vec::new(),
590        }
591    }
592
593    /// Sets the `description` of this [`InterfaceMeta`] type.
594    ///
595    /// Overwrites any previously set description.
596    #[must_use]
597    pub fn description(mut self, description: &str) -> Self {
598        self.description = Some(description.into());
599        self
600    }
601
602    /// Sets the `interfaces` this [`InterfaceMeta`] interface implements.
603    ///
604    /// Overwrites any previously set list of interfaces.
605    #[must_use]
606    pub fn interfaces(mut self, interfaces: &[Type<'a>]) -> Self {
607        self.interface_names = interfaces
608            .iter()
609            .map(|t| t.innermost_name().into())
610            .collect();
611        self
612    }
613
614    /// Wraps this [`InterfaceMeta`] type into a generic [`MetaType`].
615    pub fn into_meta(self) -> MetaType<'a, S> {
616        MetaType::Interface(self)
617    }
618}
619
620impl<'a> UnionMeta<'a> {
621    /// Build a new [`UnionMeta`] type with the specified `name` and possible
622    /// [`Type`]s.
623    pub fn new(name: Cow<'a, str>, of_types: &[Type]) -> Self {
624        Self {
625            name,
626            description: None,
627            of_type_names: of_types.iter().map(|t| t.innermost_name().into()).collect(),
628        }
629    }
630
631    /// Sets the `description` of this [`UnionMeta`] type.
632    ///
633    /// Overwrites any previously set description.
634    #[must_use]
635    pub fn description(mut self, description: &str) -> Self {
636        self.description = Some(description.into());
637        self
638    }
639
640    /// Wraps this [`UnionMeta`] type into a generic [`MetaType`].
641    pub fn into_meta<S>(self) -> MetaType<'a, S> {
642        MetaType::Union(self)
643    }
644}
645
646impl<'a, S> InputObjectMeta<'a, S> {
647    /// Builds a new [`InputObjectMeta`] type with the specified `name` and
648    /// `input_fields`.
649    pub fn new<T>(name: Cow<'a, str>, input_fields: &[Argument<'a, S>]) -> Self
650    where
651        T: FromInputValue<S>,
652        T::Error: IntoFieldError<S>,
653        S: Clone,
654    {
655        Self {
656            name,
657            description: None,
658            input_fields: input_fields.to_vec(),
659            try_parse_fn: try_parse_fn::<S, T>,
660        }
661    }
662
663    /// Set the `description` of this [`InputObjectMeta`] type.
664    ///
665    /// Overwrites any previously set description.
666    #[must_use]
667    pub fn description(mut self, description: &str) -> Self {
668        self.description = Some(description.into());
669        self
670    }
671
672    /// Wraps this [`InputObjectMeta`] type into a generic [`MetaType`].
673    pub fn into_meta(self) -> MetaType<'a, S> {
674        MetaType::InputObject(self)
675    }
676}
677
678impl<'a, S> Field<'a, S> {
679    /// Set the `description` of this [`Field`].
680    ///
681    /// Overwrites any previously set description.
682    #[must_use]
683    pub fn description(mut self, description: &str) -> Self {
684        self.description = Some(description.into());
685        self
686    }
687
688    /// Adds an `argument` to this [`Field`].
689    ///
690    /// Arguments are unordered and can't contain duplicates by name.
691    #[must_use]
692    pub fn argument(mut self, argument: Argument<'a, S>) -> Self {
693        match self.arguments {
694            None => {
695                self.arguments = Some(vec![argument]);
696            }
697            Some(ref mut args) => {
698                args.push(argument);
699            }
700        };
701        self
702    }
703
704    /// Sets this [`Field`] as deprecated with an optional `reason`.
705    ///
706    /// Overwrites any previously set deprecation reason.
707    #[must_use]
708    pub fn deprecated(mut self, reason: Option<&str>) -> Self {
709        self.deprecation_status = DeprecationStatus::Deprecated(reason.map(Into::into));
710        self
711    }
712}
713
714impl<'a, S> Argument<'a, S> {
715    /// Builds a new [`Argument`] of the given [`Type`] with the given `name`.
716    pub fn new(name: &str, arg_type: Type<'a>) -> Self {
717        Self {
718            name: name.into(),
719            description: None,
720            arg_type,
721            default_value: None,
722        }
723    }
724
725    /// Sets the `description` of this [`Argument`].
726    ///
727    /// Overwrites any previously set description.
728    #[must_use]
729    pub fn description(mut self, description: &str) -> Self {
730        self.description = Some(description.into());
731        self
732    }
733
734    /// Set the default value of this [`Argument`].
735    ///
736    /// Overwrites any previously set default value.
737    #[must_use]
738    pub fn default_value(mut self, val: InputValue<S>) -> Self {
739        self.default_value = Some(val);
740        self
741    }
742}
743
744impl EnumValue {
745    /// Constructs a new [`EnumValue`] with the provided `name`.
746    pub fn new(name: &str) -> Self {
747        Self {
748            name: name.into(),
749            description: None,
750            deprecation_status: DeprecationStatus::Current,
751        }
752    }
753
754    /// Sets the `description` of this [`EnumValue`].
755    ///
756    /// Overwrites any previously set description.
757    #[must_use]
758    pub fn description(mut self, description: &str) -> Self {
759        self.description = Some(description.into());
760        self
761    }
762
763    /// Sets this [`EnumValue`] as deprecated with an optional `reason`.
764    ///
765    /// Overwrites any previously set deprecation reason.
766    #[must_use]
767    pub fn deprecated(mut self, reason: Option<&str>) -> Self {
768        self.deprecation_status = DeprecationStatus::Deprecated(reason.map(Into::into));
769        self
770    }
771}
772
773impl<'a, S: fmt::Debug> fmt::Debug for ScalarMeta<'a, S> {
774    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
775        fmt.debug_struct("ScalarMeta")
776            .field("name", &self.name)
777            .field("description", &self.description)
778            .finish()
779    }
780}
781
782impl<'a, S: fmt::Debug> fmt::Debug for EnumMeta<'a, S> {
783    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
784        fmt.debug_struct("EnumMeta")
785            .field("name", &self.name)
786            .field("description", &self.description)
787            .field("values", &self.values)
788            .finish()
789    }
790}
791
792impl<'a, S: fmt::Debug> fmt::Debug for InputObjectMeta<'a, S> {
793    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
794        fmt.debug_struct("InputObjectMeta")
795            .field("name", &self.name)
796            .field("description", &self.description)
797            .field("input_fields", &self.input_fields)
798            .finish()
799    }
800}
801
802fn try_parse_fn<S, T>(v: &InputValue<S>) -> Result<(), FieldError<S>>
803where
804    T: FromInputValue<S>,
805    T::Error: IntoFieldError<S>,
806{
807    T::from_input_value(v)
808        .map(drop)
809        .map_err(T::Error::into_field_error)
810}