nom_kconfig/attribute/
range.rs

1use nom::{
2    branch::alt,
3    bytes::complete::tag,
4    combinator::map,
5    sequence::{pair, preceded},
6    IResult, Parser,
7};
8#[cfg(feature = "deserialize")]
9use serde::Deserialize;
10#[cfg(feature = "serialize")]
11use serde::Serialize;
12#[cfg(feature = "display")]
13use std::fmt::Display;
14
15use crate::{
16    symbol::{parse_symbol, Symbol},
17    util::ws,
18    KconfigInput,
19};
20
21use super::expression::{parse_if_attribute, parse_number, Expression};
22
23/// This attribute allows to limit the range of possible input values for int and hex symbols. The user can only input a value which is larger than or equal to the first symbol and smaller than or equal to the second symbol.
24#[derive(Debug, Clone, PartialEq)]
25#[cfg_attr(feature = "hash", derive(Hash))]
26#[cfg_attr(feature = "serialize", derive(Serialize))]
27#[cfg_attr(feature = "deserialize", derive(Deserialize))]
28pub struct Range {
29    pub lower_bound: Symbol,
30    pub upper_bound: Symbol,
31    #[cfg_attr(
32        any(feature = "serialize", feature = "deserialize"),
33        serde(skip_serializing_if = "Option::is_none")
34    )]
35    pub r#if: Option<Expression>,
36}
37
38#[cfg(feature = "display")]
39impl Display for Range {
40    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41        match &self.r#if {
42            Some(i) => write!(f, "{} {} if {}", self.lower_bound, self.upper_bound, i),
43            None => write!(f, "{} {}", self.lower_bound, self.upper_bound),
44        }
45    }
46}
47
48fn parse_bounds(input: KconfigInput) -> IResult<KconfigInput, (Symbol, Symbol)> {
49    alt((
50        map((ws(parse_number), ws(parse_number)), |(l, r)| {
51            (
52                Symbol::Constant(l.to_string()),
53                Symbol::Constant(r.to_string()),
54            )
55        }),
56        (ws(parse_symbol), ws(parse_symbol)),
57    ))
58    .parse(input)
59}
60
61/// Parses the `range` attribute.
62/// # Example
63/// ```
64/// use nom_kconfig::{
65///     assert_parsing_eq,
66///     attribute::{parse_range, Range},
67///     symbol::Symbol,
68/// };
69///
70/// assert_parsing_eq!(
71///     parse_range,
72///     "range 1 5",
73///     Ok((
74///         "",
75///         Range {
76///             lower_bound: Symbol::Constant("1".to_string()),
77///             upper_bound: Symbol::Constant("5".to_string()),
78///             r#if: None
79///         }
80///     ))
81/// )
82/// ```
83pub fn parse_range(input: KconfigInput) -> IResult<KconfigInput, Range> {
84    map(
85        preceded(ws(tag("range")), pair(ws(parse_bounds), parse_if_attribute)),
86        |((l, r), i)| Range {
87            lower_bound: l,
88            upper_bound: r,
89            r#if: i,
90        },
91    )
92    .parse(input)
93}