mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Daniel Sedlak <daniel@sedlak.dev>
To: gtimothy-dev@protonmail.com, Miguel Ojeda <ojeda@kernel.org>,
	Alex Gaynor <alex.gaynor@gmail.com>
Cc: "Boqun Feng" <boqun.feng@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <benno.lossin@proton.me>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org
Subject: Re: [PATCH RFC WIP v2] rust: add bitfield_options macro to create bitfield wrapper types
Date: Tue, 28 Jan 2025 20:29:49 +0100	[thread overview]
Message-ID: <79283554-ce12-4812-be1d-af8b420c1053@sedlak.dev> (raw)
In-Reply-To: <20250128-add-bitfield-options-macro-v2-1-d65349b389fc@protonmail.com>

Hello,
I do not have a strong opinion on whether this patch is actually needed 
thus I only do a quick review of the code/documentation part.

What I think is actually missing is an another patch integrating this or 
showing usage of this somewhere, for example in samples/drivers.

On 1/28/25 4:48 PM, Timothy Garwood via B4 Relay wrote:

> +//! Trait and macro to build bitfield wrappers.
> +//!
> +//! A trait and [`kernel::bitfield_options`] macro to build bitfield wrappers with
> +//! [`std::fs::OpenOptions`](https://doc.rust-lang.org/std/fs/struct.OpenOptions.html)-like methods to
> +//! set bits and _try to ensure an always-valid state_.
> +
> +/// A trait associating a bitfield type to a wrapper type to allow for shared trait implementations
> +/// and bitfield retrieval.
> +pub trait BitField {
> +    /// The bitfield type, usually `u8` or `u32`

Missing period at the end.

> +    type Bits;
> +
> +    /// returns the bits stored by the wrapper.
> +    fn bits(&self) -> Self::Bits;
> +}
> +
> +/// concatenate sequences using a comma separator. Uses a a `, and` (oxford comma) separation

Capitalization of the first word.

> +/// instead between the last two items.
> +#[doc(hidden)]
> +#[macro_export]
> +macro_rules! concat_with_oxford_comma {
> +    ($last:expr) => (concat!("and ", $last));
> +    ($left:expr, $($right:expr),+ ) => (
> +        concat!($left, ", ", $crate::concat_with_oxford_comma!($($right),+))
> +    )
> +}
> +
> +/// Builds a bitfield wrapper with
> +/// [`std::fs::OpenOptions`](https://doc.rust-lang.org/std/fs/struct.OpenOptions.html)-like methods to

This might be opinionated, but it may be better to use positional 
parameters [1] as it is not that noisy to read in the source code.

Link: 
https://doc.rust-lang.org/rustdoc/write-documentation/linking-to-items-by-name.html#valid-links 
[1]

> +/// set bits.
> +///
> +/// This wrapper _tries to ensure an always-valid state_, even when created from a bitfield
> +/// directly.
> +///
> +/// The wrapper implements the [`BitField`] trait.
> +///
> +/// # argument types
> +///   - `name`: the name of the wrapper to build.
> +///   - `type`: the bit field type, usually `u32` or `u8`. Must be an int primitive.
> +///   - `options`: array of `{ name:ident, true:expr, false:expr }` options where name is the name
> +///     of a method that will set the `true:expr` bit(s) when called with `true` or else the
> +///     `false:expr` bit(s). In a standard bitfield, `false:expr` is set to `false:0`, but sometimes
> +///     different bit flags designate incompatible alternatives : in these cases, set `false` to
> +///     activate the alternative bit(s).
> +///
> +/// # Examples
> +///
> +/// Call the macro to create the bitflag wrapper.
> +///
> +/// Here we create a wrapper that allows to set `RED`, `BLUE`, `GREEN` bits independently,
> +/// and additionally either the `BIG` bit or the `SMALL` bit.
> +///
> +/// `BIG` and `SMALL` are incompatible alternatives.
> +///
> +/// ```rust

The rust is implicit.

