diff --git a/src/slice/api.rs b/src/slice/api.rs index e19d0389..479a5dd0 100644 --- a/src/slice/api.rs +++ b/src/slice/api.rs @@ -46,6 +46,7 @@ use crate::{ use core::{ cmp, + marker::PhantomData, ops::{ Range, RangeFrom, @@ -54,6 +55,7 @@ use core::{ RangeTo, RangeToInclusive, }, + ptr::NonNull, slice, }; @@ -2252,9 +2254,14 @@ where O: 'a + BitOrder, T: 'a + BitStore { self, slice: &'a mut BitSlice, ) -> Self::Mut { + let bp = slice.bitptr(); + let (offset, head) = bp.head().offset(self as isize); + let ptr = bp.pointer().a().offset(offset); BitMut { - data: *slice.get_unchecked(self), - slot: slice.get_unchecked_mut(self ..= self), + _parent: PhantomData, + data: NonNull::new_unchecked(ptr as *mut T::Access), + head, + bit: (*ptr).get::(head) } } diff --git a/src/slice/proxy.rs b/src/slice/proxy.rs index de9535c2..c41a09aa 100644 --- a/src/slice/proxy.rs +++ b/src/slice/proxy.rs @@ -16,14 +16,20 @@ used in the `&mut` write reference system, as a good-enough substitute. !*/ use crate::{ + access::BitAccess, + indices::BitIdx, order::BitOrder, slice::BitSlice, store::BitStore, }; -use core::ops::{ - Deref, - DerefMut, +use core::{ + marker::PhantomData, + ops::{ + Deref, + DerefMut, + }, + ptr::NonNull, }; /** Proxy referential type, equivalent to `&mut bool`. @@ -41,10 +47,14 @@ reference-like type is as close as Rust will allow. **/ pub struct BitMut<'a, O, T> where O: BitOrder, T: 'a + BitStore { - /// A reference to a single bit in memory. - pub(super) slot: &'a mut BitSlice, + /// Inform the compiler that this has an exclusive borrow of a `BitSlice` + pub(super) _parent: PhantomData<&'a mut BitSlice>, + /// Typed pointer to the memory element containing the proxied bit. + pub(super) data: NonNull, + /// Index of the proxied bit inside the targeted memory element. + pub(super) head: BitIdx, /// A local cache for `Deref` usage. - pub(super) data: bool, + pub(super) bit: bool, } impl Deref for BitMut<'_, O, T> @@ -52,20 +62,20 @@ where O: BitOrder, T: BitStore { type Target = bool; fn deref(&self) -> &Self::Target { - &self.data + &self.bit } } impl DerefMut for BitMut<'_, O, T> where O: BitOrder, T: BitStore { fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.data + &mut self.bit } } impl Drop for BitMut<'_, O, T> where O: BitOrder, T: BitStore { fn drop(&mut self) { - unsafe { self.slot.set_unchecked(0, self.data) } + unsafe { (*self.data.as_ptr()).set::(self.head, self.bit) } } }