1#![doc = include_str!("../../doc/ptr/span.md")]
2
3use core::{
4 any,
5 fmt::{
6 self,
7 Binary,
8 Debug,
9 Display,
10 Formatter,
11 Pointer,
12 },
13 marker::PhantomData,
14 mem,
15 ptr::{
16 self,
17 NonNull,
18 },
19};
20
21use tap::Pipe;
22use wyz::{
23 comu::{
24 Address,
25 Const,
26 Mut,
27 Mutability,
28 NullPtrError,
29 Reference,
30 Referential,
31 },
32 fmt::FmtForward,
33};
34
35use super::{
36 BitPtr,
37 BitPtrError,
38 BitPtrRange,
39 MisalignError,
40};
41use crate::{
42 index::{
43 BitEnd,
44 BitIdx,
45 },
46 mem::{
47 bits_of,
48 BitRegister,
49 },
50 order::{
51 BitOrder,
52 Lsb0,
53 },
54 slice::BitSlice,
55 store::BitStore,
56};
57
58#[doc = include_str!("../../doc/ptr/BitSpan.md")]
59pub(crate) struct BitSpan<M = Const, T = usize, O = Lsb0>
60where
61 M: Mutability,
62 T: BitStore,
63 O: BitOrder,
64{
65 ptr: NonNull<()>,
67 len: usize,
71 _or: PhantomData<O>,
73 _ty: PhantomData<Address<M, [T]>>,
75}
76
77impl<M, T, O> BitSpan<M, T, O>
78where
79 M: Mutability,
80 T: BitStore,
81 O: BitOrder,
82{
83 pub(crate) const EMPTY: Self = Self {
85 ptr: NonNull::<T>::dangling().cast::<()>(),
86 len: 0,
87 _or: PhantomData,
88 _ty: PhantomData,
89 };
90 pub(crate) const LEN_HEAD_BITS: usize = 3;
96 pub(crate) const LEN_HEAD_MASK: usize = 0b111;
98 pub(crate) const PTR_ADDR_MASK: usize = !0 << Self::PTR_HEAD_BITS;
100 pub(crate) const PTR_HEAD_BITS: usize =
103 <T::Mem as BitRegister>::INDX as usize - Self::LEN_HEAD_BITS;
104 pub(crate) const PTR_HEAD_MASK: usize = !Self::PTR_ADDR_MASK;
106 pub(crate) const REGION_MAX_BITS: usize = !0 >> Self::LEN_HEAD_BITS;
110 pub(crate) const REGION_MAX_ELTS: usize =
121 crate::mem::elts::<T::Mem>(Self::REGION_MAX_BITS) + 1;
122}
123
124impl<M, T, O> BitSpan<M, T, O>
126where
127 M: Mutability,
128 T: BitStore,
129 O: BitOrder,
130{
131 #[cfg(feature = "alloc")]
145 pub(crate) fn uninhabited(addr: Address<M, T>) -> Self {
146 Self {
147 ptr: addr.into_inner().cast::<()>(),
148 ..Self::EMPTY
149 }
150 }
151
152 pub(crate) fn new(
171 addr: Address<M, T>,
172 head: BitIdx<T::Mem>,
173 bits: usize,
174 ) -> Result<Self, BitSpanError<T>> {
175 if bits > Self::REGION_MAX_BITS {
176 return Err(BitSpanError::TooLong(bits));
177 }
178 let base = BitPtr::<M, T, O>::new(addr, head)?;
179 let last = base.wrapping_add(bits);
180 if last < base {
181 return Err(BitSpanError::TooHigh(addr.to_const()));
182 }
183
184 Ok(unsafe { Self::new_unchecked(addr, head, bits) })
185 }
186
187 pub(crate) unsafe fn new_unchecked(
201 addr: Address<M, T>,
202 head: BitIdx<T::Mem>,
203 bits: usize,
204 ) -> Self {
205 let addr = addr.to_const().cast::<u8>();
206
207 let head = head.into_inner() as usize;
208 let ptr_data = addr as usize & Self::PTR_ADDR_MASK;
209 let ptr_head = head >> Self::LEN_HEAD_BITS;
210
211 let len_head = head & Self::LEN_HEAD_MASK;
212 let len_bits = bits << Self::LEN_HEAD_BITS;
213
214 let ptr_raw = ptr_data | ptr_head;
223 let ptr = addr.wrapping_add(ptr_raw.wrapping_sub(addr as usize));
224
225 Self {
226 ptr: NonNull::new_unchecked(ptr.cast::<()>() as *mut ()),
227 len: len_bits | len_head,
228 ..Self::EMPTY
229 }
230 }
231}
232
233impl<M, T, O> BitSpan<M, T, O>
235where
236 M: Mutability,
237 T: BitStore,
238 O: BitOrder,
239{
240 pub(crate) fn address(&self) -> Address<M, T> {
252 let ptr = self.ptr.as_ptr().cast::<u8>();
253 let addr = ptr as usize;
254 let ptr = ptr
255 .wrapping_add(addr & Self::PTR_ADDR_MASK)
256 .wrapping_sub(addr)
257 .cast::<T>();
258 Address::new(unsafe { NonNull::new_unchecked(ptr) })
259 }
260
261 #[cfg(feature = "alloc")]
275 pub(crate) unsafe fn set_address(&mut self, addr: Address<M, T>) {
276 let mut addr_value = addr.to_const() as usize;
277 addr_value &= Self::PTR_ADDR_MASK;
278 addr_value |= self.ptr.as_ptr() as usize & Self::PTR_HEAD_MASK;
279 self.ptr = NonNull::new_unchecked(addr_value as *mut ())
280 }
281
282 pub(crate) fn head(&self) -> BitIdx<T::Mem> {
296 let ptr = self.ptr.as_ptr() as usize;
297 let ptr_head = (ptr & Self::PTR_HEAD_MASK) << Self::LEN_HEAD_BITS;
298 let len_head = self.len & Self::LEN_HEAD_MASK;
299 unsafe { BitIdx::new_unchecked((ptr_head | len_head) as u8) }
300 }
301
302 #[cfg(feature = "alloc")]
314 pub(crate) unsafe fn set_head(&mut self, head: BitIdx<T::Mem>) {
315 let head = head.into_inner() as usize;
316 let mut ptr = self.ptr.as_ptr() as usize;
317
318 ptr &= Self::PTR_ADDR_MASK;
319 ptr |= head >> Self::LEN_HEAD_BITS;
320 self.ptr = NonNull::new_unchecked(ptr as *mut ());
321
322 self.len &= !Self::LEN_HEAD_MASK;
323 self.len |= head & Self::LEN_HEAD_MASK;
324 }
325
326 pub(crate) fn len(&self) -> usize {
336 self.len >> Self::LEN_HEAD_BITS
337 }
338
339 pub(crate) unsafe fn set_len(&mut self, new_len: usize) {
353 if cfg!(debug_assertions) {
354 *self = Self::new(self.address(), self.head(), new_len).unwrap();
355 }
356 else {
357 self.len &= Self::LEN_HEAD_MASK;
358 self.len |= new_len << Self::LEN_HEAD_BITS;
359 }
360 }
361
362 pub(crate) fn raw_parts(&self) -> (Address<M, T>, BitIdx<T::Mem>, usize) {
378 (self.address(), self.head(), self.len())
379 }
380}
381
382impl<M, T, O> BitSpan<M, T, O>
384where
385 M: Mutability,
386 T: BitStore,
387 O: BitOrder,
388{
389 pub(crate) fn elements(&self) -> usize {
403 crate::mem::elts::<T>(self.len() + self.head().into_inner() as usize)
404 }
405
406 pub(crate) fn tail(&self) -> BitEnd<T::Mem> {
420 let (head, len) = (self.head(), self.len());
421 let (_, tail) = head.span(len);
422 tail
423 }
424}
425
426impl<M, T, O> BitSpan<M, T, O>
428where
429 M: Mutability,
430 T: BitStore,
431 O: BitOrder,
432{
433 pub(crate) fn cast<U>(self) -> BitSpan<M, U, O>
439 where U: BitStore {
440 let Self { ptr, len, .. } = self;
441 BitSpan {
442 ptr,
443 len,
444 ..BitSpan::EMPTY
445 }
446 }
447
448 pub(crate) unsafe fn align_to<U>(self) -> (Self, BitSpan<M, U, O>, Self)
459 where U: BitStore {
460 let this = self.to_bitptr();
467 let mut rem = self.len();
469 let align = mem::align_of::<U>();
471 let step = this.align_offset(align);
474 if step > rem {
476 return (self, BitSpan::EMPTY, Self::EMPTY);
477 }
478 let left = this.span_unchecked(step);
479 rem -= step;
480
481 let mid_base =
482 this.add(step).address().cast::<U>().pipe(|addr| {
483 BitPtr::<M, U, O>::new_unchecked(addr, BitIdx::MIN)
484 });
485 let mid_elts = rem >> <U::Mem as BitRegister>::INDX;
486 let excess = rem & <U::Mem as BitRegister>::MASK as usize;
487 let step = rem - excess;
488 let mid = mid_base.span_unchecked(step);
489
490 let right_base =
491 mid_base.address().add(mid_elts).cast::<T>().pipe(|addr| {
492 BitPtr::<M, T, O>::new_unchecked(addr, BitIdx::MIN)
493 });
494 let right = right_base.span_unchecked(excess);
495
496 (left, mid, right)
497 }
498
499 pub(crate) fn from_bitslice_ptr_mut(raw: *mut BitSlice<T, O>) -> Self {
501 let BitSpan { ptr, len, .. } =
502 BitSpan::from_bitslice_ptr(raw as *const BitSlice<T, O>);
503 Self {
504 ptr,
505 len,
506 ..Self::EMPTY
507 }
508 }
509
510 pub(crate) fn into_bitslice_ptr(self) -> *const BitSlice<T, O> {
514 let Self { ptr, len, .. } = self;
515 ptr::slice_from_raw_parts(ptr.as_ptr(), len) as *const BitSlice<T, O>
516 }
517
518 pub(crate) unsafe fn into_bitslice_ref<'a>(self) -> &'a BitSlice<T, O> {
527 &*self.into_bitslice_ptr()
528 }
529
530 pub(crate) fn to_bitptr(self) -> BitPtr<M, T, O> {
535 unsafe { BitPtr::new_unchecked(self.address(), self.head()) }
536 }
537
538 pub(crate) fn to_bitptr_range(self) -> BitPtrRange<M, T, O> {
543 let start = self.to_bitptr();
544 let end = unsafe { start.add(self.len()) };
545 BitPtrRange { start, end }
546 }
547
548 pub(crate) fn to_bitslice_addr(self) -> Address<M, BitSlice<T, O>> {
552 (self.into_bitslice_ptr() as *mut BitSlice<T, O>)
553 .pipe(|ptr| unsafe { NonNull::new_unchecked(ptr) })
554 .pipe(Address::new)
555 }
556
557 pub(crate) fn to_bitslice<'a>(self) -> Reference<'a, M, BitSlice<T, O>>
561 where Address<M, BitSlice<T, O>>: Referential<'a> {
562 unsafe { self.to_bitslice_addr().to_ref() }
563 }
564}
565
566impl<T, O> BitSpan<Const, T, O>
568where
569 T: BitStore,
570 O: BitOrder,
571{
572 pub(crate) fn from_bitslice_ptr(raw: *const BitSlice<T, O>) -> Self {
574 let slice_nn = match NonNull::new(raw as *const [()] as *mut [()]) {
575 Some(nn) => nn,
576 None => return Self::EMPTY,
577 };
578 let ptr = slice_nn.cast::<()>();
579 let len = unsafe { slice_nn.as_ref() }.len();
580 Self {
581 ptr,
582 len,
583 ..Self::EMPTY
584 }
585 }
586}
587
588impl<T, O> BitSpan<Mut, T, O>
590where
591 T: BitStore,
592 O: BitOrder,
593{
594 pub(crate) fn into_bitslice_ptr_mut(self) -> *mut BitSlice<T, O> {
598 self.into_bitslice_ptr() as *mut BitSlice<T, O>
599 }
600
601 pub(crate) unsafe fn into_bitslice_mut<'a>(self) -> &'a mut BitSlice<T, O> {
610 &mut *self.into_bitslice_ptr_mut()
611 }
612}
613
614impl<M, T, O> BitSpan<M, T, O>
616where
617 M: Mutability,
618 T: BitStore,
619 O: BitOrder,
620{
621 #[cfg(feature = "alloc")]
625 pub(crate) fn len_encodable(len: usize) -> bool {
626 len <= Self::REGION_MAX_BITS
627 }
628
629 pub(crate) fn render<'a>(
659 &'a self,
660 fmt: &'a mut Formatter,
661 name: &'a str,
662 fields: impl IntoIterator<Item = &'a (&'a str, &'a dyn Debug)>,
663 ) -> fmt::Result {
664 write!(
665 fmt,
666 "Bit{}<{}, {}>",
667 name,
668 any::type_name::<T::Mem>(),
669 any::type_name::<O>(),
670 )?;
671 let mut builder = fmt.debug_struct("");
672 builder
673 .field("addr", &self.address().fmt_pointer())
674 .field("head", &self.head().fmt_binary())
675 .field("bits", &self.len());
676 for (name, value) in fields {
677 builder.field(name, value);
678 }
679 builder.finish()
680 }
681}
682
683#[cfg(not(tarpaulin_include))]
684impl<M, T, O> Clone for BitSpan<M, T, O>
685where
686 M: Mutability,
687 T: BitStore,
688 O: BitOrder,
689{
690 #[inline]
691 fn clone(&self) -> Self {
692 *self
693 }
694}
695
696impl<M1, M2, O, T1, T2> PartialEq<BitSpan<M2, T2, O>> for BitSpan<M1, T1, O>
697where
698 M1: Mutability,
699 M2: Mutability,
700 O: BitOrder,
701 T1: BitStore,
702 T2: BitStore,
703{
704 #[inline]
705 fn eq(&self, other: &BitSpan<M2, T2, O>) -> bool {
706 let (addr_a, head_a, bits_a) = self.raw_parts();
707 let (addr_b, head_b, bits_b) = other.raw_parts();
708 bits_of::<T1::Mem>() == bits_of::<T2::Mem>()
709 && addr_a.to_const() as usize == addr_b.to_const() as usize
710 && head_a.into_inner() == head_b.into_inner()
711 && bits_a == bits_b
712 }
713}
714
715impl<T, O> From<&BitSlice<T, O>> for BitSpan<Const, T, O>
716where
717 T: BitStore,
718 O: BitOrder,
719{
720 #[inline]
721 fn from(bits: &BitSlice<T, O>) -> Self {
722 Self::from_bitslice_ptr(bits)
723 }
724}
725
726impl<T, O> From<&mut BitSlice<T, O>> for BitSpan<Mut, T, O>
727where
728 T: BitStore,
729 O: BitOrder,
730{
731 #[inline]
732 fn from(bits: &mut BitSlice<T, O>) -> Self {
733 Self::from_bitslice_ptr_mut(bits)
734 }
735}
736
737#[cfg(not(tarpaulin_include))]
738impl<M, T, O> Default for BitSpan<M, T, O>
739where
740 M: Mutability,
741 T: BitStore,
742 O: BitOrder,
743{
744 #[inline]
745 fn default() -> Self {
746 Self::EMPTY
747 }
748}
749
750impl<M, T, O> Debug for BitSpan<M, T, O>
751where
752 M: Mutability,
753 T: BitStore,
754 O: BitOrder,
755{
756 #[inline]
757 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
758 self.render(fmt, "Span", None)
759 }
760}
761
762impl<M, T, O> Pointer for BitSpan<M, T, O>
763where
764 M: Mutability,
765 T: BitStore,
766 O: BitOrder,
767{
768 #[inline]
769 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
770 Pointer::fmt(&self.address(), fmt)?;
771 fmt.write_str("(")?;
772 Binary::fmt(&self.head(), fmt)?;
773 fmt.write_str(")[")?;
774 Display::fmt(&self.len(), fmt)?;
775 fmt.write_str("]")
776 }
777}
778
779impl<M, T, O> Copy for BitSpan<M, T, O>
780where
781 M: Mutability,
782 T: BitStore,
783 O: BitOrder,
784{
785}
786
787#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
789pub enum BitSpanError<T>
790where T: BitStore
791{
792 Null(NullPtrError),
794 Misaligned(MisalignError<T>),
796 TooLong(usize),
798 TooHigh(*const T),
800}
801
802#[cfg(not(tarpaulin_include))]
803impl<T> From<BitPtrError<T>> for BitSpanError<T>
804where T: BitStore
805{
806 #[inline]
807 fn from(err: BitPtrError<T>) -> Self {
808 match err {
809 BitPtrError::Null(err) => Self::Null(err),
810 BitPtrError::Misaligned(err) => Self::Misaligned(err),
811 }
812 }
813}
814
815#[cfg(not(tarpaulin_include))]
816impl<T> From<MisalignError<T>> for BitSpanError<T>
817where T: BitStore
818{
819 #[inline]
820 fn from(err: MisalignError<T>) -> Self {
821 Self::Misaligned(err)
822 }
823}
824
825#[cfg(not(tarpaulin_include))]
826impl<T> Debug for BitSpanError<T>
827where T: BitStore
828{
829 #[inline]
830 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
831 write!(fmt, "BitSpanError<{}>::", any::type_name::<T::Mem>())?;
832 match self {
833 Self::Null(err) => fmt.debug_tuple("Null").field(&err).finish(),
834 Self::Misaligned(err) => {
835 fmt.debug_tuple("Misaligned").field(&err).finish()
836 },
837 Self::TooLong(len) => fmt.debug_tuple("TooLong").field(len).finish(),
838 Self::TooHigh(addr) => {
839 fmt.debug_tuple("TooHigh").field(addr).finish()
840 },
841 }
842 }
843}
844
845#[cfg(not(tarpaulin_include))]
846impl<T> Display for BitSpanError<T>
847where T: BitStore
848{
849 #[inline]
850 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
851 match self {
852 Self::Null(err) => Display::fmt(err, fmt),
853 Self::Misaligned(err) => Display::fmt(err, fmt),
854 Self::TooLong(len) => write!(
855 fmt,
856 "Length {} is too long to encode in a bit-slice, which can \
857 only accept {} bits",
858 len,
859 BitSpan::<Const, T, Lsb0>::REGION_MAX_BITS,
860 ),
861 Self::TooHigh(addr) => write!(
862 fmt,
863 "Address {:p} is too high, and produces a span that wraps \
864 around to the zero address.",
865 addr,
866 ),
867 }
868 }
869}
870
871unsafe impl<T> Send for BitSpanError<T> where T: BitStore {}
872
873unsafe impl<T> Sync for BitSpanError<T> where T: BitStore {}
874
875#[cfg(feature = "std")]
876impl<T> std::error::Error for BitSpanError<T> where T: BitStore {}