1use crate::{
2 generics, Data, Function, GenericConstraint, GenericParam, Generics, Ident, Lifetime, Path,
3 Print, Signature, TypeParamBound,
4};
5use proc_macro2::TokenStream;
6use quote::{quote, ToTokens};
7use ref_cast::RefCast;
8use syn::TypePath;
9
10#[derive(Debug, Clone)]
11#[repr(C)]
12pub struct Type(pub(crate) TypeNode);
13
14#[derive(Debug, Clone)]
15pub(crate) enum TypeNode {
16 Infer,
17 Tuple(Vec<Type>),
18 PrimitiveStr,
19 Reference {
20 lifetime: Option<Lifetime>,
21 inner: Box<TypeNode>,
22 },
23 ReferenceMut {
24 lifetime: Option<Lifetime>,
25 inner: Box<TypeNode>,
26 },
27 Dereference(Box<TypeNode>),
28 TraitObject(Vec<TypeParamBound>),
29 DataStructure {
30 name: Ident,
31 generics: Generics,
32 data: Data<Type>,
33 },
34 Path(Path),
35}
36
37impl Type {
38 pub fn unit() -> Self {
39 Type(TypeNode::Tuple(Vec::new()))
40 }
41
42 pub fn tuple(types: &[Self]) -> Self {
43 Type(TypeNode::Tuple(Vec::from(types)))
44 }
45
46 pub fn primitive_str() -> Self {
47 Type(TypeNode::PrimitiveStr)
48 }
49
50 pub fn reference(&self) -> Self {
51 Type(TypeNode::Reference {
52 lifetime: None,
53 inner: Box::new(self.0.clone()),
54 })
55 }
56
57 pub fn reference_mut(&self) -> Self {
58 Type(TypeNode::ReferenceMut {
59 lifetime: None,
60 inner: Box::new(self.0.clone()),
61 })
62 }
63
64 pub fn dereference(&self) -> Self {
65 match &self.0 {
66 TypeNode::Reference { inner, .. } => Type((**inner).clone()),
67 TypeNode::ReferenceMut { inner, .. } => Type((**inner).clone()),
68 other => Type(TypeNode::Dereference(Box::new(other.clone()))),
69 }
70 }
71
72 pub fn get_function(&self, name: &str, sig: Signature) -> Function {
73 Function {
74 parent: Some(self.clone()),
75 name: name.to_owned(),
76 sig,
77 }
78 }
79
80 pub fn data(&self) -> Data<Self> {
81 match &self.0 {
82 TypeNode::DataStructure { data, .. } => data.clone().map(|field| field.element),
83 TypeNode::Reference { lifetime, inner } => {
84 Type((**inner).clone()).data().map(|field| {
85 Type(TypeNode::Reference {
86 lifetime: lifetime.clone(),
87 inner: Box::new(field.element.0),
88 })
89 })
90 }
91 TypeNode::ReferenceMut { lifetime, inner } => {
92 Type((**inner).clone()).data().map(|field| {
93 Type(TypeNode::ReferenceMut {
94 lifetime: lifetime.clone(),
95 inner: Box::new(field.element.0),
96 })
97 })
98 }
99 _ => panic!("Type::data"),
100 }
101 }
102
103 pub fn get_tuple_type(&self, index: usize) -> Self {
105 match &self.0 {
106 TypeNode::Tuple(types) => types[index].clone(),
107 _ => panic!("Type::get_tuple_type: Not a Tuple"),
108 }
109 }
110
111 pub(crate) fn syn_to_type(ty: syn::Type) -> Self {
112 match ty {
113 syn::Type::Path(TypePath {
114 qself: None,
116 path,
117 }) => Type(TypeNode::Path(Path::syn_to_path(path))),
118
119 syn::Type::Reference(reference) => {
120 let inner = Box::new(Type::syn_to_type(*reference.elem).0);
121 let lifetime = reference.lifetime.map(|lifetime| Lifetime {
122 ident: Ident::from(lifetime.ident),
123 });
124 if reference.mutability.is_some() {
125 Type(TypeNode::ReferenceMut { lifetime, inner })
126 } else {
127 Type(TypeNode::Reference { lifetime, inner })
128 }
129 }
130 syn::Type::TraitObject(type_trait_object) => Type(TypeNode::TraitObject(
132 generics::syn_to_type_param_bounds(type_trait_object.bounds),
133 )),
134
135 syn::Type::Tuple(type_tuple) => {
136 if type_tuple.elems.is_empty() {
137 Type::unit()
138 } else if type_tuple.elems.len() == 1 && !type_tuple.elems.trailing_punct() {
139 Self::syn_to_type(type_tuple.elems.into_iter().next().unwrap())
142 } else {
143 Type(TypeNode::Tuple(
144 type_tuple
145 .elems
146 .into_iter()
147 .map(Self::syn_to_type)
148 .collect(),
149 ))
150 }
151 }
152 _ => unimplemented!("Type::syn_to_type"),
153 }
154 }
155
156 pub(crate) fn name_and_generics(
157 &self,
158 ) -> (TokenStream, Vec<GenericParam>, Vec<GenericConstraint>) {
159 self.0.name_and_generics()
160 }
161}
162
163impl TypeNode {
164 pub(crate) fn get_name(&self) -> String {
165 match self {
166 TypeNode::Tuple(types) => {
168 let types = types.iter().map(Print::ref_cast);
169 quote!((#(#types),*)).to_string()
170 }
171 TypeNode::PrimitiveStr => String::from("str"),
172 TypeNode::DataStructure { name, .. } => name.to_string(),
173 TypeNode::Reference { inner, .. } => (**inner).get_name(),
174 TypeNode::ReferenceMut { inner, .. } => (**inner).get_name(),
175 TypeNode::Path(path) => {
176 let mut tokens = TokenStream::new();
177 Print::ref_cast(path).to_tokens(&mut tokens);
178 tokens.to_string()
179 }
180 _ => panic!("Type::get_name"),
181 }
182 }
183
184 pub(crate) fn name_and_generics(
185 &self,
186 ) -> (TokenStream, Vec<GenericParam>, Vec<GenericConstraint>) {
187 use super::TypeNode::*;
188 match self {
189 Infer => panic!("Type::name_and_generics: Infer"),
190
191 Tuple(types) => {
192 let types = types.iter().map(Print::ref_cast);
193 (quote!((#(#types),*)), Vec::new(), Vec::new())
194 }
195
196 PrimitiveStr => (quote!(str), Vec::new(), Vec::new()),
197
198 Reference { lifetime, inner } => {
199 let lifetime = lifetime.as_ref().map(Print::ref_cast);
200 let (name, params, constraints) = inner.name_and_generics();
201 (quote!(& #lifetime #name), params, constraints)
202 }
203
204 ReferenceMut { lifetime, inner } => {
205 let lifetime = lifetime.as_ref().map(Print::ref_cast);
206 let (name, params, constraints) = inner.name_and_generics();
207 (quote!(&mut #lifetime #name), params, constraints)
208 }
209
210 Dereference(_dereference) => panic!("Type::name_and_generics: Dereference"),
211
212 TraitObject(type_param_bound) => {
213 if type_param_bound.len() != 1 {
214 panic!("Type::name_and_generics: TraitObject has more than one bound");
215 }
216 let type_param_bound = Print::ref_cast(&type_param_bound[0]);
217 (quote!(dyn #type_param_bound), Vec::new(), Vec::new())
218 }
219
220 DataStructure {
221 name,
222 generics:
223 Generics {
224 params,
225 constraints,
226 },
227 ..
228 } => (quote!(#name), params.clone(), constraints.clone()),
229
230 Path(path) => {
231 let path = Print::ref_cast(path);
233 (quote!(path), Vec::new(), Vec::new())
234 }
235 }
236 }
237}