cynic/
schema.rs

1//! Traits for describing a GraphQL schema in Rust.
2//!
3//! The `use_schema` macro will mostly output types that make use of the
4//! traits in this module to describe the schema.  The derives then combine
5//! these types with the `QueryBuilder` type to enforce the restrictions
6//! of the schema.
7//!
8//! Note that this module is mostly concerned with the marker types output
9//! by `use_schema`, _not_ the actual types users work with.  The traits
10//! will usually be implemented on marker types, the geneirc parameters will
11//! usually be marker types and the associated types will also usually be
12//! markers.
13
14/// Indicates that a struct represents a Field in a graphql schema.
15pub trait Field {
16    /// The schema marker type of this field.
17    type Type;
18
19    /// the name of this field
20    const NAME: &'static str;
21}
22
23// TODO: Get the terminology straight in this file, it's a mess.
24
25/// Indicates that a type has a given field
26///
27/// This should be implemented several times for any given type,
28/// once per field. `FieldMarker` should be the marker type for
29/// the field,
30pub trait HasField<FieldMarker> {
31    /// The schema marker type of this field.
32    type Type;
33}
34
35/// Indicates that an input object has a given field
36///
37/// This should be implemented several times for any given input object,
38/// once per field. `FieldMarker` should be the marker type for the field,
39/// and `FieldType` should be the schema marker type of the field.
40pub trait HasInputField<FieldMarker, FieldType> {}
41
42/// Indicates that a field has an argument
43///
44/// This should be implemented on the field marker type for each argument
45/// that field has.  `ArgumentMarker` should be the marker type for the
46/// argument.
47pub trait HasArgument<ArgumentMarker> {
48    /// The schema marker type of this argument.
49    type ArgumentType;
50
51    /// The name of this argument
52    const NAME: &'static str;
53}
54
55/// Indicates that a type is a scalar that maps to the given schema scalar.
56///
57/// Note that this type is actually implemented on the users types.
58pub trait IsScalar<SchemaType> {
59    /// The schema marker type this scalar represents.
60    type SchemaType;
61}
62
63impl<T, U: ?Sized> IsScalar<T> for &U
64where
65    U: IsScalar<T>,
66{
67    type SchemaType = U::SchemaType;
68}
69
70impl<T, U> IsScalar<Option<T>> for Option<U>
71where
72    U: IsScalar<T>,
73{
74    type SchemaType = Option<U::SchemaType>;
75}
76
77impl<T, U> IsScalar<Vec<T>> for Vec<U>
78where
79    U: IsScalar<T>,
80{
81    type SchemaType = Vec<U::SchemaType>;
82}
83
84impl<T, U> IsScalar<Vec<T>> for [U]
85where
86    U: IsScalar<T>,
87{
88    type SchemaType = Vec<U::SchemaType>;
89}
90
91impl<T, U, const SIZE: usize> IsScalar<Vec<T>> for [U; SIZE]
92where
93    U: IsScalar<T>,
94{
95    type SchemaType = Vec<U::SchemaType>;
96}
97
98impl<T, U: ?Sized> IsScalar<Box<T>> for Box<U>
99where
100    U: IsScalar<T>,
101{
102    type SchemaType = Box<U::SchemaType>;
103}
104
105impl<T, U: ?Sized> IsScalar<T> for std::borrow::Cow<'_, U>
106where
107    U: IsScalar<T> + ToOwned,
108{
109    type SchemaType = U::SchemaType;
110}
111
112impl IsScalar<bool> for bool {
113    type SchemaType = bool;
114}
115
116impl IsScalar<String> for String {
117    type SchemaType = String;
118}
119
120impl IsScalar<String> for str {
121    type SchemaType = String;
122}
123
124impl IsScalar<i32> for i32 {
125    type SchemaType = i32;
126}
127
128impl IsScalar<f64> for f64 {
129    type SchemaType = f64;
130}
131
132impl IsScalar<crate::Id> for crate::Id {
133    type SchemaType = crate::Id;
134}
135
136/// A marker trait that indicates a particular type is at the root of a GraphQL
137/// schemas query hierarchy.
138pub trait QueryRoot {}
139
140/// A marker trait that indicates a particular type is at the root of a GraphQL
141/// schemas mutation hierarchy.
142pub trait MutationRoot {}
143
144/// A marker trait that indicates a particular type is at the root of a GraphQL
145/// schemas subscription hierarchy.
146pub trait SubscriptionRoot {}
147
148/// Indicates that a type has a subtype relationship with another type
149pub trait HasSubtype<Type> {}
150
151/// A marker type with a name.
152pub trait NamedType {
153    /// The name of this type
154    const NAME: &'static str;
155}
156
157impl NamedType for i32 {
158    const NAME: &'static str = "Int";
159}
160
161impl NamedType for f64 {
162    const NAME: &'static str = "Float";
163}
164
165impl NamedType for String {
166    const NAME: &'static str = "String";
167}
168
169impl NamedType for bool {
170    const NAME: &'static str = "Boolean";
171}
172
173impl NamedType for crate::Id {
174    const NAME: &'static str = "ID";
175}
176
177/// Indicates that a type is an `InputObject`
178pub trait InputObjectMarker {}
179
180/// Indicates that a type represents a GraphQL directive that can be used
181/// in field position.
182pub trait FieldDirective {
183    /// The name of the directive in GraphQL
184    const NAME: &'static str;
185}