witx_codegen/zig/
common.rs

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
111/// Checks the given word against a list of reserved keywords.
112/// If the given word conflicts with a keyword, a trailing underscore will be
113/// appended.
114pub fn escape_reserved_word(word: &str) -> String {
115    if RESERVED.iter().any(|k| *k == word) {
116        // If the camel-cased string matched any strict or reserved keywords, then
117        // append a trailing underscore to the identifier we generate.
118        format!("{}_", word)
119    } else {
120        word.to_string() // Otherwise, use the string as is.
121    }
122}
123
124/// Reserved Keywords.
125///
126/// Source: [Zig Language Reference](https://ziglang.org/documentation/master/#toc-Keyword-Reference)
127const 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];