Skip to main content

der/asn1/
bit_string.rs

1//! ASN.1 `BIT STRING` support.
2
3pub mod allowed_len_bit_string;
4
5use crate::{
6    BytesRef, DecodeValue, DerOrd, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader,
7    Result, Tag, ValueOrd, Writer,
8};
9use core::{cmp::Ordering, iter::FusedIterator};
10use unused_bits::UnusedBits;
11
12#[cfg(feature = "flagset")]
13use core::mem::size_of_val;
14
15/// ASN.1 `BIT STRING` type.
16///
17/// This type contains a sequence of any number of bits, modeled internally as
18/// a sequence of bytes with a known number of "unused bits".
19///
20/// This is a zero-copy reference type which borrows from the input data.
21#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
22pub struct BitStringRef<'a> {
23    /// Number of unused bits in the final octet.
24    unused_bits: UnusedBits,
25
26    /// Bitstring represented as a slice of bytes.
27    inner: &'a BytesRef,
28}
29
30impl<'a> BitStringRef<'a> {
31    /// Create a new ASN.1 `BIT STRING` from a byte slice.
32    ///
33    /// Accepts an optional number of "unused bits" (0-7) which are omitted
34    /// from the final octet. This number is 0 if the value is octet-aligned.
35    ///
36    /// # Errors
37    /// Returns [`Error`] if any of the following occur:
38    /// - `unused_bits` is invalid
39    /// - `bytes` is too long
40    /// - an overflow occurred calculating the bit length
41    pub fn new(unused_bits: u8, bytes: &'a [u8]) -> Result<Self> {
42        let unused_bits = UnusedBits::new(unused_bits, bytes)?;
43        let inner = BytesRef::new(bytes).map_err(|_| Self::TAG.length_error())?;
44        let value = Self::new_unchecked(unused_bits, inner);
45        value
46            .bit_len_checked()
47            .ok_or_else(|| Error::from(ErrorKind::Overflow))?;
48        Ok(value)
49    }
50
51    /// Internal function. Assumptions:
52    /// - [`UnusedBits`] was checked for given [`BytesRef`],
53    /// - [`BitStringRef::bit_len_checked`] was called and returned `Ok`.
54    pub(crate) fn new_unchecked(unused_bits: UnusedBits, inner: &'a BytesRef) -> Self {
55        Self { unused_bits, inner }
56    }
57
58    /// Create a new ASN.1 `BIT STRING` from the given bytes.
59    ///
60    /// The "unused bits" are set to 0.
61    ///
62    /// # Errors
63    /// Has the same error cases as [`BitStringRef::new`].
64    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self> {
65        Self::new(0, bytes)
66    }
67
68    /// Get the number of unused bits in this byte slice.
69    #[must_use]
70    pub fn unused_bits(&self) -> u8 {
71        *self.unused_bits
72    }
73
74    /// Is the number of unused bits a value other than 0?
75    #[must_use]
76    pub fn has_unused_bits(&self) -> bool {
77        *self.unused_bits != 0
78    }
79
80    /// Get the length of this `BIT STRING` in bits, or `None` if the value overflows.
81    ///
82    /// Ensured to be valid in the constructor.
83    fn bit_len_checked(&self) -> Option<usize> {
84        usize::try_from(self.inner.len())
85            .ok()
86            .and_then(|n| n.checked_mul(8))
87            .and_then(|n| n.checked_sub(usize::from(*self.unused_bits)))
88    }
89
90    /// Get the length of this `BIT STRING` in bits.
91    #[must_use]
92    pub fn bit_len(&self) -> usize {
93        let bit_len = self.bit_len_checked();
94        debug_assert!(bit_len.is_some());
95
96        // Ensured to be valid in the constructor.
97        bit_len.unwrap_or(0)
98    }
99
100    /// Get the number of bytes/octets needed to represent this `BIT STRING`
101    /// when serialized in an octet-aligned manner.
102    #[must_use]
103    pub fn byte_len(&self) -> Length {
104        self.inner.len()
105    }
106
107    /// Is the inner byte slice empty?
108    #[must_use]
109    pub fn is_empty(&self) -> bool {
110        self.inner.is_empty()
111    }
112
113    /// Borrow the inner byte slice.
114    ///
115    /// Returns `None` if the number of unused bits is *not* equal to zero,
116    /// i.e. if the `BIT STRING` is not octet aligned.
117    ///
118    /// Use [`BitString::raw_bytes`] to obtain access to the raw value
119    /// regardless of the presence of unused bits.
120    #[must_use]
121    pub fn as_bytes(&self) -> Option<&'a [u8]> {
122        if self.has_unused_bits() {
123            None
124        } else {
125            Some(self.raw_bytes())
126        }
127    }
128
129    /// Borrow the raw bytes of this `BIT STRING`.
130    ///
131    /// Note that the byte string may contain extra unused bits in the final
132    /// octet. If the number of unused bits is expected to be 0, the
133    /// [`BitStringRef::as_bytes`] function can be used instead.
134    #[must_use]
135    pub fn raw_bytes(&self) -> &'a [u8] {
136        self.inner.as_slice()
137    }
138
139    /// Iterator over the bits of this `BIT STRING`.
140    #[must_use]
141    pub fn bits(self) -> BitStringIter<'a> {
142        BitStringIter {
143            bit_string: self,
144            position: 0,
145        }
146    }
147
148    /// Returns Some(bit) if index is valid
149    #[must_use]
150    pub fn get(&self, position: usize) -> Option<bool> {
151        if position >= self.bit_len() {
152            return None;
153        }
154
155        let byte = self.raw_bytes().get(position / 8)?;
156        let bitmask = 1u8 << (7 - (position % 8));
157        Some(byte & bitmask != 0)
158    }
159}
160
161impl_any_conversions!(BitStringRef<'a>, 'a);
162
163impl<'a> DecodeValue<'a> for BitStringRef<'a> {
164    type Error = Error;
165
166    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
167        let header = header.with_length((header.length() - Length::ONE)?);
168
169        let unused_bits = reader.read_byte()?;
170        let inner = <&'a BytesRef>::decode_value(reader, header)?;
171        Self::new(unused_bits, inner.as_slice())
172    }
173}
174
175impl EncodeValue for BitStringRef<'_> {
176    fn value_len(&self) -> Result<Length> {
177        self.byte_len() + Length::ONE
178    }
179
180    fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
181        writer.write_byte(*self.unused_bits)?;
182        writer.write(self.raw_bytes())
183    }
184}
185
186impl ValueOrd for BitStringRef<'_> {
187    fn value_cmp(&self, other: &Self) -> Result<Ordering> {
188        match self.unused_bits.cmp(&other.unused_bits) {
189            Ordering::Equal => self.inner.der_cmp(other.inner),
190            ordering => Ok(ordering),
191        }
192    }
193}
194
195impl<'a> From<&BitStringRef<'a>> for BitStringRef<'a> {
196    fn from(value: &BitStringRef<'a>) -> BitStringRef<'a> {
197        *value
198    }
199}
200
201impl<'a> TryFrom<&'a [u8]> for BitStringRef<'a> {
202    type Error = Error;
203
204    fn try_from(bytes: &'a [u8]) -> Result<BitStringRef<'a>> {
205        BitStringRef::from_bytes(bytes)
206    }
207}
208
209/// Hack for simplifying the custom derive use case.
210impl<'a> TryFrom<&&'a [u8]> for BitStringRef<'a> {
211    type Error = Error;
212
213    fn try_from(bytes: &&'a [u8]) -> Result<BitStringRef<'a>> {
214        BitStringRef::from_bytes(bytes)
215    }
216}
217
218impl<'a, const N: usize> TryFrom<&'a [u8; N]> for BitStringRef<'a> {
219    type Error = Error;
220
221    fn try_from(bytes: &'a [u8; N]) -> Result<BitStringRef<'a>> {
222        BitStringRef::from_bytes(bytes)
223    }
224}
225
226impl<'a, const N: usize> TryFrom<BitStringRef<'a>> for [u8; N] {
227    type Error = Error;
228
229    fn try_from(bit_string: BitStringRef<'a>) -> Result<Self> {
230        let bytes: &[u8] = TryFrom::try_from(bit_string)?;
231        bytes
232            .try_into()
233            .map_err(|_| Tag::BitString.length_error().into())
234    }
235}
236
237impl<'a> TryFrom<BitStringRef<'a>> for &'a [u8] {
238    type Error = Error;
239
240    fn try_from(bit_string: BitStringRef<'a>) -> Result<&'a [u8]> {
241        bit_string
242            .as_bytes()
243            .ok_or_else(|| Tag::BitString.value_error().into())
244    }
245}
246
247impl FixedTag for BitStringRef<'_> {
248    const TAG: Tag = Tag::BitString;
249}
250
251/// [`AsBitStringRef`] marks object that will act like a `BitString`.
252///
253/// It will allow to get a [`BitStringRef`] that points back to the underlying bytes.
254///
255/// Note: this trait does not simplify to [`AsRef<BitStringRef>`], because `BIT STRING`
256/// contains unused bits prefix and therefore cannot be a simple `&'a BitStringRef` slice.
257pub trait AsBitStringRef {
258    /// Borrows the owned or ref `BIT STRING` as [`BitStringRef`]
259    fn as_bit_string_ref(&self) -> BitStringRef<'_>;
260}
261
262impl AsBitStringRef for BitStringRef<'_> {
263    fn as_bit_string_ref(&self) -> BitStringRef<'_> {
264        *self
265    }
266}
267
268/// Sealed, so that `UnusedBits` newtype can't be created directly
269mod unused_bits {
270    use core::ops::Deref;
271
272    use crate::{Result, Tag};
273
274    /// Value in range `0..=7`
275    ///
276    /// Must be zero for empty `BIT STRING`.
277    #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
278    pub(crate) struct UnusedBits(u8);
279
280    impl UnusedBits {
281        /// Maximum number of unused bits allowed.
282        pub const MAX_UNUSED_BITS: u8 = 7;
283
284        /// Represents number of "unused bits" (0-7) in `BIT STRING` which are omitted
285        /// from the final octet. This number is 0 if the value is octet-aligned.
286        pub fn new(unused_bits: u8, bytes: &[u8]) -> Result<Self> {
287            if (unused_bits > Self::MAX_UNUSED_BITS) || (unused_bits != 0 && bytes.is_empty()) {
288                Err(Tag::BitString.value_error().into())
289            } else {
290                Ok(Self(unused_bits))
291            }
292        }
293    }
294    impl Deref for UnusedBits {
295        type Target = u8;
296
297        fn deref(&self) -> &Self::Target {
298            &self.0
299        }
300    }
301}
302
303// Implement by hand because the derive would create invalid values.
304// Use the constructor to create a valid value.
305#[cfg(feature = "arbitrary")]
306impl<'a> arbitrary::Arbitrary<'a> for BitStringRef<'a> {
307    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
308        Self::new(
309            u.int_in_range(0..=UnusedBits::MAX_UNUSED_BITS)?,
310            <&'a BytesRef>::arbitrary(u)?.as_slice(),
311        )
312        .map_err(|_| arbitrary::Error::IncorrectFormat)
313    }
314
315    fn size_hint(depth: usize) -> (usize, Option<usize>) {
316        arbitrary::size_hint::and(u8::size_hint(depth), <&'a BytesRef>::size_hint(depth))
317    }
318}
319
320#[cfg(feature = "alloc")]
321pub use self::allocating::BitString;
322
323#[cfg(feature = "alloc")]
324mod allocating {
325    use super::*;
326    use crate::{asn1::Any, referenced::*};
327    use alloc::vec::Vec;
328
329    /// Owned form of ASN.1 `BIT STRING` type.
330    ///
331    /// This type provides the same functionality as [`BitStringRef`] but owns the
332    /// backing data.
333    #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
334    pub struct BitString {
335        /// Number of unused bits in the final octet.
336        unused_bits: UnusedBits,
337
338        /// Bitstring represented as a slice of bytes.
339        inner: Vec<u8>,
340    }
341
342    impl BitString {
343        /// Maximum number of unused bits allowed.
344        pub const MAX_UNUSED_BITS: u8 = 7;
345
346        /// Create a new ASN.1 `BIT STRING` from a byte slice.
347        ///
348        /// Accepts an optional number of "unused bits" (0-7) which are omitted
349        /// from the final octet. This number is 0 if the value is octet-aligned.
350        ///
351        /// # Errors
352        /// Returns [`Error`] if any of the following occur:
353        /// - `unused_bits` is invalid
354        /// - `bytes` is too long
355        /// - an overflow occurred calculating the bit length
356        pub fn new(unused_bits: u8, bytes: impl Into<Vec<u8>>) -> Result<Self> {
357            let inner = bytes.into();
358
359            // Ensure parameters parse successfully as a `BitStringRef`.
360            let ref_value = BitStringRef::new(unused_bits, &inner)?;
361
362            Ok(BitString {
363                unused_bits: ref_value.unused_bits,
364                inner,
365            })
366        }
367
368        /// Create a new ASN.1 `BIT STRING` from the given bytes.
369        ///
370        /// The "unused bits" are set to 0.
371        ///
372        /// # Errors
373        /// If `bytes` is too long.
374        pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
375            Self::new(0, bytes)
376        }
377
378        /// Get the number of unused bits in the octet serialization of this
379        /// `BIT STRING`.
380        #[must_use]
381        pub fn unused_bits(&self) -> u8 {
382            *self.unused_bits
383        }
384
385        /// Is the number of unused bits a value other than 0?
386        #[must_use]
387        pub fn has_unused_bits(&self) -> bool {
388            *self.unused_bits != 0
389        }
390
391        /// Returns inner [`BytesRef`] slice.
392        pub(crate) fn bytes_ref(&self) -> &BytesRef {
393            // Ensured to parse successfully in constructor
394            BytesRef::new_unchecked(&self.inner)
395        }
396
397        /// Get the length of this `BIT STRING` in bits, or `None` if the value overflows.
398        ///
399        /// Ensured to be valid in the constructor.
400        fn bit_len_checked(&self) -> Option<usize> {
401            BitStringRef::new_unchecked(self.unused_bits, self.bytes_ref()).bit_len_checked()
402        }
403
404        /// Get the length of this `BIT STRING` in bits.
405        #[must_use]
406        pub fn bit_len(&self) -> usize {
407            let bit_len = self.bit_len_checked();
408            debug_assert!(bit_len.is_some());
409
410            // Ensured to be valid in the constructor.
411            bit_len.unwrap_or(0)
412        }
413
414        /// Is the inner byte slice empty?
415        #[must_use]
416        pub fn is_empty(&self) -> bool {
417            self.inner.is_empty()
418        }
419
420        /// Borrow the inner byte slice.
421        ///
422        /// Returns `None` if the number of unused bits is *not* equal to zero,
423        /// i.e. if the `BIT STRING` is not octet aligned.
424        ///
425        /// Use [`BitString::raw_bytes`] to obtain access to the raw value
426        /// regardless of the presence of unused bits.
427        #[must_use]
428        pub fn as_bytes(&self) -> Option<&[u8]> {
429            if self.has_unused_bits() {
430                None
431            } else {
432                Some(self.raw_bytes())
433            }
434        }
435
436        /// Borrow the raw bytes of this `BIT STRING`.
437        #[must_use]
438        pub fn raw_bytes(&self) -> &[u8] {
439            self.inner.as_slice()
440        }
441
442        /// Iterator over the bits of this `BIT STRING`.
443        #[must_use]
444        pub fn bits(&self) -> BitStringIter<'_> {
445            BitStringRef::from(self).bits()
446        }
447
448        /// Returns Some(bit) if index is valid
449        #[must_use]
450        pub fn get(&self, position: usize) -> Option<bool> {
451            BitStringRef::from(self).get(position)
452        }
453    }
454
455    impl_any_conversions!(BitString);
456
457    impl<'a> DecodeValue<'a> for BitString {
458        type Error = Error;
459
460        fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
461            let inner_len = (header.length() - Length::ONE)?;
462            let unused_bits = reader.read_byte()?;
463            let inner = reader.read_vec(inner_len)?;
464            Self::new(unused_bits, inner)
465        }
466    }
467
468    impl EncodeValue for BitString {
469        fn value_len(&self) -> Result<Length> {
470            Length::ONE + Length::try_from(self.inner.len())?
471        }
472
473        fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
474            writer.write_byte(*self.unused_bits)?;
475            writer.write(&self.inner)
476        }
477    }
478
479    impl FixedTag for BitString {
480        const TAG: Tag = Tag::BitString;
481    }
482
483    impl<'a> From<&'a BitString> for BitStringRef<'a> {
484        fn from(bit_string: &'a BitString) -> BitStringRef<'a> {
485            // Ensured to parse successfully in constructor
486            BitStringRef::new_unchecked(bit_string.unused_bits, bit_string.bytes_ref())
487        }
488    }
489
490    impl From<BitStringRef<'_>> for Any {
491        fn from(bit_string_ref: BitStringRef<'_>) -> Any {
492            Any::from(&bit_string_ref)
493        }
494    }
495
496    impl From<&BitStringRef<'_>> for Any {
497        fn from(bit_string_ref: &BitStringRef<'_>) -> Any {
498            Any::encode_from(bit_string_ref).expect("should encode successfully")
499        }
500    }
501
502    impl From<BitString> for Any {
503        fn from(bit_string: BitString) -> Any {
504            bit_string.owned_to_ref().into()
505        }
506    }
507
508    impl From<&BitString> for Any {
509        fn from(bit_string: &BitString) -> Any {
510            bit_string.owned_to_ref().into()
511        }
512    }
513
514    /// Hack for simplifying the custom derive use case.
515    impl<'a> TryFrom<&'a Vec<u8>> for BitStringRef<'a> {
516        type Error = Error;
517
518        fn try_from(bytes: &'a Vec<u8>) -> Result<BitStringRef<'a>> {
519            BitStringRef::from_bytes(bytes)
520        }
521    }
522
523    /// Hack for simplifying the custom derive use case.
524    impl<'a> TryFrom<BitStringRef<'a>> for Vec<u8> {
525        type Error = Error;
526
527        fn try_from(bit_string: BitStringRef<'a>) -> Result<Vec<u8>> {
528            bit_string
529                .as_bytes()
530                .map(<[u8]>::to_vec)
531                .ok_or_else(|| Tag::BitString.value_error().into())
532        }
533    }
534
535    impl ValueOrd for BitString {
536        fn value_cmp(&self, other: &Self) -> Result<Ordering> {
537            match self.unused_bits.cmp(&other.unused_bits) {
538                Ordering::Equal => self.inner.der_cmp(&other.inner),
539                ordering => Ok(ordering),
540            }
541        }
542    }
543
544    // Implement by hand because the derive would create invalid values.
545    // Use the constructor to create a valid value.
546    #[cfg(feature = "arbitrary")]
547    impl<'a> arbitrary::Arbitrary<'a> for BitString {
548        fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
549            Self::new(
550                u.int_in_range(0..=Self::MAX_UNUSED_BITS)?,
551                <&'a BytesRef>::arbitrary(u)?.as_slice(),
552            )
553            .map_err(|_| arbitrary::Error::IncorrectFormat)
554        }
555
556        fn size_hint(depth: usize) -> (usize, Option<usize>) {
557            arbitrary::size_hint::and(u8::size_hint(depth), <&'a BytesRef>::size_hint(depth))
558        }
559    }
560
561    impl<'a> RefToOwned<'a> for BitStringRef<'a> {
562        type Owned = BitString;
563        fn ref_to_owned(&self) -> Self::Owned {
564            BitString {
565                unused_bits: self.unused_bits,
566                inner: Vec::from(self.inner.as_slice()),
567            }
568        }
569    }
570
571    impl OwnedToRef for BitString {
572        type Borrowed<'a> = BitStringRef<'a>;
573        fn owned_to_ref(&self) -> Self::Borrowed<'_> {
574            self.into()
575        }
576    }
577
578    impl AsBitStringRef for BitString {
579        fn as_bit_string_ref(&self) -> BitStringRef<'_> {
580            BitStringRef::from(self)
581        }
582    }
583}
584
585/// Iterator over the bits of a [`BitString`].
586#[derive(Debug)]
587pub struct BitStringIter<'a> {
588    /// [`BitString`] being iterated over.
589    bit_string: BitStringRef<'a>,
590
591    /// Current bit position within the iterator.
592    position: usize,
593}
594
595impl Iterator for BitStringIter<'_> {
596    type Item = bool;
597
598    #[allow(clippy::arithmetic_side_effects)]
599    fn next(&mut self) -> Option<bool> {
600        if self.position >= self.bit_string.bit_len() {
601            return None;
602        }
603
604        let byte = self.bit_string.raw_bytes().get(self.position / 8)?;
605        let bit = 1u8 << (7 - (self.position % 8));
606        self.position = self.position.checked_add(1)?;
607        Some(byte & bit != 0)
608    }
609
610    fn size_hint(&self) -> (usize, Option<usize>) {
611        let len = self.bit_string.bit_len().saturating_sub(self.position);
612        (len, Some(len))
613    }
614}
615
616impl ExactSizeIterator for BitStringIter<'_> {
617    fn len(&self) -> usize {
618        self.bit_string.bit_len()
619    }
620}
621
622impl FusedIterator for BitStringIter<'_> {}
623
624#[cfg(feature = "flagset")]
625impl<T: flagset::Flags> FixedTag for flagset::FlagSet<T> {
626    const TAG: Tag = BitStringRef::TAG;
627}
628
629/// Compares the BIT STRING encodings (X.690 11.6 orders `SET OF` components by their
630/// encodings). The encoding puts flag 0 in the most significant bit of the first octet and drops
631/// trailing zero bits, so this differs from comparing [`FlagSet::bits`][flagset::FlagSet::bits]
632/// as an integer.
633#[cfg(feature = "flagset")]
634impl<T> ValueOrd for flagset::FlagSet<T>
635where
636    T: flagset::Flags,
637    T::Type: From<bool>,
638    T::Type: core::ops::Shl<usize, Output = T::Type>,
639    u128: From<T::Type>,
640{
641    fn value_cmp(&self, other: &Self) -> Result<Ordering> {
642        let mut buf1 = [0u8; 17];
643        let mut buf2 = [0u8; 17];
644        let a = crate::encode::encode_value_to_slice(&mut buf1, self)?;
645        let b = crate::encode::encode_value_to_slice(&mut buf2, other)?;
646        Ok(a.cmp(b))
647    }
648}
649
650#[cfg(feature = "flagset")]
651#[allow(clippy::arithmetic_side_effects)]
652impl<'a, T> DecodeValue<'a> for flagset::FlagSet<T>
653where
654    T: flagset::Flags,
655    T::Type: From<bool>,
656    T::Type: core::ops::Shl<usize, Output = T::Type>,
657{
658    type Error = Error;
659
660    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
661        let position = reader.position();
662        let bits = BitStringRef::decode_value(reader, header)?;
663
664        let mut flags = T::none().bits();
665
666        if bits.bit_len() > size_of_val(&flags) * 8 {
667            return Err(Error::new(ErrorKind::Overlength, position));
668        }
669
670        for (i, bit) in bits.bits().enumerate() {
671            flags |= T::Type::from(bit) << i;
672        }
673
674        Ok(Self::new_truncated(flags))
675    }
676}
677
678#[cfg(feature = "flagset")]
679#[allow(clippy::arithmetic_side_effects)]
680#[inline(always)]
681fn encode_flagset<T>(set: &flagset::FlagSet<T>) -> (usize, [u8; 16])
682where
683    T: flagset::Flags,
684    u128: From<T::Type>,
685{
686    let bits: u128 = set.bits().into();
687    let mut swap = 0u128;
688
689    for i in 0..128 {
690        let on = bits & (1 << i);
691        swap |= on >> i << (128 - i - 1);
692    }
693
694    (bits.leading_zeros() as usize, swap.to_be_bytes())
695}
696
697#[cfg(feature = "flagset")]
698#[allow(clippy::cast_possible_truncation, clippy::arithmetic_side_effects)]
699impl<T: flagset::Flags> EncodeValue for flagset::FlagSet<T>
700where
701    T::Type: From<bool>,
702    T::Type: core::ops::Shl<usize, Output = T::Type>,
703    u128: From<T::Type>,
704{
705    fn value_len(&self) -> Result<Length> {
706        let (lead, buff) = encode_flagset(self);
707        let buff = &buff[..buff.len() - lead / 8];
708        BitStringRef::new((lead % 8) as u8, buff)?.value_len()
709    }
710
711    fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
712        let (lead, buff) = encode_flagset(self);
713        let buff = &buff[..buff.len() - lead / 8];
714        BitStringRef::new((lead % 8) as u8, buff)?.encode_value(writer)
715    }
716}
717
718#[cfg(test)]
719#[allow(clippy::unwrap_used)]
720mod tests {
721    use core::cmp::Ordering;
722
723    use super::{BitStringRef, Result, Tag};
724    use crate::asn1::AnyRef;
725    use hex_literal::hex;
726
727    /// Parse a `BitString` from an ASN.1 `Any` value to test decoding behaviors.
728    fn parse_bitstring(bytes: &[u8]) -> Result<BitStringRef<'_>> {
729        AnyRef::new(Tag::BitString, bytes)?.try_into()
730    }
731
732    #[test]
733    fn decode_empty_bitstring() {
734        let bs = parse_bitstring(&hex!("00")).unwrap();
735        assert_eq!(bs.as_bytes().unwrap(), &[]);
736    }
737
738    #[test]
739    fn decode_non_empty_bitstring() {
740        let bs = parse_bitstring(&hex!("00010203")).unwrap();
741        assert_eq!(bs.as_bytes().unwrap(), &[0x01, 0x02, 0x03]);
742    }
743
744    #[test]
745    fn decode_bitstring_with_unused_bits() {
746        let bs = parse_bitstring(&hex!("066e5dc0")).unwrap();
747        assert_eq!(bs.unused_bits(), 6);
748        assert_eq!(bs.raw_bytes(), &hex!("6e5dc0"));
749
750        // Expected: 011011100101110111
751        let mut bits = bs.bits();
752        assert_eq!(bits.len(), 18);
753
754        for bit in [0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1] {
755            assert_eq!(u8::from(bits.next().unwrap()), bit);
756        }
757
758        // Ensure `None` is returned on successive calls
759        assert_eq!(bits.next(), None);
760        assert_eq!(bits.next(), None);
761    }
762
763    #[test]
764    fn reject_unused_bits_in_empty_string() {
765        assert_eq!(
766            parse_bitstring(&[0x03]).err().unwrap().kind(),
767            Tag::BitString.value_error()
768        );
769    }
770
771    #[test]
772    fn bitstring_valueord_value_cmp() {
773        use crate::ord::DerOrd;
774
775        let bs1 = parse_bitstring(&hex!("00010204")).unwrap();
776        let bs2 = parse_bitstring(&hex!("00010203")).unwrap();
777        assert_eq!(bs1.der_cmp(&bs2), Ok(Ordering::Greater));
778    }
779
780    #[cfg(feature = "flagset")]
781    #[test]
782    fn flagset_valueord_is_encoding_order() {
783        use crate::{DerOrd, Encode, ValueOrd};
784
785        flagset::flags! {
786            enum Flags: u16 {
787                A, B, C, D, E, F, G, H, I,
788            }
789        }
790
791        // {A} encodes as `03 02 07 80`, {B} as `03 02 06 40`: {B} sorts first.
792        let a = flagset::FlagSet::from(Flags::A);
793        let b = flagset::FlagSet::from(Flags::B);
794        assert_eq!(b.value_cmp(&a), Ok(Ordering::Less));
795        assert_eq!(a.der_cmp(&b), Ok(Ordering::Greater));
796
797        // every pair agrees with the order of the encodings
798        let all: [flagset::FlagSet<Flags>; 512] =
799            core::array::from_fn(|i| flagset::FlagSet::new(u16::try_from(i).unwrap()).unwrap());
800        for x in &all {
801            for y in &all {
802                let mut bx = [0u8; 8];
803                let mut by = [0u8; 8];
804                let ex = x.encode_to_slice(&mut bx).unwrap();
805                let ey = y.encode_to_slice(&mut by).unwrap();
806                assert_eq!(x.der_cmp(y), Ok(ex.cmp(ey)), "{x:?} vs {y:?}");
807            }
808        }
809    }
810}