From 2006c105fc80c9a9b20ad0545e581a2a73e248da Mon Sep 17 00:00:00 2001 From: John Eckersberg Date: Mon, 10 Nov 2025 13:57:28 -0500 Subject: [PATCH 1/2] kernel_cmdline: Implement `Deref` for `Cmdline` Signed-off-by: John Eckersberg --- crates/kernel_cmdline/src/bytes.rs | 8 ++++++++ crates/kernel_cmdline/src/utf8.rs | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/crates/kernel_cmdline/src/bytes.rs b/crates/kernel_cmdline/src/bytes.rs index 73d062903..d96bfa51b 100644 --- a/crates/kernel_cmdline/src/bytes.rs +++ b/crates/kernel_cmdline/src/bytes.rs @@ -30,6 +30,14 @@ impl<'a, T: AsRef<[u8]> + ?Sized> From<&'a T> for Cmdline<'a> { } } +impl Deref for Cmdline<'_> { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl From> for CmdlineOwned { /// Creates a new `Cmdline` from an owned `Vec`. fn from(input: Vec) -> Self { diff --git a/crates/kernel_cmdline/src/utf8.rs b/crates/kernel_cmdline/src/utf8.rs index 5403154bb..19321ea27 100644 --- a/crates/kernel_cmdline/src/utf8.rs +++ b/crates/kernel_cmdline/src/utf8.rs @@ -213,6 +213,16 @@ impl<'a> Cmdline<'a> { } } +impl Deref for Cmdline<'_> { + type Target = str; + + fn deref(&self) -> &Self::Target { + // SAFETY: We know this is valid UTF-8 since we only + // construct the underlying `bytes` from valid UTF-8 + str::from_utf8(&self.0).expect("We only construct the underlying bytes from valid UTF-8") + } +} + impl<'a> AsRef for Cmdline<'a> { fn as_ref(&self) -> &str { str::from_utf8(self.0.as_ref()) From fcc92589841395d15b3e0eed995d1469eeeef1e4 Mon Sep 17 00:00:00 2001 From: John Eckersberg Date: Mon, 10 Nov 2025 11:16:34 -0500 Subject: [PATCH 2/2] kernel_cmdline: Simplify Display impl for utf8::Parameter Really we want to just return the original slice that the Parameter was created from. This also aligns with how Cmdline and ParameterKey impl Display. Where this really matters the most is to ensure we retain the quoting that the parameter was created with, so I added a test just to sanity check that. Before this change the test would fail because "foo" would be stripped of its quotes and just rendered as foo unquoted. Signed-off-by: John Eckersberg --- crates/kernel_cmdline/src/utf8.rs | 33 ++++++++++++++++--------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/crates/kernel_cmdline/src/utf8.rs b/crates/kernel_cmdline/src/utf8.rs index 19321ea27..9af6a3c76 100644 --- a/crates/kernel_cmdline/src/utf8.rs +++ b/crates/kernel_cmdline/src/utf8.rs @@ -232,8 +232,7 @@ impl<'a> AsRef for Cmdline<'a> { impl<'a> std::fmt::Display for Cmdline<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - let as_str: &str = self.as_ref(); - write!(f, "{as_str}") + f.write_str(self) } } @@ -267,7 +266,7 @@ impl<'a, 'other> Extend> for Cmdline<'a> { #[derive(Clone, Debug, Eq)] pub struct ParameterKey<'a>(bytes::ParameterKey<'a>); -impl<'a> std::ops::Deref for ParameterKey<'a> { +impl<'a> Deref for ParameterKey<'a> { type Target = str; fn deref(&self) -> &Self::Target { @@ -305,8 +304,7 @@ impl<'a, T: AsRef + ?Sized> From<&'a T> for ParameterKey<'a> { impl<'a> std::fmt::Display for ParameterKey<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - let as_str: &str = self; - write!(f, "{as_str}") + f.write_str(self) } } @@ -378,20 +376,11 @@ impl<'a> TryFrom> for Parameter<'a> { impl<'a> std::fmt::Display for Parameter<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - match self.value() { - Some(v) => { - if v.contains(|ch: char| ch.is_ascii_whitespace()) { - write!(f, "{}=\"{}\"", self.key(), v) - } else { - write!(f, "{}={}", self.key(), v) - } - } - None => write!(f, "{}", self.key()), - } + f.write_str(self) } } -impl<'a> std::ops::Deref for Parameter<'a> { +impl<'a> Deref for Parameter<'a> { type Target = str; fn deref(&self) -> &Self::Target { @@ -459,6 +448,18 @@ mod tests { assert_eq!(outside_quoted, value_quoted); } + #[test] + fn test_parameter_display() { + // Basically this should always return the original data + // without modification. + + // unquoted stays unquoted + assert_eq!(param("foo").to_string(), "foo"); + + // quoted stays quoted + assert_eq!(param("\"foo\"").to_string(), "\"foo\""); + } + #[test] fn test_parameter_extra_whitespace() { let p = param(" foo=bar ");