Skip to content

Commit 58d17f6

Browse files
Use json string representation for replace filter (#1000)
Change: json-string
1 parent 0c52884 commit 58d17f6

File tree

2 files changed

+13
-19
lines changed

2 files changed

+13
-19
lines changed

src/filter/grammar.pest

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ string = ${ "\"" ~ inner ~ "\"" }
1313
inner = @{ char* }
1414
char = {
1515
!("\"" | "\\") ~ ANY
16-
| "\\" ~ ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
16+
| "\\" ~ ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" | "u")
1717
}
1818

1919
filter_spec = { (

src/filter/parse.rs

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,15 @@ fn parse_item(pair: pest::iterators::Pair<Rule>) -> JoshResult<Op> {
6363
match pair.as_rule() {
6464
Rule::filter => {
6565
let v: Vec<_> = pair.into_inner().map(|x| unquote(x.as_str())).collect();
66-
make_op(v.as_slice())
66+
make_op(v.iter().map(String::as_str).collect::<Vec<_>>().as_slice())
6767
}
6868
Rule::filter_nop => Ok(Op::Nop),
6969
Rule::filter_subdir => Ok(Op::Subdir(
70-
Path::new(unquote(pair.into_inner().next().unwrap().as_str())).to_owned(),
70+
Path::new(&unquote(&pair.into_inner().next().unwrap().as_str())).to_owned(),
7171
)),
7272
Rule::filter_presub => {
7373
let mut inner = pair.into_inner();
74-
let arg = unquote(inner.next().unwrap().as_str());
74+
let arg = &unquote(inner.next().unwrap().as_str());
7575
if arg.ends_with('/') {
7676
let arg = arg.trim_end_matches('/');
7777
Ok(Op::Chain(
@@ -91,14 +91,14 @@ fn parse_item(pair: pest::iterators::Pair<Rule>) -> JoshResult<Op> {
9191
Rule::filter_group => {
9292
let v: Vec<_> = pair.into_inner().map(|x| unquote(x.as_str())).collect();
9393

94-
match v.as_slice() {
94+
match v.iter().map(String::as_str).collect::<Vec<_>>().as_slice() {
9595
[args] => Ok(Op::Compose(parse_group(args)?)),
9696
[cmd, args] => {
9797
let g = parse_group(args)?;
9898
match *cmd {
9999
"exclude" => Ok(Op::Exclude(to_filter(Op::Compose(g)))),
100100
"subtract" if g.len() == 2 => Ok(Op::Subtract(g[0], g[1])),
101-
_ => Err(josh_error("parse_item: no match")),
101+
_ => Err(josh_error(&format!("parse_item: no match {:?}", cmd))),
102102
}
103103
}
104104
_ => Err(josh_error("parse_item: no match {:?}")),
@@ -199,30 +199,24 @@ fn parse_workspace(filter_spec: &str) -> JoshResult<Vec<Filter>> {
199199
}
200200
}
201201

202-
// Remove double quotes from a string if present.
203-
fn unquote(s: &str) -> &str {
204-
if s.len() < 2 {
202+
// Parse json string if neccessary
203+
fn unquote(s: &str) -> String {
204+
if let Ok(serde_json::Value::String(s)) = serde_json::from_str(s) {
205205
return s;
206206
}
207-
208-
// We only need to check for a quote at the beginning,
209-
// because not properly quoted string will be rejected
210-
// by the grammar before we even get here
211-
if s.starts_with('\"') {
212-
return &s[1..s.len() - 1];
213-
}
214-
s
207+
return s.to_string();
215208
}
216209

217-
// Add quotes to a string if if contains any chars reserved
210+
// Encode string as json if it contains any chars reserved
218211
// by the filter language
219212
pub fn quote(s: &str) -> String {
220213
if let Ok(r) = Grammar::parse(Rule::filter_path, s) {
221214
if r.as_str() == s {
222215
return s.to_string();
223216
}
224217
}
225-
return format!("\"{}\"", s);
218+
serde_json::to_string(&serde_json::Value::String(s.to_string()))
219+
.unwrap_or("<invalid string>".to_string())
226220
}
227221

228222
/// Create a `Filter` from a string representation

0 commit comments

Comments
 (0)