1use convert_case::{Case, Casing};
2
3use super::tuple::Tuple;
4use crate::astype::*;
5
6pub trait IsNullable {
7 fn is_nullable(&self) -> bool;
8}
9
10impl IsNullable for ASType {
11 fn is_nullable(&self) -> bool {
12 matches!(
13 self,
14 ASType::ConstPtr(_)
15 | ASType::MutPtr(_)
16 | ASType::ReadBuffer(_)
17 | ASType::WriteBuffer(_)
18 | ASType::Enum(_)
19 | ASType::Struct(_)
20 | ASType::Tuple(_)
21 | ASType::Union(_)
22 )
23 }
24}
25
26pub trait Normalize {
27 fn as_str(&self) -> &str;
28
29 fn as_type(&self) -> String {
30 self.as_str().to_case(Case::Pascal)
31 }
32
33 fn as_fn(&self) -> String {
34 self.as_str().to_case(Case::Camel)
35 }
36
37 fn as_fn_suffix(&self) -> String {
38 self.as_str().to_case(Case::UpperCamel)
39 }
40
41 fn as_var(&self) -> String {
42 escape_reserved_word(&self.as_str().to_case(Case::Snake))
43 }
44
45 fn as_const(&self) -> String {
46 self.as_str().to_case(Case::UpperSnake)
47 }
48
49 fn as_namespace(&self) -> String {
50 self.as_str().to_string().to_case(Case::Pascal)
51 }
52}
53
54impl<T: AsRef<str>> Normalize for T {
55 fn as_str(&self) -> &str {
56 self.as_ref()
57 }
58}
59
60pub trait ToLanguageRepresentation {
61 fn as_astype(&self) -> &ASType;
62
63 fn to_string(&self) -> String {
64 self.as_lang()
65 }
66
67 fn as_lang(&self) -> String {
68 match self.as_astype() {
69 ASType::Alias(alias) => alias.name.as_type(),
70 ASType::Bool => "bool".to_string(),
71 ASType::Char32 => "Char32".to_string(),
72 ASType::Char8 => "Char8".to_string(),
73 ASType::F32 => "f32".to_string(),
74 ASType::F64 => "f64".to_string(),
75 ASType::Handle(_resource_name) => "WasiHandle".to_string(),
76 ASType::ConstPtr(pointee) => format!("WasiPtr({})", pointee.to_string()),
77 ASType::MutPtr(pointee) => format!("WasiMutPtr({})", pointee.to_string()),
78 ASType::Option(_) => todo!(),
79 ASType::Result(_) => todo!(),
80 ASType::S8 => "i8".to_string(),
81 ASType::S16 => "i16".to_string(),
82 ASType::S32 => "i32".to_string(),
83 ASType::S64 => "i64".to_string(),
84 ASType::U8 => "u8".to_string(),
85 ASType::U16 => "u16".to_string(),
86 ASType::U32 => "u32".to_string(),
87 ASType::U64 => "u64".to_string(),
88 ASType::USize => "usize".to_string(),
89 ASType::Void => "()".to_string(),
90 ASType::Constants(_) => unimplemented!(),
91 ASType::Enum(enum_) => enum_.repr.as_ref().as_lang(),
92 ASType::Struct(_) => unimplemented!(),
93 ASType::Tuple(tuple_members) => Tuple::name_for(tuple_members).as_type(),
94 ASType::Union(_) => unimplemented!(),
95 ASType::Slice(element_type) => format!("WasiMutSlice({})", element_type.as_lang()),
96 ASType::String(_) => "WasiString".to_string(),
97 ASType::ReadBuffer(element_type) => format!("WasiSlice({})", element_type.as_lang()),
98 ASType::WriteBuffer(element_type) => {
99 format!("WasiMutSlice({})", element_type.to_string())
100 }
101 }
102 }
103}
104
105impl ToLanguageRepresentation for ASType {
106 fn as_astype(&self) -> &ASType {
107 self
108 }
109}
110
111pub fn escape_reserved_word(word: &str) -> String {
115 if RESERVED.iter().any(|k| *k == word) {
116 format!("{}_", word)
119 } else {
120 word.to_string() }
122}
123
124const RESERVED: &[&str] = &[
128 "align",
129 "allowzero",
130 "and",
131 "anyframe",
132 "anytype",
133 "asm",
134 "async",
135 "await",
136 "break",
137 "catch",
138 "comptime",
139 "const",
140 "continue",
141 "defer",
142 "else",
143 "enum",
144 "errdefer",
145 "error",
146 "export",
147 "extern",
148 "false",
149 "fn",
150 "for",
151 "if",
152 "inline",
153 "noalias",
154 "nosuspend",
155 "null",
156 "or",
157 "orelse",
158 "packed",
159 "pub",
160 "resume",
161 "return",
162 "linksection",
163 "struct",
164 "suspend",
165 "switch",
166 "test",
167 "threadlocal",
168 "true",
169 "try",
170 "undefined",
171 "union",
172 "unreachable",
173 "usingnamespace",
174 "var",
175 "volatile",
176 "while",
177];