Brian Silverman | f3ec38b | 2022-07-06 20:43:36 -0700 | [diff] [blame] | 1 | // Copyright 2022 Google LLC |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| 4 | // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| 5 | // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your |
| 6 | // option. This file may not be copied, modified, or distributed |
| 7 | // except according to those terms. |
| 8 | |
| 9 | /// A C++ const reference. These are different from Rust's `&T` in that |
| 10 | /// these may exist even while the object is mutated elsewhere. |
| 11 | /// |
| 12 | /// This is a trait not a struct due to the nuances of Rust's orphan rule |
| 13 | /// - implemntations of this trait are found in each set of generated bindings |
| 14 | /// but they are essentially the same. |
| 15 | pub trait CppRef<'a, T> { |
| 16 | /// Retrieve the underlying C++ pointer. |
| 17 | fn as_ptr(&self) -> *const T; |
| 18 | |
| 19 | /// Get a regular Rust reference out of this C++ reference. |
| 20 | /// |
| 21 | /// # Safety |
| 22 | /// |
| 23 | /// Callers must guarantee that the referent is not modified by any other |
| 24 | /// C++ or Rust code while the returned reference exists. Callers must |
| 25 | /// also guarantee that no mutable Rust reference is created to the |
| 26 | /// referent while the returned reference exists. |
| 27 | unsafe fn as_ref(&self) -> &T { |
| 28 | &*self.as_ptr() |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | /// A C++ non-const reference. These are different from Rust's `&mut T` in that |
| 33 | /// several C++ references can exist to the same underlying data ("aliasing") |
| 34 | /// and that's not permitted in Rust. |
| 35 | /// |
| 36 | /// This is a trait not a struct due to the nuances of Rust's orphan rule |
| 37 | /// - implemntations of this trait are found in each set of generated bindings |
| 38 | /// but they are essentially the same. |
| 39 | pub trait CppMutRef<'a, T>: CppRef<'a, T> { |
| 40 | /// Retrieve the underlying C++ pointer. |
| 41 | fn as_mut_ptr(&self) -> *mut T; |
| 42 | |
| 43 | /// Get a regular Rust mutable reference out of this C++ reference. |
| 44 | /// |
| 45 | /// # Safety |
| 46 | /// |
| 47 | /// Callers must guarantee that the referent is not modified by any other |
| 48 | /// C++ or Rust code while the returned reference exists. Callers must |
| 49 | /// also guarantee that no other Rust reference is created to the referent |
| 50 | /// while the returned reference exists. |
| 51 | unsafe fn as_mut(&mut self) -> &mut T { |
| 52 | &mut *self.as_mut_ptr() |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | /// Any newtype wrapper which causes the contained object to obey C++ reference |
| 57 | /// semantics rather than Rust reference semantics. |
| 58 | /// |
| 59 | /// The complex generics here are working around the orphan rule - the only |
| 60 | /// important generic is `T` which is the underlying stored type. |
| 61 | /// |
| 62 | /// C++ references are permitted to alias one another, and commonly do. |
| 63 | /// Rust references must alias according only to the narrow rules of the |
| 64 | /// borrow checker. |
| 65 | /// |
| 66 | /// If you need C++ to access your Rust object, first imprison it in one of these |
| 67 | /// objects, then use [`Self::as_cpp_ref`] to obtain C++ references to it. |
| 68 | pub trait CppPin<'a, T: 'a> { |
| 69 | /// The type of C++ reference created to the contained object. |
| 70 | type CppRef: CppRef<'a, T>; |
| 71 | |
| 72 | /// The type of C++ mutable reference created to the contained object.. |
| 73 | type CppMutRef: CppMutRef<'a, T>; |
| 74 | |
| 75 | /// Get an immutable pointer to the underlying object. |
| 76 | fn as_ptr(&self) -> *const T; |
| 77 | |
| 78 | /// Get a mutable pointer to the underlying object. |
| 79 | fn as_mut_ptr(&mut self) -> *mut T; |
| 80 | |
| 81 | /// Returns a reference which obeys C++ reference semantics |
| 82 | fn as_cpp_ref(&self) -> Self::CppRef; |
| 83 | |
| 84 | /// Returns a mutable reference which obeys C++ reference semantics. |
| 85 | /// |
| 86 | /// Note that this requires unique ownership of `self`, but this is |
| 87 | /// advisory since the resulting reference can be cloned. |
| 88 | fn as_cpp_mut_ref(&mut self) -> Self::CppMutRef; |
| 89 | |
| 90 | /// Get a normal Rust reference to the underlying object. This is unsafe. |
| 91 | /// |
| 92 | /// # Safety |
| 93 | /// |
| 94 | /// You must guarantee that C++ will not mutate the object while the |
| 95 | /// reference exists. |
| 96 | unsafe fn as_ref(&self) -> &T { |
| 97 | &*self.as_ptr() |
| 98 | } |
| 99 | |
| 100 | /// Get a normal Rust mutable reference to the underlying object. This is unsafe. |
| 101 | /// |
| 102 | /// # Safety |
| 103 | /// |
| 104 | /// You must guarantee that C++ will not mutate the object while the |
| 105 | /// reference exists. |
| 106 | unsafe fn as_mut(&mut self) -> &mut T { |
| 107 | &mut *self.as_mut_ptr() |
| 108 | } |
| 109 | } |