Coverage Report

Created: 2025-12-20 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/bitvec-1.0.1/src/slice/traits.rs
Line
Count
Source
1
#![doc = include_str!("../../doc/slice/traits.md")]
2
3
#[cfg(feature = "alloc")]
4
use alloc::borrow::ToOwned;
5
use core::{
6
  cmp,
7
  convert::TryFrom,
8
  fmt::{
9
    self,
10
    Binary,
11
    Debug,
12
    Display,
13
    Formatter,
14
    LowerHex,
15
    Octal,
16
    Pointer,
17
    UpperHex,
18
  },
19
  hash::{
20
    Hash,
21
    Hasher,
22
  },
23
  str,
24
};
25
26
use wyz::fmt::FmtForward;
27
28
use super::BitSlice;
29
#[cfg(feature = "alloc")]
30
use crate::vec::BitVec;
31
use crate::{
32
  domain::Domain,
33
  mem,
34
  order::{
35
    BitOrder,
36
    Lsb0,
37
    Msb0,
38
  },
39
  store::BitStore,
40
  view::BitView,
41
};
42
43
/// [Original](https://doc.rust-lang.org/std/primitive.slice.html#impl-AsRef%3C%5BT%5D%3E)
44
impl<T, O> AsRef<Self> for BitSlice<T, O>
45
where
46
  T: BitStore,
47
  O: BitOrder,
48
{
49
  #[inline]
50
0
  fn as_ref(&self) -> &Self {
51
0
    self
52
0
  }
53
}
54
55
/// [Original](https://doc.rust-lang.org/std/primitive.slice.html#impl-AsMut%3C%5BT%5D%3E)
56
impl<T, O> AsMut<Self> for BitSlice<T, O>
57
where
58
  T: BitStore,
59
  O: BitOrder,
60
{
61
  #[inline]
62
0
  fn as_mut(&mut self) -> &mut Self {
63
0
    self
64
0
  }
65
}
66
67
/// [Original](https://doc.rust-lang.org/std/primitive.slice.html#impl-Eq)
68
impl<T, O> Eq for BitSlice<T, O>
69
where
70
  T: BitStore,
71
  O: BitOrder,
72
{
73
}
74
75
/// [Original](https://doc.rust-lang.org/std/primitive.slice.html#impl-Ord)
76
impl<T, O> Ord for BitSlice<T, O>
77
where
78
  T: BitStore,
79
  O: BitOrder,
80
{
81
  #[inline]
82
0
  fn cmp(&self, rhs: &Self) -> cmp::Ordering {
83
0
    self.partial_cmp(rhs)
84
0
      .expect("BitSlice has a total ordering")
85
0
  }
86
}
87
88
/** Tests if two `BitSlice`s are semantically — not representationally — equal.
89
90
It is valid to compare slices of different ordering or memory types.
91
92
The equality condition requires that they have the same length and that at each
93
index, the two slices have the same bit value.
94
95
[Original](https://doc.rust-lang.org/std/primitive.slice.html#impl-PartialEq%3C%5BB%5D%3E)
96
**/
97
impl<T1, T2, O1, O2> PartialEq<BitSlice<T2, O2>> for BitSlice<T1, O1>
98
where
99
  T1: BitStore,
100
  T2: BitStore,
101
  O1: BitOrder,
102
  O2: BitOrder,
103
{
104
  #[inline]
105
0
  fn eq(&self, rhs: &BitSlice<T2, O2>) -> bool {
106
0
    if let (Some(this), Some(that)) =
107
0
      (self.coerce::<T1, Lsb0>(), rhs.coerce::<T1, Lsb0>())
108
    {
109
0
      this.sp_eq(that)
110
    }
111
0
    else if let (Some(this), Some(that)) =
112
0
      (self.coerce::<T1, Msb0>(), rhs.coerce::<T1, Msb0>())
113
    {
114
0
      this.sp_eq(that)
115
    }
116
    else {
117
0
      self.len() == rhs.len()
118
0
        && self
119
0
          .iter()
120
0
          .by_vals()
121
0
          .zip(rhs.iter().by_vals())
122
0
          .all(|(l, r)| l == r)
123
    }
124
0
  }
125
}
126
127
//  ref-to-val equality
128
129
impl<T1, T2, O1, O2> PartialEq<BitSlice<T2, O2>> for &BitSlice<T1, O1>
130
where
131
  T1: BitStore,
132
  T2: BitStore,
