#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
pub enum Error {
#[error("bitRange width of 0 does not make sense")]
ZeroWidth,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct BitRange {
pub offset: u32,
pub width: u32,
pub range_type: BitRangeType,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BitRangeType {
BitRange,
OffsetWidth,
MsbLsb,
}
impl BitRange {
pub fn lsb(&self) -> u32 {
self.offset
}
pub fn msb(&self) -> u32 {
self.offset + self.width - 1
}
pub fn bit_range(&self) -> String {
format!("[{}:{}]", self.msb(), self.lsb())
}
pub fn from_offset_width(offset: u32, width: u32) -> Self {
Self {
offset,
width,
range_type: BitRangeType::OffsetWidth,
}
}
pub fn from_msb_lsb(msb: u32, lsb: u32) -> Self {
Self {
offset: lsb,
width: msb - lsb + 1,
range_type: BitRangeType::MsbLsb,
}
}
pub fn from_bit_range(text: &str) -> Option<Self> {
if !text.starts_with('[') || !text.ends_with(']') {
return None;
}
let mut parts = text[1..text.len() - 1].split(':');
let msb = parts.next()?.parse::<u32>().ok()?;
let lsb = parts.next()?.parse::<u32>().ok()?;
Some(Self {
offset: lsb,
width: msb - lsb + 1,
range_type: BitRangeType::BitRange,
})
}
}
#[cfg(feature = "serde")]
mod ser_de {
use super::*;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
enum SerBitRange {
#[serde(rename_all = "camelCase")]
BitRange {
bit_range: String,
},
#[serde(rename_all = "camelCase")]
OffsetWidth {
bit_offset: u32,
bit_width: u32,
},
MsbLsb {
lsb: u32,
msb: u32,
},
}
impl From<BitRange> for SerBitRange {
fn from(br: BitRange) -> Self {
match br.range_type {
BitRangeType::BitRange => SerBitRange::BitRange {
bit_range: br.bit_range(),
},
BitRangeType::OffsetWidth => SerBitRange::OffsetWidth {
bit_offset: br.offset,
bit_width: br.width,
},
BitRangeType::MsbLsb => SerBitRange::MsbLsb {
msb: br.msb(),
lsb: br.lsb(),
},
}
}
}
impl Serialize for BitRange {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let bit_range = SerBitRange::from(*self);
bit_range.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for BitRange {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
match SerBitRange::deserialize(deserializer)? {
SerBitRange::BitRange { bit_range } => BitRange::from_bit_range(&bit_range)
.ok_or_else(|| serde::de::Error::custom("Can't parse bitRange")),
SerBitRange::OffsetWidth {
bit_offset,
bit_width,
} => Ok(BitRange::from_offset_width(bit_offset, bit_width)),
SerBitRange::MsbLsb { msb, lsb } => Ok(BitRange::from_msb_lsb(msb, lsb)),
}
}
}
}