File
Blob: src/rust/kj/own.rs
| 1 | //! Helpers for Rust wrappers around C++ objects passed through the CXX bridge. |
| 2 | //! |
| 3 | //! Most Rust-visible wrappers in this crate hold one of two shapes: |
| 4 | //! - [`OwnOrRef`] when the underlying C++ API can hand Rust any of `kj::Own<T>`, `const T&`, or |
| 5 | //! `T&` |
| 6 | //! - [`OwnOrMut`] when the underlying C++ API only ever hands Rust `kj::Own<T>` or `T&` |
| 7 | //! |
| 8 | //! Pick the narrowest holder that matches the FFI surface you are wrapping. In particular, use |
| 9 | //! [`OwnOrMut`] for mutable-only wrappers so the type system does not represent an impossible shared |
| 10 | //! borrow state. |
| 11 | |
| 12 | use std::ops::Deref; |
| 13 | use std::pin::Pin; |
| 14 | |
| 15 | use kj_rs::KjOwn; |
| 16 | |
| 17 | /// Wrapper for C++ objects. |
| 18 | /// |
| 19 | /// `OwnOrRef` represents the three ways a C++ object can be handed to Rust through this crate's |
| 20 | /// wrappers: owned as `kj::Own<T>`, borrowed as `const T&`, or borrowed as `T&`. |
| 21 | /// |
| 22 | /// Use this type when the wrapped FFI surface genuinely accepts shared borrows. If the wrapper only |
| 23 | /// needs owned-or-mutable access, use [`OwnOrMut`] instead. |
| 24 | /// |
| 25 | /// Instances of this type are not usually exposed directly. Instead, wrapper structs store an |
| 26 | /// `OwnOrRef<T>` internally and expose an API matching the capabilities of the underlying C++ |
| 27 | /// object. |
| 28 | /// |
| 29 | /// Typical mapping from C++ to a Rust wrapper: |
| 30 | /// |
| 31 | /// - `kj::Own<T>` becomes an owned wrapper value |
| 32 | /// - `const T&` becomes `&Wrapper` |
| 33 | /// - `T&` becomes `&mut Wrapper` |
| 34 | /// |
| 35 | /// The same wrapper can then expose shared methods through `AsRef` / `Deref`, and mutable methods |
| 36 | /// through `as_mut()` when the caller knows the value is not in the `Ref` state. |
| 37 | pub enum OwnOrRef<'a, T> { |
| 38 | Own(KjOwn<T>), |
| 39 | Ref(&'a T), |
| 40 | MutRef(Pin<&'a mut T>), |
| 41 | } |
| 42 | |
| 43 | /// Wrapper for C++ objects that are always owned or mutably borrowed. |
| 44 | /// |
| 45 | /// `OwnOrMut` represents the two ways a mutable C++ object can be handed to Rust through this |
| 46 | /// crate's wrappers: owned as `kj::Own<T>` or borrowed as `T&`. |
| 47 | /// |
| 48 | /// Use this type when the wrapped FFI surface does not allow `const T&`. That keeps the wrapper's |
| 49 | /// internal state aligned with reality and allows safe mutable access through `as_mut()`. |
| 50 | /// |
| 51 | /// Instances of this type are not usually exposed directly. Instead, wrapper structs store an |
| 52 | /// `OwnOrMut<T>` internally and expose methods that operate on the underlying mutable C++ object. |
| 53 | pub enum OwnOrMut<'a, T> { |
| 54 | Own(KjOwn<T>), |
| 55 | MutRef(Pin<&'a mut T>), |
| 56 | } |
| 57 | |
| 58 | impl<T> AsRef<T> for OwnOrRef<'_, T> { |
| 59 | fn as_ref(&self) -> &T { |
| 60 | match self { |
| 61 | OwnOrRef::Own(own) => own.as_ref(), |
| 62 | OwnOrRef::Ref(ref_) => ref_, |
| 63 | OwnOrRef::MutRef(ref_) => ref_, |
| 64 | } |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | impl<T> OwnOrRef<'_, T> { |
| 69 | /// Obtain mut reference to the underlying object. |
| 70 | /// |
| 71 | /// # Safety |
| 72 | /// |
| 73 | /// - self should not be `Ref` variant. |
| 74 | /// |
| 75 | /// C++ mutable references are represented by `Pin<&mut T>`, otherwise we'd implement `AsMut`. |
| 76 | pub unsafe fn as_mut(&mut self) -> Pin<&mut T> { |
| 77 | match self { |
| 78 | OwnOrRef::Own(own) => own.as_mut(), |
| 79 | OwnOrRef::Ref(_) => unreachable!("mut reference to borrowed object"), |
| 80 | OwnOrRef::MutRef(ref_) => ref_.as_mut(), |
| 81 | } |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | impl<T> AsRef<T> for OwnOrMut<'_, T> { |
| 86 | fn as_ref(&self) -> &T { |
| 87 | match self { |
| 88 | OwnOrMut::Own(own) => own.as_ref(), |
| 89 | OwnOrMut::MutRef(ref_) => ref_, |
| 90 | } |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | impl<T> OwnOrMut<'_, T> { |
| 95 | /// Obtain a mutable reference to the underlying object. |
| 96 | pub fn as_mut(&mut self) -> Pin<&mut T> { |
| 97 | match self { |
| 98 | OwnOrMut::Own(own) => own.as_mut(), |
| 99 | OwnOrMut::MutRef(ref_) => ref_.as_mut(), |
| 100 | } |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | impl<T> Deref for OwnOrRef<'_, T> { |
| 105 | type Target = T; |
| 106 | |
| 107 | fn deref(&self) -> &Self::Target { |
| 108 | self.as_ref() |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | impl<T> Deref for OwnOrMut<'_, T> { |
| 113 | type Target = T; |
| 114 | |
| 115 | fn deref(&self) -> &Self::Target { |
| 116 | self.as_ref() |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | impl<'a, T> From<&'a T> for OwnOrRef<'a, T> { |
| 121 | fn from(value: &'a T) -> Self { |
| 122 | Self::Ref(value) |
| 123 | } |
| 124 | } |
| 125 | |
| 126 | impl<T> From<KjOwn<T>> for OwnOrRef<'_, T> { |
| 127 | fn from(value: KjOwn<T>) -> Self { |
| 128 | Self::Own(value) |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | impl<'a, T> From<Pin<&'a mut T>> for OwnOrRef<'a, T> { |
| 133 | fn from(value: Pin<&'a mut T>) -> Self { |
| 134 | Self::MutRef(value) |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | impl<T> From<KjOwn<T>> for OwnOrMut<'_, T> { |
| 139 | fn from(value: KjOwn<T>) -> Self { |
| 140 | Self::Own(value) |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | impl<'a, T> From<Pin<&'a mut T>> for OwnOrMut<'a, T> { |
| 145 | fn from(value: Pin<&'a mut T>) -> Self { |
| 146 | Self::MutRef(value) |
| 147 | } |
| 148 | } |