1use std::{char, marker::PhantomData, rc::Rc, thread::JoinHandle};
2
3use derive_more::with_trait::{Deref, Display, From, Into};
4use serde::{Deserialize, Serialize};
5
6use crate::{
7 GraphQLScalar, IntoFieldError, Scalar,
8 ast::{InputValue, Selection, ToInputValue},
9 executor::{ExecutionResult, Executor, Registry},
10 graphql_scalar,
11 macros::reflect,
12 parser::{LexerError, ParseError, ScalarToken, Token},
13 schema::meta::MetaType,
14 types::{
15 async_await::GraphQLValueAsync,
16 base::{GraphQLType, GraphQLValue},
17 subscriptions::GraphQLSubscriptionValue,
18 },
19 value::{
20 FromScalarValue, ParseScalarResult, ScalarValue, ToScalarValue, TryToPrimitive, Value,
21 WrongInputScalarTypeError,
22 },
23};
24
25#[derive(
29 Clone, Debug, Deref, Deserialize, Display, Eq, From, GraphQLScalar, Into, PartialEq, Serialize,
30)]
31#[deref(forward)]
32#[from(Box<str>, String)]
33#[into(Box<str>, String)]
34#[graphql(parse_token(String, i32))]
35pub struct ID(Box<str>);
36
37impl ID {
38 fn to_output(&self) -> &str {
39 &self.0
40 }
41
42 fn from_input<S: ScalarValue>(v: &Scalar<S>) -> Result<Self, WrongInputScalarTypeError<'_, S>> {
43 v.try_to_string()
44 .or_else(|| v.try_to_int().as_ref().map(ToString::to_string))
45 .map(|s| Self(s.into()))
46 .ok_or_else(|| WrongInputScalarTypeError {
47 type_name: arcstr::literal!("String` or `Int"),
48 input: &**v,
49 })
50 }
51}
52
53impl ID {
54 #[must_use]
56 pub fn new<S: Into<String>>(value: S) -> Self {
57 ID(value.into().into())
58 }
59}
60
61#[graphql_scalar]
62#[graphql(
63 with = impl_string_scalar,
64 to_output_with = String::as_str
65 from_input_with = __builtin,
66)]
67type String = std::string::String;
68
69mod impl_string_scalar {
70 use super::*;
71
72 impl<'s, S> FromScalarValue<'s, S> for String
73 where
74 S: TryToPrimitive<'s, Self, Error: IntoFieldError<S>> + 's,
75 {
76 type Error = S::Error;
77
78 fn from_scalar_value(v: &'s S) -> Result<Self, Self::Error> {
79 v.try_to_primitive()
80 }
81 }
82
83 pub(super) fn parse_token<S: ScalarValue>(value: ScalarToken<'_>) -> ParseScalarResult<S> {
84 if let ScalarToken::String(value) = value {
85 let mut ret = String::with_capacity(value.len());
86 let mut char_iter = value.chars();
87 while let Some(ch) = char_iter.next() {
88 match ch {
89 '\\' => match char_iter.next() {
90 Some('"') => {
91 ret.push('"');
92 }
93 Some('/') => {
94 ret.push('/');
95 }
96 Some('n') => {
97 ret.push('\n');
98 }
99 Some('r') => {
100 ret.push('\r');
101 }
102 Some('t') => {
103 ret.push('\t');
104 }
105 Some('\\') => {
106 ret.push('\\');
107 }
108 Some('f') => {
109 ret.push('\u{000c}');
110 }
111 Some('b') => {
112 ret.push('\u{0008}');
113 }
114 Some('u') => {
115 ret.push(parse_unicode_codepoint(&mut char_iter)?);
116 }
117 Some(s) => {
118 return Err(ParseError::LexerError(LexerError::UnknownEscapeSequence(
119 format!("\\{s}"),
120 )));
121 }
122 None => return Err(ParseError::LexerError(LexerError::UnterminatedString)),
123 },
124 ch => {
125 ret.push(ch);
126 }
127 }
128 }
129 Ok(ret.into())
130 } else {
131 Err(ParseError::unexpected_token(Token::Scalar(value)))
132 }
133 }
134}
135
136fn parse_unicode_codepoint<I>(char_iter: &mut I) -> Result<char, ParseError>
137where
138 I: Iterator<Item = char>,
139{
140 let escaped_code_point = char_iter
141 .next()
142 .ok_or_else(|| {
143 ParseError::LexerError(LexerError::UnknownEscapeSequence(String::from("\\u")))
144 })
145 .and_then(|c1| {
146 char_iter
147 .next()
148 .map(|c2| format!("{c1}{c2}"))
149 .ok_or_else(|| {
150 ParseError::LexerError(LexerError::UnknownEscapeSequence(format!("\\u{c1}")))
151 })
152 })
153 .and_then(|mut s| {
154 char_iter
155 .next()
156 .ok_or_else(|| {
157 ParseError::LexerError(LexerError::UnknownEscapeSequence(format!("\\u{s}")))
158 })
159 .map(|c2| {
160 s.push(c2);
161 s
162 })
163 })
164 .and_then(|mut s| {
165 char_iter
166 .next()
167 .ok_or_else(|| {
168 ParseError::LexerError(LexerError::UnknownEscapeSequence(format!("\\u{s}")))
169 })
170 .map(|c2| {
171 s.push(c2);
172 s
173 })
174 })?;
175 let code_point = u32::from_str_radix(&escaped_code_point, 16).map_err(|_| {
176 ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
177 "\\u{escaped_code_point}",
178 )))
179 })?;
180 char::from_u32(code_point).ok_or_else(|| {
181 ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
182 "\\u{escaped_code_point}",
183 )))
184 })
185}
186
187#[graphql_scalar]
188#[graphql(
189 name = "String",
190 with = impl_arcstr_scalar,
191 to_output_with = ScalarValue::from_displayable,
192 parse_token(String)
193)]
194type ArcStr = arcstr::ArcStr;
195
196mod impl_arcstr_scalar {
197 use super::ArcStr;
198 use crate::{FromScalarValue, Scalar, ScalarValue};
199
200 pub(super) fn from_input<S: ScalarValue>(
201 v: &Scalar<S>,
202 ) -> Result<ArcStr, <&str as FromScalarValue<'_, S>>::Error> {
203 if let Some(s) = v.downcast_type::<ArcStr>() {
204 Ok(s.clone())
205 } else {
206 v.try_to::<&str>().map(ArcStr::from)
207 }
208 }
209}
210
211#[graphql_scalar]
212#[graphql(
213 name = "String",
214 with = impl_compactstring_scalar,
215 to_output_with = ScalarValue::from_displayable,
216 parse_token(String),
217)]
218type CompactString = compact_str::CompactString;
219
220mod impl_compactstring_scalar {
221 use super::CompactString;
222 use crate::{FromScalarValue, Scalar, ScalarValue};
223
224 pub(super) fn from_input<S: ScalarValue>(
225 v: &Scalar<S>,
226 ) -> Result<CompactString, <&str as FromScalarValue<'_, S>>::Error> {
227 if let Some(s) = v.downcast_type::<CompactString>() {
228 Ok(s.clone())
229 } else {
230 v.try_to::<&str>().map(CompactString::from)
231 }
232 }
233}
234
235impl<S> reflect::WrappedType<S> for str {
236 const VALUE: reflect::WrappedValue = 1;
237}
238
239impl<S> reflect::BaseType<S> for str {
240 const NAME: reflect::Type = "String";
241}
242
243impl<S> reflect::BaseSubTypes<S> for str {
244 const NAMES: reflect::Types = &[<Self as reflect::BaseType<S>>::NAME];
245}
246
247impl<S> GraphQLType<S> for str
248where
249 S: ScalarValue,
250{
251 fn name(_: &()) -> Option<ArcStr> {
252 Some(arcstr::literal!("String"))
253 }
254
255 fn meta(_: &(), registry: &mut Registry<S>) -> MetaType<S> {
256 registry.build_scalar_type::<String>(&()).into_meta()
257 }
258}
259
260impl<S> GraphQLValue<S> for str
261where
262 S: ScalarValue,
263{
264 type Context = ();
265 type TypeInfo = ();
266
267 fn type_name(&self, info: &Self::TypeInfo) -> Option<ArcStr> {
268 <Self as GraphQLType<S>>::name(info)
269 }
270
271 fn resolve(
272 &self,
273 _: &(),
274 _: Option<&[Selection<S>]>,
275 _: &Executor<Self::Context, S>,
276 ) -> ExecutionResult<S> {
277 Ok(Value::Scalar(self.to_scalar_value()))
278 }
279}
280
281impl<S> GraphQLValueAsync<S> for str
282where
283 S: ScalarValue + Send + Sync,
284{
285 fn resolve_async<'a>(
286 &'a self,
287 info: &'a Self::TypeInfo,
288 selection_set: Option<&'a [Selection<S>]>,
289 executor: &'a Executor<Self::Context, S>,
290 ) -> crate::BoxFuture<'a, ExecutionResult<S>> {
291 use futures::future;
292 Box::pin(future::ready(self.resolve(info, selection_set, executor)))
293 }
294}
295
296impl<'s, S> FromScalarValue<'s, S> for &'s str
297where
298 S: TryToPrimitive<'s, Self, Error: IntoFieldError<S>> + 's,
299{
300 type Error = S::Error;
301
302 fn from_scalar_value(v: &'s S) -> Result<Self, Self::Error> {
303 v.try_to_primitive()
304 }
305}
306
307impl<S: ScalarValue> ToScalarValue<S> for str {
308 fn to_scalar_value(&self) -> S {
309 S::from_displayable(self)
310 }
311}
312
313impl<S> ToInputValue<S> for str
314where
315 Self: ToScalarValue<S>,
316{
317 fn to_input_value(&self) -> InputValue<S> {
318 InputValue::Scalar(self.to_scalar_value())
319 }
320}
321
322#[graphql_scalar]
323#[graphql(with = impl_boolean_scalar, from_input_with = __builtin)]
324type Boolean = bool;
325
326mod impl_boolean_scalar {
327 use super::*;
328
329 impl<'s, S> FromScalarValue<'s, S> for Boolean
330 where
331 S: TryToPrimitive<'s, Self, Error: IntoFieldError<S>> + 's,
332 {
333 type Error = S::Error;
334
335 fn from_scalar_value(v: &'s S) -> Result<Self, Self::Error> {
336 v.try_to_primitive()
337 }
338 }
339
340 pub(super) fn to_output<S: ScalarValue>(v: &Boolean) -> S {
341 (*v).into()
342 }
343
344 pub(super) fn parse_token<S: ScalarValue>(value: ScalarToken<'_>) -> ParseScalarResult<S> {
345 Err(ParseError::unexpected_token(Token::Scalar(value)))
347 }
348}
349
350#[graphql_scalar]
351#[graphql(with = impl_int_scalar, from_input_with = __builtin)]
352type Int = i32;
353
354mod impl_int_scalar {
355 use super::*;
356
357 impl<'s, S> FromScalarValue<'s, S> for Int
358 where
359 S: TryToPrimitive<'s, Self, Error: IntoFieldError<S>> + 's,
360 {
361 type Error = S::Error;
362
363 fn from_scalar_value(v: &'s S) -> Result<Self, Self::Error> {
364 v.try_to_primitive()
365 }
366 }
367
368 pub(super) fn to_output<S: ScalarValue>(v: &Int) -> S {
369 (*v).into()
370 }
371
372 pub(super) fn parse_token<S: ScalarValue>(value: ScalarToken<'_>) -> ParseScalarResult<S> {
373 if let ScalarToken::Int(v) = value {
374 v.parse()
375 .map_err(|_| ParseError::unexpected_token(Token::Scalar(value)))
376 .map(|s: i32| s.into())
377 } else {
378 Err(ParseError::unexpected_token(Token::Scalar(value)))
379 }
380 }
381}
382
383#[graphql_scalar]
384#[graphql(with = impl_float_scalar, from_input_with = __builtin)]
385type Float = f64;
386
387mod impl_float_scalar {
388 use super::*;
389
390 impl<'s, S> FromScalarValue<'s, S> for Float
391 where
392 S: TryToPrimitive<'s, Self, Error: IntoFieldError<S>> + 's,
393 {
394 type Error = S::Error;
395
396 fn from_scalar_value(v: &'s S) -> Result<Self, Self::Error> {
397 v.try_to_primitive()
398 }
399 }
400
401 pub(super) fn to_output<S: ScalarValue>(v: &Float) -> S {
402 (*v).into()
403 }
404
405 pub(super) fn parse_token<S: ScalarValue>(value: ScalarToken<'_>) -> ParseScalarResult<S> {
406 match value {
407 ScalarToken::Int(v) => v
408 .parse()
409 .map_err(|_| ParseError::unexpected_token(Token::Scalar(value)))
410 .map(|s: i32| f64::from(s).into()),
411 ScalarToken::Float(v) => v
412 .parse()
413 .map_err(|_| ParseError::unexpected_token(Token::Scalar(value)))
414 .map(|s: f64| s.into()),
415 ScalarToken::String(_) => Err(ParseError::unexpected_token(Token::Scalar(value))),
416 }
417 }
418}
419
420#[derive(Debug)]
425pub struct EmptyMutation<T: ?Sized = ()>(PhantomData<JoinHandle<Box<T>>>);
426
427crate::sa::assert_impl_all!(EmptyMutation<Rc<String>>: Send, Sync);
429
430impl<T: ?Sized> EmptyMutation<T> {
431 #[inline]
433 pub fn new() -> Self {
434 Self(PhantomData)
435 }
436}
437
438impl<S, T> GraphQLType<S> for EmptyMutation<T>
439where
440 S: ScalarValue,
441{
442 fn name(_: &()) -> Option<ArcStr> {
443 Some(arcstr::literal!("_EmptyMutation"))
444 }
445
446 fn meta(_: &(), registry: &mut Registry<S>) -> MetaType<S> {
447 registry.build_object_type::<Self>(&(), &[]).into_meta()
448 }
449}
450
451impl<S, T> GraphQLValue<S> for EmptyMutation<T>
452where
453 S: ScalarValue,
454{
455 type Context = T;
456 type TypeInfo = ();
457
458 fn type_name(&self, info: &Self::TypeInfo) -> Option<ArcStr> {
459 <Self as GraphQLType<S>>::name(info)
460 }
461}
462
463impl<S, T> GraphQLValueAsync<S> for EmptyMutation<T>
464where
465 Self::TypeInfo: Sync,
466 Self::Context: Sync,
467 S: ScalarValue + Send + Sync,
468{
469}
470
471impl<T> Default for EmptyMutation<T> {
474 fn default() -> Self {
475 Self::new()
476 }
477}
478
479pub struct EmptySubscription<T: ?Sized = ()>(PhantomData<JoinHandle<Box<T>>>);
484
485crate::sa::assert_impl_all!(EmptySubscription<Rc<String>>: Send, Sync);
487
488impl<T: ?Sized> EmptySubscription<T> {
489 #[inline]
491 pub fn new() -> Self {
492 Self(PhantomData)
493 }
494}
495
496impl<S, T> GraphQLType<S> for EmptySubscription<T>
497where
498 S: ScalarValue,
499{
500 fn name(_: &()) -> Option<ArcStr> {
501 Some(arcstr::literal!("_EmptySubscription"))
502 }
503
504 fn meta(_: &(), registry: &mut Registry<S>) -> MetaType<S> {
505 registry.build_object_type::<Self>(&(), &[]).into_meta()
506 }
507}
508
509impl<S, T> GraphQLValue<S> for EmptySubscription<T>
510where
511 S: ScalarValue,
512{
513 type Context = T;
514 type TypeInfo = ();
515
516 fn type_name(&self, info: &Self::TypeInfo) -> Option<ArcStr> {
517 <Self as GraphQLType<S>>::name(info)
518 }
519}
520
521impl<T, S> GraphQLSubscriptionValue<S> for EmptySubscription<T>
522where
523 Self::TypeInfo: Sync,
524 Self::Context: Sync,
525 S: ScalarValue + Send + Sync + 'static,
526{
527}
528
529impl<T> Default for EmptySubscription<T> {
532 fn default() -> Self {
533 Self::new()
534 }
535}
536
537#[cfg(test)]
538mod tests {
539 use crate::{
540 parser::ScalarToken,
541 value::{DefaultScalarValue, ParseScalarValue, ScalarValue as _},
542 };
543
544 use super::{EmptyMutation, EmptySubscription, ID};
545
546 #[test]
547 fn test_id_from_string() {
548 let actual = ID::from(String::from("foo"));
549 let expected = ID("foo".into());
550 assert_eq!(actual, expected);
551 }
552
553 #[test]
554 fn test_id_new() {
555 let actual = ID::new("foo");
556 let expected = ID("foo".into());
557 assert_eq!(actual, expected);
558 }
559
560 #[test]
561 fn test_id_deref() {
562 let id = ID("foo".into());
563 assert_eq!(id.len(), 3);
564 }
565
566 #[test]
567 fn test_id_display() {
568 let id = ID("foo".into());
569 assert_eq!(id.to_string(), "foo");
570 }
571
572 #[test]
573 fn parse_strings() {
574 fn parse_string(s: &str, expected: &str) {
575 let s =
576 <String as ParseScalarValue<DefaultScalarValue>>::from_str(ScalarToken::String(s));
577 assert!(s.is_ok(), "A parsing error occurred: {s:?}");
578 let s: Option<String> = s.unwrap().try_to().ok();
579 assert!(s.is_some(), "No string returned");
580 assert_eq!(s.unwrap(), expected);
581 }
582
583 parse_string("simple", "simple");
584 parse_string(" white space ", " white space ");
585 parse_string(r#"quote \""#, "quote \"");
586 parse_string(r"escaped \n\r\b\t\f", "escaped \n\r\u{0008}\t\u{000c}");
587 parse_string(r"slashes \\ \/", "slashes \\ /");
588 parse_string(
589 r"unicode \u1234\u5678\u90AB\uCDEF",
590 "unicode \u{1234}\u{5678}\u{90ab}\u{cdef}",
591 );
592 }
593
594 #[test]
595 fn parse_f64_from_int() {
596 for (v, expected) in [
597 ("0", 0),
598 ("128", 128),
599 ("1601942400", 1601942400),
600 ("1696550400", 1696550400),
601 ("-1", -1),
602 ] {
603 let n = <f64 as ParseScalarValue<DefaultScalarValue>>::from_str(ScalarToken::Int(v));
604 assert!(n.is_ok(), "A parsing error occurred: {:?}", n.unwrap_err());
605
606 let n: Option<f64> = n.unwrap().try_to().ok();
607 assert!(n.is_some(), "No `f64` returned");
608 assert_eq!(n.unwrap(), f64::from(expected));
609 }
610 }
611
612 #[test]
613 fn parse_f64_from_float() {
614 for (v, expected) in [
615 ("0.", 0.),
616 ("1.2", 1.2),
617 ("1601942400.", 1601942400.),
618 ("1696550400.", 1696550400.),
619 ("-1.2", -1.2),
620 ] {
621 let n = <f64 as ParseScalarValue<DefaultScalarValue>>::from_str(ScalarToken::Float(v));
622 assert!(n.is_ok(), "A parsing error occurred: {:?}", n.unwrap_err());
623
624 let n: Option<f64> = n.unwrap().try_to().ok();
625 assert!(n.is_some(), "No `f64` returned");
626 assert_eq!(n.unwrap(), expected);
627 }
628 }
629
630 #[test]
631 fn empty_mutation_is_send() {
632 fn check_if_send<T: Send>() {}
633 check_if_send::<EmptyMutation<()>>();
634 }
635
636 #[test]
637 fn empty_subscription_is_send() {
638 fn check_if_send<T: Send>() {}
639 check_if_send::<EmptySubscription<()>>();
640 }
641
642 #[test]
643 fn default_is_invariant_over_type() {
644 struct Bar;
645 let _ = EmptySubscription::<Bar>::default();
646 let _ = EmptyMutation::<Bar>::default();
647 }
648}