Skip to content

Commit

Permalink
(De)serializing ParserConfig from toml
Browse files Browse the repository at this point in the history
  • Loading branch information
notdanilo committed Nov 5, 2023
1 parent 559d255 commit 1619236
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 23 deletions.
1 change: 1 addition & 0 deletions ligen/common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod error;

pub use error::*;
pub use serde;
pub use serde::{Serialize, Deserialize};
pub use derive_more::Display;
pub use std::convert::{TryFrom, TryInto};
Expand Down
1 change: 1 addition & 0 deletions ligen/ir/src/literal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod mock;

/// Literal Enum
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, EnumAsInner)]
#[serde(untagged)]
pub enum Literal {
/// String variant
String(String),
Expand Down
5 changes: 5 additions & 0 deletions ligen/ir/src/path/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ pub struct Path {
}

impl Path {
/// Is empty.
pub fn is_empty(&self) -> bool {
self.segments.is_empty()
}

/// Get `Path` from a `string` with a specified `separator`.
pub fn from_string_with_separator(string: &str, separator: impl AsRef<str>) -> Self {
let separator = separator.as_ref();
Expand Down
2 changes: 2 additions & 0 deletions ligen/parsing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ ligen-ir.workspace = true
ligen-common.workspace = true
pretty_assertions.workspace = true
syn.workspace = true
toml = "0.8.6"
serde.workspace = true

[dev-dependencies]
ligen-ir = { workspace = true, features = ["mocks"] }
85 changes: 62 additions & 23 deletions ligen/parsing/src/parser/config.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,82 @@

use crate::prelude::*;

use std::collections::HashMap;

use ligen_ir::Literal;
use ligen_ir::{Literal, Path};

#[derive(Default)]
#[derive(Default, Serialize, Deserialize)]
pub struct ParserConfig {
map: HashMap<String, Literal>
#[serde(flatten)]
map: Group
}

impl ParserConfig {
pub fn get(&self, key: &str) -> Option<&Literal> {
self.map.get(key)
}
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum Value {
Literal(Literal),
Group(Group)
}

impl<S: Into<String>, L: Into<Literal>, I: IntoIterator<Item = (S, L)>> From<I> for ParserConfig
{
fn from(input: I) -> Self {
let mut map = HashMap::new();
for (key, value) in input.into_iter() {
map.insert(key.into(), value.into());
#[derive(Default, Serialize, Deserialize)]
struct Group {
#[serde(flatten)]
map: HashMap<String, Value>
}

impl Group {
fn get<P: Into<Path>>(&self, path: P) -> Option<&Literal> {
let mut path = path.into();
if let Some(word) = path.pop_front() {
match self
.map
.get(&word.identifier.name) {
Some(Value::Literal(literal)) => {
if path.is_empty() {
Some(literal)
} else {
None
}
},
Some(Value::Group(group)) => group.get(path),
None => None
}
} else {
None
}
Self { map }
}
}

impl TryFrom<&str> for ParserConfig {
type Error = toml::de::Error;
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
toml::from_str(value)
}
}

impl ParserConfig {
pub fn get<P: Into<Path>>(&self, path: P) -> Option<&Literal> {
self.map.get(path)
}
}

#[cfg(test)]
mod tests {
use ligen_ir::Literal;

use super::ParserConfig;

fn config() -> ParserConfig {
ParserConfig::try_from(r#"
[ligen]
parse-all = false
default-name = "library""#
).unwrap()
}

#[test]
fn parser_config() {
let config = ParserConfig::from([
("parser::config::string", Literal::from("test")),
("parser::config::bool", Literal::from(true))
]);
assert_eq!(config.get("parser::config::none"), None);
assert_eq!(config.get("parser::config::string"), Some(&"test".into()));
assert_eq!(config.get("parser::config::bool"), Some(&true.into()));
let config = config();
assert_eq!(config.get("ligen::parse_all"), None);
assert_eq!(config.get("ligen::parse-all"), Some(&false.into()));
assert_eq!(config.get("ligen::default-name"), Some(&"library".into()));
}
}

0 comments on commit 1619236

Please sign in to comment.