kconfig_represent/
lib.rs

1/*
2 Cargo KConfig - KConfig parser
3 Copyright (C) 2022  Sjoerd van Leent
4
5--------------------------------------------------------------------------------
6
7Copyright Notice: Apache
8
9Licensed under the Apache License, Version 2.0 (the "License"); you may not use
10this file except in compliance with the License. You may obtain a copy of the
11License at
12
13   https://www.apache.org/licenses/LICENSE-2.0
14
15Unless required by applicable law or agreed to in writing, software distributed
16under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17CONDITIONS OF ANY KIND, either express or implied. See the License for the
18specific language governing permissions and limitations under the License.
19
20--------------------------------------------------------------------------------
21
22Copyright Notice: GPLv2
23
24This program is free software: you can redistribute it and/or modify
25it under the terms of the GNU General Public License as published by
26the Free Software Foundation, either version 2 of the License, or
27(at your option) any later version.
28
29This program is distributed in the hope that it will be useful,
30but WITHOUT ANY WARRANTY; without even the implied warranty of
31MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32GNU General Public License for more details.
33
34You should have received a copy of the GNU General Public License
35along with this program.  If not, see <https://www.gnu.org/licenses/>.
36
37--------------------------------------------------------------------------------
38
39Copyright Notice: MIT
40
41Permission is hereby granted, free of charge, to any person obtaining a copy of
42this software and associated documentation files (the “Software”), to deal in
43the Software without restriction, including without limitation the rights to
44use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
45the Software, and to permit persons to whom the Software is furnished to do so,
46subject to the following conditions:
47
48The above copyright notice and this permission notice shall be included in all
49copies or substantial portions of the Software.
50
51THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
53FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
54COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
55IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
56CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
57*/
58
59mod ast_extra;
60mod config_registry;
61pub mod dependencies;
62pub mod error;
63mod eval;
64mod hex;
65mod item;
66#[cfg(test)]
67mod tests;
68mod variant;
69
70pub use hex::Hex;
71
72pub(crate) use ast_extra::AstExtra;
73
74pub use variant::Variant;
75pub use variant::VariantDataType;
76
77use std::{cmp::Ordering, fmt::Display, ops::Not};
78
79pub use config_registry::ConfigRegistry;
80pub use error::{Error, LoadError};
81pub use item::Item;
82use kconfig_parser::{Ast, Symbol};
83
84/// A tristate type is basically a bool wrapped in an option, where
85/// None represents 'm', or the 'maybe' state.
86#[derive(Clone, Debug, PartialEq, Eq, Copy)]
87pub struct Tristate(Option<bool>);
88
89impl Default for Tristate {
90    fn default() -> Self {
91        Tristate::FALSE
92    }
93}
94
95impl PartialOrd for Tristate {
96    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
97        Some(self.int_comp(other))
98    }
99}
100
101impl Ord for Tristate {
102    fn cmp(&self, other: &Self) -> Ordering {
103        self.int_comp(other)
104    }
105}
106
107impl Not for Tristate {
108    type Output = Tristate;
109
110    fn not(self) -> Self::Output {
111        match self {
112            Tristate::TRUE => Tristate::FALSE,
113            Tristate::FALSE => Tristate::TRUE,
114            Tristate::MAYBE => Tristate::MAYBE,
115        }
116    }
117}
118
119impl Display for Tristate {
120    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121        match *self {
122            Tristate::TRUE => f.write_str(&format!("{}", true)),
123            Tristate::FALSE => f.write_str(&format!("{}", false)),
124            Tristate::MAYBE => f.write_str("maybe"),
125        }
126    }
127}
128
129impl From<&str> for Tristate {
130    fn from(v: &str) -> Self {
131        match v {
132            "n" | "N" => Tristate::FALSE,
133            "y" | "Y" => Tristate::TRUE,
134            _ => Tristate::MAYBE,
135        }
136    }
137}
138
139impl From<bool> for Tristate {
140    fn from(b: bool) -> Self {
141        match b {
142            true => Tristate::TRUE,
143            false => Tristate::FALSE,
144        }
145    }
146}
147
148impl Tristate {
149    pub const MAYBE: Self = Self(None);
150    pub const TRUE: Self = Self(Some(true));
151    pub const FALSE: Self = Self(Some(false));
152
153    fn int_comp(&self, other: &Self) -> Ordering {
154        match (self, other) {
155            (&Self::TRUE, &Self::TRUE)
156            | (&Self::MAYBE, &Self::MAYBE)
157            | (&Self::FALSE, &Self::FALSE) => std::cmp::Ordering::Equal,
158            (&Self::TRUE, &Self::MAYBE)
159            | (&Self::TRUE, &Self::FALSE)
160            | (&Self::MAYBE, &Self::FALSE) => std::cmp::Ordering::Greater,
161            _ => std::cmp::Ordering::Less,
162        }
163    }
164}
165
166/// Determines the type, and name of a given menu item. This can either be
167/// - A Configuration Item (Config)
168/// - A Regular Menu (Menu)
169/// - A Menu Configuration Item, which is a hybrid of the former two (MenuConfig)
170/// If a Menu is defined, the name of the menu will be the full name, if any
171/// of the other two are defined, it will be the configuration name which is
172/// typically also used in the .config file.
173#[derive(Hash, PartialEq, Eq, Clone, Debug, PartialOrd, Ord)]
174pub enum ItemReference {
175    Config(String),
176    Menu(String),
177    MenuConfig(String),
178}
179
180impl Default for ItemReference {
181    fn default() -> Self {
182        ItemReference::Config("".to_owned())
183    }
184}
185
186/// Converts a menu item descriptor directly into the representation
187/// of the name of the menu item.
188impl Display for ItemReference {
189    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
190        f.write_str(match self {
191            ItemReference::Config(s) | ItemReference::Menu(s) | ItemReference::MenuConfig(s) => s,
192        })
193    }
194}
195
196/// Descriptor information contains the "help" text of a menu item.
197/// (where applicable). It also contains a item reference, to be able to lookup
198/// the originating item.
199#[derive(Clone, Debug, Default, PartialEq, Eq)]
200pub struct Info {
201    text: Vec<String>,
202    origin: ItemReference,
203}
204
205impl Info {
206    /// Creates the descriptor information for the given item reference
207    pub(crate) fn new(text: Vec<String>, origin: ItemReference) -> Self {
208        Self { text, origin }
209    }
210
211    /// Returns wether the given help text is empty, and perhaps not relevant
212    pub fn is_empty(&self) -> bool {
213        self.text.is_empty()
214    }
215
216    /// Returns the origin item reference belonging to the information
217    pub fn origin(&self) -> ItemReference {
218        self.origin.clone()
219    }
220
221    /// Returns an iterator over the text
222    pub fn iter(&self) -> Box<dyn Iterator<Item = String>> {
223        Box::new(self.text.clone().into_iter())
224    }
225}
226
227#[derive(Clone, PartialEq, Eq, Debug)]
228pub enum MutationStart {
229    String(String),
230    Hex(Hex),
231    Int(i64),
232    Bool(bool),
233    Tristate(Tristate),
234    None,
235}
236
237impl From<Variant> for MutationStart {
238    fn from(value: Variant) -> Self {
239        match value.datatype() {
240            VariantDataType::Bool => MutationStart::Bool(value.into()),
241            VariantDataType::Hex => MutationStart::Hex(value.into()),
242            VariantDataType::Int => MutationStart::Int(value.into()),
243            VariantDataType::String => MutationStart::String(value.into()),
244            VariantDataType::Tristate => MutationStart::Tristate(value.into()),
245        }
246    }
247}