Skip to main content

ironsbe_codegen/rust/
enums.rs

1//! Enum and set code generation.
2
3use ironsbe_schema::ir::{SchemaIr, TypeKind, to_pascal_case};
4use ironsbe_schema::types::PrimitiveType;
5
6/// Generator for enum and set definitions.
7pub struct EnumGenerator<'a> {
8    ir: &'a SchemaIr,
9}
10
11impl<'a> EnumGenerator<'a> {
12    /// Creates a new enum generator.
13    #[must_use]
14    pub fn new(ir: &'a SchemaIr) -> Self {
15        Self { ir }
16    }
17
18    /// Generates all enum and set definitions.
19    #[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    /// Generates an enum definition.
39    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        // We need to get the actual enum values from the schema
50        // For now, generate a placeholder
51        output.push_str("    // Values generated from schema\n");
52        output.push_str("}\n\n");
53
54        // Implement From trait
55        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    /// Generates a set (bitfield) definition.
72    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}