Tamir Duberstein
2025-Jul-04 20:16 UTC
[PATCH 0/6] Replace `kernel::str::CStr` with `core::ffi::CStr` (cycle 1)
This series makes preparations for the replacement of our custom `CStr`
type with the analogous type available in `core`.
As this is a large migration that touches many subsystems, it will take
place in several cycles, each of which may see multiple series:
1. introduces facades in the kernel crate that downstream
code can reference. [this series]
2. migrate downstream code to kernel crate facades. (N series, divided
by subsystem).
3. replace kernel crate facades to allow `Display`ing foreign types
(such as `core::ffi::CStr`). Replace `CStr` with `core::ffi::CStr`.
4. migrate uses of `c_str!` to C-String literals. Replace references to
`kernel::str::CStr` with `kernel::ffi::CStr`. (N series, divided by
subsystem).
5. rename `c_str!` to discourage use. Remove `CStr` reexport from
`kernel/str.rs`.
Signed-off-by: Tamir Duberstein <tamird at gmail.com>
---
Tamir Duberstein (6):
rust: kernel: remove `fmt!`, fix clippy::uninlined-format-args
rust: kernel: add `fmt` module
rust: use `kernel::{fmt,prelude::fmt!}`
rust: str: remove unnecessary qualification
rust: add `CStr` methods matching `core::ffi::CStr`
rust: use `core::ffi::CStr` method names
drivers/cpufreq/rcpufreq_dt.rs | 3 +-
drivers/gpu/nova-core/firmware.rs | 5 +-
rust/kernel/error.rs | 8 ++--
rust/kernel/fmt.rs | 7 +++
rust/kernel/lib.rs | 1 +
rust/kernel/opp.rs | 2 +-
rust/kernel/prelude.rs | 2 +-
rust/kernel/print.rs | 6 +--
rust/kernel/str.rs | 97 ++++++++++++++++++++++++---------------
samples/rust/rust_print_main.rs | 2 +-
10 files changed, 83 insertions(+), 50 deletions(-)
---
base-commit: 769e324b66b0d92d04f315d0c45a0f72737c7494
change-id: 20250704-core-cstr-prepare-9b9e6a7bd57e
Best regards,
--
Tamir Duberstein <tamird at gmail.com>
Tamir Duberstein
2025-Jul-04 20:16 UTC
[PATCH 1/6] rust: kernel: remove `fmt!`, fix clippy::uninlined-format-args
Rather than export a macro that delegates to `core::format_args`, simply
re-export `core::format_args` as `fmt` from the prelude. This exposes
clippy warnings which were previously obscured by this macro, such as:
warning: variables can be used directly in the `format!` string
--> ../drivers/cpufreq/rcpufreq_dt.rs:21:43
|
21 | let prop_name = CString::try_from_fmt(fmt!("{}-supply",
name)).ok()?;
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: for further information visit
https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
= note: `-W clippy::uninlined-format-args` implied by `-W clippy::all`
= help: to override `-W clippy::all` add
`#[allow(clippy::uninlined_format_args)]`
help: change this to
|
21 - let prop_name = CString::try_from_fmt(fmt!("{}-supply",
name)).ok()?;
21 + let prop_name =
CString::try_from_fmt(fmt!("{name}-supply")).ok()?;
|
Thus fix them in the same commit. This could possibly be fixed in two
stages, but the diff is small enough (outside of kernel/str.rs) that I
hope it can taken in a single commit.
Signed-off-by: Tamir Duberstein <tamird at gmail.com>
---
drivers/cpufreq/rcpufreq_dt.rs | 3 +--
drivers/gpu/nova-core/firmware.rs | 5 +++--
rust/kernel/opp.rs | 2 +-
rust/kernel/prelude.rs | 2 +-
rust/kernel/str.rs | 34 ++++++++++++++--------------------
5 files changed, 20 insertions(+), 26 deletions(-)
diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs
index 30a170570c0e..4608d2286fa1 100644
--- a/drivers/cpufreq/rcpufreq_dt.rs
+++ b/drivers/cpufreq/rcpufreq_dt.rs
@@ -9,7 +9,6 @@
cpumask::CpumaskVar,
device::{Core, Device},
error::code::*,
- fmt,
macros::vtable,
module_platform_driver, of, opp, platform,
prelude::*,
@@ -19,7 +18,7 @@
/// Finds exact supply name from the OF node.
fn find_supply_name_exact(dev: &Device, name: &str) ->
Option<CString> {
- let prop_name = CString::try_from_fmt(fmt!("{}-supply",
name)).ok()?;
+ let prop_name =
CString::try_from_fmt(fmt!("{name}-supply")).ok()?;
dev.property_present(&prop_name)
.then(|| CString::try_from_fmt(fmt!("{name}")).ok())
.flatten()
diff --git a/drivers/gpu/nova-core/firmware.rs
b/drivers/gpu/nova-core/firmware.rs
index 4b8a38358a4f..e503a4fddae0 100644
--- a/drivers/gpu/nova-core/firmware.rs
+++ b/drivers/gpu/nova-core/firmware.rs
@@ -24,11 +24,12 @@ pub(crate) struct Firmware {
impl Firmware {
pub(crate) fn new(dev: &device::Device, chipset: Chipset, ver:
&str) -> Result<Firmware> {
- let mut chip_name = CString::try_from_fmt(fmt!("{}",
chipset))?;
+ let mut chip_name =
CString::try_from_fmt(fmt!("{chipset}"))?;
chip_name.make_ascii_lowercase();
+ let chip_name = &*chip_name;
let request = |name_| {
- CString::try_from_fmt(fmt!("nvidia/{}/gsp/{}-{}.bin",
&*chip_name, name_, ver))
+
CString::try_from_fmt(fmt!("nvidia/{chip_name}/gsp/{name_}-{ver}.bin"))
.and_then(|path| firmware::Firmware::request(&path, dev))
};
diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs
index 0e94cb2703ec..5a161ad12bf7 100644
--- a/rust/kernel/opp.rs
+++ b/rust/kernel/opp.rs
@@ -345,7 +345,7 @@ fn drop(&mut self) {
/// impl ConfigOps for Driver {}
///
/// fn configure(dev: &ARef<Device>) -> Result<ConfigToken>
{
-/// let name = CString::try_from_fmt(fmt!("{}",
"slow"))?;
+/// let name = CString::try_from_fmt(fmt!("slow"))?;
///
/// // The OPP configuration is cleared once the [`ConfigToken`] goes out
of scope.
/// Config::<Driver>::new()
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index 2f30a398dddd..3ca934885797 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -31,9 +31,9 @@
// `super::std_vendor` is hidden, which makes the macro inline for some reason.
#[doc(no_inline)]
pub use super::dbg;
-pub use super::fmt;
pub use super::{dev_alert, dev_crit, dev_dbg, dev_emerg, dev_err, dev_info,
dev_notice, dev_warn};
pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info,
pr_notice, pr_warn};
+pub use core::format_args as fmt;
pub use super::{try_init, try_pin_init};
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index cbc8b459ed41..10399fb7af45 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -54,13 +54,13 @@ impl fmt::Display for BStr {
/// Formats printable ASCII characters, escaping the rest.
///
/// ```
- /// # use kernel::{fmt, b_str, str::{BStr, CString}};
+ /// # use kernel::{prelude::fmt, b_str, str::{BStr, CString}};
/// let ascii = b_str!("Hello, BStr!");
- /// let s = CString::try_from_fmt(fmt!("{}", ascii))?;
+ /// let s = CString::try_from_fmt(fmt!("{ascii}"))?;
/// assert_eq!(s.as_bytes(), "Hello, BStr!".as_bytes());
///
/// let non_ascii = b_str!("?");
- /// let s = CString::try_from_fmt(fmt!("{}", non_ascii))?;
+ /// let s = CString::try_from_fmt(fmt!("{non_ascii}"))?;
/// assert_eq!(s.as_bytes(), "\\xf0\\x9f\\xa6\\x80".as_bytes());
/// # Ok::<(), kernel::error::Error>(())
/// ```
@@ -85,14 +85,14 @@ impl fmt::Debug for BStr {
/// escaping the rest.
///
/// ```
- /// # use kernel::{fmt, b_str, str::{BStr, CString}};
+ /// # use kernel::{prelude::fmt, b_str, str::{BStr, CString}};
/// // Embedded double quotes are escaped.
/// let ascii = b_str!("Hello, \"BStr\"!");
- /// let s = CString::try_from_fmt(fmt!("{:?}", ascii))?;
+ /// let s = CString::try_from_fmt(fmt!("{ascii:?}"))?;
/// assert_eq!(s.as_bytes(), "\"Hello,
\\\"BStr\\\"!\"".as_bytes());
///
/// let non_ascii = b_str!("?");
- /// let s = CString::try_from_fmt(fmt!("{:?}", non_ascii))?;
+ /// let s = CString::try_from_fmt(fmt!("{non_ascii:?}"))?;
/// assert_eq!(s.as_bytes(),
"\"\\xf0\\x9f\\x98\\xba\"".as_bytes());
/// # Ok::<(), kernel::error::Error>(())
/// ```
@@ -429,15 +429,15 @@ impl fmt::Display for CStr {
///
/// ```
/// # use kernel::c_str;
- /// # use kernel::fmt;
+ /// # use kernel::prelude::fmt;
/// # use kernel::str::CStr;
/// # use kernel::str::CString;
/// let penguin = c_str!("?");
- /// let s = CString::try_from_fmt(fmt!("{}", penguin))?;
+ /// let s = CString::try_from_fmt(fmt!("{penguin}"))?;
/// assert_eq!(s.as_bytes_with_nul(),
"\\xf0\\x9f\\x90\\xa7\0".as_bytes());
///
/// let ascii = c_str!("so \"cool\"");
- /// let s = CString::try_from_fmt(fmt!("{}", ascii))?;
+ /// let s = CString::try_from_fmt(fmt!("{ascii}"))?;
/// assert_eq!(s.as_bytes_with_nul(), "so
\"cool\"\0".as_bytes());
/// # Ok::<(), kernel::error::Error>(())
/// ```
@@ -459,16 +459,16 @@ impl fmt::Debug for CStr {
///
/// ```
/// # use kernel::c_str;
- /// # use kernel::fmt;
+ /// # use kernel::prelude::fmt;
/// # use kernel::str::CStr;
/// # use kernel::str::CString;
/// let penguin = c_str!("?");
- /// let s = CString::try_from_fmt(fmt!("{:?}", penguin))?;
+ /// let s = CString::try_from_fmt(fmt!("{penguin:?}"))?;
/// assert_eq!(s.as_bytes_with_nul(),
"\"\\xf0\\x9f\\x90\\xa7\"\0".as_bytes());
///
/// // Embedded double quotes are escaped.
/// let ascii = c_str!("so \"cool\"");
- /// let s = CString::try_from_fmt(fmt!("{:?}", ascii))?;
+ /// let s = CString::try_from_fmt(fmt!("{ascii:?}"))?;
/// assert_eq!(s.as_bytes_with_nul(), "\"so
\\\"cool\\\"\"\0".as_bytes());
/// # Ok::<(), kernel::error::Error>(())
/// ```
@@ -578,7 +578,7 @@ mod tests {
macro_rules! format {
($($f:tt)*) => ({
- CString::try_from_fmt(::kernel::fmt!($($f)*))?.to_str()?
+ CString::try_from_fmt(fmt!($($f)*))?.to_str()?
})
}
@@ -840,7 +840,7 @@ fn write_str(&mut self, s: &str) -> fmt::Result {
/// # Examples
///
/// ```
-/// use kernel::{str::CString, fmt};
+/// use kernel::{str::CString, prelude::fmt};
///
/// let s = CString::try_from_fmt(fmt!("{}{}{}", "abc", 10,
20))?;
/// assert_eq!(s.as_bytes_with_nul(), "abc1020\0".as_bytes());
@@ -930,9 +930,3 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>)
-> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
-
-/// A convenience alias for [`core::format_args`].
-#[macro_export]
-macro_rules! fmt {
- ($($f:tt)*) => ( ::core::format_args!($($f)*) )
-}
--
2.50.0
`kernel::fmt` is a facade over `core::fmt` that can be used downstream,
allowing future changes to the formatting machinery to be contained
within the kernel crate without downstream code needing to be modified.
Signed-off-by: Tamir Duberstein <tamird at gmail.com>
---
rust/kernel/fmt.rs | 7 +++++++
rust/kernel/lib.rs | 1 +
2 files changed, 8 insertions(+)
diff --git a/rust/kernel/fmt.rs b/rust/kernel/fmt.rs
new file mode 100644
index 000000000000..0306e8388968
--- /dev/null
+++ b/rust/kernel/fmt.rs
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Formatting utilities.
+//!
+//! This module is intended to be used in place of `core::fmt` in kernel code.
+
+pub use core::fmt::{Arguments, Debug, Display, Error, Formatter, Result,
Write};
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 6b4774b2b1c3..aadcfaa5c759 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -77,6 +77,7 @@
pub mod faux;
#[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
pub mod firmware;
+pub mod fmt;
pub mod fs;
pub mod init;
pub mod io;
--
2.50.0
Tamir Duberstein
2025-Jul-04 20:16 UTC
[PATCH 3/6] rust: use `kernel::{fmt,prelude::fmt!}`
Reduce coupling to implementation details of the formatting machinery by
avoiding direct use for `core`'s formatting traits and macros.
Signed-off-by: Tamir Duberstein <tamird at gmail.com>
---
rust/kernel/error.rs | 6 +++---
rust/kernel/print.rs | 6 +++---
rust/kernel/str.rs | 2 +-
samples/rust/rust_print_main.rs | 2 +-
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
index 6277af1c1baa..ffa8efd2d547 100644
--- a/rust/kernel/error.rs
+++ b/rust/kernel/error.rs
@@ -6,10 +6,10 @@
use crate::{
alloc::{layout::LayoutError, AllocError},
+ fmt,
str::CStr,
};
-use core::fmt;
use core::num::NonZeroI32;
use core::num::TryFromIntError;
use core::str::Utf8Error;
@@ -219,8 +219,8 @@ fn from(_: LayoutError) -> Error {
}
}
-impl From<core::fmt::Error> for Error {
- fn from(_: core::fmt::Error) -> Error {
+impl From<fmt::Error> for Error {
+ fn from(_: fmt::Error) -> Error {
code::EINVAL
}
}
diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
index ecdcee43e5a5..2d743d78d220 100644
--- a/rust/kernel/print.rs
+++ b/rust/kernel/print.rs
@@ -8,10 +8,10 @@
use crate::{
ffi::{c_char, c_void},
+ fmt,
prelude::*,
str::RawFormatter,
};
-use core::fmt;
// Called from `vsprintf` with format specifier `%pA`.
#[expect(clippy::missing_safety_doc)]
@@ -149,7 +149,7 @@ macro_rules! print_macro (
// takes borrows on the arguments, but does not extend the scope of
temporaries.
// Therefore, a `match` expression is used to keep them around, since
// the scrutinee is kept until the end of the `match`.
- match format_args!($($arg)+) {
+ match $crate::prelude::fmt!($($arg)+) {
// SAFETY: This hidden macro should only be called by the
documented
// printing macros which ensure the format string is one of the
fixed
// ones. All `__LOG_PREFIX`s are null-terminated as they are
generated
@@ -168,7 +168,7 @@ macro_rules! print_macro (
// The `CONT` case.
($format_string:path, true, $($arg:tt)+) => (
$crate::print::call_printk_cont(
- format_args!($($arg)+),
+ $crate::prelude::fmt!($($arg)+),
);
);
);
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index 10399fb7af45..48d9a518db96 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -3,7 +3,7 @@
//! String representations.
use crate::alloc::{flags::*, AllocError, KVec};
-use core::fmt::{self, Write};
+use crate::fmt::{self, Write};
use core::ops::{self, Deref, DerefMut, Index};
use crate::prelude::*;
diff --git a/samples/rust/rust_print_main.rs b/samples/rust/rust_print_main.rs
index 8ea95e8c2f36..4095c72afeab 100644
--- a/samples/rust/rust_print_main.rs
+++ b/samples/rust/rust_print_main.rs
@@ -40,7 +40,7 @@ fn arc_print() -> Result {
// behaviour, contract or protocol on both `i32` and `&str` into a
single `Arc` of
// type `Arc<dyn Display>`.
- use core::fmt::Display;
+ use kernel::fmt::Display;
fn arc_dyn_print(arc: &Arc<dyn Display>) {
pr_info!("Arc<dyn Display> says {arc}");
}
--
2.50.0
Tamir Duberstein
2025-Jul-04 20:16 UTC
[PATCH 4/6] rust: str: remove unnecessary qualification
`core::ffi::*` is in the prelude, which is imported here.
Signed-off-by: Tamir Duberstein <tamird at gmail.com>
---
rust/kernel/str.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index 48d9a518db96..f326f0c40ab0 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -232,7 +232,7 @@ pub const fn is_empty(&self) -> bool {
/// last at least `'a`. When `CStr` is alive, the memory pointed by
`ptr`
/// must not be mutated.
#[inline]
- pub unsafe fn from_char_ptr<'a>(ptr: *const crate::ffi::c_char)
-> &'a Self {
+ pub unsafe fn from_char_ptr<'a>(ptr: *const c_char) ->
&'a Self {
// SAFETY: The safety precondition guarantees `ptr` is a valid pointer
// to a `NUL`-terminated C string.
let len = unsafe { bindings::strlen(ptr) } + 1;
@@ -295,7 +295,7 @@ pub unsafe fn from_bytes_with_nul_unchecked_mut(bytes:
&mut [u8]) -> &mut CStr {
/// Returns a C pointer to the string.
#[inline]
- pub const fn as_char_ptr(&self) -> *const crate::ffi::c_char {
+ pub const fn as_char_ptr(&self) -> *const c_char {
self.0.as_ptr()
}
--
2.50.0
Tamir Duberstein
2025-Jul-04 20:16 UTC
[PATCH 5/6] rust: add `CStr` methods matching `core::ffi::CStr`
Prepare for replacing `CStr` with `core::ffi::CStr` by soft-deprecating
methods which don't exist on `core::ffi::CStr`.
We could keep `as_bytes{,_with_nul}` through an extension trait but
seeing as we have to introduce `as_char_ptr_in_const_context` as a free
function, we may as well introduce `to_bytes{,_with_nul}` here to allow
downstream code to migrate in one cycle rather than two.
Link: https://github.com/Rust-for-Linux/linux/issues/1075
Signed-off-by: Tamir Duberstein <tamird at gmail.com>
---
rust/kernel/str.rs | 37 ++++++++++++++++++++++++++++++++++---
1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index f326f0c40ab0..cbb357fc0111 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -175,6 +175,15 @@ macro_rules! b_str {
}};
}
+/// Returns a C pointer to the string.
+// It is a free function rather than a method on an extension trait because:
+//
+// - error[E0379]: functions in trait impls cannot be declared const
+#[inline]
+pub const fn as_char_ptr_in_const_context(c_str: &CStr) -> *const c_char
{
+ c_str.0.as_ptr()
+}
+
/// Possible errors when using conversion functions in [`CStr`].
#[derive(Debug, Clone, Copy)]
pub enum CStrConvertError {
@@ -294,23 +303,45 @@ pub unsafe fn from_bytes_with_nul_unchecked_mut(bytes:
&mut [u8]) -> &mut CStr {
}
/// Returns a C pointer to the string.
+ ///
+ /// Using this function in a const context is deprecated in favor of
+ /// [`as_char_ptr_in_const_context`] in preparation for replacing `CStr`
with `core::ffi::CStr`
+ /// which does not have this method.
#[inline]
pub const fn as_char_ptr(&self) -> *const c_char {
- self.0.as_ptr()
+ as_char_ptr_in_const_context(self)
}
/// Convert the string to a byte slice without the trailing `NUL` byte.
#[inline]
- pub fn as_bytes(&self) -> &[u8] {
+ pub fn to_bytes(&self) -> &[u8] {
&self.0[..self.len()]
}
+ /// Convert the string to a byte slice without the trailing `NUL` byte.
+ ///
+ /// This function is deprecated in favor of [`Self::to_bytes`] in
preparation for replacing
+ /// `CStr` with `core::ffi::CStr` which does not have this method.
+ #[inline]
+ pub fn as_bytes(&self) -> &[u8] {
+ self.to_bytes()
+ }
+
/// Convert the string to a byte slice containing the trailing `NUL` byte.
#[inline]
- pub const fn as_bytes_with_nul(&self) -> &[u8] {
+ pub const fn to_bytes_with_nul(&self) -> &[u8] {
&self.0
}
+ /// Convert the string to a byte slice containing the trailing `NUL` byte.
+ ///
+ /// This function is deprecated in favor of [`Self::to_bytes_with_nul`] in
preparation for
+ /// replacing `CStr` with `core::ffi::CStr` which does not have this
method.
+ #[inline]
+ pub const fn as_bytes_with_nul(&self) -> &[u8] {
+ self.to_bytes_with_nul()
+ }
+
/// Yields a [`&str`] slice if the [`CStr`] contains valid UTF-8.
///
/// If the contents of the [`CStr`] are valid UTF-8 data, this
--
2.50.0
Tamir Duberstein
2025-Jul-04 20:16 UTC
[PATCH 6/6] rust: use `core::ffi::CStr` method names
Prepare for `core::ffi::CStr` taking the place of `kernel::str::CStr` by
avoiding methods that only exist on the latter.
Also avoid `Deref<Target=BStr> for CStr` as that impl doesn't exist on
`core::ffi::CStr`.
Link: https://github.com/Rust-for-Linux/linux/issues/1075
Signed-off-by: Tamir Duberstein <tamird at gmail.com>
---
rust/kernel/error.rs | 2 +-
rust/kernel/str.rs | 20 ++++++++++----------
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
index ffa8efd2d547..e29a5d76300e 100644
--- a/rust/kernel/error.rs
+++ b/rust/kernel/error.rs
@@ -188,7 +188,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>)
-> fmt::Result {
Some(name) => f
.debug_tuple(
// SAFETY: These strings are ASCII-only.
- unsafe { core::str::from_utf8_unchecked(name) },
+ unsafe { core::str::from_utf8_unchecked(name.to_bytes()) },
)
.finish(),
}
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index cbb357fc0111..6c892550c0ba 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -57,11 +57,11 @@ impl fmt::Display for BStr {
/// # use kernel::{prelude::fmt, b_str, str::{BStr, CString}};
/// let ascii = b_str!("Hello, BStr!");
/// let s = CString::try_from_fmt(fmt!("{ascii}"))?;
- /// assert_eq!(s.as_bytes(), "Hello, BStr!".as_bytes());
+ /// assert_eq!(s.to_bytes(), "Hello, BStr!".as_bytes());
///
/// let non_ascii = b_str!("?");
/// let s = CString::try_from_fmt(fmt!("{non_ascii}"))?;
- /// assert_eq!(s.as_bytes(), "\\xf0\\x9f\\xa6\\x80".as_bytes());
+ /// assert_eq!(s.to_bytes(), "\\xf0\\x9f\\xa6\\x80".as_bytes());
/// # Ok::<(), kernel::error::Error>(())
/// ```
fn fmt(&self, f: &mut fmt::Formatter<'_>) ->
fmt::Result {
@@ -89,11 +89,11 @@ impl fmt::Debug for BStr {
/// // Embedded double quotes are escaped.
/// let ascii = b_str!("Hello, \"BStr\"!");
/// let s = CString::try_from_fmt(fmt!("{ascii:?}"))?;
- /// assert_eq!(s.as_bytes(), "\"Hello,
\\\"BStr\\\"!\"".as_bytes());
+ /// assert_eq!(s.to_bytes(), "\"Hello,
\\\"BStr\\\"!\"".as_bytes());
///
/// let non_ascii = b_str!("?");
/// let s = CString::try_from_fmt(fmt!("{non_ascii:?}"))?;
- /// assert_eq!(s.as_bytes(),
"\"\\xf0\\x9f\\x98\\xba\"".as_bytes());
+ /// assert_eq!(s.to_bytes(),
"\"\\xf0\\x9f\\x98\\xba\"".as_bytes());
/// # Ok::<(), kernel::error::Error>(())
/// ```
fn fmt(&self, f: &mut fmt::Formatter<'_>) ->
fmt::Result {
@@ -465,15 +465,15 @@ impl fmt::Display for CStr {
/// # use kernel::str::CString;
/// let penguin = c_str!("?");
/// let s = CString::try_from_fmt(fmt!("{penguin}"))?;
- /// assert_eq!(s.as_bytes_with_nul(),
"\\xf0\\x9f\\x90\\xa7\0".as_bytes());
+ /// assert_eq!(s.to_bytes_with_nul(),
"\\xf0\\x9f\\x90\\xa7\0".as_bytes());
///
/// let ascii = c_str!("so \"cool\"");
/// let s = CString::try_from_fmt(fmt!("{ascii}"))?;
- /// assert_eq!(s.as_bytes_with_nul(), "so
\"cool\"\0".as_bytes());
+ /// assert_eq!(s.to_bytes_with_nul(), "so
\"cool\"\0".as_bytes());
/// # Ok::<(), kernel::error::Error>(())
/// ```
fn fmt(&self, f: &mut fmt::Formatter<'_>) ->
fmt::Result {
- for &c in self.as_bytes() {
+ for &c in self.to_bytes() {
if (0x20..0x7f).contains(&c) {
// Printable character.
f.write_char(c as char)?;
@@ -874,11 +874,11 @@ fn write_str(&mut self, s: &str) -> fmt::Result
{
/// use kernel::{str::CString, prelude::fmt};
///
/// let s = CString::try_from_fmt(fmt!("{}{}{}", "abc", 10,
20))?;
-/// assert_eq!(s.as_bytes_with_nul(), "abc1020\0".as_bytes());
+/// assert_eq!(s.to_bytes_with_nul(), "abc1020\0".as_bytes());
///
/// let tmp = "testing";
/// let s = CString::try_from_fmt(fmt!("{tmp}{}", 123))?;
-/// assert_eq!(s.as_bytes_with_nul(), "testing123\0".as_bytes());
+/// assert_eq!(s.to_bytes_with_nul(), "testing123\0".as_bytes());
///
/// // This fails because it has an embedded `NUL` byte.
/// let s = CString::try_from_fmt(fmt!("a\0b{}", 123));
@@ -948,7 +948,7 @@ impl<'a> TryFrom<&'a CStr> for
CString {
fn try_from(cstr: &'a CStr) -> Result<CString, AllocError>
{
let mut buf = KVec::new();
- buf.extend_from_slice(cstr.as_bytes_with_nul(), GFP_KERNEL)?;
+ buf.extend_from_slice(cstr.to_bytes_with_nul(), GFP_KERNEL)?;
// INVARIANT: The `CStr` and `CString` types have the same invariants
for
// the string data, and we copied it over without changes.
--
2.50.0
On Fri Jul 4, 2025 at 10:14 PM CEST, Tamir Duberstein wrote:> `kernel::fmt` is a facade over `core::fmt` that can be used downstream, > allowing future changes to the formatting machinery to be contained > within the kernel crate without downstream code needing to be modified. > > Signed-off-by: Tamir Duberstein <tamird at gmail.com>Reviewed-by: Benno Lossin <lossin at kernel.org> --- Cheers, Benno> --- > rust/kernel/fmt.rs | 7 +++++++ > rust/kernel/lib.rs | 1 + > 2 files changed, 8 insertions(+)
On Fri Jul 4, 2025 at 10:14 PM CEST, Tamir Duberstein wrote:> Prepare for `core::ffi::CStr` taking the place of `kernel::str::CStr` by > avoiding methods that only exist on the latter. > > Also avoid `Deref<Target=BStr> for CStr` as that impl doesn't exist on > `core::ffi::CStr`. > > Link: https://github.com/Rust-for-Linux/linux/issues/1075 > Signed-off-by: Tamir Duberstein <tamird at gmail.com>Reviewed-by: Benno Lossin <lossin at kernel.org> --- Cheers, Benno> --- > rust/kernel/error.rs | 2 +- > rust/kernel/str.rs | 20 ++++++++++---------- > 2 files changed, 11 insertions(+), 11 deletions(-)
On Fri Jul 4, 2025 at 10:14 PM CEST, Tamir Duberstein wrote:> Reduce coupling to implementation details of the formatting machinery by > avoiding direct use for `core`'s formatting traits and macros. > > Signed-off-by: Tamir Duberstein <tamird at gmail.com>Reviewed-by: Benno Lossin <lossin at kernel.org> --- Cheers, Benno> --- > rust/kernel/error.rs | 6 +++--- > rust/kernel/print.rs | 6 +++--- > rust/kernel/str.rs | 2 +- > samples/rust/rust_print_main.rs | 2 +- > 4 files changed, 8 insertions(+), 8 deletions(-)
Alice Ryhl
2025-Jul-10 13:20 UTC
[PATCH 0/6] Replace `kernel::str::CStr` with `core::ffi::CStr` (cycle 1)
On Fri, Jul 4, 2025 at 10:16?PM Tamir Duberstein <tamird at gmail.com> wrote:> > This series makes preparations for the replacement of our custom `CStr` > type with the analogous type available in `core`. > > As this is a large migration that touches many subsystems, it will take > place in several cycles, each of which may see multiple series: > 1. introduces facades in the kernel crate that downstream > code can reference. [this series] > 2. migrate downstream code to kernel crate facades. (N series, divided > by subsystem). > 3. replace kernel crate facades to allow `Display`ing foreign types > (such as `core::ffi::CStr`). Replace `CStr` with `core::ffi::CStr`. > 4. migrate uses of `c_str!` to C-String literals. Replace references to > `kernel::str::CStr` with `kernel::ffi::CStr`. (N series, divided by > subsystem). > 5. rename `c_str!` to discourage use. Remove `CStr` reexport from > `kernel/str.rs`. > > Signed-off-by: Tamir Duberstein <tamird at gmail.com> > --- > Tamir Duberstein (6): > rust: kernel: remove `fmt!`, fix clippy::uninlined-format-args > rust: kernel: add `fmt` module > rust: use `kernel::{fmt,prelude::fmt!}` > rust: str: remove unnecessary qualification > rust: add `CStr` methods matching `core::ffi::CStr` > rust: use `core::ffi::CStr` method names > > drivers/cpufreq/rcpufreq_dt.rs | 3 +- > drivers/gpu/nova-core/firmware.rs | 5 +- > rust/kernel/error.rs | 8 ++-- > rust/kernel/fmt.rs | 7 +++ > rust/kernel/lib.rs | 1 + > rust/kernel/opp.rs | 2 +- > rust/kernel/prelude.rs | 2 +- > rust/kernel/print.rs | 6 +-- > rust/kernel/str.rs | 97 ++++++++++++++++++++++++--------------- > samples/rust/rust_print_main.rs | 2 +- > 10 files changed, 83 insertions(+), 50 deletions(-) > --- > base-commit: 769e324b66b0d92d04f315d0c45a0f72737c7494 > change-id: 20250704-core-cstr-prepare-9b9e6a7bd57e > > Best regards, > -- > Tamir Duberstein <tamird at gmail.com> >Reviewed-by: Alice Ryhl <aliceryhl at google.com>