CmpCondType 추가

This commit is contained in:
freestrings 2019-02-24 23:03:42 +09:00
parent d6c35de863
commit e02db88d20
2 changed files with 59 additions and 10 deletions

View File

@ -0,0 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="filter_op - trace" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="channel" value="DEFAULT" />
<option name="command" value="test --package rs-jsonpath --lib jsonpath::json_filter::tests::op -- --exact" />
<option name="allFeatures" value="false" />
<option name="nocapture" value="true" />
<option name="backtrace" value="NO" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs>
<env name="RUST_LOG" value="trace" />
</envs>
<method v="2" />
</configuration>
</component>

View File

@ -22,6 +22,11 @@ enum CmpType {
Le, Le,
} }
enum CmpCondType {
And,
Or,
}
trait PrivCmp { trait PrivCmp {
fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool; fn cmp_bool(&self, v1: &bool, v2: &bool) -> bool;
@ -256,12 +261,19 @@ impl TermContext {
} }
} }
fn cmp_cond<F: PrivCmp>(&mut self, other: &mut TermContext, cmp_fn: F) -> TermContext { fn cmp_cond(&mut self, other: &mut TermContext, cmp_cond_type: CmpCondType) -> TermContext {
match self { match self {
TermContext::Constants(et) => { TermContext::Constants(et) => {
match other { match other {
TermContext::Constants(oet) => { TermContext::Constants(oet) => {
TermContext::Constants(ExprTerm::Bool(et.cmp(oet, cmp_fn, false))) match cmp_cond_type {
CmpCondType::Or => {
TermContext::Constants(ExprTerm::Bool(et.cmp(oet, CmpOr, false)))
}
CmpCondType::And => {
TermContext::Constants(ExprTerm::Bool(et.cmp(oet, CmpAnd, false)))
}
}
} }
TermContext::Json(_, v) => { TermContext::Json(_, v) => {
TermContext::Json(None, ValueWrapper::new(v.clone_val())) TermContext::Json(None, ValueWrapper::new(v.clone_val()))
@ -271,7 +283,10 @@ impl TermContext {
TermContext::Json(_, v) => { TermContext::Json(_, v) => {
match other { match other {
TermContext::Json(_, ov) => { TermContext::Json(_, ov) => {
TermContext::Json(None, v.union(ov)) match cmp_cond_type {
CmpCondType::Or => TermContext::Json(None, v.union(ov)),
CmpCondType::And => TermContext::Json(None, v.intersect(ov)),
}
} }
_ => { _ => {
TermContext::Json(None, ValueWrapper::new(v.clone_val())) TermContext::Json(None, ValueWrapper::new(v.clone_val()))
@ -306,11 +321,11 @@ impl TermContext {
} }
fn and(&mut self, other: &mut TermContext) -> TermContext { fn and(&mut self, other: &mut TermContext) -> TermContext {
self.cmp_cond(other, CmpAnd) self.cmp_cond(other, CmpCondType::And)
} }
fn or(&mut self, other: &mut TermContext) -> TermContext { fn or(&mut self, other: &mut TermContext) -> TermContext {
self.cmp_cond(other, CmpOr) self.cmp_cond(other, CmpCondType::Or)
} }
} }
@ -554,10 +569,10 @@ impl NodeVisitor for JsonValueFilter {
match self.token_stack.pop() { match self.token_stack.pop() {
Some(ParseToken::In) => { Some(ParseToken::In) => {
vf.step_in_all(); vf.step_in_all();
}, }
Some(ParseToken::Leaves) => { Some(ParseToken::Leaves) => {
vf.step_leaves_all(); vf.step_leaves_all();
}, }
_ => {} _ => {}
} }
} }
@ -570,10 +585,10 @@ impl NodeVisitor for JsonValueFilter {
match self.token_stack.pop() { match self.token_stack.pop() {
Some(ParseToken::In) => { Some(ParseToken::In) => {
vf.step_in_string(&key); vf.step_in_string(&key);
}, }
Some(ParseToken::Leaves) => { Some(ParseToken::Leaves) => {
vf.step_leaves(&key); vf.step_leaves(&key);
}, }
_ => {} _ => {}
} }
} }
@ -602,6 +617,8 @@ impl NodeVisitor for JsonValueFilter {
self.term_stack.push(tc); self.term_stack.push(tc);
} }
} }
trace!("filter - {:?}", self.term_stack)
} }
ParseToken::Number(v) => { ParseToken::Number(v) => {
@ -824,7 +841,12 @@ impl ValueWrapper {
} }
fn replace(&mut self, val: Value) { fn replace(&mut self, val: Value) {
self.val = val; let is_null = match &val {
Value::Array(v) => if v.is_empty() { true } else { false },
Value::Object(m) => if m.is_empty() { true } else { false },
_ => val.is_null()
};
self.val = if is_null { Value::Null } else { val };
} }
fn push(&mut self, v: Value) { fn push(&mut self, v: Value) {
@ -1105,5 +1127,18 @@ mod tests {
{ "id" : 2, "name" : "Gray Berry" } { "id" : 2, "name" : "Gray Berry" }
]); ]);
assert_eq!(&friends, jf.current_value()); assert_eq!(&friends, jf.current_value());
//
// TODO 원본 json 순서여야 하나?
//
let jf = do_filter("$.friends[?(@.id >= 2 || @.id == 1)]", "./benches/data_obj.json");
let friends = json!([
{ "id" : 2, "name" : "Gray Berry" },
{ "id" : 1, "name" : "Vincent Cannon" }
]);
assert_eq!(&friends, jf.current_value());
let jf = do_filter("$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", "./benches/data_obj.json");
assert_eq!(&Value::Null, jf.current_value());
} }
} }