1use alloc::format;
5use alloc::vec::Vec;
6use core::fmt;
7
8use crate::octets::write_hex;
9use crate::{Error, ErrorKind, Octets};
10
11#[derive(Clone, Copy, PartialEq, Eq, Hash, Default, PartialOrd, Ord)]
37pub struct Bits {
38 value: u64,
39 length: u8,
40}
41
42impl Bits {
43 pub const EMPTY: Self = Self {
45 value: 0,
46 length: 0,
47 };
48
49 pub fn new(value: u64, length: usize) -> Result<Self, Error> {
56 if length > 64 {
57 return Err(Error::new(
58 ErrorKind::Argument,
59 format!("a bit string of {length} bits is no number of 64 bits: it is a BitString"),
60 ));
61 }
62 if length < 64 && value >> length != 0 {
63 return Err(Error::new(
64 ErrorKind::Argument,
65 format!("{value} does not fit in {length} bits"),
66 ));
67 }
68 Ok(Self {
69 value,
70 length: length as u8,
71 })
72 }
73
74 pub const fn low(value: u64, length: usize) -> Self {
77 match length {
78 0 => Self::EMPTY,
79 1..=63 => Self {
80 value: value & ((1 << length) - 1),
81 length: length as u8,
82 },
83 _ => Self { value, length: 64 },
84 }
85 }
86
87 pub const fn value(&self) -> u64 {
89 self.value
90 }
91
92 pub const fn len(&self) -> usize {
94 self.length as usize
95 }
96
97 pub const fn is_empty(&self) -> bool {
99 self.length == 0
100 }
101
102 pub const fn get(&self, position: usize) -> Option<bool> {
104 if position >= self.length as usize {
105 return None;
106 }
107 Some(self.value >> (self.length as usize - 1 - position) & 1 == 1)
108 }
109
110 pub(crate) const fn leading(&self) -> [u8; 8] {
112 match self.length {
113 0 => [0; 8],
114 length => (self.value << (64 - length)).to_be_bytes(),
115 }
116 }
117
118 pub fn to_vec(&self) -> Vec<u8> {
120 self.leading()[..self.len().div_ceil(8)].to_vec()
121 }
122
123 pub fn from_octets(octets: &[u8], length: usize) -> Result<Self, Error> {
130 check_octets(octets, length)?;
131 if length > 64 {
132 return Self::new(0, length);
133 }
134 let mut leading = [0; 8];
135 leading[..octets.len()].copy_from_slice(octets);
136 let value = match length {
137 0 => 0,
138 length => u64::from_be_bytes(leading) >> (64 - length),
139 };
140 Ok(Self {
141 value,
142 length: length as u8,
143 })
144 }
145}
146
147fn check_octets(octets: &[u8], length: usize) -> Result<(), Error> {
150 if octets.len() != length.div_ceil(8) {
151 return Err(Error::new(
152 ErrorKind::Argument,
153 format!(
154 "a bit string of {length} bits has {} octets, not {}",
155 length.div_ceil(8),
156 octets.len()
157 ),
158 ));
159 }
160 let unused = octets.len() * 8 - length;
161 if octets
162 .last()
163 .is_some_and(|last| last.trailing_zeros() < unused as u32)
164 {
165 return Err(Error::new(
166 ErrorKind::Argument,
167 format!(
168 "the last {unused} bits of the octets are after the {length} bits of the bit \
169 string, and are not zero"
170 ),
171 ));
172 }
173 Ok(())
174}
175
176impl From<u8> for Bits {
177 fn from(value: u8) -> Self {
178 Self {
179 value: value.into(),
180 length: 8,
181 }
182 }
183}
184
185impl From<u16> for Bits {
186 fn from(value: u16) -> Self {
187 Self {
188 value: value.into(),
189 length: 16,
190 }
191 }
192}
193
194impl From<u32> for Bits {
195 fn from(value: u32) -> Self {
196 Self {
197 value: value.into(),
198 length: 32,
199 }
200 }
201}
202
203impl From<u64> for Bits {
204 fn from(value: u64) -> Self {
205 Self { value, length: 64 }
206 }
207}
208
209impl fmt::Debug for Bits {
211 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
212 write!(formatter, "{:#x}/{}", self.value, self.length)
213 }
214}
215
216#[derive(Clone)]
240pub struct BitString<'a>(Held<'a>);
241
242#[derive(Clone)]
243enum Held<'a> {
244 Short {
246 octets: [u8; 8],
247 length: u8,
248 },
249 Long {
250 octets: Octets<'a>,
251 length: usize,
252 },
253}
254
255impl<'a> BitString<'a> {
256 pub const EMPTY: Self = Self(Held::Short {
258 octets: [0; 8],
259 length: 0,
260 });
261
262 pub fn new(octets: impl Into<Octets<'a>>, length: usize) -> Result<Self, Error> {
269 let octets = octets.into();
270 check_octets(&octets, length)?;
271 Ok(Self::of(octets, length))
272 }
273
274 pub fn from_octets(octets: impl Into<Octets<'a>>) -> Self {
276 let octets = octets.into();
277 let length = octets.len() * 8;
278 Self::of(octets, length)
279 }
280
281 pub(crate) fn of(octets: Octets<'a>, length: usize) -> Self {
284 debug_assert!(check_octets(&octets, length).is_ok());
285 if length > 64 {
286 return Self(Held::Long { octets, length });
287 }
288 let mut short = [0; 8];
289 short[..octets.len()].copy_from_slice(&octets);
290 Self(Held::Short {
291 octets: short,
292 length: length as u8,
293 })
294 }
295
296 pub fn len(&self) -> usize {
298 match &self.0 {
299 Held::Short { length, .. } => usize::from(*length),
300 Held::Long { length, .. } => *length,
301 }
302 }
303
304 pub fn is_empty(&self) -> bool {
306 self.len() == 0
307 }
308
309 pub fn as_octets(&self) -> &[u8] {
311 match &self.0 {
312 Held::Short { octets, length } => &octets[..usize::from(*length).div_ceil(8)],
313 Held::Long { octets, .. } => octets,
314 }
315 }
316
317 pub fn get(&self, position: usize) -> Option<bool> {
319 if position >= self.len() {
320 return None;
321 }
322 Some(self.as_octets()[position / 8] & (0x80 >> (position % 8)) != 0)
323 }
324
325 pub fn to_bits(&self) -> Option<Bits> {
327 match &self.0 {
328 Held::Short { octets, length } => Some(Bits::low(
329 u64::from_be_bytes(*octets)
330 .checked_shr(64 - u32::from(*length))
331 .unwrap_or(0),
332 usize::from(*length),
333 )),
334 Held::Long { .. } => None,
335 }
336 }
337
338 #[doc(alias("to_owned", "owned", "keep"))]
342 pub fn into_owned(self) -> BitString<'static> {
343 BitString(match self.0 {
344 Held::Short { octets, length } => Held::Short { octets, length },
345 Held::Long { octets, length } => Held::Long {
346 octets: octets.into_owned(),
347 length,
348 },
349 })
350 }
351}
352
353impl Default for BitString<'_> {
354 fn default() -> Self {
355 Self::EMPTY
356 }
357}
358
359impl PartialEq for BitString<'_> {
360 fn eq(&self, other: &Self) -> bool {
361 self.len() == other.len() && self.as_octets() == other.as_octets()
362 }
363}
364
365impl Eq for BitString<'_> {}
366
367impl core::hash::Hash for BitString<'_> {
368 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
369 self.len().hash(state);
370 self.as_octets().hash(state);
371 }
372}
373
374impl PartialOrd for BitString<'_> {
375 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
376 Some(self.cmp(other))
377 }
378}
379
380impl Ord for BitString<'_> {
382 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
383 let octets = self.as_octets().cmp(other.as_octets());
384 octets.then(self.len().cmp(&other.len()))
385 }
386}
387
388impl<'a> From<&'a [u8]> for BitString<'a> {
389 fn from(octets: &'a [u8]) -> Self {
390 Self::from_octets(octets)
391 }
392}
393
394impl<'a, const N: usize> From<&'a [u8; N]> for BitString<'a> {
395 fn from(octets: &'a [u8; N]) -> Self {
396 Self::from_octets(octets)
397 }
398}
399
400impl From<Vec<u8>> for BitString<'_> {
401 fn from(octets: Vec<u8>) -> Self {
402 Self::from_octets(octets)
403 }
404}
405
406impl<const N: usize> From<[u8; N]> for BitString<'_> {
407 fn from(octets: [u8; N]) -> Self {
408 Self::from_octets(octets)
409 }
410}
411
412impl From<Bits> for BitString<'_> {
413 fn from(bits: Bits) -> Self {
414 Self(Held::Short {
415 octets: bits.leading(),
416 length: bits.len() as u8,
417 })
418 }
419}
420
421impl fmt::Debug for BitString<'_> {
423 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
424 write_hex(self.as_octets(), formatter)?;
425 write!(formatter, "/{}", self.len())
426 }
427}
428
429#[cfg(test)]
430mod tests {
431 use super::*;
432 use alloc::string::ToString;
433 use alloc::vec;
434
435 #[test]
436 fn a_short_bit_string_is_a_number_with_a_length() {
437 let set = Bits::new(0x155, 10).unwrap();
438 assert_eq!((set.value(), set.len()), (0x155, 10));
439 assert_eq!(set.to_vec(), [0x55, 0x40]);
440 assert_eq!(Bits::from_octets(&[0x55, 0x40], 10).unwrap(), set);
441 assert_eq!(set.get(0), Some(false));
442 assert_eq!(set.get(1), Some(true));
443 assert_eq!(set.get(9), Some(true));
444 assert_eq!(set.get(10), None);
445 assert_eq!(format!("{set:?}"), "0x155/10");
446
447 assert_eq!(Bits::new(0, 0).unwrap(), Bits::EMPTY);
449 assert!(Bits::EMPTY.is_empty());
450 assert!(Bits::EMPTY.to_vec().is_empty());
451 assert_eq!(Bits::new(u64::MAX, 64).unwrap(), Bits::from(u64::MAX));
452 assert_eq!(Bits::from(u64::MAX).to_vec(), [0xff; 8]);
453 assert_eq!(Bits::new(1, 65).unwrap_err().kind(), ErrorKind::Argument);
454 assert_eq!(Bits::new(1024, 10).unwrap_err().kind(), ErrorKind::Argument);
455 assert_eq!(
456 Bits::new(1024, 10).unwrap_err().to_string(),
457 "1024 does not fit in 10 bits"
458 );
459
460 assert_eq!(Bits::low(0xffff, 10), Bits::new(0x3ff, 10).unwrap());
462 assert_eq!(Bits::low(0xffff, 0), Bits::EMPTY);
463 assert_eq!(Bits::low(u64::MAX, 64), Bits::from(u64::MAX));
464 assert_eq!(Bits::low(u64::MAX, 99).len(), 64);
465
466 assert_eq!(Bits::from(0x80u8), Bits::new(0x80, 8).unwrap());
468 assert_eq!(Bits::from(0xe000u16).to_vec(), [0xe0, 0x00]);
469 assert_eq!(Bits::from(7u32).len(), 32);
470
471 assert!(Bits::from_octets(&[0x55], 10).is_err());
473 assert!(Bits::from_octets(&[0x55, 0x41], 10).is_err());
474 assert!(Bits::from_octets(&[0; 9], 72).is_err());
475 assert_eq!(Bits::from_octets(&[], 0).unwrap(), Bits::EMPTY);
476 }
477
478 #[test]
479 fn a_long_bit_string_is_its_octets_with_a_length() {
480 let key = BitString::from([0x5a; 32]);
481 assert_eq!(key.len(), 256);
482 assert_eq!(key.to_bits(), None);
483
484 let bits = BitString::new(vec![0xab, 0xcd, 0xe0], 20).unwrap();
485 assert_eq!(bits.as_octets(), [0xab, 0xcd, 0xe0]);
486 assert_eq!(bits.get(0), Some(true));
487 assert_eq!(bits.get(1), Some(false));
488 assert_eq!(bits.get(19), Some(false));
489 assert_eq!(bits.get(20), None);
490 assert_eq!(format!("{bits:?}"), "abcde0/20");
491 assert_eq!(bits.to_bits(), Some(Bits::new(0xabcde, 20).unwrap()));
492 assert_eq!(BitString::from(Bits::new(0xabcde, 20).unwrap()), bits);
493
494 assert!(BitString::new(vec![0xab, 0xcd, 0xef], 20).is_err());
495 assert!(BitString::new(vec![0xab, 0xcd], 20).is_err());
496 assert!(BitString::default().is_empty());
497 assert_eq!(BitString::default(), BitString::EMPTY);
498
499 let short = BitString::new(vec![0xff, 0x80], 9).unwrap();
501 assert_eq!(short, BitString::from(Bits::new(0x1ff, 9).unwrap()));
502 assert_eq!(short.to_bits(), Some(Bits::new(0x1ff, 9).unwrap()));
503 assert_eq!(BitString::EMPTY.to_bits(), Some(Bits::EMPTY));
504 assert_eq!(
505 BitString::from([0xffu8; 8]).to_bits(),
506 Some(Bits::from(u64::MAX))
507 );
508 assert!(BitString::new(vec![0xa0], 4).unwrap() < BitString::new(vec![0xa0], 8).unwrap());
509
510 let received = [0xffu8, 0x80];
511 let borrowed = BitString::new(&received[..], 9).unwrap();
512 let kept: BitString<'static> = borrowed.clone().into_owned();
513 assert_eq!(kept, borrowed);
514 }
515}