Squashed 'third_party/autocxx/' content from commit 629e8fa53

git-subtree-dir: third_party/autocxx
git-subtree-split: 629e8fa531a633164c0b52e2a3cab536d4cd0849
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
Change-Id: I62a03b0049f49adf029e0204639cdb5468dde1a1
diff --git a/src/rvalue_param.rs b/src/rvalue_param.rs
new file mode 100644
index 0000000..4acc52e
--- /dev/null
+++ b/src/rvalue_param.rs
@@ -0,0 +1,131 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! It would be highly desirable to share a lot of this code with `value_param.rs`
+//! but this proves to be surprisingly fiddly.
+
+use cxx::{memory::UniquePtrTarget, UniquePtr};
+use moveit::MoveRef;
+use std::{
+    marker::{PhantomData, PhantomPinned},
+    pin::Pin,
+};
+
+/// A trait representing a parameter to a C++ function which is received
+/// by rvalue (i.e. by move).
+///
+/// # Panics
+///
+/// The implementations of this trait which take a [`cxx::UniquePtr`] will
+/// panic if the pointer is NULL.
+///
+/// # Safety
+///
+/// Implementers must guarantee that the pointer returned by `get_ptr`
+/// is of the correct size and alignment of `T`.
+pub unsafe trait RValueParam<T>: Sized {
+    /// Retrieve the pointer to the underlying item, to be passed to C++.
+    /// Note that on the C++ side this is currently passed to `std::move`
+    /// and therefore may be mutated.
+    #[doc(hidden)]
+    fn get_ptr(stack: Pin<&mut Self>) -> *mut T;
+}
+
+unsafe impl<T> RValueParam<T> for UniquePtr<T>
+where
+    T: UniquePtrTarget,
+{
+    fn get_ptr(stack: Pin<&mut Self>) -> *mut T {
+        // Safety: we won't move/swap the contents of the outer pin, nor of the
+        // type stored within the UniquePtr.
+        unsafe {
+            (Pin::into_inner_unchecked(
+                (*Pin::into_inner_unchecked(stack))
+                    .as_mut()
+                    .expect("Passed a NULL UniquePtr as a C++ rvalue parameter"),
+            )) as *mut T
+        }
+    }
+}
+
+unsafe impl<T> RValueParam<T> for Pin<Box<T>> {
+    fn get_ptr(stack: Pin<&mut Self>) -> *mut T {
+        // Safety: we won't move/swap the contents of the outer pin, nor of the
+        // type stored within the UniquePtr.
+        unsafe {
+            (Pin::into_inner_unchecked((*Pin::into_inner_unchecked(stack)).as_mut())) as *mut T
+        }
+    }
+}
+
+unsafe impl<'a, T> RValueParam<T> for Pin<MoveRef<'a, T>> {
+    fn get_ptr(stack: Pin<&mut Self>) -> *mut T {
+        // Safety: we won't move/swap the contents of the outer pin, nor of the
+        // type stored within the UniquePtr.
+        unsafe {
+            (Pin::into_inner_unchecked((*Pin::into_inner_unchecked(stack)).as_mut())) as *mut T
+        }
+    }
+}
+
+/// Implementation detail for how we pass rvalue parameters into C++.
+/// This type is instantiated by auto-generated autocxx code each time we
+/// need to pass a value parameter into C++, and will take responsibility
+/// for extracting that value parameter from the [`RValueParam`] and doing
+/// any later cleanup.
+#[doc(hidden)]
+pub struct RValueParamHandler<T, RVP>
+where
+    RVP: RValueParam<T>,
+{
+    // We can't populate this on 'new' because the object may move.
+    // Hence this is an Option - it's None until populate is called.
+    space: Option<RVP>,
+    _pinned: PhantomPinned,
+    _data: PhantomData<T>,
+}
+
+impl<T, RVP: RValueParam<T>> RValueParamHandler<T, RVP> {
+    /// Populate this stack space if needs be. Note safety guarantees
+    /// on [`get_ptr`].
+    ///
+    /// # Safety
+    ///
+    /// Callers must guarantee that this type will not move
+    /// in memory between calls to [`populate`] and [`get_ptr`].
+    /// Callers must call [`populate`] exactly once prior to calling [`get_ptr`].
+    pub unsafe fn populate(self: Pin<&mut Self>, param: RVP) {
+        // Structural pinning, as documented in [`std::pin`].
+        // Safety: we will not move the contents of the pin.
+        *Pin::into_inner_unchecked(self.map_unchecked_mut(|s| &mut s.space)) = Some(param)
+    }
+
+    /// Return a pointer to the underlying value which can be passed to C++.
+    /// Per the unsafety contract of [`populate`], the object must not have moved
+    /// since it was created, and [`populate`] has been called exactly once
+    /// prior to this call.
+    pub fn get_ptr(self: Pin<&mut Self>) -> *mut T {
+        // Structural pinning, as documented in [`std::pin`]. `map_unchecked_mut` doesn't play
+        // nicely with `unwrap`, so we have to do it manually.
+        unsafe {
+            RVP::get_ptr(Pin::new_unchecked(
+                self.get_unchecked_mut().space.as_mut().unwrap(),
+            ))
+        }
+    }
+}
+
+impl<T, VP: RValueParam<T>> Default for RValueParamHandler<T, VP> {
+    fn default() -> Self {
+        Self {
+            space: None,
+            _pinned: PhantomPinned,
+            _data: PhantomData,
+        }
+    }
+}