133
  O1: BitOrder,
134
  O2: BitOrder,
135
{
136
  #[inline]
137
0
  fn eq(&self, rhs: &BitSlice<T2, O2>) -> bool {
138
0
    **self == rhs
139
0
  }
140
}
141
142
impl<T1, T2, O1, O2> PartialEq<BitSlice<T2, O2>> for &mut BitSlice<T1, O1>
143
where
144
  T1: BitStore,
145
  T2: BitStore,
146
  O1: BitOrder,
147
  O2: BitOrder,
148
{
149
  #[inline]
150
0
  fn eq(&self, rhs: &BitSlice<T2, O2>) -> bool {
151
0
    **self == rhs
152
0
  }
153
}
154
155
//  val-to-ref equality
156
157
impl<T1, T2, O1, O2> PartialEq<&BitSlice<T2, O2>> for BitSlice<T1, O1>
158
where
159
  T1: BitStore,
160
  T2: BitStore,
161
  O1: BitOrder,
162
  O2: BitOrder,
163
{
164
  #[inline]
165
0
  fn eq(&self, rhs: &&BitSlice<T2, O2>) -> bool {
166
0
    *self == **rhs
167
0
  }
168
}
169
170
impl<T1, T2, O1, O2> PartialEq<&mut BitSlice<T2, O2>> for BitSlice<T1, O1>
171
where
172
  T1: BitStore,
173
  T2: BitStore,
174
  O1: BitOrder,
175
  O2: BitOrder,
176
{
177
  #[inline]
178
0
  fn eq(&self, rhs: &&mut BitSlice<T2, O2>) -> bool {
179
0
    *self == **rhs
180
0
  }
181
}
182
183
/** Compares two `BitSlice`s by semantic — not representational — ordering.
184
185
The comparison sorts by testing at each index if one slice has a high bit where
186
the other has a low. At the first index where the slices differ, the slice with
187
the high bit is greater. If the slices are equal until at least one terminates,
188
then they are compared by length.
189
190
[Original](https://doc.rust-lang.org/std/primitive.slice.html#impl-PartialOrd%3C%5BT%5D%3E)
191
**/
192
impl<T1, T2, O1, O2> PartialOrd<BitSlice<T2, O2>> for BitSlice<T1, O1>
193
where
194
  T1: BitStore,
195
  T2: BitStore,
196
  O1: BitOrder,
197
  O2: BitOrder,
198
{
199
  #[inline]
200
0
  fn partial_cmp(&self, rhs: &BitSlice<T2, O2>) -> Option<cmp::Ordering> {
201
0
    for (l, r) in self.iter().by_vals().zip(rhs.iter().by_vals()) {
202
0
      match (l, r) {
203
0
        (true, false) => return Some(cmp::Ordering::Greater),
204
0
        (false, true) => return Some(cmp::Ordering::Less),
205
0
        _ => continue,
206
      }
207
    }
208
0
    self.len().partial_cmp(&rhs.len())
209
0
  }
210
}
211
212
//  ref-to-val ordering
213
214
impl<T1, T2, O1, O2> PartialOrd<BitSlice<T2, O2>> for &BitSlice<T1, O1>
215
where
216
  T1: BitStore,
217
  T2: BitStore,
218
  O1: BitOrder,
219
  O2: BitOrder,
220
{
221
  #[inline]
222
0
  fn partial_cmp(&self, rhs: &BitSlice<T2, O2>) -> Option<cmp::Ordering> {
223
0
    (*self).partial_cmp(rhs)
224
0
  }
225
}
226
227
impl<T1, T2, O1, O2> PartialOrd<BitSlice<T2, O2>> for &mut BitSlice<T1, O1>
228
where
229
  T1: BitStore,
230
  T2: BitStore,
231
  O1: BitOrder,
232
  O2: BitOrder,
233
{
234
  #[inline]
235
0
  fn partial_cmp(&self, rhs: &BitSlice<T2, O2>) -> Option<cmp::Ordering> {
236
0
    (**self).partial_cmp(rhs)
237
0
  }
238
}
239
240
//  val-to-ref ordering
241
242
impl<T1, T2, O1, O2> PartialOrd<&BitSlice<T2, O2>> for BitSlice<T1, O1>
243
where
244
  T1: BitStore,
245
  T2: BitStore,
246
  O1: BitOrder,
247
  O2: BitOrder,
