Skip to content
File

Blob: src/rust/kj/own.rs

rust149 lines
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 
12use std::ops::Deref;
13use std::pin::Pin;
14 
15use 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.
37pub 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.
53pub enum OwnOrMut<'a, T> {
54 Own(KjOwn<T>),
55 MutRef(Pin<&'a mut T>),
56}
57 
58impl<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 
68impl<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 
85impl<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 
94impl<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 
104impl<T> Deref for OwnOrRef<'_, T> {
105 type Target = T;
106 
107 fn deref(&self) -> &Self::Target {
108 self.as_ref()
109 }
110}
111 
112impl<T> Deref for OwnOrMut<'_, T> {
113 type Target = T;
114 
115 fn deref(&self) -> &Self::Target {
116 self.as_ref()
117 }
118}
119 
120impl<'a, T> From<&'a T> for OwnOrRef<'a, T> {
121 fn from(value: &'a T) -> Self {
122 Self::Ref(value)
123 }
124}
125 
126impl<T> From<KjOwn<T>> for OwnOrRef<'_, T> {
127 fn from(value: KjOwn<T>) -> Self {
128 Self::Own(value)
129 }
130}
131 
132impl<'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 
138impl<T> From<KjOwn<T>> for OwnOrMut<'_, T> {
139 fn from(value: KjOwn<T>) -> Self {
140 Self::Own(value)
141 }
142}
143 
144impl<'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}