1use crate::{
7 Case, EnumCase, Field, Flag, Function, Interface, ResourceId, Stream, Type, TypeDefKind,
8 UnionCase,
9};
10
11const CABI_VERSION: &str = "0.1";
12
13enum PreSpace {
14 False,
15}
16
17impl Interface {
18 pub fn mangle_funcname(&self, func: &Function) -> String {
19 self.mangle_funcname_with_name(&func.name, func)
20 }
21
22 pub fn mangle_start_funcname(&self, func: &Function) -> String {
23 self.mangle_funcname_with_name(&format!("cabi_start{{cabi={}}}", CABI_VERSION), func)
24 }
25
26 fn mangle_funcname_with_name(&self, name: &str, func: &Function) -> String {
27 format!(
28 "{}: func{} -> {}",
29 name,
30 self.mangle_funcvec(&func.params, PreSpace::False),
31 self.mangle_valtype(func.result)
32 )
33 }
34
35 fn mangle_funcvec(&self, es: &[(String, Type)], _pre_space: PreSpace) -> String {
36 format!(
37 "({})",
38 es.iter()
39 .map(|e| format!("{}: {}", e.0, self.mangle_valtype(e.1)))
40 .collect::<Vec<_>>()
41 .join(", ")
42 )
43 }
44
45 fn mangle_valtype(&self, t: Type) -> String {
46 match t {
47 Type::Unit => "unit".to_owned(),
48 Type::Bool => "bool".to_owned(),
49 Type::S8 => "s8".to_owned(),
50 Type::U8 => "u8".to_owned(),
51 Type::S16 => "s16".to_owned(),
52 Type::U16 => "u16".to_owned(),
53 Type::S32 => "s32".to_owned(),
54 Type::U32 => "u32".to_owned(),
55 Type::S64 => "s64".to_owned(),
56 Type::U64 => "u64".to_owned(),
57 Type::Float32 => "float32".to_owned(),
58 Type::Float64 => "float64".to_owned(),
59 Type::Char => "char".to_owned(),
60 Type::String => "string".to_owned(),
61 Type::Handle(id) => self.mangle_handletype(id),
62 Type::Id(id) => self.mangle_valtypedef(&self.types[id].kind),
63 }
64 }
65
66 fn mangle_valtypedef(&self, kind: &TypeDefKind) -> String {
67 match kind {
68 TypeDefKind::List(t) => format!("list<{}>", self.mangle_valtype(*t)),
69 TypeDefKind::Record(r) => self.mangle_recordtype(&r.fields),
70 TypeDefKind::Tuple(t) => self.mangle_tupletype(&t.types),
71 TypeDefKind::Flags(f) => self.mangle_flags(&f.flags),
72 TypeDefKind::Variant(v) => self.mangle_varianttype(&v.cases),
73 TypeDefKind::Enum(e) => self.mangle_enumtype(&e.cases),
74 TypeDefKind::Union(u) => self.mangle_uniontype(&u.cases),
75 TypeDefKind::Option(t) => self.mangle_optiontype(*t),
76 TypeDefKind::Result(r) => self.mangle_resulttype(r.ok, r.err),
77 TypeDefKind::Future(t) => self.mangle_futuretype(*t),
78 TypeDefKind::Stream(s) => self.mangle_streamtype(s),
79 TypeDefKind::Type(t) => self.mangle_valtype(*t),
80 }
81 }
82
83 fn mangle_recordtype(&self, fields: &[Field]) -> String {
84 format!(
85 "record {{ {} }}",
86 fields
87 .iter()
88 .map(|f| format!("{}: {}", f.name, self.mangle_valtype(f.ty)))
89 .collect::<Vec<_>>()
90 .join(", ")
91 )
92 }
93
94 fn mangle_tupletype(&self, ts: &[Type]) -> String {
95 format!(
96 "tuple<{}>",
97 ts.iter()
98 .map(|t| self.mangle_valtype(*t))
99 .collect::<Vec<_>>()
100 .join(", ")
101 )
102 }
103
104 fn mangle_flags(&self, labels: &[Flag]) -> String {
105 format!(
106 "flags {{ {} }}",
107 labels
108 .iter()
109 .map(|f| f.name.clone())
110 .collect::<Vec<_>>()
111 .join(", ")
112 )
113 }
114
115 fn mangle_varianttype(&self, cases: &[Case]) -> String {
116 format!(
117 "variant {{ {} }}",
118 cases
119 .iter()
120 .map(|c| format!("{}{}", c.name, format!("({})", self.mangle_valtype(c.ty)),))
121 .collect::<Vec<_>>()
122 .join(", ")
123 )
124 }
125
126 fn mangle_enumtype(&self, labels: &[EnumCase]) -> String {
127 format!(
128 "enum {{ {} }}",
129 labels
130 .iter()
131 .map(|l| l.name.clone())
132 .collect::<Vec<_>>()
133 .join(", ")
134 )
135 }
136
137 fn mangle_uniontype(&self, cases: &[UnionCase]) -> String {
138 format!(
139 "union {{ {} }}",
140 cases
141 .iter()
142 .map(|case| self.mangle_valtype(case.ty))
143 .collect::<Vec<_>>()
144 .join(", ")
145 )
146 }
147
148 fn mangle_optiontype(&self, t: Type) -> String {
149 format!("option<{}>", self.mangle_valtype(t))
150 }
151
152 fn mangle_resulttype(&self, ok: Type, error: Type) -> String {
153 format!(
154 "result<{}, {}>",
155 self.mangle_valtype(ok),
156 self.mangle_valtype(error)
157 )
158 }
159
160 fn mangle_handletype(&self, id: ResourceId) -> String {
161 format!("handle<{}>", self.resources[id].name)
162 }
163
164 fn mangle_futuretype(&self, ty: Type) -> String {
165 format!("future<{}>", self.mangle_valtype(ty))
166 }
167
168 fn mangle_streamtype(&self, stream: &Stream) -> String {
169 format!(
170 "stream<{}, {}>",
171 self.mangle_valtype(stream.element),
172 self.mangle_valtype(stream.end)
173 )
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180 use crate::{
181 Docs, Enum, Flag, Flags, FunctionKind, Record, Resource, Result_, Tuple, Union, Variant,
182 };
183
184 #[test]
185 fn test_funcname() {
186 let interface = Interface::default();
187
188 assert_eq!(
189 interface.mangle_funcname(&Function {
190 docs: Docs::default(),
191 name: "foo".to_owned(),
192 kind: FunctionKind::Freestanding,
193 params: Vec::new(),
194 result: Type::Unit
195 }),
196 "foo: func() -> unit"
197 );
198 assert_eq!(
199 interface.mangle_funcname(&Function {
200 docs: Docs::default(),
201 name: "foo".to_owned(),
202 kind: FunctionKind::Freestanding,
203 params: vec![("a".to_owned(), Type::S64)],
204 result: Type::S32
205 }),
206 "foo: func(a: s64) -> s32"
207 );
208 assert_eq!(
209 interface.mangle_funcname(&Function {
210 docs: Docs::default(),
211 name: "foo".to_owned(),
212 kind: FunctionKind::Freestanding,
213 params: vec![("a".to_owned(), Type::S64), ("b".to_owned(), Type::U64)],
214 result: Type::S32
215 }),
216 "foo: func(a: s64, b: u64) -> s32"
217 );
218 }
219
220 #[test]
221 fn test_start_funcname() {
222 let interface = Interface::default();
223
224 assert_eq!(
225 interface.mangle_start_funcname(&Function {
226 docs: Docs::default(),
227 name: "foo".to_owned(),
228 kind: FunctionKind::Freestanding,
229 params: Vec::new(),
230 result: Type::Unit
231 }),
232 format!("cabi_start{{cabi={}}}: func() -> unit", CABI_VERSION)
233 );
234 }
235
236 #[test]
237 fn test_types() {
238 let iface = Interface::default();
239 assert_eq!(iface.mangle_valtype(Type::Unit), "unit");
240 assert_eq!(iface.mangle_valtype(Type::Bool), "bool");
241 assert_eq!(iface.mangle_valtype(Type::S8), "s8");
242 assert_eq!(iface.mangle_valtype(Type::U8), "u8");
243 assert_eq!(iface.mangle_valtype(Type::S16), "s16");
244 assert_eq!(iface.mangle_valtype(Type::U16), "u16");
245 assert_eq!(iface.mangle_valtype(Type::S32), "s32");
246 assert_eq!(iface.mangle_valtype(Type::U32), "u32");
247 assert_eq!(iface.mangle_valtype(Type::S64), "s64");
248 assert_eq!(iface.mangle_valtype(Type::U64), "u64");
249 assert_eq!(iface.mangle_valtype(Type::Float32), "float32");
250 assert_eq!(iface.mangle_valtype(Type::Float64), "float64");
251 assert_eq!(iface.mangle_valtype(Type::Char), "char");
252 assert_eq!(iface.mangle_valtype(Type::String), "string");
253 }
254
255 #[test]
256 fn test_listtype() {
257 let iface = Interface::default();
258 assert_eq!(
259 iface.mangle_valtypedef(&TypeDefKind::List(Type::U16)),
260 "list<u16>"
261 );
262 }
263
264 #[test]
265 fn test_recordtype() {
266 let iface = Interface::default();
267 assert_eq!(
268 iface.mangle_valtypedef(&TypeDefKind::Record(Record { fields: Vec::new() })),
269 "record { }"
270 );
271 assert_eq!(
272 iface.mangle_valtypedef(&TypeDefKind::Record(Record {
273 fields: vec![Field {
274 name: "x".to_owned(),
275 docs: Docs::default(),
276 ty: Type::Float32
277 }]
278 })),
279 "record { x: float32 }"
280 );
281 assert_eq!(
282 iface.mangle_valtypedef(&TypeDefKind::Record(Record {
283 fields: vec![
284 Field {
285 name: "x".to_owned(),
286 docs: Docs::default(),
287 ty: Type::Float32
288 },
289 Field {
290 name: "y".to_owned(),
291 docs: Docs::default(),
292 ty: Type::Float64
293 }
294 ]
295 })),
296 "record { x: float32, y: float64 }"
297 );
298 }
299
300 #[test]
301 fn test_tupletype() {
302 let iface = Interface::default();
303 assert_eq!(
304 iface.mangle_valtypedef(&TypeDefKind::Tuple(Tuple { types: Vec::new() })),
305 "tuple<>"
306 );
307 assert_eq!(
308 iface.mangle_valtypedef(&TypeDefKind::Tuple(Tuple {
309 types: vec![Type::Float32]
310 })),
311 "tuple<float32>"
312 );
313 assert_eq!(
314 iface.mangle_valtypedef(&TypeDefKind::Tuple(Tuple {
315 types: vec![Type::Float32, Type::Float64]
316 })),
317 "tuple<float32, float64>"
318 );
319 }
320
321 #[test]
322 fn test_flags() {
323 let iface = Interface::default();
324 assert_eq!(
325 iface.mangle_valtypedef(&TypeDefKind::Flags(Flags { flags: Vec::new() })),
326 "flags { }"
327 );
328 assert_eq!(
329 iface.mangle_valtypedef(&TypeDefKind::Flags(Flags {
330 flags: vec![Flag {
331 name: "red".to_owned(),
332 docs: Docs::default()
333 }]
334 })),
335 "flags { red }"
336 );
337 assert_eq!(
338 iface.mangle_valtypedef(&TypeDefKind::Flags(Flags {
339 flags: vec![
340 Flag {
341 name: "red".to_owned(),
342 docs: Docs::default()
343 },
344 Flag {
345 name: "green".to_owned(),
346 docs: Docs::default()
347 }
348 ]
349 })),
350 "flags { red, green }"
351 );
352 }
353
354 #[test]
355 fn test_varianttype() {
356 let iface = Interface::default();
357 assert_eq!(
358 iface.mangle_valtypedef(&TypeDefKind::Variant(Variant { cases: Vec::new() })),
359 "variant { }"
360 );
361 assert_eq!(
362 iface.mangle_valtypedef(&TypeDefKind::Variant(Variant {
363 cases: vec![Case {
364 name: "x".to_owned(),
365 docs: Docs::default(),
366 ty: Type::Float32
367 }]
368 })),
369 "variant { x(float32) }"
370 );
371 assert_eq!(
372 iface.mangle_valtypedef(&TypeDefKind::Variant(Variant {
373 cases: vec![
374 Case {
375 name: "x".to_owned(),
376 docs: Docs::default(),
377 ty: Type::Float32
378 },
379 Case {
380 name: "y".to_owned(),
381 docs: Docs::default(),
382 ty: Type::Float64
383 }
384 ]
385 })),
386 "variant { x(float32), y(float64) }"
387 );
388 }
389
390 #[test]
391 fn test_enumtype() {
392 let iface = Interface::default();
393 assert_eq!(
394 iface.mangle_valtypedef(&TypeDefKind::Enum(Enum { cases: Vec::new() })),
395 "enum { }"
396 );
397 assert_eq!(
398 iface.mangle_valtypedef(&TypeDefKind::Enum(Enum {
399 cases: vec![EnumCase {
400 name: "x".to_owned(),
401 docs: Docs::default(),
402 }]
403 })),
404 "enum { x }"
405 );
406 assert_eq!(
407 iface.mangle_valtypedef(&TypeDefKind::Enum(Enum {
408 cases: vec![
409 EnumCase {
410 name: "x".to_owned(),
411 docs: Docs::default(),
412 },
413 EnumCase {
414 name: "y".to_owned(),
415 docs: Docs::default(),
416 }
417 ]
418 })),
419 "enum { x, y }"
420 );
421 }
422
423 #[test]
424 fn test_uniontype() {
425 let iface = Interface::default();
426 assert_eq!(
427 iface.mangle_valtypedef(&TypeDefKind::Union(Union { cases: Vec::new() })),
428 "union { }"
429 );
430 assert_eq!(
431 iface.mangle_valtypedef(&TypeDefKind::Union(Union {
432 cases: vec![UnionCase {
433 docs: Docs::default(),
434 ty: Type::Float32
435 }]
436 })),
437 "union { float32 }"
438 );
439 assert_eq!(
440 iface.mangle_valtypedef(&TypeDefKind::Union(Union {
441 cases: vec![
442 UnionCase {
443 docs: Docs::default(),
444 ty: Type::Float32
445 },
446 UnionCase {
447 docs: Docs::default(),
448 ty: Type::Float64
449 }
450 ]
451 })),
452 "union { float32, float64 }"
453 );
454 }
455
456 #[test]
457 fn test_optiontype() {
458 let iface = Interface::default();
459 assert_eq!(
460 iface.mangle_valtypedef(&TypeDefKind::Option(Type::S8)),
461 "option<s8>"
462 );
463 }
464
465 #[test]
466 fn test_resulttype() {
467 let iface = Interface::default();
468 assert_eq!(
469 iface.mangle_valtypedef(&TypeDefKind::Result(Result_ {
470 ok: Type::S32,
471 err: Type::U32
472 })),
473 "result<s32, u32>"
474 );
475 }
476
477 #[test]
478 fn test_handletype() {
479 let mut iface = Interface::default();
480 let id = iface.resources.alloc(Resource {
481 name: "thing".to_owned(),
482 docs: Docs::default(),
483 foreign_module: None,
484 supertype: None,
485 });
486 assert_eq!(iface.mangle_valtype(Type::Handle(id)), "handle<thing>");
487 }
488
489 #[test]
490 fn test_futuretype() {
491 let iface = Interface::default();
492 assert_eq!(
493 iface.mangle_valtypedef(&TypeDefKind::Future(Type::S8)),
494 "future<s8>"
495 );
496 }
497
498 #[test]
499 fn test_streamtype() {
500 let iface = Interface::default();
501 assert_eq!(
502 iface.mangle_valtypedef(&TypeDefKind::Stream(Stream {
503 element: Type::S8,
504 end: Type::U8
505 })),
506 "stream<s8, u8>"
507 );
508 }
509}