248
{
249
  #[inline]
250
0
  fn partial_cmp(&self, rhs: &&BitSlice<T2, O2>) -> Option<cmp::Ordering> {
251
0
    (*self).partial_cmp(&**rhs)
252
0
  }
253
}
254
255
impl<T1, T2, O1, O2> PartialOrd<&mut BitSlice<T2, O2>> for BitSlice<T1, O1>
256
where
257
  T1: BitStore,
258
  T2: BitStore,
259
  O1: BitOrder,
260
  O2: BitOrder,
261
{
262
  #[inline]
263
0
  fn partial_cmp(&self, rhs: &&mut BitSlice<T2, O2>) -> Option<cmp::Ordering> {
264
0
    (*self).partial_cmp(&**rhs)
265
0
  }
266
}
267
268
//  &mut-to-& ordering
269
270
impl<T1, T2, O1, O2> PartialOrd<&mut BitSlice<T2, O2>> for &BitSlice<T1, O1>
271
where
272
  T1: BitStore,
273
  T2: BitStore,
274
  O1: BitOrder,
275
  O2: BitOrder,
276
{
277
  #[inline]
278
0
  fn partial_cmp(&self, rhs: &&mut BitSlice<T2, O2>) -> Option<cmp::Ordering> {
279
0
    (**self).partial_cmp(&**rhs)
280
0
  }
281
}
282
283
impl<T1, T2, O1, O2> PartialOrd<&BitSlice<T2, O2>> for &mut BitSlice<T1, O1>
284
where
285
  T1: BitStore,
286
  T2: BitStore,
287
  O1: BitOrder,
288
  O2: BitOrder,
289
{
290
  #[inline]
291
0
  fn partial_cmp(&self, rhs: &&BitSlice<T2, O2>) -> Option<cmp::Ordering> {
292
0
    (**self).partial_cmp(&**rhs)
293
0
  }
294
}
295
296
/** Calls [`BitSlice::try_from_slice`], but returns the original Rust slice on
297
error instead of the failure event.
298
299
This only fails if `slice.len()` exceeds `BitSlice::MAX_ELTS`.
300
301
[`BitSlice::try_from_slice`]: crate::slice::BitSlice::try_from_slice
302
**/
303
impl<'a, T, O> TryFrom<&'a [T]> for &'a BitSlice<T, O>
304
where
305
  T: BitStore,
306
  O: BitOrder,
307
{
308
  type Error = &'a [T];
309
310
  #[inline]
311
0
  fn try_from(slice: &'a [T]) -> Result<Self, Self::Error> {
312
0
    BitSlice::try_from_slice(slice).map_err(|_| slice)
313
0
  }
314
}
315
316
/** Calls [`BitSlice::try_from_slice_mut`], but returns the original Rust slice
317
on error instead of the failure event.
318
319
This only fails if `slice.len()` exceeds `BitSlice::MAX_ELTS`.
320
321
[`BitSlice::try_from_slice_mut`]: crate::slice::BitSlice::try_from_slice_mut
322
**/
323
impl<'a, T, O> TryFrom<&'a mut [T]> for &'a mut BitSlice<T, O>
324
where
325
  T: BitStore,
326
  O: BitOrder,
327
{
328
  type Error = &'a mut [T];
329
330
  #[inline]
331
0
  fn try_from(slice: &'a mut [T]) -> Result<Self, Self::Error> {
332
0
    let slice_ptr = slice as *mut [T];
333
0
    BitSlice::try_from_slice_mut(slice)
334
0
      .map_err(|_| unsafe { &mut *slice_ptr })
335
0
  }
336
}
337
338
/// [Original](https://doc.rust-lang.org/std/primitive.slice.html#impl-Default-1)
339
impl<T, O> Default for &BitSlice<T, O>
340
where
341
  T: BitStore,
342
  O: BitOrder,
343
{
344
  #[inline]
345
0
  fn default() -> Self {
346
0
    BitSlice::empty()
347
0
  }
348
}
349
350
/// [Original](https://doc.rust-lang.org/std/primitive.slice.html#impl-Default)
351
impl<T, O> Default for &mut BitSlice<T, O>
352
where
353
  T: BitStore,
354
  O: BitOrder,
