diff options
Diffstat (limited to 'crates/utils/src')
-rw-r--r-- | crates/utils/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/utils/src/pin.rs | 25 |
2 files changed, 28 insertions, 0 deletions
diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs new file mode 100644 index 0000000..57143bc --- /dev/null +++ b/crates/utils/src/lib.rs @@ -0,0 +1,3 @@ +//! Common utilities. + +pub mod pin; diff --git a/crates/utils/src/pin.rs b/crates/utils/src/pin.rs new file mode 100644 index 0000000..202904d --- /dev/null +++ b/crates/utils/src/pin.rs @@ -0,0 +1,25 @@ +//! Utilities having to do with pinning. I sure hope these are sound! + +use contracts::requires; +use core::pin::Pin; +use std::ptr::NonNull; + +/// Iterates over projections of elements out of a pinned slice. +pub fn pin_project_slice_mut_iter<T>(slice: Pin<&mut [T]>) -> impl Iterator<Item = Pin<&mut T>> { + let base_ptr: NonNull<T> = NonNull::from(slice.as_ref().get_ref()).cast(); + (0..slice.len()).map(move |i| { + // SAFETY: This is in-bounds, since the original slice was valid. No other references to + // the data can exist, since we visit each index once and have an exclusive borrow on the + // slice. + let ptr = unsafe { base_ptr.add(i).as_mut() }; + // SAFETY: This is not certainly sound; see https://github.com/rust-lang/rust/issues/104108 + unsafe { Pin::new_unchecked(ptr) } + }) +} + +/// Projects a single element out of a pinned slice. +#[requires(index < slice.len())] +pub fn pin_project_slice_mut<T>(slice: Pin<&mut [T]>, index: usize) -> Pin<&mut T> { + // SAFETY: This is not certainly sound; see https://github.com/rust-lang/rust/issues/104108 + unsafe { slice.map_unchecked_mut(|slice| &mut slice[index]) } +} |