Commit 718c4069 authored by Dirk Behme's avatar Dirk Behme Committed by Miguel Ojeda
Browse files

rust: types: extend `Opaque` documentation



Update the `Opaque` documentation and add an example as proposed by
Miguel Ojeda in [1]. The documentation update is mainly taken from
Benno Lossin's description [2].

Cc: Nell Shamrell-Harrington <nells@linux.microsoft.com>
Suggested-by: default avatarMiguel Ojeda <ojeda@kernel.org>
Link: https://rust-for-linux.zulipchat.com/#narrow/stream/291565/topic/x/near/467478085 [1]
Link: https://rust-for-linux.zulipchat.com/#narrow/stream/291565/topic/x/near/470498289

 [2]
Co-developed-by: default avatarBenno Lossin <benno.lossin@proton.me>
Signed-off-by: default avatarBenno Lossin <benno.lossin@proton.me>
Signed-off-by: default avatarDirk Behme <dirk.behme@de.bosch.com>
Link: https://lore.kernel.org/r/20241002050301.1927545-1-dirk.behme@de.bosch.com


[ Used `expect`. Rewrapped docs. Added intra-doc link. Formatted
  example. Reworded to fix tag typo/order. Fixed `&mut` formatting
  as discussed. Added Benno's SOB and CDB as discussed. Shortened
  links. - Miguel ]
Signed-off-by: default avatarMiguel Ojeda <ojeda@kernel.org>
parent 28e84838
Loading
Loading
Loading
Loading
+52 −1
Original line number Diff line number Diff line
@@ -206,7 +206,58 @@ fn drop(&mut self) {

/// Stores an opaque value.
///
/// This is meant to be used with FFI objects that are never interpreted by Rust code.
/// `Opaque<T>` is meant to be used with FFI objects that are never interpreted by Rust code.
///
/// It is used to wrap structs from the C side, like for example `Opaque<bindings::mutex>`.
/// It gets rid of all the usual assumptions that Rust has for a value:
///
/// * The value is allowed to be uninitialized (for example have invalid bit patterns: `3` for a
///   [`bool`]).
/// * The value is allowed to be mutated, when a `&Opaque<T>` exists on the Rust side.
/// * No uniqueness for mutable references: it is fine to have multiple `&mut Opaque<T>` point to
///   the same value.
/// * The value is not allowed to be shared with other threads (i.e. it is `!Sync`).
///
/// This has to be used for all values that the C side has access to, because it can't be ensured
/// that the C side is adhering to the usual constraints that Rust needs.
///
/// Using `Opaque<T>` allows to continue to use references on the Rust side even for values shared
/// with C.
///
/// # Examples
///
/// ```
/// # #![expect(unreachable_pub, clippy::disallowed_names)]
/// use kernel::types::Opaque;
/// # // Emulate a C struct binding which is from C, maybe uninitialized or not, only the C side
/// # // knows.
/// # mod bindings {
/// #     pub struct Foo {
/// #         pub val: u8,
/// #     }
/// # }
///
/// // `foo.val` is assumed to be handled on the C side, so we use `Opaque` to wrap it.
/// pub struct Foo {
///     foo: Opaque<bindings::Foo>,
/// }
///
/// impl Foo {
///     pub fn get_val(&self) -> u8 {
///         let ptr = Opaque::get(&self.foo);
///
///         // SAFETY: `Self` is valid from C side.
///         unsafe { (*ptr).val }
///     }
/// }
///
/// // Create an instance of `Foo` with the `Opaque` wrapper.
/// let foo = Foo {
///     foo: Opaque::new(bindings::Foo { val: 0xdb }),
/// };
///
/// assert_eq!(foo.get_val(), 0xdb);
/// ```
#[repr(transparent)]
pub struct Opaque<T> {
    value: UnsafeCell<MaybeUninit<T>>,