import re
from typing import List, Tuple
class MatterEnum:
def __init__(self, name: str):
self.name = name
self.items: List[Tuple[int, str, str]] = [] self._force_enum_suffix = False
def add_item(self, value: int, item_name: str, summary: str = ""):
sanitized_name = self._sanitize_variant_name(item_name)
self.items.append((value, sanitized_name, summary))
def _sanitize_variant_name(self, name: str) -> str:
name = name.replace(' ', '_')
name = re.sub(r'[^a-zA-Z0-9_]', '_', name)
starts_with_digit = name and name[0].isdigit()
parts = name.split('_')
name = ''.join(part.capitalize() for part in parts if part)
if starts_with_digit:
name = f"_{name}"
return name if name else "Unknown"
def get_rust_enum_name(self) -> str:
if self._force_enum_suffix:
name = self.name
else:
name = self.name.replace('Enum', '')
words = re.findall(r'[A-Z][a-z]*', name)
return ''.join(words) if words else name
def generate_rust_enum(self) -> str:
enum_name = self.get_rust_enum_name()
max_value = max(value for value, _, _ in self.items) if self.items else 0
if max_value <= 255:
repr_type = "u8"
value_type = "u8"
elif max_value <= 65535:
repr_type = "u16"
value_type = "u16"
else:
repr_type = "u32"
value_type = "u32"
variant_definitions = []
for value, item_name, summary in self.items:
variant_name = item_name
if summary:
variant_definitions.append(f" /// {summary}")
variant_definitions.append(f" {variant_name} = {value},")
variants_str = "\n".join(variant_definitions)
if value_type == "u8":
return f'''#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr({repr_type})]
pub enum {enum_name} {{
{variants_str}
}}
impl {enum_name} {{
/// Convert from u8 value
pub fn from_u8(value: u8) -> Option<Self> {{
match value {{
{self._generate_from_value_arms(value_type)}
_ => None,
}}
}}
/// Convert to u8 value
pub fn to_u8(self) -> u8 {{
self as u8
}}
}}
impl From<{enum_name}> for u8 {{
fn from(val: {enum_name}) -> Self {{
val as u8
}}
}}'''
else:
return f'''#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr({repr_type})]
pub enum {enum_name} {{
{variants_str}
}}
impl {enum_name} {{
/// Convert from u8 value (promoted to {value_type})
pub fn from_u8(value: u8) -> Option<Self> {{
Self::from_{value_type}(value as {value_type})
}}
/// Convert from {value_type} value
pub fn from_{value_type}(value: {value_type}) -> Option<Self> {{
match value {{
{self._generate_from_value_arms(value_type)}
_ => None,
}}
}}
/// Convert to u8 value (truncated if value > 255)
pub fn to_u8(self) -> u8 {{
self as u8
}}
/// Convert to {value_type} value
pub fn to_{value_type}(self) -> {value_type} {{
self as {value_type}
}}
}}
impl From<{enum_name}> for {value_type} {{
fn from(val: {enum_name}) -> Self {{
val as {value_type}
}}
}}'''
def _generate_from_value_arms(self, value_type: str) -> str:
enum_name = self.get_rust_enum_name()
arms = []
for value, item_name, _ in self.items:
arms.append(f" {value} => Some({enum_name}::{item_name}),")
return "\n".join(arms)
def generate_bitmap_macro() -> str:
return ''
class MatterBitmap:
def __init__(self, name: str):
self.name = name
self.bitfields: List[Tuple[int, str, str]] = [] self._force_bitmap_suffix = False
def add_bitfield(self, bit_pos: int, field_name: str, summary: str = ""):
sanitized_name = self._sanitize_bitfield_name(field_name)
self.bitfields.append((bit_pos, sanitized_name, summary))
def _sanitize_bitfield_name(self, name: str) -> str:
name = name.replace(' ', '_')
name = re.sub(r'[^a-zA-Z0-9_]', '_', name)
name = re.sub(r'([a-z])([A-Z])', r'\1_\2', name)
name = name.upper()
name = re.sub(r'_+', '_', name)
if name and name[0].isdigit():
name = f"BIT_{name}"
return name if name else "UNKNOWN"
def get_rust_bitmap_name(self) -> str:
if self._force_bitmap_suffix:
name = self.name
else:
name = self.name.replace('Bitmap', '')
words = re.findall(r'[A-Z][a-z]*', name)
return ''.join(words) if words else name
def get_base_type(self) -> str:
if not self.bitfields:
return "u8"
max_bit = max(bit_pos for bit_pos, _, _ in self.bitfields)
if max_bit < 8:
return "u8"
elif max_bit < 16:
return "u16"
elif max_bit < 32:
return "u32"
else:
return "u64"
def generate_rust_bitmap(self) -> str:
bitmap_name = self.get_rust_bitmap_name()
base_type = self.get_base_type()
constants = []
for bit_pos, field_name, summary in self.bitfields:
bit_value = 1 << bit_pos
if summary:
constants.append(f" /// {summary}")
constants.append(f" pub const {field_name}: {base_type} = 0x{bit_value:02X};")
result = f'''/// {bitmap_name} bitmap type
pub type {bitmap_name} = {base_type};'''
if constants:
module_name = bitmap_name.lower().replace('bitmap', '').strip('_')
if not module_name:
module_name = bitmap_name.lower()
constants_str = "\n".join(constants)
result += f'''
/// Constants for {bitmap_name}
pub mod {module_name} {{
{constants_str}
}}'''
return result