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>
358where
359 M: Mutability,
360 T: 'a + BitStore,
361 O: BitOrder,
362 Address<M, T>: Referential<'a>,
363 Address<M, [T::Unalias]>:
364 SliceReferential<'a, ElementAddr = Address<M, T::Unalias>>,
365 Address<M, BitSlice<T, O>>: Referential<'a>,
366 Reference<'a, M, [T::Unalias]>: Default,
367{
368 pub(crate) fn new(bits: Reference<'a, M, BitSlice<T, O>>) -> Self
379 where BitSpan<M, T, O>: From<Reference<'a, M, BitSlice<T, O>>> {
380 let bitspan = bits.conv::<BitSpan<M, T, O>>();
381 let (head, elts, tail) =
382 (bitspan.head(), bitspan.elements(), bitspan.tail());
383 let base = bitspan.address();
384 let (min, max) = (BitIdx::<T::Mem>::MIN, BitEnd::<T::Mem>::MAX);
385 let ctor = match (head, elts, tail) {
386 (_, 0, _) => Self::empty,
387 (h, _, t) if h == min && t == max => Self::spanning,
388 (_, _, t) if t == max => Self::partial_head,
389 (h, ..) if h == min => Self::partial_tail,
390 (_, 1, _) => Self::minor,
391 _ => Self::major,
392 };
393 ctor(base, elts, head, tail)
394 }
395
396 #[inline]
398 fn empty(
399 _: Address<M, T>,
400 _: usize,
401 _: BitIdx<T::Mem>,
402 _: BitEnd<T::Mem>,
403 ) -> Self {
404 Default::default()
405 }
406
407 #[inline]
410 fn major(
411 addr: Address<M, T>,
412 elts: usize,
413 head: BitIdx<T::Mem>,
414 tail: BitEnd<T::Mem>,
415 ) -> Self {
416 let h_elem = addr;
417 let t_elem = unsafe { addr.add(elts - 1) };
418 let body = unsafe {
419 Address::<M, [T::Unalias]>::from_raw_parts(
420 addr.add(1).cast::<T::Unalias>(),
421 elts - 2,
422 )
423 };
424 Self::Region {
425 head: Some(PartialElement::new(h_elem, head, None)),
426 body,
427 tail: Some(PartialElement::new(t_elem, None, tail)),
428 }
429 }
430
431 #[inline]
433 fn minor(
434 addr: Address<M, T>,
435 _: usize,
436 head: BitIdx<T::Mem>,
437 tail: BitEnd<T::Mem>,
438 ) -> Self {
439 let elem = addr;
440 Self::Enclave(PartialElement::new(elem, head, tail))
441 }
442
443 #[inline]
446 fn partial_head(
447 addr: Address<M, T>,
448 elts: usize,
449 head: BitIdx<T::Mem>,
450 _: BitEnd<T::Mem>,
451 ) -> Self {
452 let elem = addr;
453 let body = unsafe {
454 Address::<M, [T::Unalias]>::from_raw_parts(
455 addr.add(1).cast::<T::Unalias>(),
456 elts - 1,
457 )
458 };
459 Self::Region {
460 head: Some(PartialElement::new(elem, head, None)),
461 body,
462 tail: None,
463 }
464 }
465
466 #[inline]
469 fn partial_tail(
470 addr: Address<M, T>,
471 elts: usize,
472 _: BitIdx<T::Mem>,
473 tail: BitEnd<T::Mem>,
474 ) -> Self {
475 let elem = unsafe { addr.add(elts - 1) };
476 let body = unsafe {
477 Address::<M, [T::Unalias]>::from_raw_parts(
478 addr.cast::<T::Unalias>(),
479 elts - 1,
480 )
481 };
482 Self::Region {
483 head: None,
484 body,
485 tail: Some(PartialElement::new(elem, None, tail)),
486 }
487 }
488
489 #[inline]
492 fn spanning(
493 addr: Address<M, T>,
494 elts: usize,
495 _: BitIdx<T::Mem>,
496 _: BitEnd<T::Mem>,
497 ) -> Self {
498 Self::Region {
499 head: None,
500 body: unsafe {
501 <Address<M, [T::Unalias]> as SliceReferential>::from_raw_parts(
502 addr.cast::<T::Unalias>(),
503 elts,
504 )
505 },
506 tail: None,
507 }
508 }
509}
510
511impl<'a, M, T, O> Default for Domain<'a, M, T, O>
512where
513 M: Mutability,
514 T: 'a + BitStore,
515 O: BitOrder,
516 Address<M, T>: Referential<'a>,
517 Address<M, [T::Unalias]>: SliceReferential<'a>,
518 Reference<'a, M, [T::Unalias]>: Default,
519{
520 #[inline]
521 fn default() -> Self {
522 Self::Region {
523 head: None,
524 body: Reference::<M, [T::Unalias]>::default(),
525 tail: None,
526 }
527 }
528}
529
530impl<'a, M, T, O> Debug for Domain<'a, M, T, O>
531where
532 M: Mutability,
533 T: 'a + BitStore,
534 O: BitOrder,
535 Address<M, T>: Referential<'a>,
536 Address<M, [T::Unalias]>: SliceReferential<'a>,
537 Reference<'a, M, [T::Unalias]>: Debug,
538{
539 #[inline]
540 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
541 write!(
542 fmt,
543 "Domain::<{} {}, {}>::",
544 M::RENDER,
545 any::type_name::<T>(),
546 any::type_name::<O>(),
547 )?;
548 match self {
549 Self::Enclave(elem) => {
550 fmt.debug_tuple("Enclave").field(elem).finish()
551 },
552 Self::Region { head, body, tail } => fmt
553 .debug_struct("Region")
554 .field("head", head)
555 .field("body", body)
556 .field("tail", tail)
557 .finish(),
558 }
559 }
560}
561
562#[cfg(not(tarpaulin_include))]
563impl<T, O> Clone for Domain<'_, Const, T, O>
564where
565 T: BitStore,
566 O: BitOrder,
567{
568 #[inline]
569 fn clone(&self) -> Self {
570 *self
571 }
572}
573
574impl<T, O> Iterator for Domain<'_, Const, T, O>
575where
576 T: BitStore,
577 O: BitOrder,
578{
579 type Item = T::Mem;
580
581 #[inline]
582 fn next(&mut self) -> Option<Self::Item> {
583 match self {
584 Self::Enclave(elem) => {
585 elem.load_value().tap(|_| *self = Default::default()).into()
586 },
587 Self::Region { head, body, tail } => {
588 if let Some(elem) = head.take() {
589 return elem.load_value().into();
590 }
591 if let Some((elem, rest)) = body.split_first() {
592 *body = rest;
593 return elem.load_value().into();
594 }
595 if let Some(elem) = tail.take() {
596 return elem.load_value().into();
597 }
598 None
599 },
600 }
601 }
602}
603
604impl<T, O> DoubleEndedIterator for Domain<'_, Const, T, O>
605where
606 T: BitStore,
607 O: BitOrder,
608{
609 #[inline]
610 fn next_back(&mut self) -> Option<Self::Item> {
611 match self {
612 Self::Enclave(elem) => {
613 elem.load_value().tap(|_| *self = Default::default()).into()
614 },
615 Self::Region { head, body, tail } => {
616 if let Some(elem) = tail.take() {
617 return elem.load_value().into();
618 }
619 if let Some((elem, rest)) = body.split_last() {
620 *body = rest;
621 return elem.load_value().into();
622 }
623 if let Some(elem) = head.take() {
624 return elem.load_value().into();
625 }
626 None
627 },
628 }
629 }
630}
631
632impl<T, O> ExactSizeIterator for Domain<'_, Const, T, O>
633where
634 T: BitStore,
635 O: BitOrder,
636{
637 #[inline]
638 fn len(&self) -> usize {
639 match self {
640 Self::Enclave(_) => 1,
641 Self::Region { head, body, tail } => {
642 head.is_some() as usize + body.len() + tail.is_some() as usize
643 },
644 }
645 }
646}
647
648impl<T, O> FusedIterator for Domain<'_, Const, T, O>
649where
650 T: BitStore,
651 O: BitOrder,
652{
653}
654
655impl<T, O> Copy for Domain<'_, Const, T, O>
656where
657 T: BitStore,
658 O: BitOrder,
659{
660}
661
662macro_rules! fmt {
664 ($($fmt:ty => $fwd:ident),+ $(,)?) => { $(
665 impl<'a, T, O> $fmt for Domain<'a, Const, T, O>
666 where
667 O: BitOrder,
668 T: BitStore,
669 {
670 #[inline]
671 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
672 fmt.debug_list()
673 .entries(self.into_iter().map(FmtForward::$fwd))
674 .finish()
675 }
676 }
677 )+ };
678}
679
680fmt! {
681 Binary => fmt_binary,
682 Display => fmt_display,
683 LowerHex => fmt_lower_hex,
684 Octal => fmt_octal,
685 UpperHex => fmt_upper_hex,
686}
687
688#[doc = include_str!("../doc/domain/PartialElement.md")]
689pub struct PartialElement<'a, M, T, O>
690where
691 M: Mutability,
692 T: 'a + BitStore,
693 O: BitOrder,
694{
695 elem: Address<M, T>,
705 mask: BitMask<T::Mem>,
707 head: BitIdx<T::Mem>,
709 tail: BitEnd<T::Mem>,
711 _ord: PhantomData<O>,
713 _ref: PhantomData<&'a T::Access>,
715}
716
717impl<'a, M, T, O> PartialElement<'a, M, T, O>
718where
719 M: Mutability,
720 T: 'a + BitStore,
721 O: BitOrder,
722{
723 #[inline]
731 fn new(
732 elem: Address<M, T>,
733 head: impl Into<Option<BitIdx<T::Mem>>>,
734 tail: impl Into<Option<BitEnd<T::Mem>>>,
735 ) -> Self {
736 let (head, tail) = (
737 head.into().unwrap_or(BitIdx::MIN),
738 tail.into().unwrap_or(BitEnd::MAX),
739 );
740 Self {
741 elem,
742 mask: O::mask(head, tail),
743 head,
744 tail,
745 _ord: PhantomData,
746 _ref: PhantomData,
747 }
748 }
749
750 #[inline]
757 pub fn load_value(&self) -> T::Mem {
758 self.elem
759 .pipe(|addr| unsafe { &*addr.to_const() })
760 .load_value()
761 & self.mask.into_inner()
762 }
763
764 #[inline]
766 #[cfg(not(tarpaulin_include))]
767 pub fn head(&self) -> BitIdx<T::Mem> {
768 self.head
769 }
770
771 #[inline]
773 #[cfg(not(tarpaulin_include))]
774 pub fn tail(&self) -> BitEnd<T::Mem> {
775 self.tail
776 }
777
778 #[inline]
781 #[cfg(not(tarpaulin_include))]
782 pub fn bounds(&self) -> (BitIdx<T::Mem>, BitEnd<T::Mem>) {
783 (self.head, self.tail)
784 }
785
786 #[inline]
788 #[cfg(not(tarpaulin_include))]
789 pub fn mask(&self) -> BitMask<T::Mem> {
790 self.mask
791 }
792
793 #[inline]
795 pub fn into_bitslice(self) -> Reference<'a, M, BitSlice<T, O>>
796 where Address<M, BitSlice<T, O>>: Referential<'a> {
797 unsafe {
798 BitSpan::new_unchecked(
799 self.elem,
800 self.head,
801 (self.tail.into_inner() - self.head.into_inner()) as usize,
802 )
803 }
804 .to_bitslice()
805 }
806}
807
808impl<'a, T, O> PartialElement<'a, Mut, T, O>
809where
810 T: BitStore,
811 O: BitOrder,
812 Address<Mut, T>: Referential<'a>,
813{
814 #[inline]
828 pub fn store_value(&mut self, value: T::Mem) -> T::Mem {
829 let this = self.access();
830 let prev = this.clear_bits(self.mask);
831 this.set_bits(self.mask & value);
832 prev & self.mask.into_inner()
833 }
834
835 #[inline]
841 #[cfg(not(tarpaulin_include))]
842 pub fn invert(&mut self) -> T::Mem {
843 self.access().invert_bits(self.mask) & self.mask.into_inner()
844 }
845
846 #[inline]
852 #[cfg(not(tarpaulin_include))]
853 pub fn clear(&mut self) -> T::Mem {
854 self.access().clear_bits(self.mask) & self.mask.into_inner()
855 }
856
857 #[inline]
863 #[cfg(not(tarpaulin_include))]
864 pub fn set(&mut self) -> T::Mem {
865 self.access().set_bits(self.mask) & self.mask.into_inner()
866 }
867
868 #[inline]
871 fn access(&self) -> &T::Access {
872 unsafe { &*self.elem.to_const().cast::<T::Access>() }
873 }
874}
875
876impl<'a, M, T, O> PartialElement<'a, M, T, O>
877where
878 M: Mutability,
879 O: BitOrder,
880 T: 'a + BitStore + radium::Radium,
881{
882 #[inline]
885 pub fn store_value_aliased(&self, value: T::Mem) -> T::Mem {
886 let this = unsafe { &*self.elem.to_const().cast::<T::Access>() };
887 let prev = this.clear_bits(self.mask);
888 this.set_bits(self.mask & value);
889 prev & self.mask.into_inner()
890 }
891}
892
893#[cfg(not(tarpaulin_include))]
894impl<'a, T, O> Clone for PartialElement<'a, Const, T, O>
895where
896 T: BitStore,
897 O: BitOrder,
898 Address<Const, T>: Referential<'a>,
899{
900 #[inline]
901 fn clone(&self) -> Self {
902 *self
903 }
904}
905
906impl<'a, M, T, O> Debug for PartialElement<'a, M, T, O>
907where
908 M: Mutability,
909 T: 'a + BitStore,
910 O: BitOrder,
911{
912 #[inline]
913 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
914 write!(
915 fmt,
916 "PartialElement<{} {}, {}>",
917 M::RENDER,
918 any::type_name::<T>(),
919 any::type_name::<O>(),
920 )?;
921 fmt.debug_struct("")
922 .field("elem", &self.load_value())
923 .field("mask", &self.mask.fmt_display())
924 .field("head", &self.head.fmt_display())
925 .field("tail", &self.tail.fmt_display())
926 .finish()
927 }
928}
929
930#[cfg(not(tarpaulin_include))]
931impl<'a, M, T, O> Hash for PartialElement<'a, M, T, O>
932where
933 M: Mutability,
934 T: 'a + BitStore,
935 O: BitOrder,
936{
937 #[inline]
938 fn hash<H>(&self, hasher: &mut H)
939 where H: Hasher {
940 self.load_value().hash(hasher);
941 self.mask.hash(hasher);
942 self.head.hash(hasher);
943 self.tail.hash(hasher);
944 }
945}
946
947impl<T, O> Copy for PartialElement<'_, Const, T, O>
948where
949 T: BitStore,
950 O: BitOrder,
951{
952}
953
954#[cfg(test)]
955mod tests {
956 use rand::random;
957
958 use super::*;
959 use crate::prelude::*;
960
961 #[test]
962 fn bit_domain() {
963 let data = BitArray::<[u32; 3], Msb0>::new(random());
964
965 let bd = data.bit_domain();
966 assert!(bd.enclave().is_none());
967 let (head, body, tail) = bd.region().unwrap();
968 assert_eq!(data, body);
969 assert!(head.is_empty());
970 assert!(tail.is_empty());
971
972 let bd = data[2 ..].bit_domain();
973 let (head, body, tail) = bd.region().unwrap();
974 assert_eq!(head, &data[2 .. 32]);
975 assert_eq!(body, &data[32 ..]);
976 assert!(tail.is_empty());
977
978 let bd = data[.. 94].bit_domain();
979 let (head, body, tail) = bd.region().unwrap();
980 assert!(head.is_empty());
981 assert_eq!(body, &data[.. 64]);
982 assert_eq!(tail, &data[64 .. 94]);
983
984 let bd = data[2 .. 94].bit_domain();
985 let (head, body, tail) = bd.region().unwrap();
986 assert_eq!(head, &data[2 .. 32]);
987 assert_eq!(body, &data[32 .. 64]);
988 assert_eq!(tail, &data[64 .. 94]);
989
990 let bd = data[34 .. 62].bit_domain();
991 assert!(bd.region().is_none());
992 assert_eq!(bd.enclave().unwrap(), data[34 .. 62]);
993
994 let (head, body, tail) =
995 BitDomain::<Const, usize, Lsb0>::default().region().unwrap();
996 assert!(head.is_empty());
997 assert!(body.is_empty());
998 assert!(tail.is_empty());
999 }
1000
1001 #[test]
1002 fn domain() {
1003 let data: [u32; 3] = random();
1004 let bits = data.view_bits::<Msb0>();
1005
1006 let d = bits.domain();
1007 assert!(d.enclave().is_none());
1008 let (head, body, tail) = d.region().unwrap();
1009 assert!(head.is_none());
1010 assert!(tail.is_none());
1011 assert_eq!(body, data);
1012
1013 let d = bits[2 ..].domain();
1014 let (head, body, tail) = d.region().unwrap();
1015 assert_eq!(head.unwrap().load_value(), (data[0] << 2) >> 2);
1016 assert_eq!(body, &data[1 ..]);
1017 assert!(tail.is_none());
1018
1019 let d = bits[.. 94].domain();
1020 let (head, body, tail) = d.region().unwrap();
1021 assert!(head.is_none());
1022 assert_eq!(body, &data[.. 2]);
1023 assert_eq!(tail.unwrap().load_value(), (data[2] >> 2) << 2);
1024
1025 let d = bits[2 .. 94].domain();
1026 let (head, body, tail) = d.region().unwrap();
1027 assert_eq!(head.unwrap().load_value(), (data[0] << 2) >> 2);
1028 assert_eq!(body, &data[1 .. 2]);
1029 assert_eq!(tail.unwrap().load_value(), (data[2] >> 2) << 2);
1030
1031 let d = bits[34 .. 62].domain();
1032 assert!(d.region().is_none());
1033 assert_eq!(
1034 d.enclave().unwrap().load_value(),
1035 ((data[1] << 2) >> 4) << 2,
1036 );
1037
1038 assert!(matches!(bits![].domain(), Domain::Region {
1039 head: None,
1040 body: &[],
1041 tail: None,
1042 }));
1043
1044 assert!(matches!(
1045 Domain::<Const, usize, Lsb0>::default(),
1046 Domain::Region {
1047 head: None,
1048 body: &[],
1049 tail: None,
1050 },
1051 ));
1052
1053 let data = core::cell::Cell::new(0u8);
1054 let partial =
1055 data.view_bits::<Lsb0>()[2 .. 6].domain().enclave().unwrap();
1056 assert_eq!(partial.store_value_aliased(!0), 0);
1057 assert_eq!(data.get(), 0b00_1111_00);
1058 }
1059
1060 #[test]
1061 fn iter() {
1062 let bits = [0x12u8, 0x34, 0x56].view_bits::<Lsb0>();
1063 let mut domain = bits[4 .. 12].domain();
1064 assert_eq!(domain.len(), 2);
1065 assert_eq!(domain.next().unwrap(), 0x10);
1066 assert_eq!(domain.next_back().unwrap(), 0x04);
1067
1068 assert!(domain.next().is_none());
1069 assert!(domain.next_back().is_none());
1070
1071 assert_eq!(bits[2 .. 6].domain().len(), 1);
1072 assert_eq!(bits[18 .. 22].domain().next_back().unwrap(), 0b00_0101_00);
1073
1074 let mut domain = bits[4 .. 20].domain();
1075 assert_eq!(domain.next_back().unwrap(), 0x06);
1076 assert_eq!(domain.next_back().unwrap(), 0x34);
1077 assert_eq!(domain.next_back().unwrap(), 0x10);
1078 }
1079
1080 #[test]
1081 #[cfg(feature = "alloc")]
1082 fn render() {
1083 #[cfg(not(feature = "std"))]
1084 use alloc::format;
1085
1086 let data = BitArray::<u32, Msb0>::new(random());
1087
1088 let render = format!("{:?}", data.bit_domain());
1089 let expected = format!(
1090 "BitDomain::<*const u32, {}>::Region {{ head: {:?}, body: {:?}, \
1091 tail: {:?} }}",
1092 any::type_name::<Msb0>(),
1093 BitSlice::<u32, Msb0>::empty(),
1094 data.as_bitslice(),
1095 BitSlice::<u32, Msb0>::empty(),
1096 );
1097 assert_eq!(render, expected);
1098
1099 let render = format!("{:?}", data[2 .. 30].bit_domain());
1100 let expected = format!(
1101 "BitDomain::<*const u32, {}>::Enclave({:?})",
1102 any::type_name::<Msb0>(),
1103 &data[2 .. 30],
1104 );
1105 assert_eq!(render, expected);
1106
1107 let render = format!("{:?}", data.domain());
1108 let expected = format!(
1109 "Domain::<*const u32, {}>::Region {{ head: None, body: {:?}, tail: \
1110 None }}",
1111 any::type_name::<Msb0>(),
1112 data.as_raw_slice(),
1113 );
1114 assert_eq!(render, expected);
1115
1116 let render = format!("{:?}", data[2 .. 30].domain());
1117 let expected = format!(
1118 "Domain::<*const u32, {}>::Enclave",
1119 any::type_name::<Msb0>(),
1120 );
1121 assert!(render.starts_with(&expected));
1122
1123 let partial = 0x3Cu8.view_bits::<Lsb0>()[2 .. 6]
1124 .domain()
1125 .enclave()
1126 .unwrap();
1127 let render = format!("{:?}", partial);
1128 assert_eq!(
1129 render,
1130 format!(
1131 "PartialElement<*const u8, {}> {{ elem: 60, mask: {}, head: \
1132 {}, tail: {} }}",
1133 any::type_name::<Lsb0>(),
1134 partial.mask,
1135 partial.head,
1136 partial.tail,
1137 ),
1138 );
1139 }
1140}