Skip to content

Commit 86f1157

Browse files
authored
Merge pull request #1611 from jeckersb/cmdline
cmdline tweaks and improvements
2 parents f4dfd81 + 8d68526 commit 86f1157

File tree

2 files changed

+99
-64
lines changed

2 files changed

+99
-64
lines changed

crates/kernel_cmdline/src/bytes.rs

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl<'a> Iterator for CmdlineIter<'a> {
4343
type Item = Parameter<'a>;
4444

4545
fn next(&mut self) -> Option<Self::Item> {
46-
let (param, rest) = Parameter::parse(self.0);
46+
let (param, rest) = Parameter::parse_one(self.0);
4747
self.0 = rest;
4848
param
4949
}
@@ -77,7 +77,7 @@ impl<'a> Cmdline<'a> {
7777
///
7878
/// Returns the first parameter matching the given key, or `None` if not found.
7979
/// Key comparison treats dashes and underscores as equivalent.
80-
pub fn find(&'a self, key: impl AsRef<[u8]>) -> Option<Parameter<'a>> {
80+
pub fn find<T: AsRef<[u8]> + ?Sized>(&'a self, key: &T) -> Option<Parameter<'a>> {
8181
let key = ParameterKey(key.as_ref());
8282
self.iter().find(|p| p.key == key)
8383
}
@@ -90,7 +90,10 @@ impl<'a> Cmdline<'a> {
9090
/// Otherwise, returns the first parameter matching the given key,
9191
/// or `None` if not found. Key comparison treats dashes and
9292
/// underscores as equivalent.
93-
pub fn find_utf8(&'a self, key: impl AsRef<str>) -> Result<Option<utf8::Parameter<'a>>> {
93+
pub fn find_utf8<T: AsRef<[u8]> + ?Sized>(
94+
&'a self,
95+
key: &T,
96+
) -> Result<Option<utf8::Parameter<'a>>> {
9497
let bytes = match self.find(key.as_ref()) {
9598
Some(p) => p,
9699
None => return Ok(None),
@@ -114,14 +117,14 @@ impl<'a> Cmdline<'a> {
114117
///
115118
/// Returns the first value matching the given key, or `None` if not found.
116119
/// Key comparison treats dashes and underscores as equivalent.
117-
pub fn value_of(&'a self, key: impl AsRef<[u8]>) -> Option<&'a [u8]> {
118-
self.find(key).and_then(|p| p.value)
120+
pub fn value_of<T: AsRef<[u8]> + ?Sized>(&'a self, key: &T) -> Option<&'a [u8]> {
121+
self.find(&key).and_then(|p| p.value)
119122
}
120123

121124
/// Find the value of the kernel argument with the provided name, which must be present.
122125
///
123126
/// Otherwise the same as [`Self::value_of`].
124-
pub fn require_value_of(&'a self, key: impl AsRef<[u8]>) -> Result<&'a [u8]> {
127+
pub fn require_value_of<T: AsRef<[u8]> + ?Sized>(&'a self, key: &T) -> Result<&'a [u8]> {
125128
let key = key.as_ref();
126129
self.value_of(key).ok_or_else(|| {
127130
let key = String::from_utf8_lossy(key);
@@ -135,7 +138,7 @@ impl<'a> Cmdline<'a> {
135138
///
136139
/// Returns `false` if the parameter already existed with the same
137140
/// content.
138-
pub fn add_or_modify(&mut self, param: Parameter) -> bool {
141+
pub fn add_or_modify(&mut self, param: &Parameter) -> bool {
139142
let mut new_params = Vec::new();
140143
let mut modified = false;
141144
let mut seen_key = false;
@@ -145,7 +148,7 @@ impl<'a> Cmdline<'a> {
145148
if !seen_key {
146149
// This is the first time we've seen this key.
147150
// We will replace it with the new parameter.
148-
if p != param {
151+
if p != *param {
149152
modified = true;
150153
}
151154
new_params.push(param.parameter);
@@ -181,12 +184,12 @@ impl<'a> Cmdline<'a> {
181184
/// Remove parameter(s) with the given key from the command line
182185
///
183186
/// Returns `true` if parameter(s) were removed.
184-
pub fn remove(&mut self, key: ParameterKey) -> bool {
187+
pub fn remove(&mut self, key: &ParameterKey) -> bool {
185188
let mut removed = false;
186189
let mut new_params = Vec::new();
187190

188191
for p in self.iter() {
189-
if p.key == key {
192+
if p.key == *key {
190193
removed = true;
191194
} else {
192195
new_params.push(p.parameter);
@@ -263,6 +266,18 @@ pub struct Parameter<'a> {
263266
}
264267

265268
impl<'a> Parameter<'a> {
269+
/// Attempt to parse a single command line parameter from a slice
270+
/// of bytes.
271+
///
272+
/// Returns `Some(Parameter)`, or `None` if a Parameter could not
273+
/// be constructed from the input. This occurs when the input is
274+
/// either empty or contains only whitespace.
275+
///
276+
/// Any remaining bytes not consumed from the input are discarded.
277+
pub fn parse<T: AsRef<[u8]> + ?Sized>(input: &'a T) -> Option<Self> {
278+
Self::parse_one(input).0
279+
}
280+
266281
/// Attempt to parse a single command line parameter from a slice
267282
/// of bytes.
268283
///
@@ -273,8 +288,8 @@ impl<'a> Parameter<'a> {
273288
///
274289
/// Any remaining bytes not consumed from the input are returned
275290
/// as the second tuple item.
276-
pub fn parse(input: &'a [u8]) -> (Option<Self>, &'a [u8]) {
277-
let input = input.trim_ascii_start();
291+
pub fn parse_one<T: AsRef<[u8]> + ?Sized>(input: &'a T) -> (Option<Self>, &'a [u8]) {
292+
let input = input.as_ref().trim_ascii_start();
278293

279294
if input.is_empty() {
280295
return (None, input);
@@ -352,33 +367,33 @@ mod tests {
352367

353368
// convenience methods for tests
354369
fn param(s: &str) -> Parameter<'_> {
355-
Parameter::parse(s.as_bytes()).0.unwrap()
370+
Parameter::parse(s.as_bytes()).unwrap()
356371
}
357372

358373
fn param_utf8(s: &str) -> utf8::Parameter<'_> {
359-
utf8::Parameter::parse(s).0.unwrap()
374+
utf8::Parameter::parse(s).unwrap()
360375
}
361376

362377
#[test]
363-
fn test_parameter_parse() {
364-
let (p, rest) = Parameter::parse(b"foo");
378+
fn test_parameter_parse_one() {
379+
let (p, rest) = Parameter::parse_one(b"foo");
365380
let p = p.unwrap();
366381
assert_eq!(p.key.0, b"foo");
367382
assert_eq!(p.value, None);
368383
assert_eq!(rest, "".as_bytes());
369384

370385
// should consume one parameter and return the rest of the input
371-
let (p, rest) = Parameter::parse(b"foo=bar baz");
386+
let (p, rest) = Parameter::parse_one(b"foo=bar baz");
372387
let p = p.unwrap();
373388
assert_eq!(p.key.0, b"foo");
374389
assert_eq!(p.value, Some(b"bar".as_slice()));
375390
assert_eq!(rest, " baz".as_bytes());
376391

377392
// should return None on empty or whitespace inputs
378-
let (p, rest) = Parameter::parse(b"");
393+
let (p, rest) = Parameter::parse_one(b"");
379394
assert!(p.is_none());
380395
assert_eq!(rest, b"".as_slice());
381-
let (p, rest) = Parameter::parse(b" ");
396+
let (p, rest) = Parameter::parse_one(b" ");
382397
assert!(p.is_none());
383398
assert_eq!(rest, b"".as_slice());
384399
}
@@ -415,7 +430,7 @@ mod tests {
415430

416431
#[test]
417432
fn test_parameter_internal_key_whitespace() {
418-
let (p, rest) = Parameter::parse("foo bar=baz".as_bytes());
433+
let (p, rest) = Parameter::parse_one("foo bar=baz".as_bytes());
419434
let p = p.unwrap();
420435
assert_eq!(p.key.0, b"foo");
421436
assert_eq!(p.value, None);
@@ -441,8 +456,7 @@ mod tests {
441456
assert!(failed_conversion.is_err());
442457
let mut p = b"foo=".to_vec();
443458
p.push(non_utf8_byte[0]);
444-
let (p, _rest) = Parameter::parse(&p);
445-
let p = p.unwrap();
459+
let p = Parameter::parse(&p).unwrap();
446460
assert_eq!(p.value, Some(non_utf8_byte.as_slice()));
447461
}
448462

@@ -630,22 +644,22 @@ mod tests {
630644
let mut kargs = Cmdline::from(b"foo=bar");
631645

632646
// add new
633-
assert!(kargs.add_or_modify(param("baz")));
647+
assert!(kargs.add_or_modify(&param("baz")));
634648
let mut iter = kargs.iter();
635649
assert_eq!(iter.next(), Some(param("foo=bar")));
636650
assert_eq!(iter.next(), Some(param("baz")));
637651
assert_eq!(iter.next(), None);
638652

639653
// modify existing
640-
assert!(kargs.add_or_modify(param("foo=fuz")));
654+
assert!(kargs.add_or_modify(&param("foo=fuz")));
641655
iter = kargs.iter();
642656
assert_eq!(iter.next(), Some(param("foo=fuz")));
643657
assert_eq!(iter.next(), Some(param("baz")));
644658
assert_eq!(iter.next(), None);
645659

646660
// already exists with same value returns false and doesn't
647661
// modify anything
648-
assert!(!kargs.add_or_modify(param("foo=fuz")));
662+
assert!(!kargs.add_or_modify(&param("foo=fuz")));
649663
iter = kargs.iter();
650664
assert_eq!(iter.next(), Some(param("foo=fuz")));
651665
assert_eq!(iter.next(), Some(param("baz")));
@@ -655,14 +669,14 @@ mod tests {
655669
#[test]
656670
fn test_add_or_modify_empty_cmdline() {
657671
let mut kargs = Cmdline::from(b"");
658-
assert!(kargs.add_or_modify(param("foo")));
672+
assert!(kargs.add_or_modify(&param("foo")));
659673
assert_eq!(kargs.0, b"foo".as_slice());
660674
}
661675

662676
#[test]
663677
fn test_add_or_modify_duplicate_parameters() {
664678
let mut kargs = Cmdline::from(b"a=1 a=2");
665-
assert!(kargs.add_or_modify(param("a=3")));
679+
assert!(kargs.add_or_modify(&param("a=3")));
666680
let mut iter = kargs.iter();
667681
assert_eq!(iter.next(), Some(param("a=3")));
668682
assert_eq!(iter.next(), None);
@@ -673,14 +687,14 @@ mod tests {
673687
let mut kargs = Cmdline::from(b"foo bar baz");
674688

675689
// remove existing
676-
assert!(kargs.remove("bar".into()));
690+
assert!(kargs.remove(&"bar".into()));
677691
let mut iter = kargs.iter();
678692
assert_eq!(iter.next(), Some(param("foo")));
679693
assert_eq!(iter.next(), Some(param("baz")));
680694
assert_eq!(iter.next(), None);
681695

682696
// doesn't exist? returns false and doesn't modify anything
683-
assert!(!kargs.remove("missing".into()));
697+
assert!(!kargs.remove(&"missing".into()));
684698
iter = kargs.iter();
685699
assert_eq!(iter.next(), Some(param("foo")));
686700
assert_eq!(iter.next(), Some(param("baz")));
@@ -690,7 +704,7 @@ mod tests {
690704
#[test]
691705
fn test_remove_duplicates() {
692706
let mut kargs = Cmdline::from(b"a=1 b=2 a=3");
693-
assert!(kargs.remove("a".into()));
707+
assert!(kargs.remove(&"a".into()));
694708
let mut iter = kargs.iter();
695709
assert_eq!(iter.next(), Some(param("b=2")));
696710
assert_eq!(iter.next(), None);

0 commit comments

Comments
 (0)