//! 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( mut slice: Pin<&mut [T]>, ) -> impl Iterator> { // SAFETY: We never move out of this pointer. let base_ptr: NonNull = NonNull::from(unsafe { slice.as_mut().get_unchecked_mut() }).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(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]) } }