1use crate::{
4 asn1::AnyRef, ByteSlice, DecodeValue, DerOrd, EncodeValue, Error, ErrorKind, FixedTag, Header,
5 Length, Reader, Result, Tag, ValueOrd, Writer,
6};
7use core::{cmp::Ordering, iter::FusedIterator};
8
9#[cfg(feature = "alloc")]
10use alloc::vec::Vec;
11
12#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
19pub struct BitStringRef<'a> {
20 unused_bits: u8,
22
23 bit_length: usize,
25
26 inner: ByteSlice<'a>,
28}
29
30impl<'a> BitStringRef<'a> {
31 pub const MAX_UNUSED_BITS: u8 = 7;
33
34 pub fn new(unused_bits: u8, bytes: &'a [u8]) -> Result<Self> {
39 if (unused_bits > Self::MAX_UNUSED_BITS) || (unused_bits != 0 && bytes.is_empty()) {
40 return Err(Self::TAG.value_error());
41 }
42
43 let inner = ByteSlice::new(bytes).map_err(|_| Self::TAG.length_error())?;
44
45 let bit_length = usize::try_from(inner.len())?
46 .checked_mul(8)
47 .and_then(|n| n.checked_sub(usize::from(unused_bits)))
48 .ok_or(ErrorKind::Overflow)?;
49
50 Ok(Self {
51 unused_bits,
52 bit_length,
53 inner,
54 })
55 }
56
57 pub fn from_bytes(bytes: &'a [u8]) -> Result<Self> {
61 Self::new(0, bytes)
62 }
63
64 pub fn unused_bits(&self) -> u8 {
66 self.unused_bits
67 }
68
69 pub fn has_unused_bits(&self) -> bool {
71 self.unused_bits != 0
72 }
73
74 pub fn bit_len(&self) -> usize {
76 self.bit_length
77 }
78
79 pub fn byte_len(&self) -> Length {
82 self.inner.len()
83 }
84
85 pub fn is_empty(&self) -> bool {
87 self.inner.is_empty()
88 }
89
90 pub fn as_bytes(&self) -> Option<&'a [u8]> {
98 if self.has_unused_bits() {
99 None
100 } else {
101 Some(self.raw_bytes())
102 }
103 }
104
105 pub fn raw_bytes(&self) -> &'a [u8] {
111 self.inner.as_slice()
112 }
113
114 pub fn bits(self) -> BitStringIter<'a> {
116 BitStringIter {
117 bit_string: self,
118 position: 0,
119 }
120 }
121}
122
123impl<'a> DecodeValue<'a> for BitStringRef<'a> {
124 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
125 let header = Header {
126 tag: header.tag,
127 length: (header.length - Length::ONE)?,
128 };
129
130 let unused_bits = reader.read_byte()?;
131 let inner = ByteSlice::decode_value(reader, header)?;
132 Self::new(unused_bits, inner.as_slice())
133 }
134}
135
136impl EncodeValue for BitStringRef<'_> {
137 fn value_len(&self) -> Result<Length> {
138 self.byte_len() + Length::ONE
139 }
140
141 fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
142 writer.write_byte(self.unused_bits)?;
143 writer.write(self.raw_bytes())
144 }
145}
146
147impl ValueOrd for BitStringRef<'_> {
148 fn value_cmp(&self, other: &Self) -> Result<Ordering> {
149 match self.unused_bits.cmp(&other.unused_bits) {
150 Ordering::Equal => self.inner.der_cmp(&other.inner),
151 ordering => Ok(ordering),
152 }
153 }
154}
155
156impl<'a> From<&BitStringRef<'a>> for BitStringRef<'a> {
157 fn from(value: &BitStringRef<'a>) -> BitStringRef<'a> {
158 *value
159 }
160}
161
162impl<'a> TryFrom<AnyRef<'a>> for BitStringRef<'a> {
163 type Error = Error;
164
165 fn try_from(any: AnyRef<'a>) -> Result<BitStringRef<'a>> {
166 any.decode_into()
167 }
168}
169
170impl<'a> TryFrom<&'a [u8]> for BitStringRef<'a> {
171 type Error = Error;
172
173 fn try_from(bytes: &'a [u8]) -> Result<BitStringRef<'a>> {
174 BitStringRef::from_bytes(bytes)
175 }
176}
177
178impl<'a> TryFrom<&&'a [u8]> for BitStringRef<'a> {
180 type Error = Error;
181
182 fn try_from(bytes: &&'a [u8]) -> Result<BitStringRef<'a>> {
183 BitStringRef::from_bytes(*bytes)
184 }
185}
186
187impl<'a> TryFrom<BitStringRef<'a>> for &'a [u8] {
188 type Error = Error;
189
190 fn try_from(bit_string: BitStringRef<'a>) -> Result<&'a [u8]> {
191 bit_string
192 .as_bytes()
193 .ok_or_else(|| Tag::BitString.value_error())
194 }
195}
196
197impl<'a> FixedTag for BitStringRef<'a> {
198 const TAG: Tag = Tag::BitString;
199}
200
201#[cfg(feature = "alloc")]
206#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
207#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
208pub struct BitString {
209 unused_bits: u8,
211
212 bit_length: usize,
214
215 inner: Vec<u8>,
217}
218
219#[cfg(feature = "alloc")]
220impl BitString {
221 pub const MAX_UNUSED_BITS: u8 = 7;
223
224 pub fn new(unused_bits: u8, bytes: impl Into<Vec<u8>>) -> Result<Self> {
229 let inner = bytes.into();
230
231 let bit_length = BitStringRef::new(unused_bits, &inner)?.bit_length;
233
234 Ok(BitString {
235 unused_bits,
236 bit_length,
237 inner,
238 })
239 }
240
241 pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
245 Self::new(0, bytes)
246 }
247
248 pub fn unused_bits(&self) -> u8 {
251 self.unused_bits
252 }
253
254 pub fn has_unused_bits(&self) -> bool {
256 self.unused_bits != 0
257 }
258
259 pub fn bit_len(&self) -> usize {
261 self.bit_length
262 }
263
264 pub fn is_empty(&self) -> bool {
266 self.inner.is_empty()
267 }
268
269 pub fn as_bytes(&self) -> Option<&[u8]> {
277 if self.has_unused_bits() {
278 None
279 } else {
280 Some(self.raw_bytes())
281 }
282 }
283
284 pub fn raw_bytes(&self) -> &[u8] {
286 self.inner.as_slice()
287 }
288
289 pub fn bits(&self) -> BitStringIter<'_> {
291 BitStringRef::from(self).bits()
292 }
293}
294
295#[cfg(feature = "alloc")]
296impl<'a> DecodeValue<'a> for BitString {
297 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
298 let inner_len = (header.length - Length::ONE)?;
299 let unused_bits = reader.read_byte()?;
300 let inner = reader.read_vec(inner_len)?;
301 Self::new(unused_bits, inner)
302 }
303}
304
305#[cfg(feature = "alloc")]
306impl EncodeValue for BitString {
307 fn value_len(&self) -> Result<Length> {
308 Length::ONE + Length::try_from(self.inner.len())?
309 }
310
311 fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
312 writer.write_byte(self.unused_bits)?;
313 writer.write(&self.inner)
314 }
315}
316
317#[cfg(feature = "alloc")]
318impl FixedTag for BitString {
319 const TAG: Tag = Tag::BitString;
320}
321
322#[cfg(feature = "alloc")]
323impl<'a> From<&'a BitString> for BitStringRef<'a> {
324 fn from(bit_string: &'a BitString) -> BitStringRef<'a> {
325 BitStringRef::new(bit_string.unused_bits, &bit_string.inner).expect("invalid BIT STRING")
327 }
328}
329
330#[cfg(feature = "alloc")]
331impl ValueOrd for BitString {
332 fn value_cmp(&self, other: &Self) -> Result<Ordering> {
333 match self.unused_bits.cmp(&other.unused_bits) {
334 Ordering::Equal => self.inner.der_cmp(&other.inner),
335 ordering => Ok(ordering),
336 }
337 }
338}
339
340pub struct BitStringIter<'a> {
342 bit_string: BitStringRef<'a>,
344
345 position: usize,
347}
348
349impl<'a> Iterator for BitStringIter<'a> {
350 type Item = bool;
351
352 #[allow(clippy::integer_arithmetic)]
353 fn next(&mut self) -> Option<bool> {
354 if self.position >= self.bit_string.bit_len() {
355 return None;
356 }
357
358 let byte = self.bit_string.raw_bytes().get(self.position / 8)?;
359 let bit = 1u8 << (7 - (self.position % 8));
360 self.position = self.position.checked_add(1)?;
361 Some(byte & bit != 0)
362 }
363}
364
365impl<'a> ExactSizeIterator for BitStringIter<'a> {
366 fn len(&self) -> usize {
367 self.bit_string.bit_len()
368 }
369}
370
371impl<'a> FusedIterator for BitStringIter<'a> {}
372
373#[cfg(feature = "flagset")]
374impl<T: flagset::Flags> FixedTag for flagset::FlagSet<T> {
375 const TAG: Tag = BitStringRef::TAG;
376}
377
378#[cfg(feature = "flagset")]
379impl<T> ValueOrd for flagset::FlagSet<T>
380where
381 T: flagset::Flags,
382 T::Type: Ord,
383{
384 fn value_cmp(&self, other: &Self) -> Result<Ordering> {
385 Ok(self.bits().cmp(&other.bits()))
386 }
387}
388
389#[cfg(feature = "flagset")]
390#[allow(clippy::integer_arithmetic)]
391impl<'a, T> DecodeValue<'a> for flagset::FlagSet<T>
392where
393 T: flagset::Flags,
394 T::Type: From<bool>,
395 T::Type: core::ops::Shl<usize, Output = T::Type>,
396{
397 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
398 let position = reader.position();
399 let bits = BitStringRef::decode_value(reader, header)?;
400
401 let mut flags = T::none().bits();
402
403 if bits.bit_len() > core::mem::size_of_val(&flags) * 8 {
404 return Err(Error::new(ErrorKind::Overlength, position));
405 }
406
407 for (i, bit) in bits.bits().enumerate() {
408 flags |= T::Type::from(bit) << i;
409 }
410
411 Ok(Self::new_truncated(flags))
412 }
413}
414
415#[cfg(feature = "flagset")]
416#[allow(clippy::integer_arithmetic)]
417#[inline(always)]
418fn encode_flagset<T>(set: &flagset::FlagSet<T>) -> (usize, [u8; 16])
419where
420 T: flagset::Flags,
421 u128: From<T::Type>,
422{
423 let bits: u128 = set.bits().into();
424 let mut swap = 0u128;
425
426 for i in 0..128 {
427 let on = bits & (1 << i);
428 swap |= on >> i << (128 - i - 1);
429 }
430
431 (bits.leading_zeros() as usize, swap.to_be_bytes())
432}
433
434#[cfg(feature = "flagset")]
435#[allow(clippy::cast_possible_truncation, clippy::integer_arithmetic)]
436impl<T: flagset::Flags> EncodeValue for flagset::FlagSet<T>
437where
438 T::Type: From<bool>,
439 T::Type: core::ops::Shl<usize, Output = T::Type>,
440 u128: From<T::Type>,
441{
442 fn value_len(&self) -> Result<Length> {
443 let (lead, buff) = encode_flagset(self);
444 let buff = &buff[..buff.len() - lead / 8];
445 BitStringRef::new((lead % 8) as u8, buff)?.value_len()
446 }
447
448 fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
449 let (lead, buff) = encode_flagset(self);
450 let buff = &buff[..buff.len() - lead / 8];
451 BitStringRef::new((lead % 8) as u8, buff)?.encode_value(writer)
452 }
453}
454
455#[cfg(test)]
456mod tests {
457 use super::{BitStringRef, Result, Tag};
458 use crate::asn1::AnyRef;
459 use hex_literal::hex;
460
461 fn parse_bitstring(bytes: &[u8]) -> Result<BitStringRef<'_>> {
463 AnyRef::new(Tag::BitString, bytes)?.try_into()
464 }
465
466 #[test]
467 fn decode_empty_bitstring() {
468 let bs = parse_bitstring(&hex!("00")).unwrap();
469 assert_eq!(bs.as_bytes().unwrap(), &[]);
470 }
471
472 #[test]
473 fn decode_non_empty_bitstring() {
474 let bs = parse_bitstring(&hex!("00010203")).unwrap();
475 assert_eq!(bs.as_bytes().unwrap(), &[0x01, 0x02, 0x03]);
476 }
477
478 #[test]
479 fn decode_bitstring_with_unused_bits() {
480 let bs = parse_bitstring(&hex!("066e5dc0")).unwrap();
481 assert_eq!(bs.unused_bits(), 6);
482 assert_eq!(bs.raw_bytes(), &hex!("6e5dc0"));
483
484 let mut bits = bs.bits();
486 assert_eq!(bits.len(), 18);
487
488 for bit in [0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1] {
489 assert_eq!(bits.next().unwrap() as u8, bit)
490 }
491
492 assert_eq!(bits.next(), None);
494 assert_eq!(bits.next(), None);
495 }
496
497 #[test]
498 fn reject_unused_bits_in_empty_string() {
499 assert_eq!(
500 parse_bitstring(&[0x03]).err().unwrap().kind(),
501 Tag::BitString.value_error().kind()
502 )
503 }
504}