Skip to content

Commit b9e0607

Browse files
committed
WIP: owned with borrow
1 parent 3399264 commit b9e0607

File tree

2 files changed

+70
-75
lines changed

2 files changed

+70
-75
lines changed

src/lib.rs

+56-64
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#![warn(missing_docs)]
2222
#![deny(unsafe_op_in_unsafe_fn)]
2323

24-
use access::{Access, ReadOnly, ReadWrite, WriteOnly};
24+
use access::{Access, NoAccess, ReadOnly, ReadWrite, WriteOnly};
2525
use core::{
2626
fmt,
2727
marker::PhantomData,
@@ -348,10 +348,20 @@ where
348348
}
349349

350350
/// Transformation methods for accessing struct fields
351-
impl<T, R, W> VolatilePtr<'_, T, Access<R, W>>
351+
impl<'a, T, R, W> VolatilePtr<'a, T, Access<R, W>>
352352
where
353353
T: ?Sized,
354354
{
355+
// TODO: Add documentation
356+
pub fn borrow(&self) -> VolatilePtr<T, Access<R, NoAccess>> {
357+
unsafe { VolatilePtr::new_generic(self.pointer) }
358+
}
359+
360+
// TODO: Add documentation
361+
pub fn borrow_mut(&mut self) -> VolatilePtr<T, Access<R, W>> {
362+
unsafe { VolatilePtr::new_generic(self.pointer) }
363+
}
364+
355365
/// Constructs a new `Volatile` reference by mapping the wrapped pointer.
356366
///
357367
/// This method is useful for accessing only a part of a volatile value, e.g. a subslice or
@@ -394,7 +404,7 @@ where
394404
/// })};
395405
/// ```
396406
#[inline]
397-
pub unsafe fn map<'a, F, U>(&'a self, f: F) -> VolatilePtr<'a, U, Access<R, access::NoAccess>>
407+
pub unsafe fn map<F, U>(self, f: F) -> VolatilePtr<'a, U, Access<R, access::NoAccess>>
398408
where
399409
F: FnOnce(NonNull<T>) -> NonNull<U>,
400410
U: ?Sized,
@@ -404,8 +414,8 @@ where
404414

405415
#[cfg(feature = "very_unstable")]
406416
#[inline]
407-
pub const unsafe fn map_const<'a, F, U>(
408-
&'a self,
417+
pub const unsafe fn map_const<F, U>(
418+
self,
409419
f: F,
410420
) -> VolatilePtr<'a, U, Access<R, access::NoAccess>>
411421
where
@@ -416,7 +426,7 @@ where
416426
}
417427

418428
#[inline]
419-
pub unsafe fn map_mut<F, U>(&mut self, f: F) -> VolatilePtr<U, Access<R, W>>
429+
pub unsafe fn map_mut<F, U>(self, f: F) -> VolatilePtr<'a, U, Access<R, W>>
420430
where
421431
F: FnOnce(NonNull<T>) -> NonNull<U>,
422432
U: ?Sized,
@@ -426,7 +436,7 @@ where
426436

