Skip to content

Commit 28d20f5

Browse files
committed
kernel_cmdline: impl IntoIterator and Extend for Cmdline
This makes it ergonomic to take two `Cmdline`s and update one by appending the parameters in the other. Signed-off-by: John Eckersberg <[email protected]>
1 parent f38017a commit 28d20f5

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed

crates/kernel_cmdline/src/bytes.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,23 @@ impl<'a> AsRef<[u8]> for Cmdline<'a> {
226226
}
227227
}
228228

229+
impl<'a> IntoIterator for &'a Cmdline<'a> {
230+
type Item = Parameter<'a>;
231+
type IntoIter = CmdlineIter<'a>;
232+
233+
fn into_iter(self) -> Self::IntoIter {
234+
self.iter()
235+
}
236+
}
237+
238+
impl<'a, 'other> Extend<Parameter<'other>> for Cmdline<'a> {
239+
fn extend<T: IntoIterator<Item = Parameter<'other>>>(&mut self, iter: T) {
240+
for param in iter {
241+
self.add(&param);
242+
}
243+
}
244+
}
245+
229246
/// A single kernel command line parameter key
230247
///
231248
/// Handles quoted values and treats dashes and underscores in keys as equivalent.
@@ -734,4 +751,49 @@ mod tests {
734751
assert_eq!(iter.next(), Some(param("b=2")));
735752
assert_eq!(iter.next(), None);
736753
}
754+
755+
#[test]
756+
fn test_extend() {
757+
let mut kargs = Cmdline::from(b"foo=bar baz");
758+
let other = Cmdline::from(b"qux=quux foo=updated");
759+
760+
kargs.extend(&other);
761+
762+
// Sanity check that the lifetimes of the two Cmdlines are not
763+
// tied to each other.
764+
drop(other);
765+
766+
// Should have preserved the original foo, added qux, baz
767+
// unchanged, and added the second (duplicate key) foo
768+
let mut iter = kargs.iter();
769+
assert_eq!(iter.next(), Some(param("foo=bar")));
770+
assert_eq!(iter.next(), Some(param("baz")));
771+
assert_eq!(iter.next(), Some(param("qux=quux")));
772+
assert_eq!(iter.next(), Some(param("foo=updated")));
773+
assert_eq!(iter.next(), None);
774+
}
775+
776+
#[test]
777+
fn test_extend_empty() {
778+
let mut kargs = Cmdline::from(b"");
779+
let other = Cmdline::from(b"foo=bar baz");
780+
781+
kargs.extend(&other);
782+
783+
let mut iter = kargs.iter();
784+
assert_eq!(iter.next(), Some(param("foo=bar")));
785+
assert_eq!(iter.next(), Some(param("baz")));
786+
assert_eq!(iter.next(), None);
787+
}
788+
789+
#[test]
790+
fn test_into_iterator() {
791+
let kargs = Cmdline::from(b"foo=bar baz=qux wiz");
792+
let params: Vec<_> = (&kargs).into_iter().collect();
793+
794+
assert_eq!(params.len(), 3);
795+
assert_eq!(params[0], param("foo=bar"));
796+
assert_eq!(params[1], param("baz=qux"));
797+
assert_eq!(params[2], param("wiz"));
798+
}
737799
}

crates/kernel_cmdline/src/utf8.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,23 @@ impl<'a> std::fmt::Display for Cmdline<'a> {
166166
}
167167
}
168168

169+
impl<'a> IntoIterator for &'a Cmdline<'a> {
170+
type Item = Parameter<'a>;
171+
type IntoIter = CmdlineIter<'a>;
172+
173+
fn into_iter(self) -> Self::IntoIter {
174+
self.iter()
175+
}
176+
}
177+
178+
impl<'a, 'other> Extend<Parameter<'other>> for Cmdline<'a> {
179+
fn extend<T: IntoIterator<Item = Parameter<'other>>>(&mut self, iter: T) {
180+
for param in iter {
181+
self.add(&param);
182+
}
183+
}
184+
}
185+
169186
/// A single kernel command line parameter key
170187
///
171188
/// Handles quoted values and treats dashes and underscores in keys as equivalent.
@@ -692,4 +709,49 @@ mod tests {
692709
assert_eq!(iter.next(), Some(param("b=2")));
693710
assert_eq!(iter.next(), None);
694711
}
712+
713+
#[test]
714+
fn test_extend() {
715+
let mut kargs = Cmdline::from("foo=bar baz");
716+
let other = Cmdline::from("qux=quux foo=updated");
717+
718+
kargs.extend(&other);
719+
720+
// Sanity check that the lifetimes of the two Cmdlines are not
721+
// tied to each other.
722+
drop(other);
723+
724+
// Should have preserved the original foo, added qux, baz
725+
// unchanged, and added the second (duplicate key) foo
726+
let mut iter = kargs.iter();
727+
assert_eq!(iter.next(), Some(param("foo=bar")));
728+
assert_eq!(iter.next(), Some(param("baz")));
729+
assert_eq!(iter.next(), Some(param("qux=quux")));
730+
assert_eq!(iter.next(), Some(param("foo=updated")));
731+
assert_eq!(iter.next(), None);
732+
}
733+
734+
#[test]
735+
fn test_extend_empty() {
736+
let mut kargs = Cmdline::from("");
737+
let other = Cmdline::from("foo=bar baz");
738+
739+
kargs.extend(&other);
740+
741+
let mut iter = kargs.iter();
742+
assert_eq!(iter.next(), Some(param("foo=bar")));
743+
assert_eq!(iter.next(), Some(param("baz")));
744+
assert_eq!(iter.next(), None);
745+
}
746+
747+
#[test]
748+
fn test_into_iterator() {
749+
let kargs = Cmdline::from("foo=bar baz=qux wiz");
750+
let params: Vec<_> = (&kargs).into_iter().collect();
751+
752+
assert_eq!(params.len(), 3);
753+
assert_eq!(params[0], param("foo=bar"));
754+
assert_eq!(params[1], param("baz=qux"));
755+
assert_eq!(params[2], param("wiz"));
756+
}
695757
}

0 commit comments

Comments
 (0)