nom_kconfig/attribute/
type.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            ))),
47            parse_if_attribute,
48        ),
49        |(t, i)| Attribute::Type(ConfigType { r#type: t, r#if: i }),
50    )
51    .parse(input)
52}
53
54#[derive(Debug, PartialEq, Clone)]
55#[cfg_attr(feature = "hash", derive(Hash))]
56#[cfg_attr(feature = "serialize", derive(Serialize))]
57#[cfg_attr(feature = "deserialize", derive(Deserialize))]
58#[cfg_attr(
59    any(feature = "serialize", feature = "deserialize"),
60    serde(rename_all = "lowercase")
61)]
62pub enum Type {
63    DefBool(Expression),
64    DefTristate(Expression),
65    Bool(Option<String>),
66    Tristate(Option<String>),
67    String(Option<String>),
68    Hex(Option<String>),
69    Int(Option<String>),
70}
71
72/// 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.
73#[derive(Debug, Clone, PartialEq)]
74#[cfg_attr(feature = "hash", derive(Hash))]
75#[cfg_attr(feature = "serialize", derive(Serialize))]
76#[cfg_attr(feature = "deserialize", derive(Deserialize))]
77pub struct ConfigType {
78    pub r#type: Type,
79    #[cfg_attr(
80        any(feature = "serialize", feature = "deserialize"),
81        serde(skip_serializing_if = "Option::is_none")
82    )]
83    pub r#if: Option<Expression>,
84}
85
86#[cfg(feature = "display")]
87impl Display for ConfigType {
88    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
89        match &self.r#if {
90            Some(i) => write!(f, "{} if {}", self.r#type, i),
91            None => write!(f, "{}", self.r#type),
92        }
93    }
94}
95
96#[cfg(feature = "display")]
97impl Display for Type {
98    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
99        match self {
100            Type::Bool(prompt) => fmt_type(f, "bool", prompt),
101            Type::Tristate(prompt) => fmt_type(f, "tristate", prompt),
102            Type::String(prompt) => fmt_type(f, "string", prompt),
103            Type::Hex(prompt) => fmt_type(f, "hex", prompt),
104            Type::Int(prompt) => fmt_type(f, "int", prompt),
105            Type::DefBool(v) => write!(f, "def_bool {}", v),
106            Type::DefTristate(v) => write!(f, "def_tristate {}", v),
107        }
108    }
109}
110
111#[cfg(feature = "display")]
112fn fmt_type(
113    f: &mut std::fmt::Formatter,
114    keyword: &str,
115    prompt: &Option<String>,
116) -> std::fmt::Result {
117    match prompt {
118        Some(p) => write!(f, "{} \"{}\"", keyword, p),
119        None => write!(f, "{}", keyword),
120    }
121}