ironsbe_codegen/rust/
enums.rs1use ironsbe_schema::ir::{SchemaIr, TypeKind, to_pascal_case};
4use ironsbe_schema::types::PrimitiveType;
5
6pub struct EnumGenerator<'a> {
8 ir: &'a SchemaIr,
9}
10
11impl<'a> EnumGenerator<'a> {
12 #[must_use]
14 pub fn new(ir: &'a SchemaIr) -> Self {
15 Self { ir }
16 }
17
18 #[must_use]
20 pub fn generate(&self) -> String {
21 let mut output = String::new();
22
23 for resolved_type in self.ir.types.values() {
24 match resolved_type.kind {
25 TypeKind::Enum(encoding) => {
26 output.push_str(&self.generate_enum(&resolved_type.name, encoding));
27 }
28 TypeKind::Set(encoding) => {
29 output.push_str(&self.generate_set(&resolved_type.name, encoding));
30 }
31 _ => {}
32 }
33 }
34
35 output
36 }
37
38 fn generate_enum(&self, name: &str, encoding: PrimitiveType) -> String {
40 let mut output = String::new();
41 let rust_name = to_pascal_case(name);
42 let rust_type = encoding.rust_type();
43
44 output.push_str(&format!("/// {} enum.\n", rust_name));
45 output.push_str("#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]\n");
46 output.push_str(&format!("#[repr({})]\n", rust_type));
47 output.push_str(&format!("pub enum {} {{\n", rust_name));
48
49 output.push_str(" // Values generated from schema\n");
52 output.push_str("}\n\n");
53
54 output.push_str(&format!("impl From<{}> for {} {{\n", rust_type, rust_name));
56 output.push_str(&format!(" fn from(value: {}) -> Self {{\n", rust_type));
57 output.push_str(" // Match implementation\n");
58 output.push_str(" unsafe { std::mem::transmute(value) }\n");
59 output.push_str(" }\n");
60 output.push_str("}\n\n");
61
62 output.push_str(&format!("impl From<{}> for {} {{\n", rust_name, rust_type));
63 output.push_str(&format!(" fn from(value: {}) -> Self {{\n", rust_name));
64 output.push_str(" value as Self\n");
65 output.push_str(" }\n");
66 output.push_str("}\n\n");
67
68 output
69 }
70
71 fn generate_set(&self, name: &str, encoding: PrimitiveType) -> String {
73 let mut output = String::new();
74 let rust_name = to_pascal_case(name);
75 let rust_type = encoding.rust_type();
76
77 output.push_str(&format!("/// {} bitfield set.\n", rust_name));
78 output.push_str("#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]\n");
79 output.push_str(&format!("pub struct {}({});\n\n", rust_name, rust_type));
80
81 output.push_str(&format!("impl {} {{\n", rust_name));
82 output.push_str(&format!(" /// Creates a new empty {}.\n", rust_name));
83 output.push_str(" #[must_use]\n");
84 output.push_str(" pub const fn new() -> Self {\n");
85 output.push_str(" Self(0)\n");
86 output.push_str(" }\n\n");
87
88 output.push_str(&format!(" /// Creates from raw {} value.\n", rust_type));
89 output.push_str(" #[must_use]\n");
90 output.push_str(&format!(
91 " pub const fn from_raw(value: {}) -> Self {{\n",
92 rust_type
93 ));
94 output.push_str(" Self(value)\n");
95 output.push_str(" }\n\n");
96
97 output.push_str(" /// Returns the raw value.\n");
98 output.push_str(" #[must_use]\n");
99 output.push_str(&format!(
100 " pub const fn raw(&self) -> {} {{\n",
101 rust_type
102 ));
103 output.push_str(" self.0\n");
104 output.push_str(" }\n\n");
105
106 output.push_str(" /// Checks if a bit is set.\n");
107 output.push_str(" #[must_use]\n");
108 output.push_str(" pub const fn is_set(&self, bit: u8) -> bool {\n");
109 output.push_str(" (self.0 >> bit) & 1 != 0\n");
110 output.push_str(" }\n\n");
111
112 output.push_str(" /// Sets a bit.\n");
113 output.push_str(" pub fn set(&mut self, bit: u8) {\n");
114 output.push_str(" self.0 |= 1 << bit;\n");
115 output.push_str(" }\n\n");
116
117 output.push_str(" /// Clears a bit.\n");
118 output.push_str(" pub fn clear(&mut self, bit: u8) {\n");
119 output.push_str(" self.0 &= !(1 << bit);\n");
120 output.push_str(" }\n");
121
122 output.push_str("}\n\n");
123
124 output
125 }
126}