async_graphql/dynamic/
type_ref.rs1use std::{
2 borrow::Cow,
3 fmt::{self, Display},
4};
5
6#[derive(Debug, Clone, Eq, PartialEq, Hash)]
8pub enum TypeRef {
9 Named(Cow<'static, str>),
11 NonNull(Box<TypeRef>),
13 List(Box<TypeRef>),
15}
16
17impl Display for TypeRef {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 match self {
20 TypeRef::Named(name) => write!(f, "{}", name),
21 TypeRef::NonNull(ty) => write!(f, "{}!", ty),
22 TypeRef::List(ty) => write!(f, "[{}]", ty),
23 }
24 }
25}
26
27impl TypeRef {
28 pub const INT: &'static str = "Int";
30
31 pub const FLOAT: &'static str = "Float";
33
34 pub const STRING: &'static str = "String";
36
37 pub const BOOLEAN: &'static str = "Boolean";
39
40 pub const ID: &'static str = "ID";
42
43 pub const UPLOAD: &'static str = "Upload";
45
46 #[inline]
50 pub fn named(type_name: impl Into<String>) -> TypeRef {
51 TypeRef::Named(type_name.into().into())
52 }
53
54 #[inline]
58 pub fn named_nn(type_name: impl Into<String>) -> TypeRef {
59 TypeRef::NonNull(Box::new(TypeRef::Named(type_name.into().into())))
60 }
61
62 #[inline]
66 pub fn named_list(type_name: impl Into<String>) -> TypeRef {
67 TypeRef::List(Box::new(TypeRef::Named(type_name.into().into())))
68 }
69
70 #[inline]
74 pub fn named_nn_list(type_name: impl Into<String>) -> TypeRef {
75 TypeRef::List(Box::new(TypeRef::NonNull(Box::new(TypeRef::Named(
76 type_name.into().into(),
77 )))))
78 }
79
80 #[inline]
84 pub fn named_list_nn(type_name: impl Into<String>) -> TypeRef {
85 TypeRef::NonNull(Box::new(TypeRef::List(Box::new(TypeRef::Named(
86 type_name.into().into(),
87 )))))
88 }
89
90 #[inline]
94 pub fn named_nn_list_nn(type_name: impl Into<String>) -> TypeRef {
95 TypeRef::NonNull(Box::new(TypeRef::List(Box::new(TypeRef::NonNull(
96 Box::new(TypeRef::Named(type_name.into().into())),
97 )))))
98 }
99
100 #[inline(always)]
104 pub fn type_name(&self) -> &str {
105 match self {
106 TypeRef::Named(name) => name,
107 TypeRef::NonNull(inner) => inner.type_name(),
108 TypeRef::List(inner) => inner.type_name(),
109 }
110 }
111
112 #[inline]
113 pub(crate) fn is_nullable(&self) -> bool {
114 match self {
115 TypeRef::Named(_) => true,
116 TypeRef::NonNull(_) => false,
117 TypeRef::List(_) => true,
118 }
119 }
120
121 pub(crate) fn is_subtype(&self, sub: &TypeRef) -> bool {
122 fn is_subtype(cur: &TypeRef, sub: &TypeRef) -> bool {
123 match (cur, sub) {
124 (TypeRef::NonNull(super_type), TypeRef::NonNull(sub_type)) => {
125 is_subtype(&super_type, &sub_type)
126 }
127 (_, TypeRef::NonNull(sub_type)) => is_subtype(cur, &sub_type),
128 (TypeRef::Named(super_type), TypeRef::Named(sub_type)) => super_type == sub_type,
129 (TypeRef::List(super_type), TypeRef::List(sub_type)) => {
130 is_subtype(super_type, sub_type)
131 }
132 _ => false,
133 }
134 }
135
136 is_subtype(self, sub)
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 #[test]
145 fn create() {
146 assert_eq!(TypeRef::named("MyObj").to_string(), "MyObj");
147 assert_eq!(TypeRef::named_nn("MyObj").to_string(), "MyObj!");
148 assert_eq!(TypeRef::named_list("MyObj").to_string(), "[MyObj]");
149 assert_eq!(TypeRef::named_list_nn("MyObj").to_string(), "[MyObj]!");
150 assert_eq!(TypeRef::named_nn_list("MyObj").to_string(), "[MyObj!]");
151 assert_eq!(TypeRef::named_nn_list_nn("MyObj").to_string(), "[MyObj!]!");
152 }
153}