1#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum TypeRef {
12 Primitive(PrimitiveType),
14 Optional(Box<TypeRef>),
16 Array(Box<TypeRef>),
18 Named(String),
20 Generic {
22 base: String,
24 args: Vec<TypeRef>,
26 },
27 Ref(Box<TypeRef>),
29 RefMut(Box<TypeRef>),
31 Unit,
33 Result {
35 ok: Box<TypeRef>,
37 err: Box<TypeRef>,
39 },
40}
41
42impl TypeRef {
43 pub fn primitive(ty: PrimitiveType) -> Self {
45 Self::Primitive(ty)
46 }
47
48 pub fn optional(inner: TypeRef) -> Self {
50 Self::Optional(Box::new(inner))
51 }
52
53 pub fn array(inner: TypeRef) -> Self {
55 Self::Array(Box::new(inner))
56 }
57
58 pub fn named(name: impl Into<String>) -> Self {
60 Self::Named(name.into())
61 }
62
63 pub fn generic(base: impl Into<String>, args: Vec<TypeRef>) -> Self {
65 Self::Generic {
66 base: base.into(),
67 args,
68 }
69 }
70
71 pub fn ref_(inner: TypeRef) -> Self {
73 Self::Ref(Box::new(inner))
74 }
75
76 pub fn ref_mut(inner: TypeRef) -> Self {
78 Self::RefMut(Box::new(inner))
79 }
80
81 pub fn unit() -> Self {
83 Self::Unit
84 }
85
86 pub fn result(ok: TypeRef, err: TypeRef) -> Self {
88 Self::Result {
89 ok: Box::new(ok),
90 err: Box::new(err),
91 }
92 }
93
94 pub fn string() -> Self {
96 Self::Primitive(PrimitiveType::String)
97 }
98
99 pub fn int() -> Self {
101 Self::Primitive(PrimitiveType::Int)
102 }
103
104 pub fn float() -> Self {
106 Self::Primitive(PrimitiveType::Float)
107 }
108
109 pub fn bool() -> Self {
111 Self::Primitive(PrimitiveType::Bool)
112 }
113
114 pub fn path() -> Self {
116 Self::Primitive(PrimitiveType::Path)
117 }
118
119 pub fn duration() -> Self {
121 Self::Primitive(PrimitiveType::Duration)
122 }
123
124 pub fn is_optional(&self) -> bool {
126 matches!(self, Self::Optional(_))
127 }
128
129 pub fn inner_type(&self) -> Option<&TypeRef> {
133 match self {
134 Self::Optional(inner) | Self::Array(inner) | Self::Ref(inner) | Self::RefMut(inner) => {
135 Some(inner)
136 }
137 _ => None,
138 }
139 }
140}
141
142#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
144pub enum PrimitiveType {
145 String,
147 Int,
149 UInt,
151 Float,
153 Bool,
155 Path,
157 Duration,
159 Char,
161 Byte,
163}
164
165impl PrimitiveType {
166 pub fn as_str(&self) -> &'static str {
168 match self {
169 Self::String => "string",
170 Self::Int => "int",
171 Self::UInt => "uint",
172 Self::Float => "float",
173 Self::Bool => "bool",
174 Self::Path => "path",
175 Self::Duration => "duration",
176 Self::Char => "char",
177 Self::Byte => "byte",
178 }
179 }
180}
181
182#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
184pub enum Visibility {
185 #[default]
187 Public,
188 Private,
190 Crate,
192 Super,
194}
195
196impl Visibility {
197 pub fn is_public(&self) -> bool {
199 matches!(self, Self::Public)
200 }
201
202 pub fn is_private(&self) -> bool {
204 matches!(self, Self::Private)
205 }
206}
207
208pub trait TypeMapper {
212 fn map_primitive(&self, ty: PrimitiveType) -> String;
214
215 fn map_optional(&self, inner: &str) -> String;
217
218 fn map_array(&self, inner: &str) -> String;
220
221 fn map_ref(&self, inner: &str) -> String {
223 inner.to_string()
224 }
225
226 fn map_ref_mut(&self, inner: &str) -> String {
228 inner.to_string()
229 }
230
231 fn map_generic(&self, base: &str, args: &[String]) -> String {
233 if args.is_empty() {
234 base.to_string()
235 } else {
236 format!("{}<{}>", base, args.join(", "))
237 }
238 }
239
240 fn map_result(&self, ok: &str, err: &str) -> String;
242
243 fn map_unit(&self) -> String;
245
246 fn render_type(&self, ty: &TypeRef) -> String {
248 match ty {
249 TypeRef::Primitive(p) => self.map_primitive(*p),
250 TypeRef::Optional(inner) => {
251 let inner_str = self.render_type(inner);
252 self.map_optional(&inner_str)
253 }
254 TypeRef::Array(inner) => {
255 let inner_str = self.render_type(inner);
256 self.map_array(&inner_str)
257 }
258 TypeRef::Named(name) => name.clone(),
259 TypeRef::Generic { base, args } => {
260 let arg_strs: Vec<_> = args.iter().map(|a| self.render_type(a)).collect();
261 self.map_generic(base, &arg_strs)
262 }
263 TypeRef::Ref(inner) => {
264 let inner_str = self.render_type(inner);
265 self.map_ref(&inner_str)
266 }
267 TypeRef::RefMut(inner) => {
268 let inner_str = self.render_type(inner);
269 self.map_ref_mut(&inner_str)
270 }
271 TypeRef::Unit => self.map_unit(),
272 TypeRef::Result { ok, err } => {
273 let ok_str = self.render_type(ok);
274 let err_str = self.render_type(err);
275 self.map_result(&ok_str, &err_str)
276 }
277 }
278 }
279}
280
281#[cfg(test)]
282mod tests {
283 use super::*;
284
285 #[test]
286 fn test_primitive_type_as_str() {
287 assert_eq!(PrimitiveType::String.as_str(), "string");
288 assert_eq!(PrimitiveType::Int.as_str(), "int");
289 assert_eq!(PrimitiveType::Bool.as_str(), "bool");
290 }
291
292 #[test]
293 fn test_type_ref_constructors() {
294 let string = TypeRef::string();
295 assert_eq!(string, TypeRef::Primitive(PrimitiveType::String));
296
297 let opt_string = TypeRef::optional(TypeRef::string());
298 assert!(matches!(opt_string, TypeRef::Optional(_)));
299
300 let arr_int = TypeRef::array(TypeRef::int());
301 assert!(matches!(arr_int, TypeRef::Array(_)));
302
303 let named = TypeRef::named("Context");
304 assert_eq!(named, TypeRef::Named("Context".into()));
305 }
306
307 #[test]
308 fn test_visibility() {
309 assert!(Visibility::Public.is_public());
310 assert!(!Visibility::Public.is_private());
311 assert!(Visibility::Private.is_private());
312 assert!(!Visibility::Private.is_public());
313 }
314
315 #[test]
316 fn test_generic_type() {
317 let map = TypeRef::generic("HashMap", vec![TypeRef::string(), TypeRef::int()]);
318 assert!(
319 matches!(map, TypeRef::Generic { base, args } if base == "HashMap" && args.len() == 2)
320 );
321 }
322}