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}