vexil_codegen_rust/
enum_gen.rs1use vexil_lang::ir::{EnumDef, TypeRegistry};
2
3use crate::annotations::{emit_tombstones, emit_type_annotations};
4use crate::emit::CodeWriter;
5
6pub fn emit_enum(w: &mut CodeWriter, en: &EnumDef, _registry: &TypeRegistry) {
18 let name = en.name.as_str();
19 let non_exhaustive = en.annotations.non_exhaustive;
20 let wire_bits = en.wire_bits;
21
22 emit_tombstones(w, name, &en.tombstones);
24
25 emit_type_annotations(w, &en.annotations);
27
28 w.line("#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]");
30 if !non_exhaustive {
31 w.line("#[repr(u64)]");
33 }
34
35 w.open_block(&format!("pub enum {name}"));
37 for variant in &en.variants {
38 let ordinal = variant.ordinal;
39 for doc in &variant.annotations.doc {
41 w.line(&format!("/// {doc}"));
42 }
43 if let Some(ref dep) = variant.annotations.deprecated {
44 match &dep.since {
45 Some(since) => w.line(&format!(
46 "#[deprecated(since = \"{since}\", note = \"{}\")]",
47 dep.reason
48 )),
49 None => w.line(&format!("#[deprecated(note = \"{}\")]", dep.reason)),
50 }
51 }
52 if non_exhaustive {
53 w.line(&format!("{},", variant.name));
55 } else {
56 w.line(&format!("{} = {ordinal}_u64,", variant.name));
57 }
58 }
59 if non_exhaustive {
60 w.line("Unknown(u64),");
62 }
63 w.close_block();
64 w.blank();
65
66 w.open_block(&format!("impl vexil_runtime::Pack for {name}"));
68 w.open_block(
69 "fn pack(&self, w: &mut vexil_runtime::BitWriter) -> Result<(), vexil_runtime::EncodeError>",
70 );
71 w.line("let disc: u64 = match self {");
74 w.indent();
75 for variant in &en.variants {
76 let ordinal = variant.ordinal;
77 w.line(&format!("Self::{} => {ordinal}_u64,", variant.name));
78 }
79 if non_exhaustive {
80 w.line("Self::Unknown(v) => *v,");
81 }
82 w.dedent();
83 w.line("};");
84 w.line(&format!("w.write_bits(disc, {wire_bits}_u8);"));
85 w.line("Ok(())");
86 w.close_block();
87 w.close_block();
88 w.blank();
89
90 w.open_block(&format!("impl vexil_runtime::Unpack for {name}"));
92 w.open_block(
93 "fn unpack(r: &mut vexil_runtime::BitReader<'_>) -> Result<Self, vexil_runtime::DecodeError>",
94 );
95 w.line(&format!("let disc = r.read_bits({wire_bits}_u8)?;"));
96 w.open_block("match disc");
97 for variant in &en.variants {
98 let ordinal = variant.ordinal;
99 w.line(&format!("{ordinal}_u64 => Ok(Self::{}),", variant.name));
100 }
101 if non_exhaustive {
102 w.line("other => Ok(Self::Unknown(other)),");
103 } else {
104 w.line(&format!(
105 "_ => Err(vexil_runtime::DecodeError::UnknownEnumVariant {{ type_name: \"{name}\", value: disc }}),"
106 ));
107 }
108 w.close_block();
109 w.close_block();
110 w.close_block();
111 w.blank();
112}