kernel/cmdline/
parser.rs

1use core::num::ParseIntError;
2
3use super::tokenizer::Tokenizer;
4
5#[derive(Debug)]
6#[allow(dead_code)]
7pub enum ParseErrorKind<'a> {
8    Unexpected { need: &'a str, got: Option<&'a str> },
9    ParseIntError(ParseIntError),
10    UnexpectedId(&'a str),
11}
12
13#[derive(Debug)]
14#[allow(dead_code)]
15pub struct ParseError<'a> {
16    kind: ParseErrorKind<'a>,
17    loc: usize,
18}
19
20impl<'a> ParseError<'a> {
21    pub fn new(kind: ParseErrorKind<'a>, loc: usize) -> Self {
22        Self { kind, loc }
23    }
24}
25
26pub type Result<'a, T> = core::result::Result<T, ParseError<'a>>;
27
28pub trait CmdlineParse<'a>
29where
30    Self: Sized,
31{
32    fn parse_cmdline(tokenizer: &mut Tokenizer<'a>) -> Result<'a, Self>;
33}
34
35impl<'a> CmdlineParse<'a> for bool {
36    fn parse_cmdline(tokenizer: &mut Tokenizer<'a>) -> Result<'a, Self> {
37        let (loc, value) = tokenizer.next_value().ok_or_else(|| {
38            ParseError::new(
39                ParseErrorKind::Unexpected {
40                    need: "true/false",
41                    got: None,
42                },
43                tokenizer.current_index(),
44            )
45        })?;
46
47        match value {
48            "true" => Ok(true),
49            "false" => Ok(false),
50            _ => Err(ParseError::new(
51                ParseErrorKind::Unexpected {
52                    need: "true/false",
53                    got: Some(value),
54                },
55                loc,
56            )),
57        }
58    }
59}
60
61impl<'a> CmdlineParse<'a> for u32 {
62    fn parse_cmdline(tokenizer: &mut Tokenizer<'a>) -> Result<'a, Self> {
63        let (loc, value) = tokenizer.next_value().ok_or_else(|| {
64            ParseError::new(
65                ParseErrorKind::Unexpected {
66                    need: "<number>",
67                    got: None,
68                },
69                tokenizer.current_index(),
70            )
71        })?;
72
73        value
74            .parse()
75            .map_err(|e| ParseError::new(ParseErrorKind::ParseIntError(e), loc))
76    }
77}
78
79impl<'a> CmdlineParse<'a> for &'a str {
80    fn parse_cmdline(tokenizer: &mut Tokenizer<'a>) -> Result<'a, Self> {
81        let (_loc, value) = tokenizer.next_value().ok_or_else(|| {
82            ParseError::new(
83                ParseErrorKind::Unexpected {
84                    need: "<str>",
85                    got: None,
86                },
87                tokenizer.current_index(),
88            )
89        })?;
90
91        Ok(value)
92    }
93}