Skip to main content

vexil_codegen_ts/
types.rs

1use vexil_lang::ast::{PrimitiveType, SemanticType, SubByteType};
2use vexil_lang::ir::{ResolvedType, TypeDef, TypeRegistry};
3
4/// Convert a ResolvedType to its TypeScript type string.
5pub fn ts_type(ty: &ResolvedType, registry: &TypeRegistry) -> String {
6    match ty {
7        ResolvedType::Primitive(p) => primitive_type(p).to_string(),
8        ResolvedType::SubByte(_) => "number".to_string(),
9        ResolvedType::Semantic(s) => semantic_type(s).to_string(),
10        ResolvedType::Named(id) => match registry.get(*id) {
11            Some(def) => type_def_name(def),
12            None => "unknown".to_string(),
13        },
14        ResolvedType::Optional(inner) => {
15            let inner_str = ts_type(inner, registry);
16            format!("{inner_str} | null")
17        }
18        ResolvedType::Array(inner) => {
19            let inner_str = ts_type(inner, registry);
20            format!("{inner_str}[]")
21        }
22        ResolvedType::Map(k, v) => {
23            let k_str = ts_type(k, registry);
24            let v_str = ts_type(v, registry);
25            format!("Map<{k_str}, {v_str}>")
26        }
27        ResolvedType::Result(ok, err) => {
28            let ok_str = ts_type(ok, registry);
29            let err_str = ts_type(err, registry);
30            format!("{{ ok: {ok_str} }} | {{ err: {err_str} }}")
31        }
32        _ => "unknown".to_string(),
33    }
34}
35
36fn primitive_type(p: &PrimitiveType) -> &'static str {
37    match p {
38        PrimitiveType::Bool => "boolean",
39        PrimitiveType::U8 | PrimitiveType::U16 | PrimitiveType::U32 => "number",
40        PrimitiveType::I8 | PrimitiveType::I16 | PrimitiveType::I32 => "number",
41        PrimitiveType::U64 | PrimitiveType::I64 => "bigint",
42        PrimitiveType::F32 | PrimitiveType::F64 => "number",
43        PrimitiveType::Void => "void",
44    }
45}
46
47fn semantic_type(s: &SemanticType) -> &'static str {
48    match s {
49        SemanticType::String => "string",
50        SemanticType::Bytes => "Uint8Array",
51        SemanticType::Rgb => "[number, number, number]",
52        SemanticType::Uuid => "Uint8Array",
53        SemanticType::Timestamp => "bigint",
54        SemanticType::Hash => "Uint8Array",
55    }
56}
57
58fn type_def_name(def: &TypeDef) -> String {
59    match def {
60        TypeDef::Message(m) => m.name.to_string(),
61        TypeDef::Enum(e) => e.name.to_string(),
62        TypeDef::Flags(f) => f.name.to_string(),
63        TypeDef::Union(u) => u.name.to_string(),
64        TypeDef::Newtype(n) => n.name.to_string(),
65        TypeDef::Config(c) => c.name.to_string(),
66        _ => "UnknownTypeDef".to_string(),
67    }
68}
69
70/// Returns true if a SubByteType is signed.
71pub fn sub_byte_signed(s: &SubByteType) -> bool {
72    s.signed
73}