427437
#[cfg(feature = "very_unstable")]
428438
#[inline]
429-
pub const unsafe fn map_mut_const<F, U>(&mut self, f: F) -> VolatilePtr<U, Access<R, W>>
439+
pub const unsafe fn map_mut_const<F, U>(self, f: F) -> VolatilePtr<'a, U, Access<R, W>>
430440
where
431441
F: FnOnce(NonNull<T>) -> NonNull<U>,
432442
U: ?Sized,
@@ -486,9 +496,9 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
486496
/// ```
487497
#[inline]
488498
pub fn index<I>(
489-
&self,
499+
self,
490500
index: I,
491-
) -> VolatilePtr<<I as SliceIndex<[T]>>::Output, Access<R, access::NoAccess>>
501+
) -> VolatilePtr<'a, <I as SliceIndex<[T]>>::Output, Access<R, access::NoAccess>>
492502
where
493503
I: SliceIndex<[T]> + SliceIndex<[()]> + Clone,
494504
{
@@ -499,7 +509,10 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
499509

500510
#[cfg(feature = "very_unstable")]
501511
#[inline]
502-
pub const fn index_const(&self, index: usize) -> VolatilePtr<T, Access<R, access::NoAccess>> {
512+
pub const fn index_const(
513+
self,
514+
index: usize,
515+
) -> VolatilePtr<'a, T, Access<R, access::NoAccess>> {
503516
assert!(index < self.pointer.len(), "index out of bounds");
504517
unsafe {
505518
self.map_const(|slice| {
@@ -510,9 +523,9 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
510523

511524
#[inline]
512525
pub fn index_mut<I>(
513-
&mut self,
526+
self,
514527
index: I,
515-
) -> VolatilePtr<<I as SliceIndex<[T]>>::Output, Access<R, W>>
528+
) -> VolatilePtr<'a, <I as SliceIndex<[T]>>::Output, Access<R, W>>
516529
where
517530
I: SliceIndex<[T]> + SliceIndex<[()]> + Clone,
518531
{
@@ -523,7 +536,7 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
523536

524537
#[cfg(feature = "very_unstable")]
525538
#[inline]
526-
pub const fn index_mut_const(&mut self, index: usize) -> VolatilePtr<T, Access<R, W>> {
539+
pub const fn index_mut_const(self, index: usize) -> VolatilePtr<'a, T, Access<R, W>> {
527540
assert!(index < self.pointer.len(), "index out of bounds");
528541
unsafe {
529542
self.map_mut_const(|slice| {
@@ -534,18 +547,16 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
534547

535548
/// Returns an iterator over the slice.
536549
#[inline]
537-
pub fn iter<'b>(
538-
&'b self,
539-
) -> impl Iterator<Item = VolatilePtr<'b, T, Access<R, access::NoAccess>>> + 'b {
550+
pub fn iter(self) -> impl Iterator<Item = VolatilePtr<'a, T, Access<R, access::NoAccess>>> {
551+
let ptr = self.as_ptr().as_ptr() as *mut T;
540552
let len = self.len();
541-
(0..len).map(move |i| self.index(i))
553+
(0..len)
554+
.map(move |i| unsafe { VolatilePtr::new_generic(NonNull::new_unchecked(ptr.add(i))) })
542555
}
543556

544557
/// Returns an iterator that allows modifying each value.
545558
#[inline]
546-
pub fn iter_mut<'b>(
547-
&'b mut self,
548-
) -> impl Iterator<Item = VolatilePtr<'b, T, Access<R, W>>> + 'b {
559+
pub fn iter_mut(self) -> impl Iterator<Item = VolatilePtr<'a, T, Access<R, W>>> {
549560
let ptr = self.as_ptr().as_ptr() as *mut T;
550561
let len = self.len();
551562
(0..len)
@@ -727,11 +738,11 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
727738

728739
#[inline]
729740
pub fn split_at(
730-
&self,
741+
self,
731742
mid: usize,
732743
) -> (
733-
VolatilePtr<[T], Access<R, access::NoAccess>>,
734-
VolatilePtr<[T], Access<R, access::NoAccess>>,
744+
VolatilePtr<'a, [T], Access<R, access::NoAccess>>,
745+
VolatilePtr<'a, [T], Access<R, access::NoAccess>>,
735746
) {
736747
assert!(mid <= self.pointer.len());
737748
// SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
@@ -741,11 +752,11 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
741752

742753
#[inline]
743754
pub fn split_at_mut(
744-
&mut self,
755+
self,
745756
mid: usize,
746757
) -> (
747-
VolatilePtr<[T], Access<R, W>>,
748-
VolatilePtr<[T], Access<R, W>>,
758+
VolatilePtr<'a, [T], Access<R, W>>,
759+
VolatilePtr<'a, [T], Access<R, W>>,
749760
) {
750761
assert!(mid <= self.pointer.len());
751762
// SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
@@ -755,11 +766,11 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
755766

756767
#[inline]
757768
unsafe fn split_at_unchecked(
758-
&self,
769+
self,
759770
mid: usize,
760771
) -> (
761-
VolatilePtr<[T], Access<R, access::NoAccess>>,
762-
VolatilePtr<[T], Access<R, access::NoAccess>>,
772+
VolatilePtr<'a, [T], Access<R, access::NoAccess>>,
773+
VolatilePtr<'a, [T], Access<R, access::NoAccess>>,
763774
) {
764775
// SAFETY: Caller has to check that `0 <= mid <= self.len()`
765776
unsafe {
@@ -772,11 +783,11 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
772783

773784
#[inline]
774785
unsafe fn split_at_mut_unchecked(
775-
&mut self,
786+
self,
776787
mid: usize,
777788
) -> (
778-
VolatilePtr<[T], Access<R, W>>,
779-
VolatilePtr<[T], Access<R, W>>,
789+
VolatilePtr<'a, [T], Access<R, W>>,
790+
VolatilePtr<'a, [T], Access<R, W>>,
780791
) {
781792
let len = self.pointer.len();
782793
let ptr = self.pointer.as_mut_ptr();
@@ -799,24 +810,24 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
799810

800811
#[inline]
801812
pub fn as_chunks<const N: usize>(
802-
&self,
813+
self,
803814
) -> (
804-
VolatilePtr<[[T; N]], Access<R, access::NoAccess>>,
805-
VolatilePtr<[T], Access<R, access::NoAccess>>,
815+
VolatilePtr<'a, [[T; N]], Access<R, access::NoAccess>>,
816+
VolatilePtr<'a, [T], Access<R, access::NoAccess>>,
806817
) {
807818
assert_ne!(N, 0);
808819
let len = self.pointer.len() / N;
809820
let (multiple_of_n, remainder) = self.split_at(len * N);
810821
// SAFETY: We already panicked for zero, and ensured by construction
811822
// that the length of the subslice is a multiple of N.
812-
let array_slice = unsafe { multiple_of_n.as_chunks_unchecked_by_val() };
823+
let array_slice = unsafe { multiple_of_n.as_chunks_unchecked() };
813824
(array_slice, remainder)
814825
}
815826

816827
#[inline]
817828
pub unsafe fn as_chunks_unchecked<const N: usize>(
818-
&self,
819-
) -> VolatilePtr<[[T; N]], Access<R, access::NoAccess>> {
829+
self,
830+
) -> VolatilePtr<'a, [[T; N]], Access<R, access::NoAccess>> {
820831
debug_assert_ne!(N, 0);
821832
debug_assert_eq!(self.pointer.len() % N, 0);
822833
let new_len =
@@ -834,41 +845,22 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
834845

835846
#[inline]
836847
pub fn as_chunks_mut<const N: usize>(
837-
&mut self,
848+
self,
838849
) -> (
839-
VolatilePtr<[[T; N]], Access<R, W>>,
840-
VolatilePtr<[T], Access<R, W>>,
850+
VolatilePtr<'a, [[T; N]], Access<R, W>>,
851+
VolatilePtr<'a, [T], Access<R, W>>,
841852
) {
842853
assert_ne!(N, 0);
843854
let len = self.pointer.len() / N;
844855
let (multiple_of_n, remainder) = self.split_at_mut(len * N);
845856
// SAFETY: We already panicked for zero, and ensured by construction
846857
// that the length of the subslice is a multiple of N.
847-
let array_slice = unsafe { multiple_of_n.as_chunks_unchecked_by_val() };
858+
let array_slice = unsafe { multiple_of_n.as_chunks_unchecked_mut() };
848859
(array_slice, remainder)
849860
}
850861

851862
#[inline]
852863
pub unsafe fn as_chunks_unchecked_mut<const N: usize>(
853-
&mut self,
854-
) -> VolatilePtr<[[T; N]], Access<R, W>> {
855-
debug_assert_ne!(N, 0);
856-
debug_assert_eq!(self.pointer.len() % N, 0);
857-
let new_len =
858-
// SAFETY: Our precondition is exactly what's needed to call this
859-
unsafe { core::intrinsics::exact_div(self.pointer.len(), N) };
860-
// SAFETY: We cast a slice of `new_len * N` elements into
861-
// a slice of `new_len` many `N` elements chunks.
862-
let pointer = NonNull::new(ptr::slice_from_raw_parts_mut(
863-
self.pointer.as_mut_ptr().cast(),
864-
new_len,
865-
))
866-
.unwrap();
867-
unsafe { VolatilePtr::new_generic(pointer) }
868-
}
869-
870-
#[inline]
871-
pub unsafe fn as_chunks_unchecked_by_val<const N: usize>(
872864
self,
873865
) -> VolatilePtr<'a, [[T; N]], Access<R, W>> {
874866
debug_assert_ne!(N, 0);
@@ -927,7 +919,7 @@ impl<R, W> VolatilePtr<'_, [u8], Access<R, W>> {
927919
/// These methods are only available with the `unstable` feature enabled (requires a nightly
928920
/// Rust compiler).
929921
#[cfg(feature = "unstable")]
930-
impl<T, R, W, const N: usize> VolatilePtr<'_, [T; N], Access<R, W>> {
922+
impl<'a, T, R, W, const N: usize> VolatilePtr<'a, [T; N], Access<R, W>> {
931923
/// Converts an array reference to a shared slice.
932924
///
933925
/// This makes it possible to use the methods defined on slices.
@@ -953,7 +945,7 @@ impl<T, R, W, const N: usize> VolatilePtr<'_, [T; N], Access<R, W>> {
953945
/// assert_eq!(dst, [1, 2]);
954946
/// ```
955947
#[inline]
956-
pub fn as_slice(&self) -> VolatilePtr<[T], Access<R, access::NoAccess>> {
948+
pub fn as_slice(self) -> VolatilePtr<'a, [T], Access<R, access::NoAccess>> {
957949
unsafe {
958950
self.map(|array| {
959951
NonNull::new(ptr::slice_from_raw_parts_mut(array.as_ptr() as *mut T, N)).unwrap()
@@ -986,7 +978,7 @@ impl<T, R, W, const N: usize> VolatilePtr<'_, [T; N], Access<R, W>> {
986978
/// assert_eq!(dst, [1, 2]);
987979
/// ```
988980
#[inline]
989-
pub fn as_slice_mut<'a>(&'a mut self) -> VolatilePtr<'a, [T], Access<R, W>> {
981+
pub fn as_slice_mut(self) -> VolatilePtr<'a, [T], Access<R, W>> {
990982
unsafe {
991983
self.map_mut(|array| {
992984
NonNull::new(ptr::slice_from_raw_parts_mut(array.as_ptr() as *mut T, N)).unwrap()

src/tests.rs

+14-11
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,9 @@ fn test_struct() {
138138
};
139139
let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(&mut val)) };
140140
unsafe {
141-
volatile.map_mut(|s| NonNull::new(core::ptr::addr_of_mut!((*s.as_ptr()).field_1)).unwrap())
141+
volatile
142+
.borrow_mut()
143+
.map_mut(|s| NonNull::new(core::ptr::addr_of_mut!((*s.as_ptr()).field_1)).unwrap())
142144
}
143145
.update(|v| *v += 1);
144146
let mut field_2 = unsafe {
@@ -168,7 +170,8 @@ fn test_struct_macro() {
168170
field_2: true,
169171
};
170172
let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(&mut val)) };
171-
let mut field_1 = map_field_mut!(volatile.field_1);
173+
let volatile_borrowed = volatile.borrow_mut();
174+
let mut field_1 = map_field_mut!(volatile_borrowed.field_1);
172175
field_1.update(|v| *v += 1);
173176
let mut field_2 = map_field_mut!(volatile.field_2);
174177
assert!(field_2.read());
@@ -187,7 +190,7 @@ fn test_struct_macro() {
187190
fn test_slice() {
188191
let val: &mut [u32] = &mut [1, 2, 3];
189192
let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
190-
volatile.index_mut(0).update(|v| *v += 1);
193+
volatile.borrow_mut().index_mut(0).update(|v| *v += 1);
191194

192195
let mut dst = [0; 3];
193196
volatile.copy_into_slice(&mut dst);
@@ -199,7 +202,7 @@ fn test_slice() {
199202
#[should_panic]
200203
fn test_bounds_check_1() {
201204
let val: &mut [u32] = &mut [1, 2, 3];
202-
let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
205+
let volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
203206
volatile.index_mut(3);
204207
}
205208

@@ -208,7 +211,7 @@ fn test_bounds_check_1() {
208211
#[should_panic]
209212
fn test_bounds_check_2() {
210213
let val: &mut [u32] = &mut [1, 2, 3];
211-
let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
214+
let volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
212215
volatile.index_mut(2..1);
213216
}
214217

@@ -217,15 +220,15 @@ fn test_bounds_check_2() {
217220
#[should_panic]
218221
fn test_bounds_check_3() {
219222
let val: &mut [u32] = &mut [1, 2, 3];
220-
let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
223+
let volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
221224
volatile.index_mut(4..); // `3..` is is still ok (see next test)
222225
}
223226

224227
#[cfg(feature = "unstable")]
225228
#[test]
226229
fn test_bounds_check_4() {
227230
let val: &mut [u32] = &mut [1, 2, 3];
228-
let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
231+
let volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
229232
assert_eq!(volatile.index_mut(3..).len(), 0);
230233
}
231234

@@ -234,18 +237,18 @@ fn test_bounds_check_4() {
234237
#[should_panic]
235238
fn test_bounds_check_5() {
236239
let val: &mut [u32] = &mut [1, 2, 3];
237-
let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
240+
let volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
238241
volatile.index_mut(..4);
239242
}
240243

241244
#[cfg(feature = "unstable")]
242245
#[test]
243246
fn test_chunks() {
244247
let val: &mut [u32] = &mut [1, 2, 3, 4, 5, 6];
245-
let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
248+
let volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(val)) };
246249
let mut chunks = volatile.as_chunks_mut().0;
247-
chunks.index_mut(1).write([10, 11, 12]);
248-
assert_eq!(chunks.index(0).read(), [1, 2, 3]);
250+
chunks.borrow_mut().index_mut(1).write([10, 11, 12]);
251+
assert_eq!(chunks.borrow().index(0).read(), [1, 2, 3]);
249252
assert_eq!(chunks.index(1).read(), [10, 11, 12]);
250253
}
251254

0 commit comments

Comments
 (0)