355
{
356
  #[inline]
357
188k
  fn default() -> Self {
358
188k
    BitSlice::empty_mut()
359
188k
  }
Unexecuted instantiation: <&mut bitvec::slice::BitSlice<bitvec::access::BitSafeU8> as core::default::Default>::default
<&mut bitvec::slice::BitSlice<bitvec::access::BitSafeU8, bitvec::order::Msb0> as core::default::Default>::default
Line
Count
Source
357
188k
  fn default() -> Self {
358
188k
    BitSlice::empty_mut()
359
188k
  }
Unexecuted instantiation: <&mut bitvec::slice::BitSlice<_, _> as core::default::Default>::default
360
}
361
362
/// [Original](https://doc.rust-lang.org/std/primitive.slice.html#impl-Debug)
363
impl<T, O> Debug for BitSlice<T, O>
364
where
365
  T: BitStore,
366
  O: BitOrder,
367
{
368
  #[inline]
369
0
  fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
370
0
    self.as_bitspan().render(fmt, "Slice", None)?;
371
0
    fmt.write_str(" ")?;
372
0
    Display::fmt(self, fmt)
373
0
  }
374
}
375
376
impl<T, O> Display for BitSlice<T, O>
377
where
378
  T: BitStore,
379
  O: BitOrder,
380
{
381
  #[inline]
382
0
  fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
383
0
    fmt.debug_list()
384
0
      .entries(self.iter().by_vals().map(|b| if b { 1 } else { 0 }))
385
0
      .finish()
386
0
  }
387
}
388
389
impl<T, O> Pointer for BitSlice<T, O>
390
where
391
  T: BitStore,
392
  O: BitOrder,
393
{
394
  #[inline]
395
0
  fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
396
0
    Pointer::fmt(&self.as_bitspan(), fmt)
397
0
  }
398
}
399
400
/// Encodes a short bit-slice into an ASCII b36 value.
401
#[inline(always)]
402
0
fn bits_to_ascii<T, O>(bits: &BitSlice<T, O>, alpha: u8) -> u8
403
0
where
404
0
  T: BitStore,
405
0
  O: BitOrder,
406
{
407
0
  let mut val = 0u8;
408
0
  for bit in bits.iter().by_vals() {
409
0
    val <<= 1;
410
0
    val |= bit as u8;
411
0
  }
412
0
  match val {
413
0
    v @ 0 ..= 9 => b'0' + v,
414
0
    v @ 10 ..= 35 => alpha - 10 + v,
415
0
    _ => unreachable!(
416
      "bit-slices wider than five bits cannot be rendered to ASCII b36"
417
    ),
418
  }
419
0
}
420
421
/** Encodes an arbitrary bit-slice into an ASCII b36 string.
422
423
## Parameters
424
425
- `bits`: the bit-slice to encode.
426
- `into`: a provided buffer into which the bit-slice is encoded.
427
- `radix`: the bit width of each digit (log2 of its radix).
428
- `skip`: the number of bytes to skip before beginning the write.
429
- `alpha`: one of `b'a'` or `b'A'`.
430
431
## Returns
432
433
A subset of `into` that is now initialized to the ASCII encoding.
434
**/
435
#[inline(always)]
436
0
fn encode_ascii<'a, T, O>(
437
0
  bits: &BitSlice<T, O>,
438
0
  into: &'a mut [u8],
439
0
  radix: usize,
440
0
  mut skip: usize,
441
0
  alpha: u8,
442
0
) -> &'a str
443
0
where
444
0
  T: BitStore,
445
0
  O: BitOrder,
