1#![doc = include_str!("../../doc/slice/traits.md")]
2
3#[cfg(feature = "alloc")]
4use alloc::borrow::ToOwned;
5use 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
26use wyz::fmt::FmtForward;
27
28use super::BitSlice;
29#[cfg(feature = "alloc")]
30use crate::vec::BitVec;
31use crate::{
32 domain::Domain,
33 mem,
34 order::{
35 BitOrder,
36 Lsb0,
37 Msb0,
38 },
39 store::BitStore,
40 view::BitView,
41};
42
43impl<T, O> AsRef<Self> for BitSlice<T, O>
45where
46 T: BitStore,
47 O: BitOrder,
48{
49 #[inline]
50 fn as_ref(&self) -> &Self {
51 self
52 }
53}
54
55impl<T, O> AsMut<Self> for BitSlice<T, O>
57where
58 T: BitStore,
59 O: BitOrder,
60{
61 #[inline]
62 fn as_mut(&mut self) -> &mut Self {
63 self
64 }
65}
66
67impl<T, O> Eq for BitSlice<T, O>
69where
70 T: BitStore,
71 O: BitOrder,
72{
73}
74
75impl<T, O> Ord for BitSlice<T, O>
77where
78 T: BitStore,
79 O: BitOrder,
80{
81 #[inline]
82 fn cmp(&self, rhs: &Self) -> cmp::Ordering {
83 self.partial_cmp(rhs)
84 .expect("BitSlice has a total ordering")
85 }
86}
87
88impl<T1, T2, O1, O2> PartialEq<BitSlice<T2, O2>> for BitSlice<T1, O1>
98where
99 T1: BitStore,
100 T2: BitStore,
101 O1: BitOrder,
102 O2: BitOrder,
103{
104 #[inline]
105 fn eq(&self, rhs: &BitSlice<T2, O2>) -> bool {
106 if let (Some(this), Some(that)) =
107 (self.coerce::<T1, Lsb0>(), rhs.coerce::<T1, Lsb0>())
108 {
109 this.sp_eq(that)
110 }
111 else if let (Some(this), Some(that)) =
112 (self.coerce::<T1, Msb0>(), rhs.coerce::<T1, Msb0>())
113 {
114 this.sp_eq(that)
115 }
116 else {
117 self.len() == rhs.len()
118 && self
119 .iter()
120 .by_vals()
121 .zip(rhs.iter().by_vals())
122 .all(|(l, r)| l == r)
123 }
124 }
125}
126
127impl<T1, T2, O1, O2> PartialEq<BitSlice<T2, O2>> for &BitSlice<T1, O1>
130where
131 T1: BitStore,
132 T2: BitStore,
133 O1: BitOrder,
134 O2: BitOrder,
135{
136 #[inline]
137 fn eq(&self, rhs: &BitSlice<T2, O2>) -> bool {
138 **self == rhs
139 }
140}
141
142impl<T1, T2, O1, O2> PartialEq<BitSlice<T2, O2>> for &mut BitSlice<T1, O1>
143where
144 T1: BitStore,
145 T2: BitStore,
146 O1: BitOrder,
147 O2: BitOrder,
148{
149 #[inline]
150 fn eq(&self, rhs: &BitSlice<T2, O2>) -> bool {
151 **self == rhs
152 }
153}
154
155impl<T1, T2, O1, O2> PartialEq<&BitSlice<T2, O2>> for BitSlice<T1, O1>
158where
159 T1: BitStore,
160 T2: BitStore,
161 O1: BitOrder,
162 O2: BitOrder,
163{
164 #[inline]
165 fn eq(&self, rhs: &&BitSlice<T2, O2>) -> bool {
166 *self == **rhs
167 }
168}
169
170impl<T1, T2, O1, O2> PartialEq<&mut BitSlice<T2, O2>> for BitSlice<T1, O1>
171where
172 T1: BitStore,
173 T2: BitStore,
174 O1: BitOrder,
175 O2: BitOrder,
176{
177 #[inline]
178 fn eq(&self, rhs: &&mut BitSlice<T2, O2>) -> bool {
179 *self == **rhs
180 }
181}
182
183impl<T1, T2, O1, O2> PartialOrd<BitSlice<T2, O2>> for BitSlice<T1, O1>
193where
194 T1: BitStore,
195 T2: BitStore,
196 O1: BitOrder,
197 O2: BitOrder,
198{
199 #[inline]
200 fn partial_cmp(&self, rhs: &BitSlice<T2, O2>) -> Option<cmp::Ordering> {
201 for (l, r) in self.iter().by_vals().zip(rhs.iter().by_vals()) {
202 match (l, r) {
203 (true, false) => return Some(cmp::Ordering::Greater),
204 (false, true) => return Some(cmp::Ordering::Less),
205 _ => continue,
206 }
207 }
208 self.len().partial_cmp(&rhs.len())
209 }
210}
211
212impl<T1, T2, O1, O2> PartialOrd<BitSlice<T2, O2>> for &BitSlice<T1, O1>
215where
216 T1: BitStore,
217 T2: BitStore,
218 O1: BitOrder,
219 O2: BitOrder,
220{
221 #[inline]
222 fn partial_cmp(&self, rhs: &BitSlice<T2, O2>) -> Option<cmp::Ordering> {
223 (*self).partial_cmp(rhs)
224 }
225}
226
227impl<T1, T2, O1, O2> PartialOrd<BitSlice<T2, O2>> for &mut BitSlice<T1, O1>
228where
229 T1: BitStore,
230 T2: BitStore,
231 O1: BitOrder,
232 O2: BitOrder,
233{
234 #[inline]
235 fn partial_cmp(&self, rhs: &BitSlice<T2, O2>) -> Option<cmp::Ordering> {
236 (**self).partial_cmp(rhs)
237 }
238}
239
240impl<T1, T2, O1, O2> PartialOrd<&BitSlice<T2, O2>> for BitSlice<T1, O1>
243where
244 T1: BitStore,
245 T2: BitStore,
246 O1: BitOrder,
247 O2: BitOrder,
248{
249 #[inline]
250 fn partial_cmp(&self, rhs: &&BitSlice<T2, O2>) -> Option<cmp::Ordering> {
251 (*self).partial_cmp(&**rhs)
252 }
253}
254
255impl<T1, T2, O1, O2> PartialOrd<&mut BitSlice<T2, O2>> for BitSlice<T1, O1>
256where
257 T1: BitStore,
258 T2: BitStore,
259 O1: BitOrder,
260 O2: BitOrder,
261{
262 #[inline]
263 fn partial_cmp(&self, rhs: &&mut BitSlice<T2, O2>) -> Option<cmp::Ordering> {
264 (*self).partial_cmp(&**rhs)
265 }
266}
267
268impl<T1, T2, O1, O2> PartialOrd<&mut BitSlice<T2, O2>> for &BitSlice<T1, O1>
271where
272 T1: BitStore,
273 T2: BitStore,
274 O1: BitOrder,
275 O2: BitOrder,
276{
277 #[inline]
278 fn partial_cmp(&self, rhs: &&mut BitSlice<T2, O2>) -> Option<cmp::Ordering> {
279 (**self).partial_cmp(&**rhs)
280 }
281}
282
283impl<T1, T2, O1, O2> PartialOrd<&BitSlice<T2, O2>> for &mut BitSlice<T1, O1>
284where
285 T1: BitStore,
286 T2: BitStore,
287 O1: BitOrder,
288 O2: BitOrder,
289{
290 #[inline]
291 fn partial_cmp(&self, rhs: &&BitSlice<T2, O2>) -> Option<cmp::Ordering> {
292 (**self).partial_cmp(&**rhs)
293 }
294}
295
296impl<'a, T, O> TryFrom<&'a [T]> for &'a BitSlice<T, O>
304where
305 T: BitStore,
306 O: BitOrder,
307{
308 type Error = &'a [T];
309
310 #[inline]
311 fn try_from(slice: &'a [T]) -> Result<Self, Self::Error> {
312 BitSlice::try_from_slice(slice).map_err(|_| slice)
313 }
314}
315
316impl<'a, T, O> TryFrom<&'a mut [T]> for &'a mut BitSlice<T, O>
324where
325 T: BitStore,
326 O: BitOrder,
327{
328 type Error = &'a mut [T];
329
330 #[inline]
331 fn try_from(slice: &'a mut [T]) -> Result<Self, Self::Error> {
332 let slice_ptr = slice as *mut [T];
333 BitSlice::try_from_slice_mut(slice)
334 .map_err(|_| unsafe { &mut *slice_ptr })
335 }
336}
337
338impl<T, O> Default for &BitSlice<T, O>
340where
341 T: BitStore,
342 O: BitOrder,
343{
344 #[inline]
345 fn default() -> Self {
346 BitSlice::empty()
347 }
348}
349
350impl<T, O> Default for &mut BitSlice<T, O>
352where
353 T: BitStore,
354 O: BitOrder,
355{
356 #[inline]
357 fn default() -> Self {
358 BitSlice::empty_mut()
359 }
360}
361
362impl<T, O> Debug for BitSlice<T, O>
364where
365 T: BitStore,
366 O: BitOrder,
367{
368 #[inline]
369 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
370 self.as_bitspan().render(fmt, "Slice", None)?;
371 fmt.write_str(" ")?;
372 Display::fmt(self, fmt)
373 }
374}
375
376impl<T, O> Display for BitSlice<T, O>
377where
378 T: BitStore,
379 O: BitOrder,
380{
381 #[inline]
382 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
383 fmt.debug_list()
384 .entries(self.iter().by_vals().map(|b| if b { 1 } else { 0 }))
385 .finish()
386 }
387}
388
389impl<T, O> Pointer for BitSlice<T, O>
390where
391 T: BitStore,
392 O: BitOrder,
393{
394 #[inline]
395 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
396 Pointer::fmt(&self.as_bitspan(), fmt)
397 }
398}
399
400#[inline(always)]
402fn bits_to_ascii<T, O>(bits: &BitSlice<T, O>, alpha: u8) -> u8
403where
404 T: BitStore,
405 O: BitOrder,
406{
407 let mut val = 0u8;
408 for bit in bits.iter().by_vals() {
409 val <<= 1;
410 val |= bit as u8;
411 }
412 match val {
413 v @ 0 ..= 9 => b'0' + v,
414 v @ 10 ..= 35 => alpha - 10 + v,
415 _ => unreachable!(
416 "bit-slices wider than five bits cannot be rendered to ASCII b36"
417 ),
418 }
419}
420
421#[inline(always)]
436fn encode_ascii<'a, T, O>(
437 bits: &BitSlice<T, O>,
438 into: &'a mut [u8],
439 radix: usize,
440 mut skip: usize,
441 alpha: u8,
442) -> &'a str
443where
444 T: BitStore,
445 O: BitOrder,
446{
447 for (chunk, slot) in
448 bits.rchunks(radix).rev().zip(into.iter_mut().skip(skip))
449 {
450 *slot = bits_to_ascii(chunk, alpha);
451 skip += 1;
452 }
453 unsafe { str::from_utf8_unchecked(&into[.. skip]) }
454}
455
456macro_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)] 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 let mut txt: [u8; W + 2] = [b'0'; W + 2];
473 txt[1] = $pfx;
474
475 let start = if fmt.alternate() { 0 } else { 2 };
476 let mut seq = fmt.debug_list();
477 match self.domain() {
478 Domain::Enclave(elem) => {
479 seq.entry(&encode_ascii(
480 elem.into_bitslice(),
481 &mut txt[start ..],
482 $radix,
483 2 - start,
484 $alpha,
485 ).fmt_display());
486 },
487 Domain::Region { head, body, tail } => {
488 if let Some(elem) = head {
489 seq.entry(&encode_ascii(
490 elem.into_bitslice(),
491 &mut txt[start ..],
492 $radix,
493 2 - start,
494 $alpha,
495 ).fmt_display());
496 }
497 for elem in body.iter().map(BitStore::load_value) {
498 seq.entry(&encode_ascii(
499 elem.view_bits::<O>(),
500 &mut txt[start ..],
501 $radix,
502 2 - start,
503 $alpha,
504 ).fmt_display());
505 }
506 if let Some(elem) = tail {
507 seq.entry(&encode_ascii(
508 elem.into_bitslice(),
509 &mut txt[start ..],
510 $radix,
511 2 - start,
512 $alpha,
513 ).fmt_display());
514 }
515 },
516 }
517 seq.finish()
518 }
519 }
520 )+ };
521}
522
523fmt! {
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#[cfg(not(tarpaulin_include))]
532impl<T, O> Hash for BitSlice<T, O>
533where
534 T: BitStore,
535 O: BitOrder,
536{
537 #[inline]
538 fn hash<H>(&self, hasher: &mut H)
539 where H: Hasher {
540 self.iter().by_vals().for_each(|bit| bit.hash(hasher));
541 }
542}
543
544#[doc = include_str!("../../doc/slice/threadsafe.md")]
545unsafe impl<T, O> Send for BitSlice<T, O>
546where
547 T: BitStore + Sync,
548 O: BitOrder,
549{
550}
551
552#[doc = include_str!("../../doc/slice/threadsafe.md")]
553unsafe impl<T, O> Sync for BitSlice<T, O>
554where
555 T: BitStore + Sync,
556 O: BitOrder,
557{
558}
559
560impl<T, O> Unpin for BitSlice<T, O>
562where
563 T: BitStore,
564 O: BitOrder,
565{
566}
567
568#[cfg(feature = "alloc")]
570#[cfg(not(tarpaulin_include))]
571impl<T, O> ToOwned for BitSlice<T, O>
572where
573 T: BitStore,
574 O: BitOrder,
575{
576 type Owned = BitVec<T, O>;
577
578 #[inline]
579 fn to_owned(&self) -> Self::Owned {
580 BitVec::from_bitslice(self)
581 }
582}