1#![doc = include_str!("../doc/domain.md")]
2
3use core::{
4 any,
5 convert::{
6 TryFrom,
7 TryInto,
8 },
9 fmt::{
10 self,
11 Binary,
12 Debug,
13 Display,
14 Formatter,
15 LowerHex,
16 Octal,
17 UpperHex,
18 },
19 hash::{
20 Hash,
21 Hasher,
22 },
23 iter::FusedIterator,
24 marker::PhantomData,
25};
26
27use tap::{
28 Conv,
29 Pipe,
30 Tap,
31};
32use wyz::{
33 comu::{
34 Address,
35 Const,
36 Mut,
37 Mutability,
38 Reference,
39 Referential,
40 SliceReferential,
41 },
42 fmt::FmtForward,
43};
44
45use crate::{
46 access::BitAccess,
47 index::{
48 BitEnd,
49 BitIdx,
50 BitMask,
51 },
52 order::{
53 BitOrder,
54 Lsb0,
55 },
56 ptr::BitSpan,
57 slice::BitSlice,
58 store::BitStore,
59};
60
61#[doc = include_str!("../doc/domain/BitDomain.md")]
62pub enum BitDomain<'a, M = Const, T = usize, O = Lsb0>
63where
64 M: Mutability,
65 T: 'a + BitStore,
66 O: BitOrder,
67 Address<M, BitSlice<T, O>>: Referential<'a>,
68 Address<M, BitSlice<T::Unalias, O>>: Referential<'a>,
69{
70 Enclave(Reference<'a, M, BitSlice<T, O>>),
75 Region {
82 head: Reference<'a, M, BitSlice<T, O>>,
88 body: Reference<'a, M, BitSlice<T::Unalias, O>>,
105 tail: Reference<'a, M, BitSlice<T, O>>,
111 },
112}
113
114impl<'a, M, T, O> BitDomain<'a, M, T, O>
115where
116 M: Mutability,
117 T: 'a + BitStore,
118 O: BitOrder,
119 Address<M, BitSlice<T, O>>: Referential<'a>,
120 Address<M, BitSlice<T::Unalias, O>>: Referential<'a>,
121{
122 #[inline]
127 pub fn enclave(self) -> Option<Reference<'a, M, BitSlice<T, O>>> {
128 match self {
129 Self::Enclave(bits) => Some(bits),
130 _ => None,
131 }
132 }
133
134 #[inline]
139 pub fn region(
140 self,
141 ) -> Option<(
142 Reference<'a, M, BitSlice<T, O>>,
143 Reference<'a, M, BitSlice<T::Unalias, O>>,
144 Reference<'a, M, BitSlice<T, O>>,
145 )> {
146 match self {
147 Self::Region { head, body, tail } => Some((head, body, tail)),
148 _ => None,
149 }
150 }
151}
152
153impl<'a, M, T, O> Default for BitDomain<'a, M, T, O>
154where
155 M: Mutability,
156 T: 'a + BitStore,
157 O: BitOrder,
158 Address<M, BitSlice<T, O>>: Referential<'a>,
159 Address<M, BitSlice<T::Unalias, O>>: Referential<'a>,
160 Reference<'a, M, BitSlice<T, O>>: Default,
161 Reference<'a, M, BitSlice<T::Unalias, O>>: Default,
162{
163 #[inline]
164 fn default() -> Self {
165 Self::Region {
166 head: Default::default(),
167 body: Default::default(),
168 tail: Default::default(),
169 }
170 }
171}
172
173impl<'a, M, T, O> Debug for BitDomain<'a, M, T, O>
174where
175 M: Mutability,
176 T: 'a + BitStore,
177 O: BitOrder,
178 Address<M, BitSlice<T, O>>: Referential<'a>,
179 Address<M, BitSlice<T::Unalias, O>>: Referential<'a>,
180 Reference<'a, M, BitSlice<T, O>>: Debug,
181 Reference<'a, M, BitSlice<T::Unalias, O>>: Debug,
182{
183 #[inline]
184 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
185 write!(
186 fmt,
187 "BitDomain::<{} {}, {}>::",
188 M::RENDER,
189 any::type_name::<T::Mem>(),
190 any::type_name::<O>(),
191 )?;
192 match self {
193 Self::Enclave(elem) => {
194 fmt.debug_tuple("Enclave").field(elem).finish()
195 },
196 Self::Region { head, body, tail } => fmt
197 .debug_struct("Region")
198 .field("head", head)
199 .field("body", body)
200 .field("tail", tail)
201 .finish(),
202 }
203 }
204}
205
206#[cfg(not(tarpaulin_include))]
207impl<T, O> Clone for BitDomain<'_, Const, T, O>
208where
209 T: BitStore,
210 O: BitOrder,
211{
212 #[inline]
213 fn clone(&self) -> Self {
214 *self
215 }
216}
217
218impl<T, O> Copy for BitDomain<'_, Const, T, O>
219where
220 T: BitStore,
221 O: BitOrder,
222{
223}
224
225#[doc = include_str!("../doc/domain/Domain.md")]
226pub enum Domain<'a, M = Const, T = usize, O = Lsb0>
227where
228 M: Mutability,
229 T: 'a + BitStore,
230 O: BitOrder,
231 Address<M, T>: Referential<'a>,
232 Address<M, [T::Unalias]>: SliceReferential<'a>,
233{
234 Enclave(PartialElement<'a, M, T, O>),
241 Region {
248 head: Option<PartialElement<'a, M, T, O>>,
251 body: Reference<'a, M, [T::Unalias]>,
259 tail: Option<PartialElement<'a, M, T, O>>,
262 },
263}
264
265impl<'a, M, T, O> Domain<'a, M, T, O>
266where
267 M: Mutability,
268 T: 'a + BitStore,
269 O: BitOrder,
270 Address<M, T>: Referential<'a>,
271 Address<M, [T::Unalias]>: SliceReferential<'a>,
272{
273 #[inline]
278 pub fn enclave(self) -> Option<PartialElement<'a, M, T, O>> {
279 match self {
280 Self::Enclave(elem) => Some(elem),
281 _ => None,
282 }
283 }
284
285 #[inline]
290 pub fn region(
291 self,
292 ) -> Option<(
293 Option<PartialElement<'a, M, T, O>>,
294 Reference<'a, M, [T::Unalias]>,
295 Option<PartialElement<'a, M, T, O>>,
296 )> {
297 match self {
298 Self::Region { head, body, tail } => Some((head, body, tail)),
299 _ => None,
300 }
301 }
302
303 #[inline]
308 pub fn into_bit_domain(self) -> BitDomain<'a, M, T, O>
309 where
310 Address<M, BitSlice<T, O>>: Referential<'a>,
311 Address<M, BitSlice<T::Unalias, O>>: Referential<'a>,
312 Reference<'a, M, BitSlice<T, O>>: Default,
313 Reference<'a, M, BitSlice<T::Unalias, O>>:
314 TryFrom<Reference<'a, M, [T::Unalias]>>,
315 {
316 match self {
317 Self::Enclave(elem) => BitDomain::Enclave(elem.into_bitslice()),
318 Self::Region { head, body, tail } => BitDomain::Region {
319 head: head.map_or_else(
320 Default::default,
321 PartialElement::into_bitslice,
322 ),
323 body: body.try_into().unwrap_or_else(|_| {
324 match option_env!("CARGO_PKG_REPOSITORY") {
325 Some(env) => unreachable!(
326 "Construction of a slice with length {} should not \
327 be possible. If this assumption is outdated, \
328 please file an issue at {}",
329 (isize::MIN as usize) >> 3,
330 env,
331 ),
332 None => unreachable!(
333 "Construction of a slice with length {} should not \
334 be possible. If this assumption is outdated, \
335 please consider filing an issue",
336 (isize::MIN as usize) >> 3
337 ),
338 }
339 }),
340 tail: tail.map_or_else(
341 Default::default,
342 PartialElement::into_bitslice,
343 ),
344 },
345 }
346 }
347}
348
349impl<'a, M, T, O> Domain<'a, M, T, O>
357where
358 M: Mutability,
359 T: 'a + BitStore,
360 O: BitOrder,
361 Address<M, T>: Referential<'a>,
362 Address<M, [T::Unalias]>:
363 SliceReferential<'a, ElementAddr = Address<M, T::Unalias>>,
364 Address<M, BitSlice<T, O>>: Referential<'a>,
365 Reference<'a, M, [T::Unalias]>: Default,
366{
367 pub(crate) fn new(bits: Reference<'a, M, BitSlice<T, O>>) -> Self
378 where BitSpan<M, T, O>: From<Reference<'a, M, BitSlice<T, O>>> {
379 let bitspan = bits.conv::<BitSpan<M, T, O>>();
380 let (head, elts, tail) =
381 (bitspan.head(), bitspan.elements(), bitspan.tail());
382 let base = bitspan.address();
383 let (min, max) = (BitIdx::<T::Mem>::MIN, BitEnd::<T::Mem>::MAX);
384 let ctor = match (head, elts, tail) {
385 (_, 0, _) => Self::empty,
386 (h, _, t) if h == min && t == max => Self::spanning,
387 (_, _, t) if t == max => Self::partial_head,
388 (h, ..) if h == min => Self::partial_tail,
389 (_, 1, _) => Self::minor,
390 _ => Self::major,
391 };
392 ctor(base, elts, head, tail)
393 }
394
395 #[inline]
397 fn empty(
398 _: Address<M, T>,
399 _: usize,
400 _: BitIdx<T::Mem>,
401 _: BitEnd<T::Mem>,
402 ) -> Self {
403 Default::default()
404 }
405
406 #[inline]
409 fn major(
410 addr: Address<M, T>,
411 elts: usize,
412 head: BitIdx<T::Mem>,
413 tail: BitEnd<T::Mem>,
414 ) -> Self {
415 let h_elem = addr;
416 let t_elem = unsafe { addr.add(elts - 1) };
417 let body = unsafe {
418 Address::<M, [T::Unalias]>::from_raw_parts(
419 addr.add(1).cast::<T::Unalias>(),
420 elts - 2,
421 )
422 };
423 Self::Region {
424 head: Some(PartialElement::new(h_elem, head, None)),
425 body,
426 tail: Some(PartialElement::new(t_elem, None, tail)),
427 }
428 }
429
430 #[inline]
432 fn minor(
433 addr: Address<M, T>,
434 _: usize,
435 head: BitIdx<T::Mem>,
436 tail: BitEnd<T::Mem>,
437 ) -> Self {
438 let elem = addr;
439 Self::Enclave(PartialElement::new(elem, head, tail))
440 }
441
442 #[inline]
445 fn partial_head(
446 addr: Address<M, T>,
447 elts: usize,
448 head: BitIdx<T::Mem>,
449 _: BitEnd<T::Mem>,
450 ) -> Self {
451 let elem = addr;
452 let body = unsafe {
453 Address::<M, [T::Unalias]>::from_raw_parts(
454 addr.add(1).cast::<T::Unalias>(),
455 elts - 1,
456 )
457 };
458 Self::Region {
459 head: Some(PartialElement::new(elem, head, None)),
460 body,
461 tail: None,
462 }
463 }
464
465 #[inline]
468 fn partial_tail(
469 addr: Address<M, T>,
470 elts: usize,
471 _: BitIdx<T::Mem>,
472 tail: BitEnd<T::Mem>,
473 ) -> Self {
474 let elem = unsafe { addr.add(elts - 1) };
475 let body = unsafe {
476 Address::<M, [T::Unalias]>::from_raw_parts(
477 addr.cast::<T::Unalias>(),
478 elts - 1,
479 )
480 };
481 Self::Region {
482 head: None,
483 body,
484 tail: Some(PartialElement::new(elem, None, tail)),
485 }
486 }
487
488 #[inline]
491 fn spanning(
492 addr: Address<M, T>,
493 elts: usize,
494 _: BitIdx<T::Mem>,
495 _: BitEnd<T::Mem>,
496 ) -> Self {
497 Self::Region {
498 head: None,
499 body: unsafe {
500 <Address<M, [T::Unalias]> as SliceReferential>::from_raw_parts(
501 addr.cast::<T::Unalias>(),
502 elts,
503 )
504 },
505 tail: None,
506 }
507 }
508}
509
510impl<'a, M, T, O> Default for Domain<'a, M, T, O>
511where
512 M: Mutability,
513 T: 'a + BitStore,
514 O: BitOrder,
515 Address<M, T>: Referential<'a>,
516 Address<M, [T::Unalias]>: SliceReferential<'a>,
517 Reference<'a, M, [T::Unalias]>: Default,
518{
519 #[inline]
520 fn default() -> Self {
521 Self::Region {
522 head: None,
523 body: Reference::<M, [T::Unalias]>::default(),
524 tail: None,
525 }
526 }
527}
528
529impl<'a, M, T, O> Debug for Domain<'a, M, T, O>
530where
531 M: Mutability,
532 T: 'a + BitStore,
533 O: BitOrder,
534 Address<M, T>: Referential<'a>,
535 Address<M, [T::Unalias]>: SliceReferential<'a>,
536 Reference<'a, M, [T::Unalias]>: Debug,
537{
538 #[inline]
539 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
540 write!(
541 fmt,
542 "Domain::<{} {}, {}>::",
543 M::RENDER,
544 any::type_name::<T>(),
545 any::type_name::<O>(),
546 )?;
547 match self {
548 Self::Enclave(elem) => {
549 fmt.debug_tuple("Enclave").field(elem).finish()
550 },
551 Self::Region { head, body, tail } => fmt
552 .debug_struct("Region")
553 .field("head", head)
554 .field("body", body)
555 .field("tail", tail)
556 .finish(),
557 }
558 }
559}
560
561#[cfg(not(tarpaulin_include))]
562impl<T, O> Clone for Domain<'_, Const, T, O>
563where
564 T: BitStore,
565 O: BitOrder,
566{
567 #[inline]
568 fn clone(&self) -> Self {
569 *self
570 }
571}
572
573impl<T, O> Iterator for Domain<'_, Const, T, O>
574where
575 T: BitStore,
576 O: BitOrder,
577{
578 type Item = T::Mem;
579
580 #[inline]
581 fn next(&mut self) -> Option<Self::Item> {
582 match self {
583 Self::Enclave(elem) => {
584 elem.load_value().tap(|_| *self = Default::default()).into()
585 },
586 Self::Region { head, body, tail } => {
587 if let Some(elem) = head.take() {
588 return elem.load_value().into();
589 }
590 if let Some((elem, rest)) = body.split_first() {
591 *body = rest;
592 return elem.load_value().into();
593 }
594 if let Some(elem) = tail.take() {
595 return elem.load_value().into();
596 }
597 None
598 },
599 }
600 }
601}
602
603impl<T, O> DoubleEndedIterator for Domain<'_, Const, T, O>
604where
605 T: BitStore,
606 O: BitOrder,
607{
608 #[inline]
609 fn next_back(&mut self) -> Option<Self::Item> {
610 match self {
611 Self::Enclave(elem) => {
612 elem.load_value().tap(|_| *self = Default::default()).into()
613 },
614 Self::Region { head, body, tail } => {
615 if let Some(elem) = tail.take() {
616 return elem.load_value().into();
617 }
618 if let Some((elem, rest)) = body.split_last() {
619 *body = rest;
620 return elem.load_value().into();
621 }
622 if let Some(elem) = head.take() {
623 return elem.load_value().into();
624 }
625 None
626 },
627 }
628 }
629}
630
631impl<T, O> ExactSizeIterator for Domain<'_, Const, T, O>
632where
633 T: BitStore,
634 O: BitOrder,
635{
636 #[inline]
637 fn len(&self) -> usize {
638 match self {
639 Self::Enclave(_) => 1,
640 Self::Region { head, body, tail } => {
641 head.is_some() as usize + body.len() + tail.is_some() as usize
642 },
643 }
644 }
645}
646
647impl<T, O> FusedIterator for Domain<'_, Const, T, O>
648where
649 T: BitStore,
650 O: BitOrder,
651{
652}
653
654impl<T, O> Copy for Domain<'_, Const, T, O>
655where
656 T: BitStore,
657 O: BitOrder,
658{
659}
660
661macro_rules! fmt {
663 ($($fmt:ty => $fwd:ident),+ $(,)?) => { $(
664 impl<'a, T, O> $fmt for Domain<'a, Const, T, O>
665 where
666 O: BitOrder,
667 T: BitStore,
668 {
669 #[inline]
670 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
671 fmt.debug_list()
672 .entries(self.into_iter().map(FmtForward::$fwd))
673 .finish()
674 }
675 }
676 )+ };
677}
678
679fmt! {
680 Binary => fmt_binary,
681 Display => fmt_display,
682 LowerHex => fmt_lower_hex,
683 Octal => fmt_octal,
684 UpperHex => fmt_upper_hex,
685}
686
687#[doc = include_str!("../doc/domain/PartialElement.md")]
688pub struct PartialElement<'a, M, T, O>
689where
690 M: Mutability,
691 T: 'a + BitStore,
692 O: BitOrder,
693{
694 elem: Address<M, T>,
704 mask: BitMask<T::Mem>,
706 head: BitIdx<T::Mem>,
708 tail: BitEnd<T::Mem>,
710 _ord: PhantomData<O>,
712 _ref: PhantomData<&'a T::Access>,
714}
715
716impl<'a, M, T, O> PartialElement<'a, M, T, O>
717where
718 M: Mutability,
719 T: 'a + BitStore,
720 O: BitOrder,
721{
722 #[inline]
730 fn new(
731 elem: Address<M, T>,
732 head: impl Into<Option<BitIdx<T::Mem>>>,
733 tail: impl Into<Option<BitEnd<T::Mem>>>,
734 ) -> Self {
735 let (head, tail) = (
736 head.into().unwrap_or(BitIdx::MIN),
737 tail.into().unwrap_or(BitEnd::MAX),
738 );
739 Self {
740 elem,
741 mask: O::mask(head, tail),
742 head,
743 tail,
744 _ord: PhantomData,
745 _ref: PhantomData,
746 }
747 }
748
749 #[inline]
756 pub fn load_value(&self) -> T::Mem {
757 self.elem
758 .pipe(|addr| unsafe { &*addr.to_const() })
759 .load_value()
760 & self.mask.into_inner()
761 }
762
763 #[inline]
765 #[cfg(not(tarpaulin_include))]
766 pub fn head(&self) -> BitIdx<T::Mem> {
767 self.head
768 }
769
770 #[inline]
772 #[cfg(not(tarpaulin_include))]
773 pub fn tail(&self) -> BitEnd<T::Mem> {
774 self.tail
775 }
776
777 #[inline]
780 #[cfg(not(tarpaulin_include))]
781 pub fn bounds(&self) -> (BitIdx<T::Mem>, BitEnd<T::Mem>) {
782 (self.head, self.tail)
783 }
784
785 #[inline]
787 #[cfg(not(tarpaulin_include))]
788 pub fn mask(&self) -> BitMask<T::Mem> {
789 self.mask
790 }
791
792 #[inline]
794 pub fn into_bitslice(self) -> Reference<'a, M, BitSlice<T, O>>
795 where Address<M, BitSlice<T, O>>: Referential<'a> {
796 unsafe {
797 BitSpan::new_unchecked(
798 self.elem,
799 self.head,
800 (self.tail.into_inner() - self.head.into_inner()) as usize,
801 )
802 }
803 .to_bitslice()
804 }
805}
806
807impl<'a, T, O> PartialElement<'a, Mut, T, O>
808where
809 T: BitStore,
810 O: BitOrder,
811 Address<Mut, T>: Referential<'a>,
812{
813 #[inline]
827 pub fn store_value(&mut self, value: T::Mem) -> T::Mem {
828 let this = self.access();
829 let prev = this.clear_bits(self.mask);
830 this.set_bits(self.mask & value);
831 prev & self.mask.into_inner()
832 }
833
834 #[inline]
840 #[cfg(not(tarpaulin_include))]
841 pub fn invert(&mut self) -> T::Mem {
842 self.access().invert_bits(self.mask) & self.mask.into_inner()
843 }
844
845 #[inline]
851 #[cfg(not(tarpaulin_include))]
852 pub fn clear(&mut self) -> T::Mem {
853 self.access().clear_bits(self.mask) & self.mask.into_inner()
854 }
855
856 #[inline]
862 #[cfg(not(tarpaulin_include))]
863 pub fn set(&mut self) -> T::Mem {
864 self.access().set_bits(self.mask) & self.mask.into_inner()
865 }
866
867 #[inline]
870 fn access(&self) -> &T::Access {
871 unsafe { &*self.elem.to_const().cast::<T::Access>() }
872 }
873}
874
875impl<'a, M, T, O> PartialElement<'a, M, T, O>
876where
877 M: Mutability,
878 O: BitOrder,
879 T: 'a + BitStore + radium::Radium,
880{
881 #[inline]
884 pub fn store_value_aliased(&self, value: T::Mem) -> T::Mem {
885 let this = unsafe { &*self.elem.to_const().cast::<T::Access>() };
886 let prev = this.clear_bits(self.mask);
887 this.set_bits(self.mask & value);
888 prev & self.mask.into_inner()
889 }
890}
891
892#[cfg(not(tarpaulin_include))]
893impl<'a, T, O> Clone for PartialElement<'a, Const, T, O>
894where
895 T: BitStore,
896 O: BitOrder,
897 Address<Const, T>: Referential<'a>,
898{
899 #[inline]
900 fn clone(&self) -> Self {
901 *self
902 }
903}
904
905impl<'a, M, T, O> Debug for PartialElement<'a, M, T, O>
906where
907 M: Mutability,
908 T: 'a + BitStore,
909 O: BitOrder,
910{
911 #[inline]
912 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
913 write!(
914 fmt,
915 "PartialElement<{} {}, {}>",
916 M::RENDER,
917 any::type_name::<T>(),
918 any::type_name::<O>(),
919 )?;
920 fmt.debug_struct("")
921 .field("elem", &self.load_value())
922 .field("mask", &self.mask.fmt_display())
923 .field("head", &self.head.fmt_display())
924 .field("tail", &self.tail.fmt_display())
925 .finish()
926 }
927}
928
929#[cfg(not(tarpaulin_include))]
930impl<'a, M, T, O> Hash for PartialElement<'a, M, T, O>
931where
932 M: Mutability,
933 T: 'a + BitStore,
934 O: BitOrder,
935{
936 #[inline]
937 fn hash<H>(&self, hasher: &mut H)
938 where H: Hasher {
939 self.load_value().hash(hasher);
940 self.mask.hash(hasher);
941 self.head.hash(hasher);
942 self.tail.hash(hasher);
943 }
944}
945
946impl<T, O> Copy for PartialElement<'_, Const, T, O>
947where
948 T: BitStore,
949 O: BitOrder,
950{
951}
952
953#[cfg(test)]
954mod tests {
955 use rand::random;
956
957 use super::*;
958 use crate::prelude::*;
959
960 #[test]
961 fn bit_domain() {
962 let data = BitArray::<[u32; 3], Msb0>::new(random());
963
964 let bd = data.bit_domain();
965 assert!(bd.enclave().is_none());
966 let (head, body, tail) = bd.region().unwrap();
967 assert_eq!(data, body);
968 assert!(head.is_empty());
969 assert!(tail.is_empty());
970
971 let bd = data[2 ..].bit_domain();
972 let (head, body, tail) = bd.region().unwrap();
973 assert_eq!(head, &data[2 .. 32]);
974 assert_eq!(body, &data[32 ..]);
975 assert!(tail.is_empty());
976
977 let bd = data[.. 94].bit_domain();
978 let (head, body, tail) = bd.region().unwrap();
979 assert!(head.is_empty());
980 assert_eq!(body, &data[.. 64]);
981 assert_eq!(tail, &data[64 .. 94]);
982
983 let bd = data[2 .. 94].bit_domain();
984 let (head, body, tail) = bd.region().unwrap();
985 assert_eq!(head, &data[2 .. 32]);
986 assert_eq!(body, &data[32 .. 64]);
987 assert_eq!(tail, &data[64 .. 94]);
988
989 let bd = data[34 .. 62].bit_domain();
990 assert!(bd.region().is_none());
991 assert_eq!(bd.enclave().unwrap(), data[34 .. 62]);
992
993 let (head, body, tail) =
994 BitDomain::<Const, usize, Lsb0>::default().region().unwrap();
995 assert!(head.is_empty());
996 assert!(body.is_empty());
997 assert!(tail.is_empty());
998 }
999
1000 #[test]
1001 fn domain() {
1002 let data: [u32; 3] = random();
1003 let bits = data.view_bits::<Msb0>();
1004
1005 let d = bits.domain();
1006 assert!(d.enclave().is_none());
1007 let (head, body, tail) = d.region().unwrap();
1008 assert!(head.is_none());
1009 assert!(tail.is_none());
1010 assert_eq!(body, data);
1011
1012 let d = bits[2 ..].domain();
1013 let (head, body, tail) = d.region().unwrap();
1014 assert_eq!(head.unwrap().load_value(), (data[0] << 2) >> 2);
1015 assert_eq!(body, &data[1 ..]);
1016 assert!(tail.is_none());
1017
1018 let d = bits[.. 94].domain();
1019 let (head, body, tail) = d.region().unwrap();
1020 assert!(head.is_none());
1021 assert_eq!(body, &data[.. 2]);
1022 assert_eq!(tail.unwrap().load_value(), (data[2] >> 2) << 2);
1023
1024 let d = bits[2 .. 94].domain();
1025 let (head, body, tail) = d.region().unwrap();
1026 assert_eq!(head.unwrap().load_value(), (data[0] << 2) >> 2);
1027 assert_eq!(body, &data[1 .. 2]);
1028 assert_eq!(tail.unwrap().load_value(), (data[2] >> 2) << 2);
1029
1030 let d = bits[34 .. 62].domain();
1031 assert!(d.region().is_none());
1032 assert_eq!(
1033 d.enclave().unwrap().load_value(),
1034 ((data[1] << 2) >> 4) << 2,
1035 );
1036
1037 assert!(matches!(bits![].domain(), Domain::Region {
1038 head: None,
1039 body: &[],
1040 tail: None,
1041 }));
1042
1043 assert!(matches!(
1044 Domain::<Const, usize, Lsb0>::default(),
1045 Domain::Region {
1046 head: None,
1047 body: &[],
1048 tail: None,
1049 },
1050 ));
1051
1052 let data = core::cell::Cell::new(0u8);
1053 let partial =
1054 data.view_bits::<Lsb0>()[2 .. 6].domain().enclave().unwrap();
1055 assert_eq!(partial.store_value_aliased(!0), 0);
1056 assert_eq!(data.get(), 0b00_1111_00);
1057 }
1058
1059 #[test]
1060 fn iter() {
1061 let bits = [0x12u8, 0x34, 0x56].view_bits::<Lsb0>();
1062 let mut domain = bits[4 .. 12].domain();
1063 assert_eq!(domain.len(), 2);
1064 assert_eq!(domain.next().unwrap(), 0x10);
1065 assert_eq!(domain.next_back().unwrap(), 0x04);
1066
1067 assert!(domain.next().is_none());
1068 assert!(domain.next_back().is_none());
1069
1070 assert_eq!(bits[2 .. 6].domain().len(), 1);
1071 assert_eq!(bits[18 .. 22].domain().next_back().unwrap(), 0b00_0101_00);
1072
1073 let mut domain = bits[4 .. 20].domain();
1074 assert_eq!(domain.next_back().unwrap(), 0x06);
1075 assert_eq!(domain.next_back().unwrap(), 0x34);
1076 assert_eq!(domain.next_back().unwrap(), 0x10);
1077 }
1078
1079 #[test]
1080 #[cfg(feature = "alloc")]
1081 fn render() {
1082 #[cfg(not(feature = "std"))]
1083 use alloc::format;
1084
1085 let data = BitArray::<u32, Msb0>::new(random());
1086
1087 let render = format!("{:?}", data.bit_domain());
1088 let expected = format!(
1089 "BitDomain::<*const u32, {}>::Region {{ head: {:?}, body: {:?}, \
1090 tail: {:?} }}",
1091 any::type_name::<Msb0>(),
1092 BitSlice::<u32, Msb0>::empty(),
1093 data.as_bitslice(),
1094 BitSlice::<u32, Msb0>::empty(),
1095 );
1096 assert_eq!(render, expected);
1097
1098 let render = format!("{:?}", data[2 .. 30].bit_domain());
1099 let expected = format!(
1100 "BitDomain::<*const u32, {}>::Enclave({:?})",
1101 any::type_name::<Msb0>(),
1102 &data[2 .. 30],
1103 );
1104 assert_eq!(render, expected);
1105
1106 let render = format!("{:?}", data.domain());
1107 let expected = format!(
1108 "Domain::<*const u32, {}>::Region {{ head: None, body: {:?}, tail: \
1109 None }}",
1110 any::type_name::<Msb0>(),
1111 data.as_raw_slice(),
1112 );
1113 assert_eq!(render, expected);
1114
1115 let render = format!("{:?}", data[2 .. 30].domain());
1116 let expected = format!(
1117 "Domain::<*const u32, {}>::Enclave",
1118 any::type_name::<Msb0>(),
1119 );
1120 assert!(render.starts_with(&expected));
1121
1122 let partial = 0x3Cu8.view_bits::<Lsb0>()[2 .. 6]
1123 .domain()
1124 .enclave()
1125 .unwrap();
1126 let render = format!("{:?}", partial);
1127 assert_eq!(
1128 render,
1129 format!(
1130 "PartialElement<*const u8, {}> {{ elem: 60, mask: {}, head: \
1131 {}, tail: {} }}",
1132 any::type_name::<Lsb0>(),
1133 partial.mask,
1134 partial.head,
1135 partial.tail,
1136 ),
1137 );
1138 }
1139}