[PATCH] rust: types: 'real-life' example for Either

Timo Grautstueck posted 1 patch 1 month, 3 weeks ago
rust/kernel/types.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
[PATCH] rust: types: 'real-life' example for Either
Posted by Timo Grautstueck 1 month, 3 weeks ago
Added a 'real-life' example for the type `Either`. This example
uses a work queue and extends the first example in `workqueue.rs`
(commit ID: 15b286d) to demonstrate how to hold and distinguish
between two different data types.

Suggested-by: Miguel Ojeda <ojeda@kernel.org>
Link: https://github.com/Rust-for-Linux/linux/issues/1122
Signed-off-by: Timo Grautstueck <timo.grautstueck@web.de>
---
 rust/kernel/types.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
index 5ea9126c8c93..a56192141a0c 100644
--- a/rust/kernel/types.rs
+++ b/rust/kernel/types.rs
@@ -322,6 +322,60 @@ pub const fn raw_get(this: *const Self) -> *mut T {
 /// let left_value: Either<i32, &str> = Either::Left(7);
 /// let right_value: Either<i32, &str> = Either::Right("right value");
 /// ```
+///
+/// The following example demonstrates how we can create a struct
+/// that uses `Either` to hold either an integer or a string.
+/// This struct will be scheduled on the workqueue, and when executed,
+/// we will perform different actions depending on whether it holds
+/// a `Left` value (integer) or a `Right` value (string).
+///
+/// ```
+/// use kernel::prelude::*;
+/// use kernel::sync::Arc;
+/// use kernel::types::Either;
+/// use kernel::workqueue::{self, new_work, Work, WorkItem};
+///
+/// #[pin_data]
+/// struct WorkStruct {
+///     value: Either<i32, &'static str>,
+///     #[pin]
+///     work: Work<WorkStruct>,
+/// }
+///
+/// impl_has_work! {
+///     impl HasWork<Self> for WorkStruct { self.work }
+/// }
+///
+/// impl WorkStruct {
+///     fn new(value: Either<i32, &'static str>) -> Result<Arc<Self>> {
+///         Arc::pin_init(pin_init!(WorkStruct {
+///             value,
+///             work <- new_work!("WorkStruct::work"),
+///         }), GFP_KERNEL)
+///     }
+/// }
+///
+/// impl WorkItem for WorkStruct {
+///     type Pointer = Arc<WorkStruct>;
+///
+///     fn run(this: Arc<WorkStruct>) {
+///         match &this.value {
+///             Either::Left(left_value) => {
+///                 pr_info!("Left value: {}", left_value);
+///                 pr_info!("Left value times two: {}", left_value << 1);
+///             }
+///             Either::Right(right_value) => {
+///                 pr_info!("Right value: {}", right_value);
+///                 pr_info!("Length of right value: {}", right_value.len());
+///             }
+///         }
+///     }
+/// }
+///
+/// fn enqueue_work(work_item: Arc<WorkStruct>) {
+///     let _ = workqueue::system().enqueue(work_item);
+/// }
+/// ```
 pub enum Either<L, R> {
     /// Constructs an instance of [`Either`] containing a value of type `L`.
     Left(L),
--
2.46.2
Re: [PATCH] rust: types: 'real-life' example for Either
Posted by Miguel Ojeda 1 month, 3 weeks ago
On Mon, Oct 7, 2024 at 5:54 PM Timo Grautstueck <timo.grautstueck@web.de> wrote:
>
> Added a 'real-life' example for the type `Either`. This example
> uses a work queue and extends the first example in `workqueue.rs`
> (commit ID: 15b286d) to demonstrate how to hold and distinguish
> between two different data types.
>
> Suggested-by: Miguel Ojeda <ojeda@kernel.org>
> Link: https://github.com/Rust-for-Linux/linux/issues/1122
> Signed-off-by: Timo Grautstueck <timo.grautstueck@web.de>

This is a nice, self-contained example, thanks!

In the linked issue, I was aiming more to have a case where `Either`
was used in an interface (or similar) carrying two existing different
types, i.e. like in the talk I mentioned in the issue. I feel a custom
`enum` may work better anyway for something like the example in this
patch, i.e. when one does not have already types on each side that
make it obvious what each side is about.

So perhaps we can modify this example with two "message" or "action"
types (that may be hidden) or something similar that `Either` can
carry, so that it is a bit more concrete.

It wouldn't hurt either to showcase in addition the interface the talk
showed, perhaps in an `ignore` example so that we don't have to "mock"
everything.

Cheers,
Miguel