@@ -206,7 +206,58 @@ impl<T, F: FnOnce(T)> Drop for ScopeGuard<T, F> {
206206
207207/// Stores an opaque value.
208208///
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+ /// ```
210261#[ repr( transparent) ]
211262pub struct Opaque < T > {
212263 value : UnsafeCell < MaybeUninit < T > > ,
0 commit comments