Skip to main content

nom_kconfig/attribute/type/
mod.rs

1use crate::Attribute;
2use crate::{util::ws, KconfigInput};
3use nom::sequence::pair;
4use nom::Parser;
5use nom::{
6    branch::alt,
7    bytes::complete::tag,
8    combinator::{map, opt},
9    sequence::preceded,
10    IResult,
11};
12#[cfg(feature = "deserialize")]
13use serde::Deserialize;
14#[cfg(feature = "serialize")]
15use serde::Serialize;
16#[cfg(feature = "display")]
17use std::fmt::Display;
18
19use super::{parse_expression, parse_if_attribute, parse_prompt_value, Expression};
20
21pub fn parse_type(input: KconfigInput) -> IResult<KconfigInput, Attribute> {
22    map(
23        pair(
24            ws(alt((
25                map(
26                    preceded(tag("boolean"), opt(parse_prompt_value)),
27                    Type::Bool,
28                ),
29                map(preceded(tag("bool"), opt(parse_prompt_value)), Type::Bool),
30                map(preceded(tag("hex"), opt(parse_prompt_value)), Type::Hex),
31                map(preceded(tag("int"), opt(parse_prompt_value)), Type::Int),
32                map(
33                    preceded(tag("string"), opt(parse_prompt_value)),
34                    Type::String,
35                ),
36                map(
37                    preceded(tag("tristate"), opt(parse_prompt_value)),
38                    Type::Tristate,
39                ),
40                map(preceded(tag("def_bool"), ws(parse_expression)), |e| {
41                    Type::DefBool(e)
42                }),
43                map(preceded(tag("def_tristate"), ws(parse_expression)), |e| {
44                    Type::DefTristate(e)
45                }),
46                #[cfg(feature = "kconfiglib")]
47                map(preceded(tag("def_int"), ws(parse_expression)), |e| {
48                    Type::DefInt(e)
49                }),
50                #[cfg(feature = "kconfiglib")]
51                map(preceded(tag("def_hex"), ws(parse_expression)), |e| {
52                    Type::DefHex(e)
53                }),
54                #[cfg(feature = "kconfiglib")]
55                map(preceded(tag("def_string"), ws(parse_expression)), |e| {
56                    Type::DefString(e)
57                }),
58            ))),
59            parse_if_attribute,
60        ),
61        |(t, i)| Attribute::Type(ConfigType { r#type: t, r#if: i }),
62    )
63    .parse(input)
64}
65
66#[derive(Debug, PartialEq, Clone)]
67#[cfg_attr(feature = "hash", derive(Hash))]
68#[cfg_attr(feature = "serialize", derive(Serialize))]
69#[cfg_attr(feature = "deserialize", derive(Deserialize))]
70#[cfg_attr(
71    any(feature = "serialize", feature = "deserialize"),
72    serde(rename_all = "lowercase")
73)]
74pub enum Type {
75    Bool(Option<String>),
76    Tristate(Option<String>),
77    String(Option<String>),
78    Hex(Option<String>),
79    Int(Option<String>),
80    DefBool(Expression),
81    DefTristate(Expression),
82    #[cfg(feature = "kconfiglib")]
83    DefInt(Expression),
84    #[cfg(feature = "kconfiglib")]
85    DefHex(Expression),
86    #[cfg(feature = "kconfiglib")]
87    DefString(Expression),
88}
89
90/// Every config option must have a type. There are only two basic types: tristate and string; the other types are based on these two. The type definition optionally accepts an input prompt.
91#[derive(Debug, Clone, PartialEq)]
92#[cfg_attr(feature = "hash", derive(Hash))]
93#[cfg_attr(feature = "serialize", derive(Serialize))]
94#[cfg_attr(feature = "deserialize", derive(Deserialize))]
95pub struct ConfigType {
96    pub r#type: Type,
97    #[cfg_attr(
98        any(feature = "serialize", feature = "deserialize"),
99        serde(skip_serializing_if = "Option::is_none")
100    )]
101    pub r#if: Option<Expression>,
102}
103
104#[cfg(feature = "display")]
105impl Display for ConfigType {
106    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
107        match &self.r#if {
108            Some(i) => write!(f, "{} if {}", self.r#type, i),
109            None => write!(f, "{}", self.r#type),
110        }
111    }
112}
113
114#[cfg(feature = "display")]
115impl Display for Type {
116    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
117        match self {
118            Type::Bool(prompt) => fmt_type(f, "bool", prompt),
119            Type::Tristate(prompt) => fmt_type(f, "tristate", prompt),
120            Type::String(prompt) => fmt_type(f, "string", prompt),
121            Type::Hex(prompt) => fmt_type(f, "hex", prompt),
122            Type::Int(prompt) => fmt_type(f, "int", prompt),
123            Type::DefBool(v) => write!(f, "def_bool {}", v),
124            Type::DefTristate(v) => write!(f, "def_tristate {}", v),
125            #[cfg(feature = "kconfiglib")]
126            Type::DefInt(v) => write!(f, "def_int {}", v),
127            #[cfg(feature = "kconfiglib")]
128            Type::DefHex(v) => write!(f, "def_hex {}", v),
129            #[cfg(feature = "kconfiglib")]
130            Type::DefString(v) => write!(f, "def_string {}", v),
131        }
132    }
133}
134
135#[cfg(feature = "display")]
136fn fmt_type(
137    f: &mut std::fmt::Formatter,
138    keyword: &str,
139    prompt: &Option<String>,
140) -> std::fmt::Result {
141    match prompt {
142        Some(p) => write!(f, "{} \"{}\"", keyword, p),
143        None => write!(f, "{}", keyword),
144    }
145}
146
147#[cfg(test)]
148mod mod_test;