446
{
447
0
  for (chunk, slot) in
448
0
    bits.rchunks(radix).rev().zip(into.iter_mut().skip(skip))
449
0
  {
450
0
    *slot = bits_to_ascii(chunk, alpha);
451
0
    skip += 1;
452
0
  }
453
0
  unsafe { str::from_utf8_unchecked(&into[.. skip]) }
454
0
}
455
456
/// Constructs the numeric formatting implementations.
457
macro_rules! fmt {
458
  ($($trait:ident: $alpha:expr, $pfx:expr, $radix:expr;)+) => { $(
459
    #[doc = include_str!("../../doc/slice/format.md")]
460
    impl<T, O> $trait for BitSlice<T, O>
461
    where
462
      T: BitStore,
463
      O: BitOrder,
464
    {
465
      #[inline]
466
      #[allow(clippy::modulo_one)] // I know what I’m doing.
467
      //  TODO(myrrlyn): See if Binary codegen ditches the loops.
468
0
      fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
469
        const D: usize = mem::bits_of::<usize>() / $radix;
470
        const M: usize = mem::bits_of::<usize>() % $radix;
471
        const W: usize = D + (M != 0) as usize;
472
0
        let mut txt: [u8; W + 2] = [b'0'; W + 2];
473
0
        txt[1] = $pfx;
474
475
0
        let start = if fmt.alternate() { 0 } else { 2 };
476
0
        let mut seq = fmt.debug_list();
477
0
        match self.domain() {
478
0
          Domain::Enclave(elem) => {
479
0
            seq.entry(&encode_ascii(
480
0
              elem.into_bitslice(),
481
0
              &mut txt[start ..],
482
0
              $radix,
483
0
              2 - start,
484
0
              $alpha,
485
0
            ).fmt_display());
486
0
          },
487
0
          Domain::Region { head, body, tail } => {
488
0
            if let Some(elem) = head {
489
0
              seq.entry(&encode_ascii(
490
0
                elem.into_bitslice(),
491
0
                &mut txt[start ..],
492
0
                $radix,
493
0
                2 - start,
494
0
                $alpha,
495
0
              ).fmt_display());
496
0
            }
497
0
            for elem in body.iter().map(BitStore::load_value) {
498
0
              seq.entry(&encode_ascii(
499
0
                elem.view_bits::<O>(),
500
0
                &mut txt[start ..],
501
0
                $radix,
502
0
                2 - start,
503
0
                $alpha,
504
0
              ).fmt_display());
505
0
            }
506
0
            if let Some(elem) = tail {
507
0
              seq.entry(&encode_ascii(
508
0
                elem.into_bitslice(),
509
0
                &mut txt[start ..],
510
0
                $radix,
511
0
                2 - start,
512
0
                $alpha,
513
0
              ).fmt_display());
514
0
            }
515
          },
516
        }
517
0
        seq.finish()
518
0
      }
Unexecuted instantiation: <bitvec::slice::BitSlice<_, _> as core::fmt::Binary>::fmt
Unexecuted instantiation: <bitvec::slice::BitSlice<_, _> as core::fmt::Octal>::fmt
Unexecuted instantiation: <bitvec::slice::BitSlice<_, _> as core::fmt::LowerHex>::fmt
Unexecuted instantiation: <bitvec::slice::BitSlice<_, _> as core::fmt::UpperHex>::fmt
519
    }
520
  )+ };
521
}
522
523
fmt! {
524
  Binary: b'0', b'b', 1;
525
  Octal: b'0', b'o', 3;
526
  LowerHex: b'a', b'x', 4;
527
  UpperHex: b'A', b'x', 4;
528
}
529
530
/// [Original](https://doc.rust-lang.org/std/primitive.slice.html#impl-Hash)
531
#[cfg(not(tarpaulin_include))]
532
impl<T, O> Hash for BitSlice<T, O>
533
where
534
  T: BitStore,
535
  O: BitOrder,
536
{
537
  #[inline]
538
0
  fn hash<H>(&self, hasher: &mut H)
539
0
  where H: Hasher {
540
0
    self.iter().by_vals().for_each(|bit| bit.hash(hasher));
541
0
  }
542
}
543
544
#[doc = include_str!("../../doc/slice/threadsafe.md")]
545
unsafe impl<T, O> Send for BitSlice<T, O>
546
where
547
  T: BitStore + Sync,
548
  O: BitOrder,
549
{
550
}
551
552
#[doc = include_str!("../../doc/slice/threadsafe.md")]
553
unsafe impl<T, O> Sync for BitSlice<T, O>
554
where
555
  T: BitStore + Sync,
556
  O: BitOrder,
557
{
558
}
559
560
/// [Original](https://doc.rust-lang.org/std/primitive.slice.html#impl-Unpin)
561
impl<T, O> Unpin for BitSlice<T, O>
562
where
563
  T: BitStore,
564
  O: BitOrder,
565
{
566
}
567
568
/// [Original](https://doc.rust-lang.org/std/primitive.slice.html#impl-ToOwned)
569
#[cfg(feature = "alloc")]
570
#[cfg(not(tarpaulin_include))]
571
impl<T, O> ToOwned for BitSlice<T, O>
572
where
573
  T: BitStore,
574
  O: BitOrder,
575
{
576
  type Owned = BitVec<T, O>;
577
578
  #[inline]
579
0
  fn to_owned(&self) -> Self::Owned {
580
0
    BitVec::from_bitslice(self)
581
0
  }
582
}