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: Miguel 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: Benno Lossin <benno.lossin@proton.me>
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
Signed-off-by: Dirk 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: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
Dirk Behme 2024-10-02 07:03:01 +02:00 committed by Miguel Ojeda
parent 28e848386b
commit 718c406989

View File

@ -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>>,