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#[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}