> +/// use kernel::bitfield_options;
> +///
> +/// const BIG: u32 = 16;
> +/// const SMALL: u32 = 1;
> +///
> +/// const RED: u32 = 2;
> +/// const GREEN: u32 = 4;
> +/// const BLUE: u32 = 8;
> +///
> +/// bitfield_options! {
> +///     name: SizeAndColors,
> +///     type: u32,
> +///     options: [
> +///         {name:big, true:BIG, false:SMALL},
> +///         {name:red, true:RED, false:0u32},
> +///         {name:blue, true:BLUE, false:0u32},
> +///         {name:green, true:GREEN, false:0u32}
> +///     ]
> +/// };
> +/// ```
> +///
> +/// The `SizeAndColor` type is now available in this scope.
> +///
> +/// It implements the [`Default`] trait where all options are set to `false`:
> +///
> +/// ```rust

The rust is implicit.

> +/// # use kernel::bitfield_options;
> +/// # use kernel::bitfield::BitField; // to have access to the bits() method
> +/// #
> +/// # const BIG: u32 = 16;
> +/// # const SMALL: u32 = 1;
> +/// #
> +/// # const RED: u32 = 2;
> +/// # const GREEN: u32 = 4;
> +/// # const BLUE: u32 = 8;
> +/// #
> +/// # bitfield_options! {
> +/// #     name: SizeAndColors,
> +/// #     type: u32,
> +/// #     options: [
> +/// #         {name:big, true:BIG, false:SMALL},
> +/// #         {name:red, true:RED, false:0u32},
> +/// #         {name:blue, true:BLUE, false:0u32},
> +/// #         {name:green, true:GREEN, false:0u32}
> +/// #     ]
> +/// # };
> +/// let sac = SizeAndColors::default();
> +///
> +/// // the default state, with all the options set to false should be the field with only the
> +/// // `SMALL` bit(s) set
> +/// assert_eq!(
> +///     sac.bits(),
> +///     SMALL | 0u32 | 0u32 | 0u32)
> +/// ```
> +///
> +/// It implements the [`TryFrom`] trait which succeeds only if the passed bitfield is a valid state:
> +///
> +/// ```rust

The rust is implicit.

> +/// # use kernel::bitfield_options;
> +/// #
> +/// # const BIG: u32 = 16;
> +/// # const SMALL: u32 = 1;
> +/// #
> +/// # const RED: u32 = 2;
> +/// # const GREEN: u32 = 4;
> +/// # const BLUE: u32 = 8;
> +/// #
> +/// # bitfield_options! {
> +/// #     name: SizeAndColors,
> +/// #     type: u32,
> +/// #     options: [
> +/// #         {name:big, true:BIG, false:SMALL},
> +/// #         {name:red, true:RED, false:0u32},
> +/// #         {name:blue, true:BLUE, false:0u32},
> +/// #         {name:green, true:GREEN, false:0u32}
> +/// #     ]
> +/// # };
> +/// # let sac = SizeAndColors::default();
> +/// let small_and_no_colors = SizeAndColors::try_from(SMALL)
> +///    .expect("having only the SMALL bit to 1 should be a valid state");
> +///
> +/// // Having only the `SMALL` bit set to 1 is the default state.
> +/// assert_eq!(sac, small_and_no_colors);
> +///
> +/// let big_and_rgb = SizeAndColors::try_from(BIG | RED | GREEN | BLUE)
> +///     .expect("having the BIG, RED, GREEN and BLUE bits set to 1 should be a valid state");
> +///
> +/// assert_eq!(
> +///     SizeAndColors::default()
> +///         .big(true)
> +///         .red(true)
> +///         .blue(true)
> +///         .green(true),
> +///     big_and_rgb
> +/// );
> +///
> +/// let big_and_small = SizeAndColors::try_from(BIG | SMALL)
> +///     .expect_err("BIG and SMALL are incompatible, this should fail");
> +///
> +/// let intense:u32 = 1024;
> +/// let big_and_intense = SizeAndColors::try_from(BIG | intense)
> +///     .expect_err("BIG|intense is not a valid state, this should fail");
> +/// ```

Daniel


  reply	other threads:[~2025-01-28 19:29 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-28 15:48 Timothy Garwood via B4 Relay
2025-01-28 19:29 ` Daniel Sedlak [this message]
2025-01-28 21:24   ` Timothy Garwood

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=79283554-ce12-4812-be1d-af8b420c1053@sedlak.dev \
    --to=daniel@sedlak.dev \
    --cc=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=gary@garyguo.net \
    --cc=gtimothy-dev@protonmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tmgross@umich.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®