1use std::{borrow::Cow, fmt, hash::Hash, mem, slice, vec};
2
3use arcstr::ArcStr;
4use compact_str::CompactString;
5use indexmap::IndexMap;
6
7#[cfg(doc)]
8use self::TypeModifier::{List, NonNull};
9use crate::{
10 executor::Variables,
11 parser::Spanning,
12 value::{DefaultScalarValue, Scalar, ScalarValue, ToScalarValue},
13};
14
15#[derive(Clone, Copy, Debug, Eq, PartialEq)]
17pub enum TypeModifier {
18 NonNull,
20
21 List(Option<usize>),
23}
24
25#[derive(Clone, Debug)]
27pub enum TypeModifiers {
28 Static(&'static [TypeModifier]),
30
31 Dynamic(Box<[TypeModifier]>),
33}
34
35impl Default for TypeModifiers {
36 fn default() -> Self {
37 Self::Static(&[])
38 }
39}
40
41impl AsRef<[TypeModifier]> for TypeModifiers {
42 fn as_ref(&self) -> &[TypeModifier] {
43 match self {
44 Self::Static(s) => s,
45 Self::Dynamic(bs) => bs,
46 }
47 }
48}
49
50impl Extend<TypeModifier> for TypeModifiers {
51 fn extend<T: IntoIterator<Item = TypeModifier>>(&mut self, iter: T) {
52 for modifier in iter {
53 self.wrap(modifier);
54 }
55 }
56}
57
58impl TypeModifiers {
59 fn wrap(&mut self, modifier: TypeModifier) {
61 *self = match (mem::take(self), modifier) {
62 (Self::Static(&[]), TypeModifier::NonNull) => Self::Static(&[TypeModifier::NonNull]),
63 (Self::Static(&[]), TypeModifier::List(None)) => {
64 Self::Static(&[TypeModifier::List(None)])
65 }
66 (Self::Static(&[TypeModifier::NonNull]), TypeModifier::List(None)) => {
67 Self::Static(&[TypeModifier::NonNull, TypeModifier::List(None)])
68 }
69 (Self::Static(s), modifier) => {
70 let mut vec: Vec<_> = s.to_vec();
71 vec.push(modifier);
72 Self::Dynamic(vec.into_boxed_slice())
73 }
74 (Self::Dynamic(s), modifier) => {
75 let mut vec = s.into_vec();
76 vec.push(modifier);
77 Self::Dynamic(vec.into_boxed_slice())
78 }
79 };
80 }
81
82 fn pop(&mut self) {
84 *self = match mem::take(self) {
85 Self::Static(s) => Self::Static(&s[..s.len() - 1]),
86 Self::Dynamic(s) if s.len() == 1 => Self::Static(&[]),
87 Self::Dynamic(s) => {
88 let mut vec = s.into_vec();
89 vec.pop();
90 Self::Dynamic(vec.into_boxed_slice())
91 }
92 }
93 }
94}
95
96#[derive(Clone, Copy, Debug)]
100pub struct Type<N = ArcStr, M = TypeModifiers> {
101 name: N,
103
104 modifiers: M,
108}
109
110impl<N, M> Eq for Type<N, M> where Self: PartialEq {}
111
112impl<N1, N2, M1, M2> PartialEq<Type<N2, M2>> for Type<N1, M1>
113where
114 N1: AsRef<str>,
115 N2: AsRef<str>,
116 M1: AsRef<[TypeModifier]>,
117 M2: AsRef<[TypeModifier]>,
118{
119 fn eq(&self, other: &Type<N2, M2>) -> bool {
120 self.name.as_ref() == other.name.as_ref()
121 && self.modifiers.as_ref() == other.modifiers.as_ref()
122 }
123}
124
125impl<N, M> fmt::Display for Type<N, M>
126where
127 N: AsRef<str>,
128 M: AsRef<[TypeModifier]>,
129{
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 match self.modifier() {
132 Some(TypeModifier::NonNull) => write!(f, "{}!", self.borrow_inner()),
133 Some(TypeModifier::List(..)) => write!(f, "[{}]", self.borrow_inner()),
134 None => write!(f, "{}", self.name.as_ref()),
135 }
136 }
137}
138
139impl<'a, N, M> From<&'a Type<N, M>> for BorrowedType<'a>
140where
141 N: AsRef<str>,
142 M: AsRef<[TypeModifier]>,
143{
144 fn from(value: &'a Type<N, M>) -> Self {
145 Self {
146 name: value.name.as_ref(),
147 modifiers: value.modifiers.as_ref(),
148 }
149 }
150}
151
152impl<N: AsRef<str>, M: AsRef<[TypeModifier]>> Type<N, M> {
153 pub(crate) fn borrow_inner(&self) -> BorrowedType<'_> {
159 let modifiers = self.modifiers.as_ref();
160 match modifiers.len() {
161 0 => panic!("no inner `Type` available"),
162 n => Type {
163 name: self.name.as_ref(),
164 modifiers: &modifiers[..n - 1],
165 },
166 }
167 }
168
169 #[must_use]
173 pub fn name(&self) -> Option<&str> {
174 (!self.is_list()).then(|| self.name.as_ref())
175 }
176
177 #[must_use]
181 pub fn innermost_name(&self) -> &str {
182 self.name.as_ref()
183 }
184
185 #[must_use]
187 pub fn modifier(&self) -> Option<&TypeModifier> {
188 self.modifiers().last()
189 }
190
191 #[must_use]
195 pub fn modifiers(&self) -> &[TypeModifier] {
196 self.modifiers.as_ref()
197 }
198
199 #[must_use]
201 pub fn is_non_null(&self) -> bool {
202 match self.modifiers.as_ref().last() {
203 Some(TypeModifier::NonNull) => true,
204 Some(TypeModifier::List(..)) | None => false,
205 }
206 }
207
208 #[must_use]
210 pub fn is_list(&self) -> bool {
211 match self.modifiers.as_ref().last() {
212 Some(TypeModifier::NonNull) => self.borrow_inner().is_non_null(),
213 Some(TypeModifier::List(..)) => true,
214 None => false,
215 }
216 }
217}
218
219impl<N, M: Default> Type<N, M> {
220 #[must_use]
222 pub fn nullable(name: impl Into<N>) -> Self {
223 Self {
224 name: name.into(),
225 modifiers: M::default(),
226 }
227 }
228}
229
230impl<N, M: Extend<TypeModifier>> Type<N, M> {
231 fn wrap(mut self, modifier: TypeModifier) -> Self {
233 self.modifiers.extend([modifier]);
234 self
235 }
236
237 #[must_use]
239 pub fn wrap_list(self, expected_size: Option<usize>) -> Self {
240 self.wrap(TypeModifier::List(expected_size))
241 }
242
243 #[must_use]
245 pub fn wrap_non_null(self) -> Self {
246 self.wrap(TypeModifier::NonNull)
247 }
248}
249
250impl<N: AsRef<str>> Type<N> {
251 pub(crate) fn into_nullable(mut self) -> Self {
253 if self.is_non_null() {
254 self.modifiers.pop();
255 }
256 self
257 }
258}
259
260pub(crate) type BorrowedType<'a> = Type<&'a str, &'a [TypeModifier]>;
262
263impl<'a> BorrowedType<'a> {
264 pub(crate) fn non_null(name: &'a str) -> Self {
266 Self {
267 name,
268 modifiers: &[TypeModifier::NonNull],
269 }
270 }
271
272 pub(crate) fn borrow_list_inner(&self) -> Option<Self> {
274 let mut out = None;
275 for (n, m) in self.modifiers.iter().enumerate().rev() {
276 match m {
277 TypeModifier::NonNull => {}
278 TypeModifier::List(..) => {
279 out = Some(Self {
280 name: self.name,
281 modifiers: &self.modifiers[..n],
282 });
283 break;
284 }
285 }
286 }
287 out
288 }
289}
290
291#[expect(missing_docs, reason = "self-explanatory")]
298#[derive(Clone, Debug, PartialEq)]
299pub enum InputValue<S = DefaultScalarValue> {
300 Null,
301 Scalar(S),
302 Enum(String),
303 Variable(String),
304 List(Vec<Spanning<InputValue<S>>>),
305 Object(Vec<(Spanning<String>, Spanning<InputValue<S>>)>),
306}
307
308#[derive(Clone, Debug, PartialEq)]
309pub struct VariableDefinition<'a, S> {
310 pub var_type: Spanning<Type<&'a str>>,
311 pub default_value: Option<Spanning<InputValue<S>>>,
312 pub directives: Option<Vec<Spanning<Directive<'a, S>>>>,
313}
314
315#[derive(Clone, Debug, PartialEq)]
316pub struct Arguments<'a, S> {
317 pub items: Vec<(Spanning<&'a str>, Spanning<InputValue<S>>)>,
318}
319
320#[derive(Clone, Debug, PartialEq)]
321pub struct VariableDefinitions<'a, S> {
322 pub items: Vec<(Spanning<&'a str>, VariableDefinition<'a, S>)>,
323}
324
325#[derive(Clone, Debug, PartialEq)]
326pub struct Field<'a, S> {
327 pub alias: Option<Spanning<&'a str>>,
328 pub name: Spanning<&'a str>,
329 pub arguments: Option<Spanning<Arguments<'a, S>>>,
330 pub directives: Option<Vec<Spanning<Directive<'a, S>>>>,
331 pub selection_set: Option<Vec<Selection<'a, S>>>,
332}
333
334#[derive(Clone, Debug, PartialEq)]
335pub struct FragmentSpread<'a, S> {
336 pub name: Spanning<&'a str>,
337 pub directives: Option<Vec<Spanning<Directive<'a, S>>>>,
338}
339
340#[derive(Clone, Debug, PartialEq)]
341pub struct InlineFragment<'a, S> {
342 pub type_condition: Option<Spanning<&'a str>>,
343 pub directives: Option<Vec<Spanning<Directive<'a, S>>>>,
344 pub selection_set: Vec<Selection<'a, S>>,
345}
346
347#[expect(missing_docs, reason = "self-explanatory")]
363#[derive(Clone, Debug, PartialEq)]
364pub enum Selection<'a, S = DefaultScalarValue> {
365 Field(Spanning<Field<'a, S>>),
366 FragmentSpread(Spanning<FragmentSpread<'a, S>>),
367 InlineFragment(Spanning<InlineFragment<'a, S>>),
368}
369
370#[derive(Clone, Debug, PartialEq)]
371pub struct Directive<'a, S> {
372 pub name: Spanning<&'a str>,
373 pub arguments: Option<Spanning<Arguments<'a, S>>>,
374}
375
376#[expect(missing_docs, reason = "self-explanatory")]
377#[derive(Clone, Copy, Debug, Eq, PartialEq)]
378pub enum OperationType {
379 Query,
380 Mutation,
381 Subscription,
382}
383
384#[expect(missing_docs, reason = "self-explanatory")]
385#[derive(Clone, Debug, PartialEq)]
386pub struct Operation<'a, S> {
387 pub operation_type: OperationType,
388 pub name: Option<Spanning<&'a str>>,
389 pub variable_definitions: Option<Spanning<VariableDefinitions<'a, S>>>,
390 pub directives: Option<Vec<Spanning<Directive<'a, S>>>>,
391 pub selection_set: Vec<Selection<'a, S>>,
392}
393
394#[derive(Clone, Debug, PartialEq)]
395pub struct Fragment<'a, S> {
396 pub name: Spanning<&'a str>,
397 pub type_condition: Spanning<&'a str>,
398 pub directives: Option<Vec<Spanning<Directive<'a, S>>>>,
399 pub selection_set: Vec<Selection<'a, S>>,
400}
401
402#[doc(hidden)]
403#[derive(Clone, Debug, PartialEq)]
404pub enum Definition<'a, S> {
405 Operation(Spanning<Operation<'a, S>>),
406 Fragment(Spanning<Fragment<'a, S>>),
407}
408
409#[doc(hidden)]
410pub type Document<'a, S> = [Definition<'a, S>];
411#[doc(hidden)]
412pub type OwnedDocument<'a, S> = Vec<Definition<'a, S>>;
413
414pub trait FromInputValue<S = DefaultScalarValue>: Sized {
422 type Error;
429
430 fn from_input_value(v: &InputValue<S>) -> Result<Self, Self::Error>;
432
433 fn from_implicit_null() -> Result<Self, Self::Error> {
441 Self::from_input_value(&InputValue::<S>::Null)
442 }
443}
444
445pub trait ToInputValue<S = DefaultScalarValue> {
447 fn to_input_value(&self) -> InputValue<S>;
449}
450
451impl<S> InputValue<S> {
452 pub fn null() -> Self {
454 Self::Null
455 }
456
457 pub fn scalar<T: Into<S>>(v: T) -> Self {
459 Self::Scalar(v.into())
460 }
461
462 pub fn enum_value<T: AsRef<str>>(s: T) -> Self {
464 Self::Enum(s.as_ref().into())
465 }
466
467 pub fn variable<T: AsRef<str>>(v: T) -> Self {
469 Self::Variable(v.as_ref().into())
470 }
471
472 pub fn list(l: Vec<Self>) -> Self {
478 Self::List(l.into_iter().map(Spanning::unlocated).collect())
479 }
480
481 pub fn parsed_list(l: Vec<Spanning<Self>>) -> Self {
483 Self::List(l)
484 }
485
486 pub fn object<K>(o: IndexMap<K, Self>) -> Self
491 where
492 K: AsRef<str> + Eq + Hash,
493 {
494 Self::Object(
495 o.into_iter()
496 .map(|(k, v)| {
497 (
498 Spanning::unlocated(k.as_ref().into()),
499 Spanning::unlocated(v),
500 )
501 })
502 .collect(),
503 )
504 }
505
506 pub fn parsed_object(o: Vec<(Spanning<String>, Spanning<Self>)>) -> Self {
508 Self::Object(o)
509 }
510
511 #[must_use]
524 pub fn into_const(self, values: &Variables<S>) -> Option<Self>
525 where
526 S: Clone,
527 {
528 match self {
529 Self::Variable(v) => values.get(&v).cloned(),
530 Self::List(l) => Some(Self::List(
531 l.into_iter()
532 .map(|s| s.map(|v| v.into_const(values).unwrap_or_else(Self::null)))
533 .collect(),
534 )),
535 Self::Object(o) => Some(Self::Object(
536 o.into_iter()
537 .filter_map(|(sk, sv)| sv.and_then(|v| v.into_const(values)).map(|sv| (sk, sv)))
538 .collect(),
539 )),
540 v => Some(v),
541 }
542 }
543
544 pub fn convert<T: FromInputValue<S>>(&self) -> Result<T, T::Error> {
546 T::from_input_value(self)
547 }
548
549 pub fn is_null(&self) -> bool {
551 matches!(self, Self::Null)
552 }
553
554 pub fn is_variable(&self) -> bool {
556 matches!(self, Self::Variable(_))
557 }
558
559 pub fn as_enum_value(&self) -> Option<&str> {
561 match self {
562 Self::Enum(e) => Some(e.as_str()),
563 _ => None,
564 }
565 }
566
567 pub fn as_scalar(&self) -> Option<&S> {
569 match self {
570 Self::Scalar(s) => Some(s),
571 _ => None,
572 }
573 }
574
575 pub fn to_object_value(&self) -> Option<IndexMap<&str, &Self>> {
580 match self {
581 Self::Object(o) => Some(
582 o.iter()
583 .map(|(sk, sv)| (sk.item.as_str(), &sv.item))
584 .collect(),
585 ),
586 _ => None,
587 }
588 }
589
590 pub fn to_list_value(&self) -> Option<Vec<&Self>> {
595 match self {
596 Self::List(l) => Some(l.iter().map(|s| &s.item).collect()),
597 _ => None,
598 }
599 }
600
601 pub fn referenced_variables(&self) -> Vec<&str> {
603 match self {
604 Self::Variable(name) => vec![name.as_str()],
605 Self::List(l) => l
606 .iter()
607 .flat_map(|v| v.item.referenced_variables())
608 .collect(),
609 Self::Object(o) => o
610 .iter()
611 .flat_map(|(_, v)| v.item.referenced_variables())
612 .collect(),
613 _ => vec![],
614 }
615 }
616
617 pub fn unlocated_eq(&self, other: &Self) -> bool
620 where
621 S: PartialEq,
622 {
623 match (self, other) {
624 (Self::Null, Self::Null) => true,
625 (Self::Scalar(s1), Self::Scalar(s2)) => s1 == s2,
626 (Self::Enum(s1), Self::Enum(s2)) | (Self::Variable(s1), Self::Variable(s2)) => s1 == s2,
627 (Self::List(l1), Self::List(l2)) => l1
628 .iter()
629 .zip(l2.iter())
630 .all(|(v1, v2)| v1.item.unlocated_eq(&v2.item)),
631 (Self::Object(o1), Self::Object(o2)) => {
632 o1.len() == o2.len()
633 && o1.iter().all(|(sk1, sv1)| {
634 o2.iter().any(|(sk2, sv2)| {
635 sk1.item == sk2.item && sv1.item.unlocated_eq(&sv2.item)
636 })
637 })
638 }
639 _ => false,
640 }
641 }
642}
643
644impl<S: ScalarValue> fmt::Display for InputValue<S> {
645 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
646 match self {
647 Self::Null => write!(f, "null"),
648 Self::Scalar(s) => fmt::Display::fmt(<&Scalar<_>>::from(s), f),
649 Self::Enum(v) => write!(f, "{v}"),
650 Self::Variable(v) => write!(f, "${v}"),
651 Self::List(v) => {
652 write!(f, "[")?;
653 for (i, spanning) in v.iter().enumerate() {
654 spanning.item.fmt(f)?;
655 if i < v.len() - 1 {
656 write!(f, ", ")?;
657 }
658 }
659 write!(f, "]")
660 }
661 Self::Object(o) => {
662 write!(f, "{{")?;
663 for (i, (k, v)) in o.iter().enumerate() {
664 write!(f, "{}: ", k.item)?;
665 v.item.fmt(f)?;
666 if i < o.len() - 1 {
667 write!(f, ", ")?;
668 }
669 }
670 write!(f, "}}")
671 }
672 }
673 }
674}
675
676pub trait IntoInputValue<S> {
689 #[must_use]
691 fn into_input_value(self) -> InputValue<S>;
692}
693
694impl<S> IntoInputValue<S> for InputValue<S> {
695 fn into_input_value(self) -> Self {
696 self
697 }
698}
699
700impl<T, S> IntoInputValue<S> for Option<T>
701where
702 T: IntoInputValue<S>,
703{
704 fn into_input_value(self) -> InputValue<S> {
705 match self {
706 Some(v) => v.into_input_value(),
707 None => InputValue::Null,
708 }
709 }
710}
711
712impl<T, S> IntoInputValue<S> for &T
713where
714 T: ToScalarValue<S> + ?Sized,
715{
716 fn into_input_value(self) -> InputValue<S> {
717 InputValue::Scalar(self.to_scalar_value())
718 }
719}
720
721impl<S> IntoInputValue<S> for String
722where
723 String: Into<S>,
724{
725 fn into_input_value(self) -> InputValue<S> {
726 InputValue::Scalar(self.into())
727 }
728}
729
730impl<S> IntoInputValue<S> for Cow<'_, str>
731where
732 for<'a> &'a str: IntoInputValue<S>,
733 String: IntoInputValue<S>,
734{
735 fn into_input_value(self) -> InputValue<S> {
736 match self {
737 Cow::Borrowed(s) => s.into_input_value(),
738 Cow::Owned(s) => s.into_input_value(),
739 }
740 }
741}
742
743impl<S: ScalarValue> IntoInputValue<S> for ArcStr
744where
745 ArcStr: ToScalarValue<S>,
746{
747 fn into_input_value(self) -> InputValue<S> {
748 InputValue::Scalar(self.to_scalar_value())
749 }
750}
751
752impl<S: ScalarValue> IntoInputValue<S> for CompactString
753where
754 CompactString: ToScalarValue<S>,
755{
756 fn into_input_value(self) -> InputValue<S> {
757 InputValue::Scalar(self.to_scalar_value())
758 }
759}
760
761impl<S> IntoInputValue<S> for i32
762where
763 i32: ToScalarValue<S>,
764{
765 fn into_input_value(self) -> InputValue<S> {
766 InputValue::Scalar(self.to_scalar_value())
767 }
768}
769
770impl<S> IntoInputValue<S> for f64
771where
772 f64: ToScalarValue<S>,
773{
774 fn into_input_value(self) -> InputValue<S> {
775 InputValue::Scalar(self.to_scalar_value())
776 }
777}
778
779impl<S> IntoInputValue<S> for bool
780where
781 bool: ToScalarValue<S>,
782{
783 fn into_input_value(self) -> InputValue<S> {
784 InputValue::Scalar(self.to_scalar_value())
785 }
786}
787
788impl<'a, S> Arguments<'a, S> {
789 pub fn into_iter(self) -> vec::IntoIter<(Spanning<&'a str>, Spanning<InputValue<S>>)> {
790 self.items.into_iter()
791 }
792
793 pub fn iter(&self) -> slice::Iter<'_, (Spanning<&'a str>, Spanning<InputValue<S>>)> {
794 self.items.iter()
795 }
796
797 pub fn iter_mut(&mut self) -> slice::IterMut<'_, (Spanning<&'a str>, Spanning<InputValue<S>>)> {
798 self.items.iter_mut()
799 }
800
801 pub fn len(&self) -> usize {
802 self.items.len()
803 }
804
805 pub fn get(&self, key: &str) -> Option<&Spanning<InputValue<S>>> {
806 self.items
807 .iter()
808 .filter(|&(k, _)| k.item == key)
809 .map(|(_, v)| v)
810 .next()
811 }
812}
813
814impl<'a, S> VariableDefinitions<'a, S> {
815 pub fn iter(&self) -> slice::Iter<'_, (Spanning<&'a str>, VariableDefinition<'a, S>)> {
816 self.items.iter()
817 }
818}
819
820#[cfg(test)]
821mod spec_input_value_fmt {
822 use crate::graphql_input_value;
823
824 use super::InputValue;
825
826 #[test]
827 fn correct() {
828 let value: InputValue = graphql_input_value!(null);
829 assert_eq!(value.to_string(), "null");
830
831 let value: InputValue = graphql_input_value!(123);
832 assert_eq!(value.to_string(), "123");
833
834 let value: InputValue = graphql_input_value!(12.3);
835 assert_eq!(value.to_string(), "12.3");
836
837 let value: InputValue = graphql_input_value!("FOO");
838 assert_eq!(value.to_string(), "\"FOO\"");
839
840 let value: InputValue = graphql_input_value!(true);
841 assert_eq!(value.to_string(), "true");
842
843 let value: InputValue = graphql_input_value!(BAR);
844 assert_eq!(value.to_string(), "BAR");
845
846 let value: InputValue = graphql_input_value!(@baz);
847 assert_eq!(value.to_string(), "$baz");
848
849 let value: InputValue = graphql_input_value!([1, 2]);
850 assert_eq!(value.to_string(), "[1, 2]");
851
852 let value: InputValue = graphql_input_value!({"foo": 1,"bar": 2});
853 assert_eq!(value.to_string(), "{foo: 1, bar: 2}");
854 }
855}