summaryrefslogtreecommitdiffstats
path: root/third_party/rust/pin-utils/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/pin-utils/src
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/pin-utils/src')
-rw-r--r--third_party/rust/pin-utils/src/lib.rs17
-rw-r--r--third_party/rust/pin-utils/src/projection.rs100
-rw-r--r--third_party/rust/pin-utils/src/stack_pin.rs25
3 files changed, 142 insertions, 0 deletions
diff --git a/third_party/rust/pin-utils/src/lib.rs b/third_party/rust/pin-utils/src/lib.rs
new file mode 100644
index 0000000000..6198e9823a
--- /dev/null
+++ b/third_party/rust/pin-utils/src/lib.rs
@@ -0,0 +1,17 @@
+//! Utilities for pinning
+
+#![no_std]
+#![warn(missing_docs, missing_debug_implementations)]
+#![deny(bare_trait_objects)]
+#![allow(unknown_lints)]
+#![doc(html_root_url = "https://docs.rs/pin-utils/0.1.0")]
+
+#[doc(hidden)]
+pub mod core_reexport {
+ pub use core::*;
+}
+
+#[macro_use]
+mod stack_pin;
+#[macro_use]
+mod projection;
diff --git a/third_party/rust/pin-utils/src/projection.rs b/third_party/rust/pin-utils/src/projection.rs
new file mode 100644
index 0000000000..6af90c56be
--- /dev/null
+++ b/third_party/rust/pin-utils/src/projection.rs
@@ -0,0 +1,100 @@
+/// A pinned projection of a struct field.
+///
+/// # Safety
+///
+/// To make using this macro safe, three things need to be ensured:
+/// - If the struct implements [`Drop`], the [`drop`] method is not allowed to
+/// move the value of the field.
+/// - If the struct wants to implement [`Unpin`], it has to do so conditionally:
+/// The struct can only implement [`Unpin`] if the field's type is [`Unpin`].
+/// - The struct must not be `#[repr(packed)]`.
+///
+/// # Example
+///
+/// ```rust
+/// use pin_utils::unsafe_pinned;
+/// use std::marker::Unpin;
+/// use std::pin::Pin;
+///
+/// struct Foo<T> {
+/// field: T,
+/// }
+///
+/// impl<T> Foo<T> {
+/// unsafe_pinned!(field: T);
+///
+/// fn baz(mut self: Pin<&mut Self>) {
+/// let _: Pin<&mut T> = self.field(); // Pinned reference to the field
+/// }
+/// }
+///
+/// impl<T: Unpin> Unpin for Foo<T> {} // Conditional Unpin impl
+/// ```
+///
+/// Note: borrowing the field multiple times requires using `.as_mut()` to
+/// avoid consuming the `Pin`.
+///
+/// [`Unpin`]: core::marker::Unpin
+/// [`drop`]: Drop::drop
+#[macro_export]
+macro_rules! unsafe_pinned {
+ ($f:tt: $t:ty) => (
+ #[allow(unsafe_code)]
+ fn $f<'__a>(
+ self: $crate::core_reexport::pin::Pin<&'__a mut Self>
+ ) -> $crate::core_reexport::pin::Pin<&'__a mut $t> {
+ unsafe {
+ $crate::core_reexport::pin::Pin::map_unchecked_mut(
+ self, |x| &mut x.$f
+ )
+ }
+ }
+ )
+}
+
+/// An unpinned projection of a struct field.
+///
+/// # Safety
+///
+/// This macro is unsafe because it creates a method that returns a normal
+/// non-pin reference to the struct field. It is up to the programmer to ensure
+/// that the contained value can be considered not pinned in the current
+/// context.
+///
+/// # Example
+///
+/// ```rust
+/// use pin_utils::unsafe_unpinned;
+/// use std::pin::Pin;
+///
+/// struct Bar;
+/// struct Foo {
+/// field: Bar,
+/// }
+///
+/// impl Foo {
+/// unsafe_unpinned!(field: Bar);
+///
+/// fn baz(mut self: Pin<&mut Self>) {
+/// let _: &mut Bar = self.field(); // Normal reference to the field
+/// }
+/// }
+/// ```
+///
+/// Note: borrowing the field multiple times requires using `.as_mut()` to
+/// avoid consuming the [`Pin`].
+///
+/// [`Pin`]: core::pin::Pin
+#[macro_export]
+macro_rules! unsafe_unpinned {
+ ($f:tt: $t:ty) => (
+ #[allow(unsafe_code)]
+ fn $f<'__a>(
+ self: $crate::core_reexport::pin::Pin<&'__a mut Self>
+ ) -> &'__a mut $t {
+ unsafe {
+ &mut $crate::core_reexport::pin::Pin::get_unchecked_mut(self).$f
+ }
+ }
+ )
+}
diff --git a/third_party/rust/pin-utils/src/stack_pin.rs b/third_party/rust/pin-utils/src/stack_pin.rs
new file mode 100644
index 0000000000..8a1ed2c5af
--- /dev/null
+++ b/third_party/rust/pin-utils/src/stack_pin.rs
@@ -0,0 +1,25 @@
+/// Pins a value on the stack.
+///
+/// # Example
+///
+/// ```rust
+/// # use pin_utils::pin_mut;
+/// # use core::pin::Pin;
+/// # struct Foo {}
+/// let foo = Foo { /* ... */ };
+/// pin_mut!(foo);
+/// let _: Pin<&mut Foo> = foo;
+/// ```
+#[macro_export]
+macro_rules! pin_mut {
+ ($($x:ident),* $(,)?) => { $(
+ // Move the value to ensure that it is owned
+ let mut $x = $x;
+ // Shadow the original binding so that it can't be directly accessed
+ // ever again.
+ #[allow(unused_mut)]
+ let mut $x = unsafe {
+ $crate::core_reexport::pin::Pin::new_unchecked(&mut $x)
+ };
+ )* }
+}