Skip to content

Commit ff0ee4f

Browse files
committed
WIP: owned with borrow
1 parent 554c806 commit ff0ee4f

File tree

2 files changed

+70
-74
lines changed

2 files changed

+70
-74
lines changed

src/lib.rs

+56-63
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,
@@ -337,10 +337,20 @@ where
337337
}
338338

339339
/// Transformation methods for accessing struct fields
340-
impl<T, R, W> VolatilePtr<'_, T, Access<R, W>>
340+
impl<'a, T, R, W> VolatilePtr<'a, T, Access<R, W>>
341341
where
342342
T: ?Sized,
343343
{
344+
// TODO: Add documentation
345+
pub fn borrow(&self) -> VolatilePtr<T, Access<R, NoAccess>> {
346+
unsafe { VolatilePtr::new_generic(self.pointer) }
347+
}
348+
349+
// TODO: Add documentation
350+
pub fn borrow_mut(&mut self) -> VolatilePtr<T, Access<R, W>> {
351+
unsafe { VolatilePtr::new_generic(self.pointer) }
352+
}
353+
344354
/// Constructs a new `Volatile` reference by mapping the wrapped pointer.
345355
///
346356
/// This method is useful for accessing only a part of a volatile value, e.g. a subslice or
@@ -382,7 +392,7 @@ where
382392
/// value
383393
/// })};
384394
/// ```
385-
pub unsafe fn map<'a, F, U>(&'a self, f: F) -> VolatilePtr<'a, U, Access<R, access::NoAccess>>
395+
pub unsafe fn map<F, U>(self, f: F) -> VolatilePtr<'a, U, Access<R, access::NoAccess>>
386396
where
387397
F: FnOnce(NonNull<T>) -> NonNull<U>,
388398
U: ?Sized,
@@ -391,8 +401,8 @@ where
391401
}
392402

393403
#[cfg(feature = "very_unstable")]
394-
pub const unsafe fn map_const<'a, F, U>(
395-
&'a self,
404+
pub const unsafe fn map_const<F, U>(
405+
self,
396406
f: F,
397407
) -> VolatilePtr<'a, U, Access<R, access::NoAccess>>
398408
where
@@ -402,7 +412,7 @@ where
402412
unsafe { VolatilePtr::new_generic(f(self.pointer)) }
403413
}
404414

405-
pub unsafe fn map_mut<F, U>(&mut self, f: F) -> VolatilePtr<U, Access<R, W>>
415+
pub unsafe fn map_mut<F, U>(self, f: F) -> VolatilePtr<'a, U, Access<R, W>>
406416
where
407417
F: FnOnce(NonNull<T>) -> NonNull<U>,
408418
U: ?Sized,
@@ -411,7 +421,7 @@ where
411421
}
412422

413423
#[cfg(feature = "very_unstable")]
414-
pub const unsafe fn map_mut_const<F, U>(&mut self, f: F) -> VolatilePtr<U, Access<R, W>>
424+
pub const unsafe fn map_mut_const<F, U>(self, f: F) -> VolatilePtr<'a, U, Access<R, W>>
415425
where
416426
F: FnOnce(NonNull<T>) -> NonNull<U>,
417427
U: ?Sized,
@@ -468,9 +478,9 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
468478
/// assert_eq!(subslice.index(0).read(), 2);
469479
/// ```
470480
pub fn index<I>(
471-
&self,
481+
self,
472482
index: I,
473-
) -> VolatilePtr<<I as SliceIndex<[T]>>::Output, Access<R, access::NoAccess>>
483+
) -> VolatilePtr<'a, <I as SliceIndex<[T]>>::Output, Access<R, access::NoAccess>>
474484
where
475485
I: SliceIndex<[T]> + SliceIndex<[()]> + Clone,
476486
{
@@ -480,7 +490,10 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
480490
}
481491

