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