alef/backends/go/
type_map.rs1use std::borrow::Cow;
2
3use crate::codegen::naming::go_type_name;
4use crate::codegen::type_mapper::TypeMapper;
5use crate::core::ir::{PrimitiveType, TypeRef};
6
7pub struct GoMapper;
19
20impl TypeMapper for GoMapper {
21 fn primitive(&self, prim: &PrimitiveType) -> Cow<'static, str> {
22 Cow::Borrowed(match prim {
23 PrimitiveType::Bool => "bool",
24 PrimitiveType::U8 => "uint8",
25 PrimitiveType::U16 => "uint16",
26 PrimitiveType::U32 => "uint32",
27 PrimitiveType::U64 => "uint64",
28 PrimitiveType::I8 => "int8",
29 PrimitiveType::I16 => "int16",
30 PrimitiveType::I32 => "int32",
31 PrimitiveType::I64 => "int64",
32 PrimitiveType::F32 => "float32",
33 PrimitiveType::F64 => "float64",
34 PrimitiveType::Usize => "uint",
35 PrimitiveType::Isize => "int",
36 })
37 }
38
39 fn string(&self) -> Cow<'static, str> {
40 Cow::Borrowed("string")
41 }
42
43 fn bytes(&self) -> Cow<'static, str> {
44 Cow::Borrowed("[]byte")
45 }
46
47 fn path(&self) -> Cow<'static, str> {
48 Cow::Borrowed("string")
49 }
50
51 fn json(&self) -> Cow<'static, str> {
52 Cow::Borrowed("json.RawMessage")
53 }
54
55 fn unit(&self) -> Cow<'static, str> {
56 Cow::Borrowed("") }
58
59 fn duration(&self) -> Cow<'static, str> {
60 Cow::Borrowed("uint64")
61 }
62
63 fn optional(&self, inner: &str) -> String {
64 format!("*{inner}")
65 }
66
67 fn vec(&self, inner: &str) -> String {
68 format!("[]{inner}")
69 }
70
71 fn map(&self, key: &str, value: &str) -> String {
72 format!("map[{key}]{value}")
73 }
74
75 fn named<'a>(&self, name: &'a str) -> Cow<'a, str> {
76 Cow::Owned(go_type_name(name))
77 }
78
79 fn error_wrapper(&self) -> &str {
80 "error"
81 }
82}
83
84pub fn go_type(ty: &TypeRef) -> Cow<'static, str> {
89 Cow::Owned(GoMapper.map_type(ty))
90}
91
92pub fn go_optional_type(ty: &TypeRef) -> Cow<'static, str> {
101 match ty {
102 TypeRef::Optional(_) | TypeRef::Vec(_) | TypeRef::Map(_, _) | TypeRef::Bytes => go_type(ty),
104 TypeRef::String
106 | TypeRef::Char
107 | TypeRef::Path
108 | TypeRef::Json
109 | TypeRef::Named(_)
110 | TypeRef::Primitive(_)
111 | TypeRef::Duration
112 | TypeRef::Unit => Cow::Owned(format!("*{}", GoMapper.map_type(ty))),
113 }
114}
115
116pub fn go_zero_value(ty: &TypeRef) -> String {
125 match ty {
126 TypeRef::Primitive(PrimitiveType::Bool) => "false".to_string(),
127 TypeRef::Primitive(_) | TypeRef::Duration => "0".to_string(),
128 TypeRef::String | TypeRef::Char | TypeRef::Path => "\"\"".to_string(),
129 TypeRef::Json => "nil".to_string(), TypeRef::Bytes
131 | TypeRef::Vec(_)
132 | TypeRef::Map(_, _)
133 | TypeRef::Optional(_)
134 | TypeRef::Named(_)
135 | TypeRef::Unit => "nil".to_string(),
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn test_primitives() {
145 let m = GoMapper;
146 assert_eq!(m.primitive(&PrimitiveType::Bool), "bool");
147 assert_eq!(m.primitive(&PrimitiveType::U8), "uint8");
148 assert_eq!(m.primitive(&PrimitiveType::U16), "uint16");
149 assert_eq!(m.primitive(&PrimitiveType::U32), "uint32");
150 assert_eq!(m.primitive(&PrimitiveType::U64), "uint64");
151 assert_eq!(m.primitive(&PrimitiveType::I8), "int8");
152 assert_eq!(m.primitive(&PrimitiveType::I16), "int16");
153 assert_eq!(m.primitive(&PrimitiveType::I32), "int32");
154 assert_eq!(m.primitive(&PrimitiveType::I64), "int64");
155 assert_eq!(m.primitive(&PrimitiveType::F32), "float32");
156 assert_eq!(m.primitive(&PrimitiveType::F64), "float64");
157 assert_eq!(m.primitive(&PrimitiveType::Usize), "uint");
158 assert_eq!(m.primitive(&PrimitiveType::Isize), "int");
159 }
160
161 #[test]
162 fn test_string_and_char() {
163 assert_eq!(GoMapper.map_type(&TypeRef::String), "string");
164 assert_eq!(GoMapper.map_type(&TypeRef::Char), "string");
165 }
166
167 #[test]
168 fn test_bytes() {
169 assert_eq!(GoMapper.map_type(&TypeRef::Bytes), "[]byte");
170 }
171
172 #[test]
173 fn test_path() {
174 assert_eq!(GoMapper.map_type(&TypeRef::Path), "string");
175 }
176
177 #[test]
178 fn test_json() {
179 assert_eq!(GoMapper.map_type(&TypeRef::Json), "json.RawMessage");
180 }
181
182 #[test]
183 fn test_unit() {
184 assert_eq!(GoMapper.map_type(&TypeRef::Unit), "");
185 }
186
187 #[test]
188 fn test_duration() {
189 assert_eq!(GoMapper.map_type(&TypeRef::Duration), "uint64");
190 }
191
192 #[test]
193 fn test_optional() {
194 assert_eq!(
195 GoMapper.map_type(&TypeRef::Optional(Box::new(TypeRef::String))),
196 "*string"
197 );
198 }
199
200 #[test]
201 fn test_vec() {
202 assert_eq!(GoMapper.map_type(&TypeRef::Vec(Box::new(TypeRef::String))), "[]string");
203 }
204
205 #[test]
206 fn test_map() {
207 assert_eq!(
208 GoMapper.map_type(&TypeRef::Map(
209 Box::new(TypeRef::String),
210 Box::new(TypeRef::Primitive(PrimitiveType::I32))
211 )),
212 "map[string]int32"
213 );
214 }
215
216 #[test]
217 fn test_go_type_delegate() {
218 let ty = TypeRef::Vec(Box::new(TypeRef::Primitive(PrimitiveType::U32)));
219 assert_eq!(go_type(&ty).as_ref(), GoMapper.map_type(&ty));
220 }
221
222 #[test]
223 fn test_go_optional_type_already_optional() {
224 let ty = TypeRef::Optional(Box::new(TypeRef::String));
226 assert_eq!(go_optional_type(&ty), go_type(&ty));
227 }
228
229 #[test]
230 fn test_go_optional_type_non_optional() {
231 assert_eq!(go_optional_type(&TypeRef::String), "*string");
233 }
234
235 #[test]
236 fn test_go_optional_type_vec_not_pointer() {
237 let ty = TypeRef::Vec(Box::new(TypeRef::String));
239 assert_eq!(go_optional_type(&ty), "[]string");
240 }
241
242 #[test]
243 fn test_go_optional_type_bytes_not_pointer() {
244 assert_eq!(go_optional_type(&TypeRef::Bytes), "[]byte");
246 }
247
248 #[test]
249 fn test_go_optional_type_map_not_pointer() {
250 let ty = TypeRef::Map(Box::new(TypeRef::String), Box::new(TypeRef::String));
252 assert_eq!(go_optional_type(&ty), "map[string]string");
253 }
254}