use crate::*; pub struct PackedBinaryLiteral { pub value: usize, pub fields: Vec, pub errors: Vec, } impl PackedBinaryLiteral { pub fn from_str(string: &str, parent: &Tokeniser) -> Self { parse_packed_binary_literal(string, parent) } } 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() { if (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(()); } }