nom_kconfig/attribute/
type.rs

1use crate::Attribute;
2use crate::{util::ws, KconfigInput};
3use nom::sequence::pair;
4use nom::{
5    branch::alt,
6    bytes::complete::tag,
7    combinator::{map, opt},
8    sequence::preceded,
9    IResult,
10};
11#[cfg(feature = "deserialize")]
12use serde::Deserialize;
13#[cfg(feature = "serialize")]
14use serde::Serialize;
15#[cfg(feature = "display")]
16use std::fmt::Display;
17
18use super::{parse_expression, parse_if_attribute, parse_prompt_value, Expression};
19
20pub fn parse_type(input: KconfigInput) -> IResult<KconfigInput, Attribute> {
21    map(
22        pair(
23            ws(alt((
24                map(
25                    preceded(tag("boolean"), opt(parse_prompt_value)),
26                    Type::Bool,
27                ),
28                map(preceded(tag("bool"), opt(parse_prompt_value)), Type::Bool),
29                map(preceded(tag("hex"), opt(parse_prompt_value)), Type::Hex),
30                map(preceded(tag("int"), opt(parse_prompt_value)), Type::Int),
31                map(
32                    preceded(tag("string"), opt(parse_prompt_value)),
33                    Type::String,
34                ),
35                map(
36                    preceded(tag("tristate"), opt(parse_prompt_value)),
37                    Type::Tristate,
38                ),
39                map(preceded(tag("def_bool"), ws(parse_expression)), |e| {
40                    Type::DefBool(e)
41                }),
42                map(preceded(tag("def_tristate"), ws(parse_expression)), |e| {
43                    Type::DefTristate(e)
44                }),
45            ))),
46            parse_if_attribute,
47        ),
48        |(t, i)| Attribute::Type(ConfigType { r#type: t, r#if: i }),
49    )(input)
50}
51
52#[derive(Debug, PartialEq, Clone)]
53#[cfg_attr(feature = "hash", derive(Hash))]
54#[cfg_attr(feature = "serialize", derive(Serialize))]
55#[cfg_attr(feature = "deserialize", derive(Deserialize))]
56#[cfg_attr(
57    any(feature = "serialize", feature = "deserialize"),
58    serde(rename_all = "lowercase")
59)]
60pub enum Type {
61    DefBool(Expression),
62    DefTristate(Expression),
63    Bool(Option<String>),
64    Tristate(Option<String>),
65    String(Option<String>),
66    Hex(Option<String>),
67    Int(Option<String>),
68}
69
70/// 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.
71#[derive(Debug, Clone, PartialEq)]
72#[cfg_attr(feature = "hash", derive(Hash))]
73#[cfg_attr(feature = "serialize", derive(Serialize))]
74#[cfg_attr(feature = "deserialize", derive(Deserialize))]
75pub struct ConfigType {
76    pub r#type: Type,
77    #[cfg_attr(
78        any(feature = "serialize", feature = "deserialize"),
79        serde(skip_serializing_if = "Option::is_none")
80    )]
81    pub r#if: Option<Expression>,
82}
83
84#[cfg(feature = "display")]
85impl Display for ConfigType {
86    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
87        match &self.r#if {
88            Some(i) => write!(f, "{} if {}", self.r#type, i),
89            None => write!(f, "{}", self.r#type),
90        }
91    }
92}
93
94#[cfg(feature = "display")]
95impl Display for Type {
96    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
97        match self {
98            Type::Bool(prompt) => fmt_type(f, "bool", prompt),
99            Type::Tristate(prompt) => fmt_type(f, "tristate", prompt),
100            Type::String(prompt) => fmt_type(f, "string", prompt),
101            Type::Hex(prompt) => fmt_type(f, "hex", prompt),
102            Type::Int(prompt) => fmt_type(f, "int", prompt),
103            Type::DefBool(v) => write!(f, "def_bool {}", v),
104            Type::DefTristate(v) => write!(f, "def_tristate {}", v),
105        }
106    }
107}
108
109#[cfg(feature = "display")]
110fn fmt_type(
111    f: &mut std::fmt::Formatter,
112    keyword: &str,
113    prompt: &Option<String>,
114) -> std::fmt::Result {
115    match prompt {
116        Some(p) => write!(f, "{} \"{}\"", keyword, p),
117        None => write!(f, "{}", keyword),
118    }
119}