From 3e10ac86f9a25c70e5ae7a4b9b8d74e146955c0b Mon Sep 17 00:00:00 2001 From: Huck Boles Date: Thu, 4 May 2023 18:09:20 -0500 Subject: [PATCH] get functions for metafile --- src/metafile.rs | 29 +++++++++++++++++++++++++- src/parser/parse.rs | 42 +++++++++++++++++--------------------- src/tests.rs | 1 + src/tests/test_metafile.rs | 29 ++++++++++++++++++++++++++ src/tests/test_parser.rs | 9 +------- 5 files changed, 78 insertions(+), 32 deletions(-) create mode 100644 src/tests/test_metafile.rs diff --git a/src/metafile.rs b/src/metafile.rs index 9b6ec42..8a9248a 100644 --- a/src/metafile.rs +++ b/src/metafile.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, path::PathBuf}; #[derive(Debug, Default, Clone)] pub struct MetaFile<'a> { @@ -17,8 +17,28 @@ impl<'a> MetaFile<'a> { source: Vec::new(), } } + + pub fn get_var(&self, key: &str) -> Option<&str> { + self.variables.get(key).copied() + } + + pub fn get_arr(&self, key: &str) -> Option<&[&str]> { + self.arrays.get(key).map(|val| &val[..]) + } + + pub fn get_pat(&self, key: &str) -> Option<&str> { + self.patterns.get(key).copied() + } } +#[macro_export] +macro_rules! source ( + (var($s:expr)) => { Source::Sub(Substitution::Variable($s))}; + (arr($s:expr)) => { Source::Sub(Substitution::Array($s))}; + (pat($s:expr)) => { Source::Sub(Substitution::Pattern($s))}; + ($s:expr) => { Source::Str($s)}; +); + #[derive(Debug, Clone, PartialEq)] pub enum Source<'a> { Str(&'a str), @@ -31,3 +51,10 @@ pub enum Substitution<'a> { Array(&'a str), Pattern(&'a str), } + +#[derive(Debug, Clone)] +pub struct RootDirs { + pub source: PathBuf, + pub build: PathBuf, + pub pattern: PathBuf, +} diff --git a/src/parser/parse.rs b/src/parser/parse.rs index 5af268d..094c17a 100644 --- a/src/parser/parse.rs +++ b/src/parser/parse.rs @@ -1,4 +1,4 @@ -use crate::{MetaFile, Source, Substitution}; +use crate::{source, MetaFile, Source, Substitution}; use color_eyre::Result; use pest::{ iterators::{Pair, Pairs}, @@ -48,7 +48,7 @@ fn parse_defs(pairs: Pairs) -> HashMap<&'_ str, &'_ str> { map } -fn parse_array_defs(pairs: Pairs) -> HashMap<&'_ str, Vec<&'_ str>> { +fn parse_array_defs(pairs: Pairs) -> HashMap<&str, Vec<&str>> { let mut map = HashMap::new(); for pair in pairs { if Rule::assign == pair.as_rule() { @@ -60,21 +60,13 @@ fn parse_array_defs(pairs: Pairs) -> HashMap<&'_ str, Vec<&'_ str>> { } fn parse_source(pairs: Pairs) -> Vec { - let mut vec: Vec = Vec::new(); - - macro_rules! push_src ( - (var($s:expr)) => { vec.push(Source::Sub(Substitution::Variable($s))) }; - (arr($s:expr)) => { vec.push(Source::Sub(Substitution::Array($s))) }; - (pat($s:expr)) => { vec.push(Source::Sub(Substitution::Pattern($s))) }; - ($s:expr) => { vec.push(Source::Str($s)) }; - ); - + let mut vec = Vec::new(); for pair in pairs { match pair.as_rule() { - Rule::var_sub => push_src!(var(parse_substitution(pair))), - Rule::arr_sub => push_src!(arr(parse_substitution(pair))), - Rule::pat_sub => push_src!(pat(parse_substitution(pair))), - Rule::char_seq => push_src!(pair.as_str()), + Rule::var_sub => vec.push(source!(var(parse_sub(pair)))), + Rule::arr_sub => vec.push(source!(arr(parse_sub(pair)))), + Rule::pat_sub => vec.push(source!(pat(parse_sub(pair)))), + Rule::char_seq => vec.push(source!(pair.as_str())), // anything that isn't a substitution is a char_seq inside source _ => unreachable!(), } @@ -83,19 +75,20 @@ fn parse_source(pairs: Pairs) -> Vec { vec } -fn parse_substitution(pair: Pair) -> &'_ str { +fn parse_sub(pair: Pair) -> &'_ str { match pair.as_rule() { Rule::var_sub | Rule::arr_sub | Rule::pat_sub => { let str = pair.as_str(); // return the value as the inner string for substitution // all substitutions have the format of // *{ ... } - // we return everything except the first - // two characters: (sigil and preceding brace) - // and the trailing brace + // we return everything except: + // first two characters: (sigil and preceding brace) + // and the trailing brace &str[2..str.len() - 1] } // this function only gets called to parse substituiton patterns + // so anything else should never be called _ => unreachable!(), } } @@ -114,7 +107,10 @@ fn parse_assign(pair: Pair) -> (&'_ str, &'_ str) { if tmp == "BLANK" || tmp == "DEFAULT" { return ("", ""); } - // remove surrounding quotes from values + // remove surrounding quotes from values by returning + // everything except first and last characters + // a string is defined as " ... " or ' ... ' + // so it's safe to strip these characters val = &tmp[1..tmp.len() - 1]; } } @@ -122,9 +118,9 @@ fn parse_assign(pair: Pair) -> (&'_ str, &'_ str) { (key, val) } -fn parse_assign_array(pair: Pair) -> (&'_ str, Vec<&'_ str>) { +fn parse_assign_array(pair: Pair) -> (&str, Vec<&str>) { let mut key = ""; - let mut val: Vec<&str> = Vec::default(); + let mut val = Vec::default(); for pair in pair.into_inner() { if Rule::key == pair.as_rule() { key = pair.as_str(); @@ -137,7 +133,7 @@ fn parse_assign_array(pair: Pair) -> (&'_ str, Vec<&'_ str>) { (key, val) } -fn parse_array(pairs: Pairs) -> Vec<&'_ str> { +fn parse_array(pairs: Pairs) -> Vec<&str> { let mut vec: Vec<&str> = Vec::default(); for pair in pairs { diff --git a/src/tests.rs b/src/tests.rs index 33567a0..2dfbe1d 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1 +1,2 @@ +mod test_metafile; mod test_parser; diff --git a/src/tests/test_metafile.rs b/src/tests/test_metafile.rs new file mode 100644 index 0000000..f6a30be --- /dev/null +++ b/src/tests/test_metafile.rs @@ -0,0 +1,29 @@ +use crate::parse_file; +use color_eyre::Result; + +static SOURCE: &str = include_str!("test_source.meta"); + +#[test] +fn test_metafile_gets() -> Result<()> { + let source = parse_file(SOURCE)?; + + assert_eq!(source.get_var("var").unwrap(), "good"); + assert_eq!(source.get_var("single").unwrap(), "quotes"); + assert_eq!(source.get_var("blank"), None); + assert_eq!(source.get_var("not_defined"), None); + + assert_eq!(source.get_arr("sub.array").unwrap(), ["sub", "value"]); + assert_eq!(source.get_arr("arr").unwrap(), ["split", "up", "values"]); + assert_eq!( + source.get_arr("with_spaces").unwrap(), + ["stuff", "with", "spaces"] + ); + assert_eq!(source.get_arr("not_defined"), None); + + assert_eq!(source.get_pat("pat").unwrap(), "pattern"); + assert_eq!(source.get_pat("pat.sub_pat"), None); + assert_eq!(source.get_pat("blank_pat"), None); + assert_eq!(source.get_pat("not_defined"), None); + + Ok(()) +} diff --git a/src/tests/test_parser.rs b/src/tests/test_parser.rs index c477446..2e063f1 100644 --- a/src/tests/test_parser.rs +++ b/src/tests/test_parser.rs @@ -1,4 +1,4 @@ -use crate::{parse_file, Source, Substitution}; +use crate::{parse_file, source, Source, Substitution}; use color_eyre::Result; static SOURCE: &str = include_str!("test_source.meta"); @@ -36,13 +36,6 @@ fn build_meta_file() -> Result<()> { #[test] fn build_pattern_file() -> Result<()> { - macro_rules! source ( - (var($s:literal)) => { Source::Sub(Substitution::Variable($s))}; - (arr($s:literal)) => { Source::Sub(Substitution::Array($s))}; - (pat($s:literal)) => { Source::Sub(Substitution::Pattern($s))}; - ($s:literal) => { Source::Str($s)}; - ); - let mut pattern_src = parse_file(PATTERN)?.source.into_iter(); pattern_src.next(); -- 2.44.2