Skip to content

Commit a22b019

Browse files
committed
kernel: Add docstrings
Assisted-by: Claude Code Signed-off-by: Colin Walters <[email protected]>
1 parent 87b7d9d commit a22b019

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

crates/lib/src/kernel.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
//! Kernel command line parsing utilities.
2+
//!
3+
//! This module provides functionality for parsing and working with kernel command line
4+
//! arguments, supporting both key-only switches and key-value pairs with proper quote handling.
5+
16
use std::borrow::Cow;
27

38
use anyhow::Result;
@@ -7,19 +12,35 @@ pub(crate) const INITRD_ARG_PREFIX: &[u8] = b"rd.";
712
/// The kernel argument for configuring the rootfs flags.
813
pub(crate) const ROOTFLAGS: &[u8] = b"rootflags";
914

15+
/// A parsed kernel command line.
16+
///
17+
/// Wraps the raw command line bytes and provides methods for parsing and iterating
18+
/// over individual parameters. Uses copy-on-write semantics to avoid unnecessary
19+
/// allocations when working with borrowed data.
1020
pub(crate) struct Cmdline<'a>(Cow<'a, [u8]>);
1121

1222
impl<'a, T: AsRef<[u8]> + ?Sized> From<&'a T> for Cmdline<'a> {
23+
/// Creates a new `Cmdline` from any type that can be referenced as bytes.
24+
///
25+
/// Uses borrowed data when possible to avoid unnecessary allocations.
1326
fn from(input: &'a T) -> Self {
1427
Self(Cow::Borrowed(input.as_ref()))
1528
}
1629
}
1730

1831
impl<'a> Cmdline<'a> {
32+
/// Reads the kernel command line from `/proc/cmdline`.
33+
///
34+
/// Returns an error if the file cannot be read or if there are I/O issues.
1935
pub fn from_proc() -> Result<Self> {
2036
Ok(Self(Cow::Owned(std::fs::read("/proc/cmdline")?)))
2137
}
2238

39+
/// Returns an iterator over all parameters in the command line.
40+
///
41+
/// Properly handles quoted values containing whitespace and splits on
42+
/// unquoted whitespace characters. Parameters are parsed as either
43+
/// key-only switches or key=value pairs.
2344
pub fn iter(&'a self) -> impl Iterator<Item = Parameter<'a>> {
2445
let mut in_quotes = false;
2546

@@ -34,29 +55,50 @@ impl<'a> Cmdline<'a> {
3455
}
3556

3657
/// Locate a kernel argument with the given key name.
58+
///
59+
/// Returns the first parameter matching the given key, or `None` if not found.
60+
/// Key comparison treats dashes and underscores as equivalent.
3761
pub fn find(&'a self, key: impl AsRef<[u8]>) -> Option<Parameter<'a>> {
3862
let key = key.as_ref();
3963
self.iter().find(|p| p.key == key)
4064
}
4165
}
4266

67+
/// A single kernel command line parameter.
68+
///
69+
/// Can represent either a simple switch (key only) or a key-value pair.
70+
/// Handles quoted values and treats dashes and underscores in keys as equivalent.
4371
#[derive(Debug, Eq)]
4472
pub(crate) struct Parameter<'a> {
73+
/// The parameter key as raw bytes
4574
pub key: &'a [u8],
75+
/// The parameter value as raw bytes, if present
4676
pub value: Option<&'a [u8]>,
4777
}
4878

4979
impl<'a> Parameter<'a> {
80+
/// Returns the key as a lossy UTF-8 string.
81+
///
82+
/// Invalid UTF-8 sequences are replaced with the Unicode replacement character.
5083
pub fn key_lossy(&self) -> String {
5184
String::from_utf8_lossy(self.key).to_string()
5285
}
5386

87+
/// Returns the value as a lossy UTF-8 string.
88+
///
89+
/// Invalid UTF-8 sequences are replaced with the Unicode replacement character.
90+
/// Returns an empty string if no value is present.
5491
pub fn value_lossy(&self) -> String {
5592
String::from_utf8_lossy(self.value.unwrap_or(&[])).to_string()
5693
}
5794
}
5895

5996
impl<'a, T: AsRef<[u8]> + ?Sized> From<&'a T> for Parameter<'a> {
97+
/// Parses a parameter from raw bytes.
98+
///
99+
/// Splits on the first `=` character to separate key and value.
100+
/// Strips only the outermost pair of double quotes from values.
101+
/// If no `=` is found, treats the entire input as a key-only parameter.
60102
fn from(input: &'a T) -> Self {
61103
let input = input.as_ref();
62104
let equals = input.iter().position(|b| *b == b'=');
@@ -90,6 +132,11 @@ impl<'a, T: AsRef<[u8]> + ?Sized> From<&'a T> for Parameter<'a> {
90132
}
91133

92134
impl PartialEq for Parameter<'_> {
135+
/// Compares two parameters for equality.
136+
///
137+
/// Keys are compared with dashes and underscores treated as equivalent.
138+
/// Values must match exactly if both are present, or both must be absent.
139+
/// Prevents substring matching by ensuring full length equality.
93140
fn eq(&self, other: &Self) -> bool {
94141
let dedashed = |&c: &u8| {
95142
if c == b'-' {
@@ -118,6 +165,11 @@ impl PartialEq for Parameter<'_> {
118165
}
119166

120167
impl std::fmt::Display for Parameter<'_> {
168+
/// Formats the parameter for display.
169+
///
170+
/// Key-only parameters are displayed as just the key.
171+
/// Key-value parameters are displayed as `key=value`.
172+
/// Values containing whitespace are automatically quoted.
121173
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
122174
let key = self.key_lossy();
123175

0 commit comments

Comments
 (0)