summaryrefslogtreecommitdiff
path: root/crates/utils
diff options
context:
space:
mode:
Diffstat (limited to 'crates/utils')
-rw-r--r--crates/utils/Cargo.toml8
-rw-r--r--crates/utils/src/lib.rs3
-rw-r--r--crates/utils/src/pin.rs25
3 files changed, 36 insertions, 0 deletions
diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml
new file mode 100644
index 0000000..5b55a5c
--- /dev/null
+++ b/crates/utils/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "vernos_utils"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[dependencies]
+contracts = { version = "0.6.3", default-features = false }
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]) }
+}