svd_rs/
bitrange.rs

1/// Errors for bit ranges
2#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
3pub enum Error {
4    /// The bit range is 0 bits wide
5    #[error("bitRange width of 0 does not make sense")]
6    ZeroWidth,
7}
8
9/// A bit range, describing the [least significant bit](Self::lsb) and [most significant bit](Self::msb)
10#[derive(Clone, Copy, Debug, PartialEq, Eq)]
11pub struct BitRange {
12    /// Value defining the position of the least significant bit of the field within the register
13    pub offset: u32,
14
15    /// Value defining the bit-width of the bitfield within the register
16    pub width: u32,
17
18    /// The underlying description of the bit range
19    pub range_type: BitRangeType,
20}
21
22/// The style of bit range that describes a [BitRange]
23#[derive(Clone, Copy, Debug, PartialEq, Eq)]
24pub enum BitRangeType {
25    /// A bit range in the format: `[<msb>:<lsb>]`
26    BitRange,
27    /// A bit range described as offset and width
28    OffsetWidth,
29    /// A bit range described as lsb and msb as separate elements
30    MsbLsb,
31}
32
33impl BitRange {
34    /// Get the position of the least significant bit
35    pub fn lsb(&self) -> u32 {
36        self.offset
37    }
38    /// Get the position of the most significant bit
39    pub fn msb(&self) -> u32 {
40        self.offset + self.width - 1
41    }
42    /// Get the bit range in the format `[<msb>:<lsb>]`
43    pub fn bit_range(&self) -> String {
44        format!("[{}:{}]", self.msb(), self.lsb())
45    }
46    /// Construct a [`BitRange`] from a offset and width
47    pub fn from_offset_width(offset: u32, width: u32) -> Self {
48        Self {
49            offset,
50            width,
51            range_type: BitRangeType::OffsetWidth,
52        }
53    }
54
55    /// Construct a [`BitRange`] from a msb and lsb
56    pub fn from_msb_lsb(msb: u32, lsb: u32) -> Self {
57        Self {
58            offset: lsb,
59            width: msb - lsb + 1,
60            range_type: BitRangeType::MsbLsb,
61        }
62    }
63    /// Construct a [`BitRange`] from a string in the format `[<msb>:<lsb>]`
64    pub fn from_bit_range(text: &str) -> Option<Self> {
65        if !text.starts_with('[') || !text.ends_with(']') {
66            return None;
67        }
68        let mut parts = text[1..text.len() - 1].split(':');
69        let msb = parts.next()?.parse::<u32>().ok()?;
70        let lsb = parts.next()?.parse::<u32>().ok()?;
71        Some(Self {
72            offset: lsb,
73            width: msb - lsb + 1,
74            range_type: BitRangeType::BitRange,
75        })
76    }
77}
78
79#[cfg(feature = "serde")]
80mod ser_de {
81    use super::*;
82    use serde::{Deserialize, Deserializer, Serialize, Serializer};
83
84    #[derive(serde::Serialize, serde::Deserialize)]
85    #[serde(untagged)]
86    enum SerBitRange {
87        #[serde(rename_all = "camelCase")]
88        BitRange {
89            bit_range: String,
90        },
91        #[serde(rename_all = "camelCase")]
92        OffsetWidth {
93            bit_offset: u32,
94            bit_width: u32,
95        },
96        MsbLsb {
97            lsb: u32,
98            msb: u32,
99        },
100    }
101
102    impl From<BitRange> for SerBitRange {
103        fn from(br: BitRange) -> Self {
104            match br.range_type {
105                BitRangeType::BitRange => SerBitRange::BitRange {
106                    bit_range: br.bit_range(),
107                },
108                BitRangeType::OffsetWidth => SerBitRange::OffsetWidth {
109                    bit_offset: br.offset,
110                    bit_width: br.width,
111                },
112                BitRangeType::MsbLsb => SerBitRange::MsbLsb {
113                    msb: br.msb(),
114                    lsb: br.lsb(),
115                },
116            }
117        }
118    }
119
120    impl Serialize for BitRange {
121        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
122        where
123            S: Serializer,
124        {
125            let bit_range = SerBitRange::from(*self);
126            bit_range.serialize(serializer)
127        }
128    }
129
130    impl<'de> Deserialize<'de> for BitRange {
131        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
132        where
133            D: Deserializer<'de>,
134        {
135            match SerBitRange::deserialize(deserializer)? {
136                SerBitRange::BitRange { bit_range } => BitRange::from_bit_range(&bit_range)
137                    .ok_or_else(|| serde::de::Error::custom("Can't parse bitRange")),
138                SerBitRange::OffsetWidth {
139                    bit_offset,
140                    bit_width,
141                } => Ok(BitRange::from_offset_width(bit_offset, bit_width)),
142                SerBitRange::MsbLsb { msb, lsb } => Ok(BitRange::from_msb_lsb(msb, lsb)),
143            }
144        }
145    }
146}