Skip to content

Commit 8d68526

Browse files
committed
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<Parameter>`. 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 <[email protected]>
1 parent 78b677b commit 8d68526

File tree

2 files changed

+49
-25
lines changed

2 files changed

+49
-25
lines changed

crates/kernel_cmdline/src/bytes.rs

Lines changed: 23 additions & 12 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
}
@@ -266,6 +266,18 @@ pub struct Parameter<'a> {
266266
}
267267

268268
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+
269281
/// Attempt to parse a single command line parameter from a slice
270282
/// of bytes.
271283
///
@@ -276,7 +288,7 @@ impl<'a> Parameter<'a> {
276288
///
277289
/// Any remaining bytes not consumed from the input are returned
278290
/// as the second tuple item.
279-
pub fn parse<T: AsRef<[u8]> + ?Sized>(input: &'a T) -> (Option<Self>, &'a [u8]) {
291+
pub fn parse_one<T: AsRef<[u8]> + ?Sized>(input: &'a T) -> (Option<Self>, &'a [u8]) {
280292
let input = input.as_ref().trim_ascii_start();
281293

282294
if input.is_empty() {
@@ -355,33 +367,33 @@ mod tests {
355367

356368
// convenience methods for tests
357369
fn param(s: &str) -> Parameter<'_> {
358-
Parameter::parse(s.as_bytes()).0.unwrap()
370+
Parameter::parse(s.as_bytes()).unwrap()
359371
}
360372

361373
fn param_utf8(s: &str) -> utf8::Parameter<'_> {
362-
utf8::Parameter::parse(s).0.unwrap()
374+
utf8::Parameter::parse(s).unwrap()
363375
}
364376

365377
#[test]
366-
fn test_parameter_parse() {
367-
let (p, rest) = Parameter::parse(b"foo");
378+
fn test_parameter_parse_one() {
379+
let (p, rest) = Parameter::parse_one(b"foo");
368380
let p = p.unwrap();
369381
assert_eq!(p.key.0, b"foo");
370382
assert_eq!(p.value, None);
371383
assert_eq!(rest, "".as_bytes());
372384

373385
// should consume one parameter and return the rest of the input
374-
let (p, rest) = Parameter::parse(b"foo=bar baz");
386+
let (p, rest) = Parameter::parse_one(b"foo=bar baz");
375387
let p = p.unwrap();
376388
assert_eq!(p.key.0, b"foo");
377389
assert_eq!(p.value, Some(b"bar".as_slice()));
378390
assert_eq!(rest, " baz".as_bytes());
379391

380392
// should return None on empty or whitespace inputs
381-
let (p, rest) = Parameter::parse(b"");
393+
let (p, rest) = Parameter::parse_one(b"");
382394
assert!(p.is_none());
383395
assert_eq!(rest, b"".as_slice());
384-
let (p, rest) = Parameter::parse(b" ");
396+
let (p, rest) = Parameter::parse_one(b" ");
385397
assert!(p.is_none());
386398
assert_eq!(rest, b"".as_slice());
387399
}
@@ -418,7 +430,7 @@ mod tests {
418430

419431
#[test]
420432
fn test_parameter_internal_key_whitespace() {
421-
let (p, rest) = Parameter::parse("foo bar=baz".as_bytes());
433+
let (p, rest) = Parameter::parse_one("foo bar=baz".as_bytes());
422434
let p = p.unwrap();
423435
assert_eq!(p.key.0, b"foo");
424436
assert_eq!(p.value, None);
@@ -444,8 +456,7 @@ mod tests {
444456
assert!(failed_conversion.is_err());
445457
let mut p = b"foo=".to_vec();
446458
p.push(non_utf8_byte[0]);
447-
let (p, _rest) = Parameter::parse(&p);
448-
let p = p.unwrap();
459+
let p = Parameter::parse(&p).unwrap();
449460
assert_eq!(p.value, Some(non_utf8_byte.as_slice()));
450461
}
451462

crates/kernel_cmdline/src/utf8.rs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,19 @@ impl PartialEq for ParameterKey<'_> {
195195
pub struct Parameter<'a>(bytes::Parameter<'a>);
196196

197197
impl<'a> Parameter<'a> {
198+
/// Attempt to parse a single command line parameter from a UTF-8
199+
/// string.
200+
///
201+
/// Returns `Some(Parameter)`, or `None` if a Parameter could not
202+
/// be constructed from the input. This occurs when the input is
203+
/// either empty or contains only whitespace.
204+
///
205+
/// Any remaining characters not consumed from the input are
206+
/// discarded.
207+
pub fn parse<T: AsRef<str> + ?Sized>(input: &'a T) -> Option<Self> {
208+
Self::parse_one(input).0
209+
}
210+
198211
/// Attempt to parse a single command line parameter from a UTF-8
199212
/// string.
200213
///
@@ -205,8 +218,8 @@ impl<'a> Parameter<'a> {
205218
///
206219
/// Any remaining characters not consumed from the input are
207220
/// returned as the second tuple item.
208-
pub fn parse<T: AsRef<str> + ?Sized>(input: &'a T) -> (Option<Self>, &'a str) {
209-
let (bytes, rest) = bytes::Parameter::parse(input.as_ref().as_bytes());
221+
pub fn parse_one<T: AsRef<str> + ?Sized>(input: &'a T) -> (Option<Self>, &'a str) {
222+
let (bytes, rest) = bytes::Parameter::parse_one(input.as_ref().as_bytes());
210223

211224
// SAFETY: we know this is valid UTF-8 since input is &str,
212225
// and `rest` is a subslice of that &str which was split on
@@ -288,29 +301,29 @@ mod tests {
288301

289302
// convenience method for tests
290303
fn param(s: &str) -> Parameter<'_> {
291-
Parameter::parse(s).0.unwrap()
304+
Parameter::parse(s).unwrap()
292305
}
293306

294307
#[test]
295-
fn test_parameter_parse() {
296-
let (p, rest) = Parameter::parse("foo");
308+
fn test_parameter_parse_one() {
309+
let (p, rest) = Parameter::parse_one("foo");
297310
let p = p.unwrap();
298311
assert_eq!(p.key(), "foo".into());
299312
assert_eq!(p.value(), None);
300313
assert_eq!(rest, "");
301314

302315
// should consume one parameter and return the rest of the input
303-
let (p, rest) = Parameter::parse("foo=bar baz");
316+
let (p, rest) = Parameter::parse_one("foo=bar baz");
304317
let p = p.unwrap();
305318
assert_eq!(p.key(), "foo".into());
306319
assert_eq!(p.value(), Some("bar"));
307320
assert_eq!(rest, " baz");
308321

309322
// should return None on empty or whitespace inputs
310-
let (p, rest) = Parameter::parse("");
323+
let (p, rest) = Parameter::parse_one("");
311324
assert!(p.is_none());
312325
assert_eq!(rest, "");
313-
let (p, rest) = Parameter::parse(" ");
326+
let (p, rest) = Parameter::parse_one(" ");
314327
assert!(p.is_none());
315328
assert_eq!(rest, "");
316329
}
@@ -341,7 +354,7 @@ mod tests {
341354

342355
#[test]
343356
fn test_parameter_internal_key_whitespace() {
344-
let (p, rest) = Parameter::parse("foo bar=baz");
357+
let (p, rest) = Parameter::parse_one("foo bar=baz");
345358
let p = p.unwrap();
346359
assert_eq!(p.key(), "foo".into());
347360
assert_eq!(p.value(), None);
@@ -393,27 +406,27 @@ mod tests {
393406
#[test]
394407
fn test_parameter_tryfrom() {
395408
// ok switch
396-
let p = bytes::Parameter::parse(b"foo").0.unwrap();
409+
let p = bytes::Parameter::parse(b"foo").unwrap();
397410
let utf = Parameter::try_from(p).unwrap();
398411
assert_eq!(utf.key(), "foo".into());
399412
assert_eq!(utf.value(), None);
400413

401414
// ok key/value
402-
let p = bytes::Parameter::parse(b"foo=bar").0.unwrap();
415+
let p = bytes::Parameter::parse(b"foo=bar").unwrap();
403416
let utf = Parameter::try_from(p).unwrap();
404417
assert_eq!(utf.key(), "foo".into());
405418
assert_eq!(utf.value(), Some("bar".into()));
406419

407420
// bad switch
408-
let p = bytes::Parameter::parse(b"f\xffoo").0.unwrap();
421+
let p = bytes::Parameter::parse(b"f\xffoo").unwrap();
409422
let e = Parameter::try_from(p);
410423
assert_eq!(
411424
e.unwrap_err().to_string(),
412425
"Parameter key is not valid UTF-8"
413426
);
414427

415428
// bad key/value
416-
let p = bytes::Parameter::parse(b"foo=b\xffar").0.unwrap();
429+
let p = bytes::Parameter::parse(b"foo=b\xffar").unwrap();
417430
let e = Parameter::try_from(p);
418431
assert_eq!(
419432
e.unwrap_err().to_string(),

0 commit comments

Comments
 (0)