Skip to content

Commit bb6794b

Browse files
committed
ENH: no more try-from, started thinking about function interface
1 parent b30911d commit bb6794b

File tree

5 files changed

+136
-60
lines changed

5 files changed

+136
-60
lines changed

src/data.rs

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
//!
33
44
use crate::error::Error;
5-
use crate::NULL;
5+
use crate::value::Evaluated;
6+
use crate::{Parser, NULL};
67
use serde_json::{Map, Number, Value};
78
use std::convert::{From, TryFrom};
89

@@ -25,12 +26,30 @@ impl From<&KeyType<'_>> for Value {
2526
}
2627
}
2728

29+
#[derive(Debug)]
30+
pub struct Raw<'a> {
31+
value: &'a Value,
32+
}
33+
impl<'a> Parser<'a> for Raw<'a> {
34+
fn from_value(value: &'a Value) -> Result<Option<Self>, Error> {
35+
Ok(Some(Self { value }))
36+
}
37+
fn evaluate(&self, _data: &Value) -> Result<Evaluated, Error> {
38+
Ok(Evaluated::Raw(self.value))
39+
}
40+
}
41+
impl From<Raw<'_>> for Value {
42+
fn from(raw: Raw) -> Self {
43+
raw.value.clone()
44+
}
45+
}
46+
2847
#[derive(Debug)]
2948
pub struct Missing<'a> {
3049
values: Vec<KeyType<'a>>,
3150
}
32-
impl<'a> Missing<'a> {
33-
pub fn from_value(value: &'a Value) -> Result<Option<Self>, Error> {
51+
impl<'a> Parser<'a> for Missing<'a> {
52+
fn from_value(value: &'a Value) -> Result<Option<Self>, Error> {
3453
match value {
3554
Value::Object(obj) => {
3655
if let Some(val) = obj.get("missing") {
@@ -44,9 +63,9 @@ impl<'a> Missing<'a> {
4463
}
4564
}
4665

47-
pub fn evaluate(&self, data: &Value) -> Result<Value, Error> {
66+
fn evaluate(&self, data: &Value) -> Result<Evaluated, Error> {
4867
let missing_keys = missing_keys(data, &self.values)?;
49-
Ok(Value::Array(missing_keys))
68+
Ok(Evaluated::New(Value::Array(missing_keys)))
5069
}
5170
}
5271
impl From<Missing<'_>> for Value {
@@ -62,8 +81,8 @@ pub struct MissingSome<'a> {
6281
minimum: u64,
6382
keys: Vec<KeyType<'a>>,
6483
}
65-
impl<'a> MissingSome<'a> {
66-
pub fn from_value(value: &'a Value) -> Result<Option<Self>, Error> {
84+
impl<'a> Parser<'a> for MissingSome<'a> {
85+
fn from_value(value: &'a Value) -> Result<Option<Self>, Error> {
6786
match value {
6887
Value::Object(obj) => Ok(obj
6988
// Option<Value>
@@ -112,14 +131,15 @@ impl<'a> MissingSome<'a> {
112131
_ => Ok(None),
113132
}
114133
}
115-
pub fn evaluate(&self, data: &Value) -> Result<Value, Error> {
134+
fn evaluate(&self, data: &Value) -> Result<Evaluated, Error> {
116135
let missing = missing_keys(data, &self.keys)?;
117-
let present_keys = self.keys.len() - missing.len();
118-
if (present_keys as u64) >= self.minimum {
119-
Ok(Value::Array(Vec::with_capacity(0)))
136+
let present_keys = self.keys.len() - missing.len();
137+
let val = if (present_keys as u64) >= self.minimum {
138+
Value::Array(Vec::with_capacity(0))
120139
} else {
121-
Ok(Value::Array(missing))
122-
}
140+
Value::Array(missing)
141+
};
142+
Ok(Evaluated::New(val))
123143
}
124144
}
125145
impl<'a> From<MissingSome<'a>> for Value {
@@ -140,8 +160,8 @@ impl<'a> From<MissingSome<'a>> for Value {
140160
pub struct Variable<'a> {
141161
value: &'a Value,
142162
}
143-
impl<'a> Variable<'a> {
144-
pub fn from_value(value: &'a Value) -> Result<Option<Self>, Error> {
163+
impl<'a> Parser<'a> for Variable<'a> {
164+
fn from_value(value: &'a Value) -> Result<Option<Self>, Error> {
145165
match value {
146166
Value::Object(map) => {
147167
if map.len() != 1 {
@@ -170,20 +190,21 @@ impl<'a> Variable<'a> {
170190
}
171191
}
172192

173-
pub fn evaluate(&self, data: &'a Value) -> Result<&'a Value, Error> {
193+
fn evaluate(&self, data: &'a Value) -> Result<Evaluated, Error> {
174194
// if self.name == "" { return data };
175195
match self.value {
176-
Value::Null => Ok(data),
177-
Value::String(var_name) => self.interpolate_string_var(data, var_name),
178-
Value::Number(idx) => self.interpolate_numeric_var(data, idx),
179-
Value::Array(var) => self.interpolate_array_var(data, var),
196+
Value::Null => Ok(Evaluated::Raw(data)),
197+
Value::String(var_name) => self.interpolate_string_var(data, var_name).map(Evaluated::Raw),
198+
Value::Number(idx) => self.interpolate_numeric_var(data, idx).map(Evaluated::Raw),
199+
Value::Array(var) => self.interpolate_array_var(data, var).map(Evaluated::Raw),
180200
_ => Err(Error::InvalidVariable{
181201
value: self.value.clone(),
182202
reason: "Unsupported variable type. Variables must be strings, integers, arrays, or null.".into()
183203
})
184204
}
185205
}
186-
206+
}
207+
impl<'a> Variable<'a> {
187208
fn get_default(&self) -> &'a Value {
188209
match self.value {
189210
Value::Array(val) => val.get(1).unwrap_or(&NULL),

src/func.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//! FUnctions
2+
3+
use serde_json::Value;
4+
5+
use crate::error::Error;
6+
7+
/// A (potentially user-defined) function
8+
///
9+
/// The simplest function definition looks like:
10+
///
11+
/// ```jsonc
12+
/// {
13+
/// "def": [ // function definition operator
14+
/// "is_even", // function name
15+
/// [a], // function params
16+
/// // function expression
17+
/// {
18+
/// "===": [
19+
/// {"%": [{"param": "a"}, 2]},
20+
/// 0
21+
/// ]
22+
/// }
23+
/// ]
24+
/// }
25+
/// ```
26+
///
27+
/// Once defined, the above function can be used like:
28+
///
29+
/// ```jsonc
30+
/// {"is_even": [5]} // false
31+
/// {"is_even": [2]} // true
32+
/// ```
33+
///
34+
/// Function expressions may use any of the standard operators or any
35+
/// previously defined functions.
36+
///
37+
pub struct Function {
38+
name: String,
39+
params: Vec<String>,
40+
expression: Value,
41+
}

src/lib.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,15 @@ mod op;
88
mod value;
99

1010
use error::Error;
11-
use value::Parsed;
11+
use value::{Evaluated, Parsed};
1212

1313
const NULL: Value = Value::Null;
1414

15+
trait Parser<'a>: Sized + Into<Value> {
16+
fn from_value(value: &'a Value) -> Result<Option<Self>, Error>;
17+
fn evaluate(&self, data: &'a Value) -> Result<Evaluated, Error>;
18+
}
19+
1520
/// Run JSONLogic for the given operation and data.
1621
///
1722
pub fn jsonlogic(value: &Value, data: &Value) -> Result<Value, Error> {
@@ -52,7 +57,11 @@ mod jsonlogic_tests {
5257
(json!({"==": [1, 1]}), json!({}), Ok(json!(true))),
5358
(json!({"==": [1, 2]}), json!({}), Ok(json!(false))),
5459
(json!({"==": [1, "1"]}), json!({}), Ok(json!(true))),
55-
(json!({"==": [{}, "[object Object]"]}), json!({}), Ok(json!(true))),
60+
(
61+
json!({"==": [{}, "[object Object]"]}),
62+
json!({}),
63+
Ok(json!(true)),
64+
),
5665
(json!({"==": [1, [1]]}), json!({}), Ok(json!(true))),
5766
(json!({"==": [1, true]}), json!({}), Ok(json!(true))),
5867
// Recursive evaluation
@@ -77,7 +86,11 @@ mod jsonlogic_tests {
7786
(json!({"===": [1, 1]}), json!({}), Ok(json!(true))),
7887
(json!({"===": [1, 2]}), json!({}), Ok(json!(false))),
7988
(json!({"===": [1, "1"]}), json!({}), Ok(json!(false))),
80-
(json!({"===": [{}, "[object Object]"]}), json!({}), Ok(json!(false))),
89+
(
90+
json!({"===": [{}, "[object Object]"]}),
91+
json!({}),
92+
Ok(json!(false)),
93+
),
8194
(json!({"===": [1, [1]]}), json!({}), Ok(json!(false))),
8295
(json!({"===": [1, true]}), json!({}), Ok(json!(false))),
8396
// Recursive evaluation
@@ -102,7 +115,11 @@ mod jsonlogic_tests {
102115
(json!({"!==": [1, 1]}), json!({}), Ok(json!(false))),
103116
(json!({"!==": [1, 2]}), json!({}), Ok(json!(true))),
104117
(json!({"!==": [1, "1"]}), json!({}), Ok(json!(true))),
105-
(json!({"!==": [{}, "[object Object]"]}), json!({}), Ok(json!(true))),
118+
(
119+
json!({"!==": [{}, "[object Object]"]}),
120+
json!({}),
121+
Ok(json!(true)),
122+
),
106123
(json!({"!==": [1, [1]]}), json!({}), Ok(json!(true))),
107124
(json!({"!==": [1, true]}), json!({}), Ok(json!(true))),
108125
// Recursive evaluation

src/op.rs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33
44
use phf::phf_map;
55
use serde_json::{Map, Value};
6-
use std::convert::TryFrom;
76
use std::fmt;
87

98
use crate::error::Error;
10-
use crate::js_op;
119
use crate::value::{Evaluated, Parsed};
10+
use crate::{js_op, Parser};
1211

1312
pub struct Operator {
1413
symbol: &'static str,
@@ -51,8 +50,8 @@ pub struct Operation<'a> {
5150
operator: &'a Operator,
5251
arguments: Vec<Parsed<'a>>,
5352
}
54-
impl<'a> Operation<'a> {
55-
pub fn from_value(value: &'a Value) -> Result<Option<Self>, Error> {
53+
impl<'a> Parser<'a> for Operation<'a> {
54+
fn from_value(value: &'a Value) -> Result<Option<Self>, Error> {
5655
match value {
5756
// Operations are Objects
5857
Value::Object(obj) => {
@@ -109,7 +108,7 @@ impl<'a> Operation<'a> {
109108
}
110109
}
111110
/// Evaluate the operation after recursively evaluating any nested operations
112-
pub fn evaluate(&self, data: &'a Value) -> Result<Evaluated<'a>, Error> {
111+
fn evaluate(&self, data: &'a Value) -> Result<Evaluated, Error> {
113112
let arguments = self
114113
.arguments
115114
.iter()
@@ -121,18 +120,16 @@ impl<'a> Operation<'a> {
121120
}
122121
}
123122

124-
impl TryFrom<Operation<'_>> for Value {
125-
type Error = Error;
126-
127-
fn try_from(op: Operation) -> Result<Self, Self::Error> {
123+
impl From<Operation<'_>> for Value {
124+
fn from(op: Operation) -> Value {
128125
let mut rv = Map::with_capacity(1);
129126
let values = op
130127
.arguments
131128
.into_iter()
132-
.map(Value::try_from)
133-
.collect::<Result<Vec<Self>, Self::Error>>()?;
129+
.map(Value::from)
130+
.collect::<Vec<Value>>();
134131
rv.insert(op.operator.symbol.into(), Value::Array(values));
135-
Ok(Value::Object(rv))
132+
Value::Object(rv)
136133
}
137134
}
138135

@@ -179,9 +176,9 @@ mod test_operators {
179176
/// All operators symbols must match their keys
180177
#[test]
181178
fn test_symbols() {
182-
OPERATOR_MAP.into_iter().for_each(
183-
|(k, op)| assert_eq!(*k, op.symbol)
184-
)
179+
OPERATOR_MAP
180+
.into_iter()
181+
.for_each(|(k, op)| assert_eq!(*k, op.symbol))
185182
}
186183
}
187184

src/value.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
use serde_json::Value;
22

3-
use std::convert::{From, TryFrom};
4-
5-
use crate::data;
63
use crate::error::Error;
74
use crate::op::Operation;
5+
use crate::{data, Parser};
86

97
/// A Parsed JSON value
108
///
@@ -14,20 +12,24 @@ use crate::op::Operation;
1412
#[derive(Debug)]
1513
pub enum Parsed<'a> {
1614
Operation(Operation<'a>),
17-
Raw(&'a Value),
15+
Raw(data::Raw<'a>),
1816
Variable(data::Variable<'a>),
1917
Missing(data::Missing<'a>),
2018
MissingSome(data::MissingSome<'a>),
2119
}
2220
impl<'a> Parsed<'a> {
2321
/// Recursively parse a value
2422
pub fn from_value(value: &'a Value) -> Result<Self, Error> {
25-
Ok(data::Variable::from_value(value)?
23+
data::Variable::from_value(value)?
2624
.map(Self::Variable)
2725
.or(data::Missing::from_value(value)?.map(Self::Missing))
2826
.or(data::MissingSome::from_value(value)?.map(Self::MissingSome))
2927
.or(Operation::from_value(value)?.map(Self::Operation))
30-
.unwrap_or(Self::Raw(value)))
28+
.or(data::Raw::from_value(value)?.map(Self::Raw))
29+
.ok_or(Error::UnexpectedError(format!(
30+
"Failed to parse Value {:?}",
31+
value
32+
)))
3133
}
3234

3335
pub fn from_values(values: &'a Vec<Value>) -> Result<Vec<Self>, Error> {
@@ -37,26 +39,24 @@ impl<'a> Parsed<'a> {
3739
.collect::<Result<Vec<Self>, Error>>()
3840
}
3941

40-
pub fn evaluate(&self, data: &'a Value) -> Result<Evaluated<'a>, Error> {
42+
pub fn evaluate(&self, data: &'a Value) -> Result<Evaluated, Error> {
4143
match self {
4244
Self::Operation(op) => op.evaluate(data),
43-
Self::Raw(val) => Ok(Evaluated::Raw(*val)),
44-
Self::Variable(var) => var.evaluate(data).map(Evaluated::Raw),
45-
Self::Missing(missing) => missing.evaluate(data).map(Evaluated::New),
46-
Self::MissingSome(missing) => missing.evaluate(data).map(Evaluated::New),
45+
Self::Raw(val) => val.evaluate(data),
46+
Self::Variable(var) => var.evaluate(data),
47+
Self::Missing(missing) => missing.evaluate(data),
48+
Self::MissingSome(missing) => missing.evaluate(data),
4749
}
4850
}
4951
}
50-
impl TryFrom<Parsed<'_>> for Value {
51-
type Error = Error;
52-
53-
fn try_from(item: Parsed) -> Result<Self, Self::Error> {
52+
impl From<Parsed<'_>> for Value {
53+
fn from(item: Parsed) -> Value {
5454
match item {
55-
Parsed::Operation(op) => Value::try_from(op),
56-
Parsed::Raw(val) => Ok(val.clone()),
57-
Parsed::Variable(var) => Ok(Value::from(var)),
58-
Parsed::Missing(missing) => Ok(Value::from(missing)),
59-
Parsed::MissingSome(missing) => Ok(Value::from(missing)),
55+
Parsed::Operation(op) => Value::from(op),
56+
Parsed::Raw(raw) => Value::from(raw),
57+
Parsed::Variable(var) => Value::from(var),
58+
Parsed::Missing(missing) => Value::from(missing),
59+
Parsed::MissingSome(missing) => Value::from(missing),
6060
}
6161
}
6262
}

0 commit comments

Comments
 (0)