der/asn1/
bit_string.rs

1//! ASN.1 `BIT STRING` support.
2
3use crate::{
4    asn1::Any, ByteSlice, DecodeValue, Decoder, DerOrd, EncodeValue, Encoder, Error, ErrorKind,
5    FixedTag, Length, Result, Tag, ValueOrd,
6};
7use core::{cmp::Ordering, iter::FusedIterator};
8
9/// ASN.1 `BIT STRING` type.
10///
11/// This type contains a sequence of any number of bits, modeled internally as
12/// a sequence of bytes with a known number of "unused bits".
13#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
14pub struct BitString<'a> {
15    /// Number of unused bits in the final octet.
16    unused_bits: u8,
17
18    /// Length of this `BIT STRING` in bits.
19    bit_length: usize,
20
21    /// Bitstring represented as a slice of bytes.
22    inner: ByteSlice<'a>,
23}
24
25impl<'a> BitString<'a> {
26    /// Maximum number of unused bits allowed.
27    pub const MAX_UNUSED_BITS: u8 = 7;
28
29    /// Create a new ASN.1 `BIT STRING` from a byte slice.
30    ///
31    /// Accepts an optional number of "unused bits" (0-7) which are omitted
32    /// from the final octet. This number is 0 if the value is octet-aligned.
33    pub fn new(unused_bits: u8, bytes: &'a [u8]) -> Result<Self> {
34        if (unused_bits > Self::MAX_UNUSED_BITS) || (unused_bits != 0 && bytes.is_empty()) {
35            return Err(Self::TAG.value_error());
36        }
37
38        let inner = ByteSlice::new(bytes).map_err(|_| Self::TAG.length_error())?;
39
40        let bit_length = usize::try_from(inner.len())?
41            .checked_mul(8)
42            .and_then(|n| n.checked_sub(usize::from(unused_bits)))
43            .ok_or(ErrorKind::Overflow)?;
44
45        Ok(Self {
46            unused_bits,
47            bit_length,
48            inner,
49        })
50    }
51
52    /// Create a new ASN.1 `BIT STRING` from the given bytes.
53    ///
54    /// The "unused bits" are set to 0.
55    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self> {
56        Self::new(0, bytes)
57    }
58
59    /// Get the number of unused bits in this byte slice.
60    pub fn unused_bits(&self) -> u8 {
61        self.unused_bits
62    }
63
64    /// Is the number of unused bits a value other than 0?
65    pub fn has_unused_bits(&self) -> bool {
66        self.unused_bits != 0
67    }
68
69    /// Get the length of this `BIT STRING` in bits.
70    pub fn bit_len(&self) -> usize {
71        self.bit_length
72    }
73
74    /// Get the number of bytes/octets needed to represent this `BIT STRING`
75    /// when serialized in an octet-aligned manner.
76    pub fn byte_len(&self) -> Length {
77        self.inner.len()
78    }
79
80    /// Is the inner byte slice empty?
81    pub fn is_empty(&self) -> bool {
82        self.inner.is_empty()
83    }
84
85    /// Borrow the inner byte slice.
86    ///
87    /// Returns `None` if the number of unused bits is *not* equal to zero,
88    /// i.e. if the `BIT STRING` is not octet aligned.
89    ///
90    /// Use [`BitString::raw_bytes`] to obtain access to the raw value
91    /// regardless of the presence of unused bits.
92    pub fn as_bytes(&self) -> Option<&'a [u8]> {
93        if self.has_unused_bits() {
94            None
95        } else {
96            Some(self.raw_bytes())
97        }
98    }
99
100    /// Borrow the raw bytes of this `BIT STRING`.
101    ///
102    /// Note that the byte string may contain extra unused bits in the final
103    /// octet. If the number of unused bits is expected to be 0, the
104    /// [`BitString::as_bytes`] function can be used instead.
105    pub fn raw_bytes(&self) -> &'a [u8] {
106        self.inner.as_bytes()
107    }
108
109    /// Iterator over the bits of this `BIT STRING`.
110    pub fn bits(self) -> BitStringIter<'a> {
111        BitStringIter {
112            bit_string: self,
113            position: 0,
114        }
115    }
116}
117
118impl<'a> DecodeValue<'a> for BitString<'a> {
119    fn decode_value(decoder: &mut Decoder<'a>, encoded_len: Length) -> Result<Self> {
120        let unused_bits = decoder.byte()?;
121        let inner = ByteSlice::decode_value(decoder, (encoded_len - Length::ONE)?)?;
122        Self::new(unused_bits, inner.as_bytes())
123    }
124}
125
126impl EncodeValue for BitString<'_> {
127    fn value_len(&self) -> Result<Length> {
128        self.byte_len() + Length::ONE
129    }
130
131    fn encode_value(&self, encoder: &mut Encoder<'_>) -> Result<()> {
132        encoder.byte(self.unused_bits)?;
133        encoder.bytes(self.raw_bytes())
134    }
135}
136
137impl ValueOrd for BitString<'_> {
138    fn value_cmp(&self, other: &Self) -> Result<Ordering> {
139        match self.unused_bits.cmp(&other.unused_bits) {
140            Ordering::Equal => self.inner.der_cmp(&other.inner),
141            ordering => Ok(ordering),
142        }
143    }
144}
145
146impl<'a> From<&BitString<'a>> for BitString<'a> {
147    fn from(value: &BitString<'a>) -> BitString<'a> {
148        *value
149    }
150}
151
152impl<'a> TryFrom<Any<'a>> for BitString<'a> {
153    type Error = Error;
154
155    fn try_from(any: Any<'a>) -> Result<BitString<'a>> {
156        any.decode_into()
157    }
158}
159
160impl<'a> TryFrom<&'a [u8]> for BitString<'a> {
161    type Error = Error;
162
163    fn try_from(bytes: &'a [u8]) -> Result<BitString<'a>> {
164        BitString::from_bytes(bytes)
165    }
166}
167
168/// Hack for simplifying the custom derive use case.
169impl<'a> TryFrom<&&'a [u8]> for BitString<'a> {
170    type Error = Error;
171
172    fn try_from(bytes: &&'a [u8]) -> Result<BitString<'a>> {
173        BitString::from_bytes(*bytes)
174    }
175}
176
177impl<'a> TryFrom<BitString<'a>> for &'a [u8] {
178    type Error = Error;
179
180    fn try_from(bit_string: BitString<'a>) -> Result<&'a [u8]> {
181        bit_string
182            .as_bytes()
183            .ok_or_else(|| Tag::BitString.value_error())
184    }
185}
186
187impl<'a> FixedTag for BitString<'a> {
188    const TAG: Tag = Tag::BitString;
189}
190
191/// Iterator over the bits of a [`BitString`].
192pub struct BitStringIter<'a> {
193    /// [`BitString`] being iterated over.
194    bit_string: BitString<'a>,
195
196    /// Current bit position within the iterator.
197    position: usize,
198}
199
200impl<'a> Iterator for BitStringIter<'a> {
201    type Item = bool;
202
203    fn next(&mut self) -> Option<bool> {
204        if self.position >= self.bit_string.bit_len() {
205            return None;
206        }
207
208        let byte = self.bit_string.raw_bytes().get(self.position / 8)?;
209        let bit = 1u8 << (7 - (self.position % 8));
210        self.position = self.position.checked_add(1)?;
211        Some(byte & bit != 0)
212    }
213}
214
215impl<'a> ExactSizeIterator for BitStringIter<'a> {
216    fn len(&self) -> usize {
217        self.bit_string.bit_len()
218    }
219}
220
221impl<'a> FusedIterator for BitStringIter<'a> {}
222
223#[cfg(test)]
224mod tests {
225    use super::{BitString, Result, Tag};
226    use crate::asn1::Any;
227    use hex_literal::hex;
228
229    /// Parse a `BitString` from an ASN.1 `Any` value to test decoding behaviors.
230    fn parse_bitstring(bytes: &[u8]) -> Result<BitString<'_>> {
231        Any::new(Tag::BitString, bytes)?.try_into()
232    }
233
234    #[test]
235    fn decode_empty_bitstring() {
236        let bs = parse_bitstring(&hex!("00")).unwrap();
237        assert_eq!(bs.as_bytes().unwrap(), &[]);
238    }
239
240    #[test]
241    fn decode_non_empty_bitstring() {
242        let bs = parse_bitstring(&hex!("00010203")).unwrap();
243        assert_eq!(bs.as_bytes().unwrap(), &[0x01, 0x02, 0x03]);
244    }
245
246    #[test]
247    fn decode_bitstring_with_unused_bits() {
248        let bs = parse_bitstring(&hex!("066e5dc0")).unwrap();
249        assert_eq!(bs.unused_bits(), 6);
250        assert_eq!(bs.raw_bytes(), &hex!("6e5dc0"));
251
252        // Expected: 011011100101110111
253        let mut bits = bs.bits();
254        assert_eq!(bits.len(), 18);
255
256        for bit in [0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1] {
257            assert_eq!(bits.next().unwrap() as u8, bit)
258        }
259
260        // Ensure `None` is returned on successive calls
261        assert_eq!(bits.next(), None);
262        assert_eq!(bits.next(), None);
263    }
264
265    #[test]
266    fn reject_unused_bits_in_empty_string() {
267        assert_eq!(
268            parse_bitstring(&[0x03]).err().unwrap().kind(),
269            Tag::BitString.value_error().kind()
270        )
271    }
272}