482492
#[cfg(feature = "very_unstable")]
483-
pub const fn index_const(&self, index: usize) -> VolatilePtr<T, Access<R, access::NoAccess>> {
493+
pub const fn index_const(
494+
self,
495+
index: usize,
496+
) -> VolatilePtr<'a, T, Access<R, access::NoAccess>> {
484497
assert!(index < self.pointer.len(), "index out of bounds");
485498
unsafe {
486499
self.map_const(|slice| {
@@ -490,9 +503,9 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
490503
}
491504

492505
pub fn index_mut<I>(
493-
&mut self,
506+
self,
494507
index: I,
495-
) -> VolatilePtr<<I as SliceIndex<[T]>>::Output, Access<R, W>>
508+
) -> VolatilePtr<'a, <I as SliceIndex<[T]>>::Output, Access<R, W>>
496509
where
497510
I: SliceIndex<[T]> + SliceIndex<[()]> + Clone,
498511
{
@@ -502,7 +515,7 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
502515
}
503516

504517
#[cfg(feature = "very_unstable")]
505-
pub const fn index_mut_const(&mut self, index: usize) -> VolatilePtr<T, Access<R, W>> {
518+
pub const fn index_mut_const(self, index: usize) -> VolatilePtr<'a, T, Access<R, W>> {
506519
assert!(index < self.pointer.len(), "index out of bounds");
507520
unsafe {
508521
self.map_mut_const(|slice| {
@@ -512,17 +525,15 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
512525
}
513526

514527
/// Returns an iterator over the slice.
515-
pub fn iter<'b>(
516-
&'b self,
517-
) -> impl Iterator<Item = VolatilePtr<'b, T, Access<R, access::NoAccess>>> + 'b {
528+
pub fn iter(self) -> impl Iterator<Item = VolatilePtr<'a, T, Access<R, access::NoAccess>>> {
529+
let ptr = self.as_ptr().as_ptr() as *mut T;
518530
let len = self.len();
519-
(0..len).map(move |i| self.index(i))
531+
(0..len)
532+
.map(move |i| unsafe { VolatilePtr::new_generic(NonNull::new_unchecked(ptr.add(i))) })
520533
}
521534

522535
/// Returns an iterator that allows modifying each value.
523-
pub fn iter_mut<'b>(
524-
&'b mut self,
525-
) -> impl Iterator<Item = VolatilePtr<'b, T, Access<R, W>>> + 'b {
536+
pub fn iter_mut(self) -> impl Iterator<Item = VolatilePtr<'a, T, Access<R, W>>> {
526537
let ptr = self.as_ptr().as_ptr() as *mut T;
527538
let len = self.len();
528539
(0..len)
@@ -700,11 +711,11 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
700711
}
701712

702713
pub fn split_at(
703-
&self,
714+
self,
704715
mid: usize,
705716
) -> (
706-
VolatilePtr<[T], Access<R, access::NoAccess>>,
707-
VolatilePtr<[T], Access<R, access::NoAccess>>,
717+
VolatilePtr<'a, [T], Access<R, access::NoAccess>>,
718+
VolatilePtr<'a, [T], Access<R, access::NoAccess>>,
708719
) {
709720
assert!(mid <= self.pointer.len());
710721
// SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
@@ -713,11 +724,11 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
713724
}
714725

715726
pub fn split_at_mut(
716-
&mut self,
727+
self,
717728
mid: usize,
718729
) -> (
719-
VolatilePtr<[T], Access<R, W>>,
720-
VolatilePtr<[T], Access<R, W>>,
730+
VolatilePtr<'a, [T], Access<R, W>>,
731+
VolatilePtr<'a, [T], Access<R, W>>,
721732
) {
722733
assert!(mid <= self.pointer.len());
723734
// SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
@@ -726,11 +737,11 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
726737
}
727738

728739
unsafe fn split_at_unchecked(
729-
&self,
740+
self,
730741
mid: usize,
731742
) -> (
732-
VolatilePtr<[T], Access<R, access::NoAccess>>,
733-
VolatilePtr<[T], Access<R, access::NoAccess>>,
743+
VolatilePtr<'a, [T], Access<R, access::NoAccess>>,
744+
VolatilePtr<'a, [T], Access<R, access::NoAccess>>,
734745
) {
735746
// SAFETY: Caller has to check that `0 <= mid <= self.len()`
736747
unsafe {
@@ -742,11 +753,11 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
742753
}
743754

744755
unsafe fn split_at_mut_unchecked(
745-
&mut self,
756+
self,
746757
mid: usize,
747758
) -> (
748-
VolatilePtr<[T], Access<R, W>>,
749-
VolatilePtr<[T], Access<R, W>>,
759+
VolatilePtr<'a, [T], Access<R, W>>,
760+
VolatilePtr<'a, [T], Access<R, W>>,
750761
) {
751762
let len = self.pointer.len();
752763
let ptr = self.pointer.as_mut_ptr();
@@ -768,23 +779,23 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
768779
}
769780

770781
pub fn as_chunks<const N: usize>(
771-
&self,
782+
self,
772783
) -> (
773-
VolatilePtr<[[T; N]], Access<R, access::NoAccess>>,
774-
VolatilePtr<[T], Access<R, access::NoAccess>>,
784+
VolatilePtr<'a, [[T; N]], Access<R, access::NoAccess>>,
785+
VolatilePtr<'a, [T], Access<R, access::NoAccess>>,
775786
) {
776787
assert_ne!(N, 0);
777788
let len = self.pointer.len() / N;
778789
let (multiple_of_n, remainder) = self.split_at(len * N);
779790
// SAFETY: We already panicked for zero, and ensured by construction
780791
// that the length of the subslice is a multiple of N.
781-
let array_slice = unsafe { multiple_of_n.as_chunks_unchecked_by_val() };
792+
let array_slice = unsafe { multiple_of_n.as_chunks_unchecked() };
782793
(array_slice, remainder)
783794
}
784795

785796
pub unsafe fn as_chunks_unchecked<const N: usize>(
786-
&self,
787-
) -> VolatilePtr<[[T; N]], Access<R, access::NoAccess>> {
797+
self,
798+
) -> VolatilePtr<'a, [[T; N]], Access<R, access::NoAccess>> {
788799
debug_assert_ne!(N, 0);
789800
debug_assert_eq!(self.pointer.len() % N, 0);
790801
let new_len =
@@ -801,39 +812,21 @@ impl<'a, T, R, W> VolatilePtr<'a, [T], Access<R, W>> {
801812
}
802813

803814
pub fn as_chunks_mut<const N: usize>(
804-
&mut self,
815+
self,
805816
) -> (
806-
VolatilePtr<[[T; N]], Access<R, W>>,
807-
VolatilePtr<[T], Access<R, W>>,
817+
VolatilePtr<'a, [[T; N]], Access<R, W>>,
818+
VolatilePtr<'a, [T], Access<R, W>>,
808819
) {
809820
assert_ne!(N, 0);
810821
let len = self.pointer.len() / N;
811822
let (multiple_of_n, remainder) = self.split_at_mut(len * N);
812823
// SAFETY: We already panicked for zero, and ensured by construction
813824
// that the length of the subslice is a multiple of N.
814-
let array_slice = unsafe { multiple_of_n.as_chunks_unchecked_by_val() };
825+
let array_slice = unsafe { multiple_of_n.as_chunks_unchecked_mut() };
815826
(array_slice, remainder)
816827
}
817828

818829
pub unsafe fn as_chunks_unchecked_mut<const N: usize>(
819-
&mut self,
820-
) -> VolatilePtr<[[T; N]], Access<R, W>> {
821-
debug_assert_ne!(N, 0);
822-
debug_assert_eq!(self.pointer.len() % N, 0);
823-
let new_len =
824-
// SAFETY: Our precondition is exactly what's needed to call this
825-
unsafe { core::intrinsics::exact_div(self.pointer.len(), N) };
826-
// SAFETY: We cast a slice of `new_len * N` elements into
827-
// a slice of `new_len` many `N` elements chunks.
828-
let pointer = NonNull::new(ptr::slice_from_raw_parts_mut(
829-
self.pointer.as_mut_ptr().cast(),
830-
new_len,
831-
))
832-
.unwrap();
833-
unsafe { VolatilePtr::new_generic(pointer) }
834-
}
835-
836-
pub unsafe fn as_chunks_unchecked_by_val<const N: usize>(
837830
self,
838831
) -> VolatilePtr<'a, [[T; N]], Access<R, W>> {
839832
debug_assert_ne!(N, 0);
@@ -891,7 +884,7 @@ impl<R, W> VolatilePtr<'_, [u8], Access<R, W>> {
891884
/// These methods are only available with the `unstable` feature enabled (requires a nightly
892885
/// Rust compiler).
893886
#[cfg(feature = "unstable")]
894-
impl<T, R, W, const N: usize> VolatilePtr<'_, [T; N], Access<R, W>> {
887+
impl<'a, T, R, W, const N: usize> VolatilePtr<'a, [T; N], Access<R, W>> {
895888
/// Converts an array reference to a shared slice.
896889
///
897890
/// This makes it possible to use the methods defined on slices.
@@ -916,7 +909,7 @@ impl<T, R, W, const N: usize> VolatilePtr<'_, [T; N], Access<R, W>> {
916909
///
917910
/// assert_eq!(dst, [1, 2]);
918911
/// ```
919-
pub fn as_slice(&self) -> VolatilePtr<[T], Access<R, access::NoAccess>> {
912+
pub fn as_slice(self) -> VolatilePtr<'a, [T], Access<R, access::NoAccess>> {
920913
unsafe {
921914
self.map(|array| {
922915
NonNull::new(ptr::slice_from_raw_parts_mut(array.as_ptr() as *mut T, N)).unwrap()
@@ -948,7 +941,7 @@ impl<T, R, W, const N: usize> VolatilePtr<'_, [T; N], Access<R, W>> {
948941
///
949942
/// assert_eq!(dst, [1, 2]);
950943
/// ```
951-
pub fn as_slice_mut<'a>(&'a mut self) -> VolatilePtr<'a, [T], Access<R, W>> {
944+
pub fn as_slice_mut(self) -> VolatilePtr<'a, [T], Access<R, W>> {
952945
unsafe {
953946
self.map_mut(|array| {
954947
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)