1use crate::definition::{
2 EnumTypeDefinition, InterfaceTypeDefinition, ObjectTypeDefinition, ScalarTypeDefinition,
3 SchemaDefinition, TypeDefinition, TypeDefinitionReference, UnionTypeDefinition,
4};
5use crate::BuiltinScalarDefinition;
6
7#[derive(Debug)]
8pub enum BaseOutputTypeReference<'a, O: OutputType> {
9 BuiltinScalar(BuiltinScalarDefinition),
10 CustomScalar(&'a O::CustomScalarTypeDefinition),
11 Enum(&'a O::EnumTypeDefinition),
12 Object(&'a O::ObjectTypeDefinition),
13 Interface(&'a O::InterfaceTypeDefinition),
14 Union(&'a O::UnionTypeDefinition),
15}
16
17impl<'a, O: OutputType> BaseOutputTypeReference<'a, O> {
18 pub fn name(&self) -> &'a str {
19 match self {
20 Self::BuiltinScalar(bstd) => bstd.name(),
21 Self::CustomScalar(cstd) => cstd.name(),
22 Self::Enum(etd) => etd.name(),
23 Self::Object(otd) => otd.name(),
24 Self::Interface(itd) => itd.name(),
25 Self::Union(utd) => utd.name(),
26 }
27 }
28
29 pub fn is_scalar_or_enum(&self) -> bool {
30 matches!(
31 self,
32 Self::BuiltinScalar(_) | Self::CustomScalar(_) | Self::Enum(_)
33 )
34 }
35
36 pub fn is_composite(&self) -> bool {
37 matches!(self, Self::Object(_) | Self::Interface(_) | Self::Union(_))
38 }
39}
40
41impl<O: OutputType> Clone for BaseOutputTypeReference<'_, O> {
42 fn clone(&self) -> Self {
43 *self
44 }
45}
46
47impl<O: OutputType> Copy for BaseOutputTypeReference<'_, O> {}
48
49pub enum OutputTypeReference<'a, O: OutputType> {
50 Base(BaseOutputTypeReference<'a, O>, bool),
51 List(&'a O, bool),
52}
53
54impl<O: OutputType> Clone for OutputTypeReference<'_, O> {
55 fn clone(&self) -> Self {
56 *self
57 }
58}
59
60impl<O: OutputType> Copy for OutputTypeReference<'_, O> {}
61
62impl<'a, O: OutputType> OutputTypeReference<'a, O> {
63 pub fn is_required(&self) -> bool {
64 match self {
65 Self::Base(_, r) => *r,
66 Self::List(_, r) => *r,
67 }
68 }
69
70 pub fn base<
71 S: SchemaDefinition<
72 CustomScalarTypeDefinition = O::CustomScalarTypeDefinition,
73 EnumTypeDefinition = O::EnumTypeDefinition,
74 ObjectTypeDefinition = O::ObjectTypeDefinition,
75 InterfaceTypeDefinition = O::InterfaceTypeDefinition,
76 UnionTypeDefinition = O::UnionTypeDefinition,
77 >,
78 >(
79 &self,
80 schema_definition: &'a S,
81 ) -> BaseOutputTypeReference<'a, O> {
82 match self {
83 Self::Base(b, _) => *b,
84 Self::List(l, _) => l.base(schema_definition),
85 }
86 }
87}
88
89#[derive(Clone)]
90pub enum ShallowOutputTypeReference<'a, O: OutputType> {
91 Base(&'a str, bool),
92 List(&'a O, bool),
93}
94
95impl<'a, O: OutputType> ShallowOutputTypeReference<'a, O> {
96 pub fn is_required(&self) -> bool {
97 match self {
98 Self::Base(_, r) => *r,
99 Self::List(_, r) => *r,
100 }
101 }
102
103 pub fn base_name(&self) -> &'a str {
104 match self {
105 Self::Base(b, _) => b,
106 Self::List(inner, _) => inner.as_shallow_ref().base_name(),
107 }
108 }
109}
110
111impl<O: OutputType> PartialEq for ShallowOutputTypeReference<'_, O> {
112 fn eq(&self, other: &Self) -> bool {
113 match (self, other) {
114 (
115 ShallowOutputTypeReference::Base(name1, required1),
116 ShallowOutputTypeReference::Base(name2, required2),
117 ) => required1 == required2 && name1 == name2,
118 (
119 ShallowOutputTypeReference::List(inner1, required1),
120 ShallowOutputTypeReference::List(inner2, required2),
121 ) => required1 == required2 && inner1.as_shallow_ref() == inner2.as_shallow_ref(),
122 _ => false,
123 }
124 }
125}
126
127impl<O: OutputType> std::fmt::Display for ShallowOutputTypeReference<'_, O> {
128 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129 match self {
130 ShallowOutputTypeReference::Base(name, required) => {
131 write!(f, "{}{}", name, if *required { "!" } else { "" })
132 }
133 ShallowOutputTypeReference::List(inner, required) => {
134 write!(
135 f,
136 "[{}]{}",
137 inner.as_shallow_ref(),
138 if *required { "!" } else { "" }
139 )
140 }
141 }
142 }
143}
144
145pub trait OutputType: Sized {
146 type CustomScalarTypeDefinition: ScalarTypeDefinition;
147 type EnumTypeDefinition: EnumTypeDefinition;
148 type ObjectTypeDefinition: ObjectTypeDefinition;
149 type InterfaceTypeDefinition: InterfaceTypeDefinition;
150 type UnionTypeDefinition: UnionTypeDefinition;
151
152 fn as_ref<
153 'a,
154 S: SchemaDefinition<
155 CustomScalarTypeDefinition = Self::CustomScalarTypeDefinition,
156 EnumTypeDefinition = Self::EnumTypeDefinition,
157 ObjectTypeDefinition = Self::ObjectTypeDefinition,
158 InterfaceTypeDefinition = Self::InterfaceTypeDefinition,
159 UnionTypeDefinition = Self::UnionTypeDefinition,
160 >,
161 >(
162 &'a self,
163 schema_definition: &'a S,
164 ) -> OutputTypeReference<'a, Self>;
165
166 fn as_shallow_ref(&self) -> ShallowOutputTypeReference<'_, Self>;
167
168 fn display_name(&self) -> String {
169 self.as_shallow_ref().to_string()
170 }
171
172 fn is_required(&self) -> bool {
173 self.as_shallow_ref().is_required()
174 }
175
176 fn base_name(&self) -> &str {
177 self.as_shallow_ref().base_name()
178 }
179
180 fn base<
181 'a,
182 S: SchemaDefinition<
183 CustomScalarTypeDefinition = Self::CustomScalarTypeDefinition,
184 EnumTypeDefinition = Self::EnumTypeDefinition,
185 ObjectTypeDefinition = Self::ObjectTypeDefinition,
186 InterfaceTypeDefinition = Self::InterfaceTypeDefinition,
187 UnionTypeDefinition = Self::UnionTypeDefinition,
188 >,
189 >(
190 &'a self,
191 schema_definition: &'a S,
192 ) -> BaseOutputTypeReference<'a, Self> {
193 self.as_ref(schema_definition).base(schema_definition)
194 }
195}
196
197impl<
198 'a,
199 T: TypeDefinition,
200 O: OutputType<
201 CustomScalarTypeDefinition = T::CustomScalarTypeDefinition,
202 EnumTypeDefinition = T::EnumTypeDefinition,
203 ObjectTypeDefinition = T::ObjectTypeDefinition,
204 InterfaceTypeDefinition = T::InterfaceTypeDefinition,
205 UnionTypeDefinition = T::UnionTypeDefinition,
206 >,
207 > TryFrom<TypeDefinitionReference<'a, T>> for BaseOutputTypeReference<'a, O>
208{
209 type Error = ();
210
211 fn try_from(value: TypeDefinitionReference<'a, T>) -> Result<Self, Self::Error> {
212 match value {
213 TypeDefinitionReference::BuiltinScalar(bstd) => Ok(Self::BuiltinScalar(bstd)),
214 TypeDefinitionReference::CustomScalar(cstd) => Ok(Self::CustomScalar(cstd)),
215 TypeDefinitionReference::Enum(etd) => Ok(Self::Enum(etd)),
216 TypeDefinitionReference::Interface(itd) => Ok(Self::Interface(itd)),
217 TypeDefinitionReference::Object(otd) => Ok(Self::Object(otd)),
218 TypeDefinitionReference::Union(utd) => Ok(Self::Union(utd)),
219 TypeDefinitionReference::InputObject(_) => Err(()),
220 }
221 }
222}