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 escape_reserved_word(&self.as_str().to_case(Case::Snake))
35 }
36
37 fn as_fn_suffix(&self) -> String {
38 escape_reserved_word(&self.as_str().to_case(Case::Snake))
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::UpperSnake)
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_) => {
92 format!("{} /* Enum */", enum_.repr.as_ref().as_lang())
93 }
94 ASType::Struct(_) => unimplemented!(),
95 ASType::Tuple(tuple_members) => Tuple::name_for(tuple_members).as_type(),
96 ASType::Union(_) => unimplemented!(),
97 ASType::Slice(element_type) => format!("WasiMutSlice<{}>", element_type.as_lang()),
98 ASType::String(_) => "WasiString".to_string(),
99 ASType::ReadBuffer(element_type) => format!("WasiSlice<{}>", element_type.as_lang()),
100 ASType::WriteBuffer(element_type) => {
101 format!("WasiMutSlice<{}>", element_type.to_string())
102 }
103 }
104 }
105}
106
107impl ToLanguageRepresentation for ASType {
108 fn as_astype(&self) -> &ASType {
109 self
110 }
111}
112
113pub fn escape_reserved_word(word: &str) -> String {
119 if STRICT.iter().chain(RESERVED).any(|k| *k == word) {
120 format!("{}_", word)
123 } else {
124 word.to_string() }
126}
127
128const STRICT: &[&str] = &[
132 "as", "async", "await", "break", "const", "continue", "crate", "dyn", "else", "enum", "extern",
133 "false", "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub",
134 "ref", "return", "self", "Self", "static", "struct", "super", "trait", "true", "type",
135 "unsafe", "use", "where", "while",
136];
137
138const RESERVED: &[&str] = &[
147 "abstract", "become", "box", "do", "final", "macro", "override", "priv", "try", "typeof",
148 "unsized", "virtual", "yield",
149];