1use arcstr::ArcStr;
2
3use crate::{
4 ast::{FromInputValue, InputValue, Selection, ToInputValue},
5 executor::{ExecutionResult, Executor, Registry},
6 schema::meta::MetaType,
7 types::{
8 async_await::GraphQLValueAsync,
9 base::{GraphQLType, GraphQLValue},
10 marker::IsInputType,
11 },
12 value::{ScalarValue, Value},
13};
14
15#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
34pub enum Nullable<T> {
35 ImplicitNull,
37
38 ExplicitNull,
40
41 Some(T),
43}
44
45impl<T> Default for Nullable<T> {
48 fn default() -> Self {
49 Self::ImplicitNull
50 }
51}
52
53impl<T> Nullable<T> {
54 #[inline]
56 pub fn is_explicit_null(&self) -> bool {
57 matches!(self, Self::ExplicitNull)
58 }
59
60 #[inline]
62 pub fn is_implicit_null(&self) -> bool {
63 matches!(self, Self::ImplicitNull)
64 }
65
66 #[inline]
68 pub fn is_some(&self) -> bool {
69 matches!(self, Self::Some(_))
70 }
71
72 #[inline]
74 pub fn is_null(&self) -> bool {
75 !matches!(self, Self::Some(_))
76 }
77
78 #[inline]
80 pub fn as_mut(&mut self) -> Nullable<&mut T> {
81 match *self {
82 Self::Some(ref mut x) => Nullable::Some(x),
83 Self::ImplicitNull => Nullable::ImplicitNull,
84 Self::ExplicitNull => Nullable::ExplicitNull,
85 }
86 }
87
88 #[inline]
94 #[track_caller]
95 pub fn expect(self, msg: &str) -> T {
96 self.some().expect(msg)
97 }
98
99 #[inline]
101 pub fn unwrap_or(self, default: T) -> T {
102 self.some().unwrap_or(default)
103 }
104
105 #[inline]
107 pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
108 self.some().unwrap_or_else(f)
109 }
110
111 #[inline]
113 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Nullable<U> {
114 match self {
115 Self::Some(x) => Nullable::Some(f(x)),
116 Self::ImplicitNull => Nullable::ImplicitNull,
117 Self::ExplicitNull => Nullable::ExplicitNull,
118 }
119 }
120
121 #[inline]
124 pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
125 self.some().map_or(default, f)
126 }
127
128 #[inline]
130 pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U {
131 self.some().map_or_else(default, f)
132 }
133
134 #[inline]
137 pub fn ok_or<E>(self, err: E) -> Result<T, E> {
138 self.some().ok_or(err)
139 }
140
141 #[inline]
144 pub fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<T, E> {
145 self.some().ok_or_else(err)
146 }
147
148 #[inline]
150 #[must_use]
151 pub fn or(self, b: Self) -> Self {
152 match self {
153 Self::Some(_) => self,
154 _ => b,
155 }
156 }
157
158 #[inline]
161 #[must_use]
162 pub fn or_else<F: FnOnce() -> Nullable<T>>(self, f: F) -> Nullable<T> {
163 match self {
164 Self::Some(_) => self,
165 _ => f(),
166 }
167 }
168
169 #[inline]
172 #[must_use]
173 pub fn replace(&mut self, value: T) -> Self {
174 std::mem::replace(self, Self::Some(value))
175 }
176
177 pub fn some(self) -> Option<T> {
179 match self {
180 Self::Some(v) => Some(v),
181 _ => None,
182 }
183 }
184
185 pub fn explicit(self) -> Option<Option<T>> {
188 match self {
189 Self::Some(v) => Some(Some(v)),
190 Self::ExplicitNull => Some(None),
191 Self::ImplicitNull => None,
192 }
193 }
194}
195
196impl<T: Copy> Nullable<&T> {
197 pub fn copied(self) -> Nullable<T> {
199 self.map(|&t| t)
200 }
201}
202
203impl<T: Copy> Nullable<&mut T> {
204 pub fn copied(self) -> Nullable<T> {
206 self.map(|&mut t| t)
207 }
208}
209
210impl<T: Clone> Nullable<&T> {
211 pub fn cloned(self) -> Nullable<T> {
213 self.map(|t| t.clone())
214 }
215}
216
217impl<T: Clone> Nullable<&mut T> {
218 pub fn cloned(self) -> Nullable<T> {
220 self.map(|t| t.clone())
221 }
222}
223
224impl<S, T> GraphQLType<S> for Nullable<T>
225where
226 T: GraphQLType<S>,
227 S: ScalarValue,
228{
229 fn name(_: &Self::TypeInfo) -> Option<ArcStr> {
230 None
231 }
232
233 fn meta(info: &Self::TypeInfo, registry: &mut Registry<S>) -> MetaType<S> {
234 registry.build_nullable_type::<T>(info).into_meta()
235 }
236}
237
238impl<S, T> GraphQLValue<S> for Nullable<T>
239where
240 S: ScalarValue,
241 T: GraphQLValue<S>,
242{
243 type Context = T::Context;
244 type TypeInfo = T::TypeInfo;
245
246 fn type_name(&self, _: &Self::TypeInfo) -> Option<ArcStr> {
247 None
248 }
249
250 fn resolve(
251 &self,
252 info: &Self::TypeInfo,
253 _: Option<&[Selection<S>]>,
254 executor: &Executor<Self::Context, S>,
255 ) -> ExecutionResult<S> {
256 match *self {
257 Self::Some(ref obj) => executor.resolve(info, obj),
258 _ => Ok(Value::null()),
259 }
260 }
261}
262
263impl<S, T> GraphQLValueAsync<S> for Nullable<T>
264where
265 T: GraphQLValueAsync<S>,
266 T::TypeInfo: Sync,
267 T::Context: Sync,
268 S: ScalarValue + Send + Sync,
269{
270 fn resolve_async<'a>(
271 &'a self,
272 info: &'a Self::TypeInfo,
273 _: Option<&'a [Selection<S>]>,
274 executor: &'a Executor<Self::Context, S>,
275 ) -> crate::BoxFuture<'a, ExecutionResult<S>> {
276 let f = async move {
277 let value = match self {
278 Self::Some(obj) => executor.resolve_into_value_async(info, obj).await,
279 _ => Value::null(),
280 };
281 Ok(value)
282 };
283 Box::pin(f)
284 }
285}
286
287impl<S, T: FromInputValue<S>> FromInputValue<S> for Nullable<T> {
288 type Error = <T as FromInputValue<S>>::Error;
289
290 fn from_input_value(v: &InputValue<S>) -> Result<Self, Self::Error> {
291 match v {
292 &InputValue::Null => Ok(Self::ExplicitNull),
293 v => v.convert().map(Self::Some),
294 }
295 }
296
297 fn from_implicit_null() -> Result<Self, Self::Error> {
298 Ok(Self::ImplicitNull)
299 }
300}
301
302impl<S, T> ToInputValue<S> for Nullable<T>
303where
304 T: ToInputValue<S>,
305{
306 fn to_input_value(&self) -> InputValue<S> {
307 match self {
308 Self::Some(v) => v.to_input_value(),
309 _ => InputValue::null(),
310 }
311 }
312}
313
314impl<S, T> IsInputType<S> for Nullable<T>
315where
316 T: IsInputType<S>,
317 S: ScalarValue,
318{
319}