@@ -206,7 +206,58 @@ impl<T, F: FnOnce(T)> Drop for ScopeGuard<T, F> {
206
206
207
207
/// Stores an opaque value.
208
208
///
209
- /// This is meant to be used with FFI objects that are never interpreted by Rust code.
209
+ /// `Opaque<T>` is meant to be used with FFI objects that are never interpreted by Rust code.
210
+ ///
211
+ /// It is used to wrap structs from the C side, like for example `Opaque<bindings::mutex>`.
212
+ /// It gets rid of all the usual assumptions that Rust has for a value:
213
+ ///
214
+ /// * The value is allowed to be uninitialized (for example have invalid bit patterns: `3` for a
215
+ /// [`bool`]).
216
+ /// * The value is allowed to be mutated, when a `&Opaque<T>` exists on the Rust side.
217
+ /// * No uniqueness for mutable references: it is fine to have multiple `&mut Opaque<T>` point to
218
+ /// the same value.
219
+ /// * The value is not allowed to be shared with other threads (i.e. it is `!Sync`).
220
+ ///
221
+ /// This has to be used for all values that the C side has access to, because it can't be ensured
222
+ /// that the C side is adhering to the usual constraints that Rust needs.
223
+ ///
224
+ /// Using `Opaque<T>` allows to continue to use references on the Rust side even for values shared
225
+ /// with C.
226
+ ///
227
+ /// # Examples
228
+ ///
229
+ /// ```
230
+ /// # #![expect(unreachable_pub, clippy::disallowed_names)]
231
+ /// use kernel::types::Opaque;
232
+ /// # // Emulate a C struct binding which is from C, maybe uninitialized or not, only the C side
233
+ /// # // knows.
234
+ /// # mod bindings {
235
+ /// # pub struct Foo {
236
+ /// # pub val: u8,
237
+ /// # }
238
+ /// # }
239
+ ///
240
+ /// // `foo.val` is assumed to be handled on the C side, so we use `Opaque` to wrap it.
241
+ /// pub struct Foo {
242
+ /// foo: Opaque<bindings::Foo>,
243
+ /// }
244
+ ///
245
+ /// impl Foo {
246
+ /// pub fn get_val(&self) -> u8 {
247
+ /// let ptr = Opaque::get(&self.foo);
248
+ ///
249
+ /// // SAFETY: `Self` is valid from C side.
250
+ /// unsafe { (*ptr).val }
251
+ /// }
252
+ /// }
253
+ ///
254
+ /// // Create an instance of `Foo` with the `Opaque` wrapper.
255
+ /// let foo = Foo {
256
+ /// foo: Opaque::new(bindings::Foo { val: 0xdb }),
257
+ /// };
258
+ ///
259
+ /// assert_eq!(foo.get_val(), 0xdb);
260
+ /// ```
210
261
#[ repr( transparent) ]
211
262
pub struct Opaque < T > {
212
263
value : UnsafeCell < MaybeUninit < T > > ,
0 commit comments