use crate::*; pub struct PackedBinaryLiteral { pub source: SourceSpan, pub value: usize, pub bits: usize, pub fields: Vec<BitField>, pub errors: Vec<PackedBinaryLiteralParseError>, } pub struct BitField { pub name: char, pub source: SourceSpan, /// Length of field in bits pub bits: usize, /// Distance to left-shift field in value pub shift: usize, } pub struct PackedBinaryLiteralParseError { pub source: SourceSpan, pub variant: PackedBinaryLiteralParseErrorVariant, } pub enum PackedBinaryLiteralParseErrorVariant { DuplicateFieldName(char), InvalidCharacter(char), } impl std::fmt::Display for PackedBinaryLiteral { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { if self.value == 0 { write!(f, "0")?; } else { let bitcount = (self.value.ilog2() + 1) as usize; 'bit: for i in (0..bitcount).rev() { let is_first_bit = i+1 == bitcount; if !is_first_bit && (i+1) % 4 == 0 { write!(f, "_")?; } for field in &self.fields { if i <= field.bits + field.shift - 1 && i >= field.shift { write!(f, "{}", field.name)?; continue 'bit; } } match (self.value >> i) & 1 { 0 => write!(f, "0")?, _ => write!(f, "1")?, } } } return Ok(()); } }