diff options
Diffstat (limited to 'src/barbfile.rs')
-rw-r--r-- | src/barbfile.rs | 76 |
1 files changed, 68 insertions, 8 deletions
diff --git a/src/barbfile.rs b/src/barbfile.rs index 91ffd0a..f3cb58f 100644 --- a/src/barbfile.rs +++ b/src/barbfile.rs @@ -2,6 +2,11 @@ use regex::Regex; use std::str::FromStr; use std::string::ToString; use std::{error::Error, fmt}; + +use jsonpath_rust::JsonPathQuery; +use serde_json::{json, Value}; + +#[cfg(feature = "jq")] use jq_rs; #[derive(Debug)] @@ -86,16 +91,22 @@ impl Header { } } +enum FilterType { + JQ, + PATH, +} + pub struct BarbFilter { name: Option<String>, filter: String, + filter_type: FilterType, } impl FromStr for BarbFilter { type Err = BarbParseError; fn from_str(s: &str) -> Result<Self, Self::Err> { - let re = Regex::new("^#(?P<name>[A-Za-z0-9_]*)\\|(?P<filter>.+)$").unwrap(); + let re = Regex::new("^#(?P<name>[A-Za-z0-9_]*)(?P<type>[|$])(?P<filter>.+)$").unwrap(); let groups = re.captures(s).ok_or(BarbParseError {})?; Ok(BarbFilter::new( @@ -104,20 +115,36 @@ impl FromStr for BarbFilter { any => Some(String::from(any)), }, String::from(&groups["filter"]), + match &groups["type"] { + "|" => FilterType::JQ, + _ => FilterType::PATH, + }, )) } } impl PreambleLine for BarbFilter { fn is_match(s: String) -> bool { - let re = Regex::new("^#(?P<name>[A-Za-z0-9_]*)\\|(?P<filter>.+)$").unwrap(); + let re = Regex::new("^#(?P<name>[A-Za-z0-9_]*)[|$](?P<filter>.+)$").unwrap(); re.is_match(s.as_str()) } } impl BarbFilter { - pub fn new(name: Option<String>, filter: String) -> BarbFilter { - BarbFilter { name, filter } + fn new(name: Option<String>, filter: String, filter_type: FilterType) -> BarbFilter { + BarbFilter { + name, + filter, + filter_type, + } + } + + pub fn from_path(filter: String) -> BarbFilter { + BarbFilter { + name: None, + filter_type: FilterType::PATH, + filter, + } } pub fn name(&self) -> &Option<String> { @@ -128,11 +155,38 @@ impl BarbFilter { &self.filter } - pub fn apply(&self, body: &String) -> Result<String, String> { + #[cfg(feature = "jq")] + fn apply_jq(&self, body: &String) -> Result<String, String> { jq_rs::run(self.filter.as_str(), body.as_str()) .map_err(|x| x.to_string()) .map(|x| String::from(x.trim().trim_matches('"'))) } + + fn apply_path(&self, body: &String) -> Result<String, String> { + let json: Value = serde_json::from_str(body.as_str()) + .map_err(|_| String::from("Failed to decode body"))?; + let path = &json.path(self.filter.as_str())?; + Ok(match path { + Value::Array(val) => match val.len() { + 1 => val.first().unwrap(), + _ => path, + }, + _ => path, + } + .to_string() + .trim() + .trim_matches('"') + .to_string()) + } + + pub fn apply(&self, body: &String) -> Result<String, String> { + match self.filter_type { + #[cfg(feature = "jq")] + FilterType::JQ => self.apply_jq(body), + FilterType::PATH => self.apply_path(body), + _ => Ok(body.to_string()), + } + } } struct BarbPreamble { @@ -225,7 +279,7 @@ impl FromStr for BarbFile { if BarbFilter::is_match(String::from(line)) { match BarbFilter::from_str(line) { Ok(filter) => filters.push(filter), - Err(_) => () + Err(_) => (), }; } } @@ -277,7 +331,10 @@ mod tests { .unwrap(); assert!(matches!(barbfile.preamble.method, Method::GET)); assert_eq!(barbfile.preamble.url, "https://blah.com/api/blah"); - assert_eq!(barbfile.preamble.filters[0].filter(), &String::from("filtr")); + assert_eq!( + barbfile.preamble.filters[0].filter(), + &String::from("filtr") + ); assert_eq!(barbfile.preamble.headers.len(), 1); assert_eq!(barbfile.preamble.headers[0].name, "Authorization"); assert_eq!(barbfile.preamble.headers[0].value, "BLAH"); @@ -291,7 +348,10 @@ mod tests { .unwrap(); assert!(matches!(barbfile.preamble.method, Method::POST)); assert_eq!(barbfile.preamble.url, "https://blah.com/api/blah"); - assert_eq!(barbfile.preamble.filters[0].filter(), &String::from("filtr")); + assert_eq!( + barbfile.preamble.filters[0].filter(), + &String::from("filtr") + ); assert_eq!(barbfile.preamble.headers.len(), 1); assert_eq!(barbfile.preamble.headers[0].name, "Authorization"); assert_eq!(barbfile.preamble.headers[0].value, "BLAH"); |