From 02b06c01a619d59d51390c4c17753ea329841816 Mon Sep 17 00:00:00 2001 From: John Eckersberg Date: Fri, 12 Sep 2025 10:52:15 -0400 Subject: [PATCH 1/4] kernel_cmdline: Consistently take AsRef + ?Sized references where possible Signed-off-by: John Eckersberg --- crates/kernel_cmdline/src/bytes.rs | 17 ++++++++++------- crates/kernel_cmdline/src/utf8.rs | 23 ++++++++++++----------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/crates/kernel_cmdline/src/bytes.rs b/crates/kernel_cmdline/src/bytes.rs index 56a5a8dd5..400dd0e3b 100644 --- a/crates/kernel_cmdline/src/bytes.rs +++ b/crates/kernel_cmdline/src/bytes.rs @@ -77,7 +77,7 @@ impl<'a> Cmdline<'a> { /// /// Returns the first parameter matching the given key, or `None` if not found. /// Key comparison treats dashes and underscores as equivalent. - pub fn find(&'a self, key: impl AsRef<[u8]>) -> Option> { + pub fn find + ?Sized>(&'a self, key: &T) -> Option> { let key = ParameterKey(key.as_ref()); self.iter().find(|p| p.key == key) } @@ -90,7 +90,10 @@ impl<'a> Cmdline<'a> { /// Otherwise, returns the first parameter matching the given key, /// or `None` if not found. Key comparison treats dashes and /// underscores as equivalent. - pub fn find_utf8(&'a self, key: impl AsRef) -> Result>> { + pub fn find_utf8 + ?Sized>( + &'a self, + key: &T, + ) -> Result>> { let bytes = match self.find(key.as_ref()) { Some(p) => p, None => return Ok(None), @@ -114,14 +117,14 @@ impl<'a> Cmdline<'a> { /// /// Returns the first value matching the given key, or `None` if not found. /// Key comparison treats dashes and underscores as equivalent. - pub fn value_of(&'a self, key: impl AsRef<[u8]>) -> Option<&'a [u8]> { - self.find(key).and_then(|p| p.value) + pub fn value_of + ?Sized>(&'a self, key: &T) -> Option<&'a [u8]> { + self.find(&key).and_then(|p| p.value) } /// Find the value of the kernel argument with the provided name, which must be present. /// /// Otherwise the same as [`Self::value_of`]. - pub fn require_value_of(&'a self, key: impl AsRef<[u8]>) -> Result<&'a [u8]> { + pub fn require_value_of + ?Sized>(&'a self, key: &T) -> Result<&'a [u8]> { let key = key.as_ref(); self.value_of(key).ok_or_else(|| { let key = String::from_utf8_lossy(key); @@ -273,8 +276,8 @@ impl<'a> Parameter<'a> { /// /// Any remaining bytes not consumed from the input are returned /// as the second tuple item. - pub fn parse(input: &'a [u8]) -> (Option, &'a [u8]) { - let input = input.trim_ascii_start(); + pub fn parse + ?Sized>(input: &'a T) -> (Option, &'a [u8]) { + let input = input.as_ref().trim_ascii_start(); if input.is_empty() { return (None, input); diff --git a/crates/kernel_cmdline/src/utf8.rs b/crates/kernel_cmdline/src/utf8.rs index 0f87bd6e2..3d33793b5 100644 --- a/crates/kernel_cmdline/src/utf8.rs +++ b/crates/kernel_cmdline/src/utf8.rs @@ -72,7 +72,7 @@ impl<'a> Cmdline<'a> { /// /// Returns the first parameter matching the given key, or `None` if not found. /// Key comparison treats dashes and underscores as equivalent. - pub fn find(&'a self, key: impl AsRef) -> Option> { + pub fn find + ?Sized>(&'a self, key: &T) -> Option> { let key = ParameterKey::from(key.as_ref()); self.iter().find(|p| p.key() == key) } @@ -80,18 +80,19 @@ impl<'a> Cmdline<'a> { /// Find all kernel arguments starting with the given UTF-8 prefix. /// /// This is a variant of [`Self::find`]. - pub fn find_all_starting_with( + pub fn find_all_starting_with + ?Sized>( &'a self, - prefix: &'a str, + prefix: &'a T, ) -> impl Iterator> + 'a { - self.iter().filter(move |p| p.key().starts_with(prefix)) + self.iter() + .filter(move |p| p.key().starts_with(prefix.as_ref())) } /// Locate the value of the kernel argument with the given key name. /// /// Returns the first value matching the given key, or `None` if not found. /// Key comparison treats dashes and underscores as equivalent. - pub fn value_of(&'a self, key: impl AsRef) -> Option<&'a str> { + pub fn value_of + ?Sized>(&'a self, key: &T) -> Option<&'a str> { self.0.value_of(key.as_ref().as_bytes()).map(|v| { // SAFETY: We know this is valid UTF-8 since we only // construct the underlying `bytes` from valid UTF-8 @@ -102,7 +103,7 @@ impl<'a> Cmdline<'a> { /// Find the value of the kernel argument with the provided name, which must be present. /// /// Otherwise the same as [`Self::value_of`]. - pub fn require_value_of(&'a self, key: impl AsRef) -> Result<&'a str> { + pub fn require_value_of + ?Sized>(&'a self, key: &T) -> Result<&'a str> { let key = key.as_ref(); self.value_of(key) .ok_or_else(|| anyhow::anyhow!("Failed to find kernel argument '{key}'")) @@ -159,9 +160,9 @@ impl<'a> ParameterKey<'a> { } } -impl<'a> From<&'a str> for ParameterKey<'a> { - fn from(input: &'a str) -> Self { - Self(bytes::ParameterKey(input.as_bytes())) +impl<'a, T: AsRef + ?Sized> From<&'a T> for ParameterKey<'a> { + fn from(input: &'a T) -> Self { + Self(bytes::ParameterKey(input.as_ref().as_bytes())) } } @@ -197,8 +198,8 @@ impl<'a> Parameter<'a> { /// /// Any remaining characters not consumed from the input are /// returned as the second tuple item. - pub fn parse(input: &'a str) -> (Option, &'a str) { - let (bytes, rest) = bytes::Parameter::parse(input.as_bytes()); + pub fn parse + ?Sized>(input: &'a T) -> (Option, &'a str) { + let (bytes, rest) = bytes::Parameter::parse(input.as_ref().as_bytes()); // SAFETY: we know this is valid UTF-8 since input is &str, // and `rest` is a subslice of that &str which was split on From 1cf09f39dff1c7c9c1e2ff2792ce2b8a64e069af Mon Sep 17 00:00:00 2001 From: John Eckersberg Date: Fri, 12 Sep 2025 10:56:14 -0400 Subject: [PATCH 2/4] kernel_cmdline: impl Display for utf8::Cmdline We already impl AsRef but this just makes it more convenient to render the command line for users. Signed-off-by: John Eckersberg --- crates/kernel_cmdline/src/utf8.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/kernel_cmdline/src/utf8.rs b/crates/kernel_cmdline/src/utf8.rs index 3d33793b5..0336c7542 100644 --- a/crates/kernel_cmdline/src/utf8.rs +++ b/crates/kernel_cmdline/src/utf8.rs @@ -134,6 +134,13 @@ 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}") + } +} + /// A single kernel command line parameter key /// /// Handles quoted values and treats dashes and underscores in keys as equivalent. From 78b677bded5634e5497dffecdd0a785e2c722a5a Mon Sep 17 00:00:00 2001 From: John Eckersberg Date: Fri, 12 Sep 2025 14:21:26 -0400 Subject: [PATCH 3/4] kernel_cmdline: `add_or_modify` and `remove` should take borrowed input There's no reason these need to be owned. Signed-off-by: John Eckersberg --- crates/kernel_cmdline/src/bytes.rs | 24 ++++++++++++------------ crates/kernel_cmdline/src/utf8.rs | 24 ++++++++++++------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/crates/kernel_cmdline/src/bytes.rs b/crates/kernel_cmdline/src/bytes.rs index 400dd0e3b..de7ed0a18 100644 --- a/crates/kernel_cmdline/src/bytes.rs +++ b/crates/kernel_cmdline/src/bytes.rs @@ -138,7 +138,7 @@ impl<'a> Cmdline<'a> { /// /// Returns `false` if the parameter already existed with the same /// content. - pub fn add_or_modify(&mut self, param: Parameter) -> bool { + pub fn add_or_modify(&mut self, param: &Parameter) -> bool { let mut new_params = Vec::new(); let mut modified = false; let mut seen_key = false; @@ -148,7 +148,7 @@ impl<'a> Cmdline<'a> { if !seen_key { // This is the first time we've seen this key. // We will replace it with the new parameter. - if p != param { + if p != *param { modified = true; } new_params.push(param.parameter); @@ -184,12 +184,12 @@ impl<'a> Cmdline<'a> { /// Remove parameter(s) with the given key from the command line /// /// Returns `true` if parameter(s) were removed. - pub fn remove(&mut self, key: ParameterKey) -> bool { + pub fn remove(&mut self, key: &ParameterKey) -> bool { let mut removed = false; let mut new_params = Vec::new(); for p in self.iter() { - if p.key == key { + if p.key == *key { removed = true; } else { new_params.push(p.parameter); @@ -633,14 +633,14 @@ mod tests { let mut kargs = Cmdline::from(b"foo=bar"); // add new - assert!(kargs.add_or_modify(param("baz"))); + assert!(kargs.add_or_modify(¶m("baz"))); let mut iter = kargs.iter(); assert_eq!(iter.next(), Some(param("foo=bar"))); assert_eq!(iter.next(), Some(param("baz"))); assert_eq!(iter.next(), None); // modify existing - assert!(kargs.add_or_modify(param("foo=fuz"))); + assert!(kargs.add_or_modify(¶m("foo=fuz"))); iter = kargs.iter(); assert_eq!(iter.next(), Some(param("foo=fuz"))); assert_eq!(iter.next(), Some(param("baz"))); @@ -648,7 +648,7 @@ mod tests { // already exists with same value returns false and doesn't // modify anything - assert!(!kargs.add_or_modify(param("foo=fuz"))); + assert!(!kargs.add_or_modify(¶m("foo=fuz"))); iter = kargs.iter(); assert_eq!(iter.next(), Some(param("foo=fuz"))); assert_eq!(iter.next(), Some(param("baz"))); @@ -658,14 +658,14 @@ mod tests { #[test] fn test_add_or_modify_empty_cmdline() { let mut kargs = Cmdline::from(b""); - assert!(kargs.add_or_modify(param("foo"))); + assert!(kargs.add_or_modify(¶m("foo"))); assert_eq!(kargs.0, b"foo".as_slice()); } #[test] fn test_add_or_modify_duplicate_parameters() { let mut kargs = Cmdline::from(b"a=1 a=2"); - assert!(kargs.add_or_modify(param("a=3"))); + assert!(kargs.add_or_modify(¶m("a=3"))); let mut iter = kargs.iter(); assert_eq!(iter.next(), Some(param("a=3"))); assert_eq!(iter.next(), None); @@ -676,14 +676,14 @@ mod tests { let mut kargs = Cmdline::from(b"foo bar baz"); // remove existing - assert!(kargs.remove("bar".into())); + assert!(kargs.remove(&"bar".into())); let mut iter = kargs.iter(); assert_eq!(iter.next(), Some(param("foo"))); assert_eq!(iter.next(), Some(param("baz"))); assert_eq!(iter.next(), None); // doesn't exist? returns false and doesn't modify anything - assert!(!kargs.remove("missing".into())); + assert!(!kargs.remove(&"missing".into())); iter = kargs.iter(); assert_eq!(iter.next(), Some(param("foo"))); assert_eq!(iter.next(), Some(param("baz"))); @@ -693,7 +693,7 @@ mod tests { #[test] fn test_remove_duplicates() { let mut kargs = Cmdline::from(b"a=1 b=2 a=3"); - assert!(kargs.remove("a".into())); + assert!(kargs.remove(&"a".into())); let mut iter = kargs.iter(); assert_eq!(iter.next(), Some(param("b=2"))); assert_eq!(iter.next(), None); diff --git a/crates/kernel_cmdline/src/utf8.rs b/crates/kernel_cmdline/src/utf8.rs index 0336c7542..d6a4d35e3 100644 --- a/crates/kernel_cmdline/src/utf8.rs +++ b/crates/kernel_cmdline/src/utf8.rs @@ -115,15 +115,15 @@ impl<'a> Cmdline<'a> { /// /// Returns `false` if the parameter already existed with the same /// content. - pub fn add_or_modify(&mut self, param: Parameter) -> bool { - self.0.add_or_modify(param.0) + pub fn add_or_modify(&mut self, param: &Parameter) -> bool { + self.0.add_or_modify(¶m.0) } /// Remove parameter(s) with the given key from the command line /// /// Returns `true` if parameter(s) were removed. - pub fn remove(&mut self, key: ParameterKey) -> bool { - self.0.remove(key.0) + pub fn remove(&mut self, key: &ParameterKey) -> bool { + self.0.remove(&key.0) } } @@ -563,14 +563,14 @@ mod tests { let mut kargs = Cmdline::from("foo=bar"); // add new - assert!(kargs.add_or_modify(param("baz"))); + assert!(kargs.add_or_modify(¶m("baz"))); let mut iter = kargs.iter(); assert_eq!(iter.next(), Some(param("foo=bar"))); assert_eq!(iter.next(), Some(param("baz"))); assert_eq!(iter.next(), None); // modify existing - assert!(kargs.add_or_modify(param("foo=fuz"))); + assert!(kargs.add_or_modify(¶m("foo=fuz"))); iter = kargs.iter(); assert_eq!(iter.next(), Some(param("foo=fuz"))); assert_eq!(iter.next(), Some(param("baz"))); @@ -578,7 +578,7 @@ mod tests { // already exists with same value returns false and doesn't // modify anything - assert!(!kargs.add_or_modify(param("foo=fuz"))); + assert!(!kargs.add_or_modify(¶m("foo=fuz"))); iter = kargs.iter(); assert_eq!(iter.next(), Some(param("foo=fuz"))); assert_eq!(iter.next(), Some(param("baz"))); @@ -588,14 +588,14 @@ mod tests { #[test] fn test_add_or_modify_empty_cmdline() { let mut kargs = Cmdline::from(""); - assert!(kargs.add_or_modify(param("foo"))); + assert!(kargs.add_or_modify(¶m("foo"))); assert_eq!(kargs.as_ref(), "foo"); } #[test] fn test_add_or_modify_duplicate_parameters() { let mut kargs = Cmdline::from("a=1 a=2"); - assert!(kargs.add_or_modify(param("a=3"))); + assert!(kargs.add_or_modify(¶m("a=3"))); let mut iter = kargs.iter(); assert_eq!(iter.next(), Some(param("a=3"))); assert_eq!(iter.next(), None); @@ -606,14 +606,14 @@ mod tests { let mut kargs = Cmdline::from("foo bar baz"); // remove existing - assert!(kargs.remove("bar".into())); + assert!(kargs.remove(&"bar".into())); let mut iter = kargs.iter(); assert_eq!(iter.next(), Some(param("foo"))); assert_eq!(iter.next(), Some(param("baz"))); assert_eq!(iter.next(), None); // doesn't exist? returns false and doesn't modify anything - assert!(!kargs.remove("missing".into())); + assert!(!kargs.remove(&"missing".into())); iter = kargs.iter(); assert_eq!(iter.next(), Some(param("foo"))); assert_eq!(iter.next(), Some(param("baz"))); @@ -623,7 +623,7 @@ mod tests { #[test] fn test_remove_duplicates() { let mut kargs = Cmdline::from("a=1 b=2 a=3"); - assert!(kargs.remove("a".into())); + assert!(kargs.remove(&"a".into())); let mut iter = kargs.iter(); assert_eq!(iter.next(), Some(param("b=2"))); assert_eq!(iter.next(), None); From 8d68526cc2f8e3edaede4c00a51e7bc2324e4341 Mon Sep 17 00:00:00 2001 From: John Eckersberg Date: Fri, 12 Sep 2025 15:42:48 -0400 Subject: [PATCH 4/4] kernel_cmdline: rename `parse` to `parse_one` and add new `parse` method The (now-named) parse_one method is not particularly useful outside of `CmdlineIter`. Almost always end users don't care about extra unparsed content, they just want the `Option`. This greatly improves ergnomics for users so they can create parameters like... `Parameter::parse("foo=bar").unwrap()` ... knowing at the call-site that "foo=bar" is a valid parameter so the `unwrap()` is safe. Signed-off-by: John Eckersberg --- crates/kernel_cmdline/src/bytes.rs | 35 ++++++++++++++++++--------- crates/kernel_cmdline/src/utf8.rs | 39 ++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 25 deletions(-) diff --git a/crates/kernel_cmdline/src/bytes.rs b/crates/kernel_cmdline/src/bytes.rs index de7ed0a18..8ff518e89 100644 --- a/crates/kernel_cmdline/src/bytes.rs +++ b/crates/kernel_cmdline/src/bytes.rs @@ -43,7 +43,7 @@ impl<'a> Iterator for CmdlineIter<'a> { type Item = Parameter<'a>; fn next(&mut self) -> Option { - let (param, rest) = Parameter::parse(self.0); + let (param, rest) = Parameter::parse_one(self.0); self.0 = rest; param } @@ -266,6 +266,18 @@ pub struct Parameter<'a> { } impl<'a> Parameter<'a> { + /// Attempt to parse a single command line parameter from a slice + /// of bytes. + /// + /// Returns `Some(Parameter)`, or `None` if a Parameter could not + /// be constructed from the input. This occurs when the input is + /// either empty or contains only whitespace. + /// + /// Any remaining bytes not consumed from the input are discarded. + pub fn parse + ?Sized>(input: &'a T) -> Option { + Self::parse_one(input).0 + } + /// Attempt to parse a single command line parameter from a slice /// of bytes. /// @@ -276,7 +288,7 @@ impl<'a> Parameter<'a> { /// /// Any remaining bytes not consumed from the input are returned /// as the second tuple item. - pub fn parse + ?Sized>(input: &'a T) -> (Option, &'a [u8]) { + pub fn parse_one + ?Sized>(input: &'a T) -> (Option, &'a [u8]) { let input = input.as_ref().trim_ascii_start(); if input.is_empty() { @@ -355,33 +367,33 @@ mod tests { // convenience methods for tests fn param(s: &str) -> Parameter<'_> { - Parameter::parse(s.as_bytes()).0.unwrap() + Parameter::parse(s.as_bytes()).unwrap() } fn param_utf8(s: &str) -> utf8::Parameter<'_> { - utf8::Parameter::parse(s).0.unwrap() + utf8::Parameter::parse(s).unwrap() } #[test] - fn test_parameter_parse() { - let (p, rest) = Parameter::parse(b"foo"); + fn test_parameter_parse_one() { + let (p, rest) = Parameter::parse_one(b"foo"); let p = p.unwrap(); assert_eq!(p.key.0, b"foo"); assert_eq!(p.value, None); assert_eq!(rest, "".as_bytes()); // should consume one parameter and return the rest of the input - let (p, rest) = Parameter::parse(b"foo=bar baz"); + let (p, rest) = Parameter::parse_one(b"foo=bar baz"); let p = p.unwrap(); assert_eq!(p.key.0, b"foo"); assert_eq!(p.value, Some(b"bar".as_slice())); assert_eq!(rest, " baz".as_bytes()); // should return None on empty or whitespace inputs - let (p, rest) = Parameter::parse(b""); + let (p, rest) = Parameter::parse_one(b""); assert!(p.is_none()); assert_eq!(rest, b"".as_slice()); - let (p, rest) = Parameter::parse(b" "); + let (p, rest) = Parameter::parse_one(b" "); assert!(p.is_none()); assert_eq!(rest, b"".as_slice()); } @@ -418,7 +430,7 @@ mod tests { #[test] fn test_parameter_internal_key_whitespace() { - let (p, rest) = Parameter::parse("foo bar=baz".as_bytes()); + let (p, rest) = Parameter::parse_one("foo bar=baz".as_bytes()); let p = p.unwrap(); assert_eq!(p.key.0, b"foo"); assert_eq!(p.value, None); @@ -444,8 +456,7 @@ mod tests { assert!(failed_conversion.is_err()); let mut p = b"foo=".to_vec(); p.push(non_utf8_byte[0]); - let (p, _rest) = Parameter::parse(&p); - let p = p.unwrap(); + let p = Parameter::parse(&p).unwrap(); assert_eq!(p.value, Some(non_utf8_byte.as_slice())); } diff --git a/crates/kernel_cmdline/src/utf8.rs b/crates/kernel_cmdline/src/utf8.rs index d6a4d35e3..9d51592fa 100644 --- a/crates/kernel_cmdline/src/utf8.rs +++ b/crates/kernel_cmdline/src/utf8.rs @@ -195,6 +195,19 @@ impl PartialEq for ParameterKey<'_> { pub struct Parameter<'a>(bytes::Parameter<'a>); impl<'a> Parameter<'a> { + /// Attempt to parse a single command line parameter from a UTF-8 + /// string. + /// + /// Returns `Some(Parameter)`, or `None` if a Parameter could not + /// be constructed from the input. This occurs when the input is + /// either empty or contains only whitespace. + /// + /// Any remaining characters not consumed from the input are + /// discarded. + pub fn parse + ?Sized>(input: &'a T) -> Option { + Self::parse_one(input).0 + } + /// Attempt to parse a single command line parameter from a UTF-8 /// string. /// @@ -205,8 +218,8 @@ impl<'a> Parameter<'a> { /// /// Any remaining characters not consumed from the input are /// returned as the second tuple item. - pub fn parse + ?Sized>(input: &'a T) -> (Option, &'a str) { - let (bytes, rest) = bytes::Parameter::parse(input.as_ref().as_bytes()); + pub fn parse_one + ?Sized>(input: &'a T) -> (Option, &'a str) { + let (bytes, rest) = bytes::Parameter::parse_one(input.as_ref().as_bytes()); // SAFETY: we know this is valid UTF-8 since input is &str, // and `rest` is a subslice of that &str which was split on @@ -288,29 +301,29 @@ mod tests { // convenience method for tests fn param(s: &str) -> Parameter<'_> { - Parameter::parse(s).0.unwrap() + Parameter::parse(s).unwrap() } #[test] - fn test_parameter_parse() { - let (p, rest) = Parameter::parse("foo"); + fn test_parameter_parse_one() { + let (p, rest) = Parameter::parse_one("foo"); let p = p.unwrap(); assert_eq!(p.key(), "foo".into()); assert_eq!(p.value(), None); assert_eq!(rest, ""); // should consume one parameter and return the rest of the input - let (p, rest) = Parameter::parse("foo=bar baz"); + let (p, rest) = Parameter::parse_one("foo=bar baz"); let p = p.unwrap(); assert_eq!(p.key(), "foo".into()); assert_eq!(p.value(), Some("bar")); assert_eq!(rest, " baz"); // should return None on empty or whitespace inputs - let (p, rest) = Parameter::parse(""); + let (p, rest) = Parameter::parse_one(""); assert!(p.is_none()); assert_eq!(rest, ""); - let (p, rest) = Parameter::parse(" "); + let (p, rest) = Parameter::parse_one(" "); assert!(p.is_none()); assert_eq!(rest, ""); } @@ -341,7 +354,7 @@ mod tests { #[test] fn test_parameter_internal_key_whitespace() { - let (p, rest) = Parameter::parse("foo bar=baz"); + let (p, rest) = Parameter::parse_one("foo bar=baz"); let p = p.unwrap(); assert_eq!(p.key(), "foo".into()); assert_eq!(p.value(), None); @@ -393,19 +406,19 @@ mod tests { #[test] fn test_parameter_tryfrom() { // ok switch - let p = bytes::Parameter::parse(b"foo").0.unwrap(); + let p = bytes::Parameter::parse(b"foo").unwrap(); let utf = Parameter::try_from(p).unwrap(); assert_eq!(utf.key(), "foo".into()); assert_eq!(utf.value(), None); // ok key/value - let p = bytes::Parameter::parse(b"foo=bar").0.unwrap(); + let p = bytes::Parameter::parse(b"foo=bar").unwrap(); let utf = Parameter::try_from(p).unwrap(); assert_eq!(utf.key(), "foo".into()); assert_eq!(utf.value(), Some("bar".into())); // bad switch - let p = bytes::Parameter::parse(b"f\xffoo").0.unwrap(); + let p = bytes::Parameter::parse(b"f\xffoo").unwrap(); let e = Parameter::try_from(p); assert_eq!( e.unwrap_err().to_string(), @@ -413,7 +426,7 @@ mod tests { ); // bad key/value - let p = bytes::Parameter::parse(b"foo=b\xffar").0.unwrap(); + let p = bytes::Parameter::parse(b"foo=b\xffar").unwrap(); let e = Parameter::try_from(p); assert_eq!( e.unwrap_err().to_string(),