1
1
use crate :: BigNum ;
2
+ use serde:: { Deserialize , Serialize } ;
2
3
use serde_json:: {
3
4
value:: { Map as SerdeMap , Value as SerdeValue } ,
4
5
Number ,
5
6
} ;
6
7
use std:: convert:: TryFrom ;
8
+ use std:: fmt;
7
9
8
10
pub type Map = SerdeMap < String , SerdeValue > ;
9
- pub type Rule = SerdeValue ;
10
11
12
+ #[ derive( Debug ) ]
11
13
pub enum Error {
12
14
TypeError ,
13
15
UnknownVariable ,
14
16
}
15
17
16
- #[ derive( Debug , Clone , PartialEq , Eq ) ]
17
- pub enum EvalValue {
18
- Null ,
18
+ impl fmt:: Display for Error {
19
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
20
+ match self {
21
+ Error :: TypeError => write ! ( f, "TypeError: Wrong type" ) ,
22
+ Error :: UnknownVariable => write ! ( f, "UnknownVariable: Unknown varialbe passed" ) ,
23
+ }
24
+ }
25
+ }
26
+
27
+ #[ derive( Debug , Clone , Serialize , Deserialize , PartialEq , Eq ) ]
28
+ #[ serde( try_from = "SerdeValue" ) ]
29
+ pub enum Value {
19
30
Bool ( bool ) ,
20
31
Number ( Number ) ,
21
32
String ( String ) ,
22
- Array ( Vec < EvalValue > ) ,
33
+ Array ( Vec < Value > ) ,
23
34
BigNum ( BigNum ) ,
24
35
}
25
36
26
- impl TryFrom < SerdeValue > for EvalValue {
37
+ #[ derive( Debug , Serialize , Deserialize , Clone , PartialEq , Eq ) ]
38
+ #[ serde( untagged) ]
39
+ pub enum Rule {
40
+ Function ( Function ) ,
41
+ Value ( Value ) ,
42
+ }
43
+
44
+ #[ derive( Debug , Serialize , Deserialize , Clone , PartialEq , Eq ) ]
45
+ #[ serde( rename_all = "camelCase" ) ]
46
+ pub enum Function {
47
+ If ( Box < Rule > , Box < Rule > ) ,
48
+ And ( Box < Rule > , Box < Rule > ) ,
49
+ Intersects ( Box < Rule > , Box < Rule > ) ,
50
+ Get ( String ) ,
51
+ }
52
+
53
+ impl TryFrom < SerdeValue > for Value {
27
54
type Error = Error ;
28
55
29
56
fn try_from ( serde_value : SerdeValue ) -> Result < Self , Self :: Error > {
30
57
match serde_value {
31
- SerdeValue :: Null => Ok ( Self :: Null ) ,
32
58
SerdeValue :: Bool ( bool) => Ok ( Self :: Bool ( bool) ) ,
33
59
SerdeValue :: Number ( number) => Ok ( Self :: Number ( number) ) ,
34
60
SerdeValue :: String ( string) => Ok ( Self :: String ( string) ) ,
35
61
SerdeValue :: Array ( serde_array) => {
36
62
let array = serde_array
37
63
. into_iter ( )
38
- . map ( EvalValue :: try_from)
64
+ . map ( Value :: try_from)
39
65
. collect :: < Result < _ , _ > > ( ) ?;
40
66
Ok ( Self :: Array ( array) )
41
67
}
42
- SerdeValue :: Object ( _) => Err ( Error :: TypeError ) ,
68
+ SerdeValue :: Object ( _) | SerdeValue :: Null => Err ( Error :: TypeError ) ,
43
69
}
44
70
}
45
71
}
46
72
47
- impl EvalValue {
48
- pub fn try_bool ( & self ) -> Result < bool , Error > {
49
- match * self {
73
+ impl Value {
74
+ pub fn try_bool ( self ) -> Result < bool , Error > {
75
+ match self {
50
76
Self :: Bool ( b) => Ok ( b) ,
51
77
_ => Err ( Error :: TypeError ) ,
52
78
}
53
79
}
54
80
55
- pub fn try_array ( & self ) -> Result < Vec < EvalValue > , Error > {
56
- match * self {
57
- Self :: Array ( ref array) => Ok ( array. to_vec ( ) ) ,
81
+ pub fn try_array ( self ) -> Result < Vec < Value > , Error > {
82
+ match self {
83
+ Self :: Array ( array) => Ok ( array) ,
58
84
_ => Err ( Error :: TypeError ) ,
59
85
}
60
86
}
@@ -69,39 +95,124 @@ impl EvalValue {
69
95
/// - Array
70
96
/// - Mutates output
71
97
/// - Throws an error
72
- // TODO: Move to own module!
73
- pub fn eval ( input : & Map , output : & mut Map , rule : & Rule ) -> Result < EvalValue , Error > {
74
- let rule = match rule {
75
- Rule :: Null => return Err ( Error :: TypeError ) ,
76
- Rule :: Object ( map) => map,
77
- value => return EvalValue :: try_from ( value. to_owned ( ) ) ,
98
+ pub fn eval ( input : & Map , output : & mut Map , rule : & Rule ) -> Result < Option < Value > , Error > {
99
+ let function = match rule {
100
+ Rule :: Value ( value) => return Ok ( Some ( value. clone ( ) ) ) ,
101
+ Rule :: Function ( function) => function,
78
102
} ;
79
103
80
104
// basic operators
81
- if let Some ( SerdeValue :: Array ( array) ) = rule. get ( "if" ) {
82
- let ( first_rule, second_rule) = match array. get ( 0 ..=1 ) {
83
- Some ( & [ ref first_rule, ref second_rule] ) => ( first_rule, second_rule) ,
84
- _ => return Err ( Error :: TypeError ) ,
85
- } ;
105
+ let value = match function {
106
+ Function :: If ( first_rule, second_rule) => {
107
+ let eval_if = eval ( input, output, first_rule) ?
108
+ . ok_or ( Error :: TypeError ) ?
109
+ . try_bool ( ) ?;
110
+
111
+ if eval_if {
112
+ let bool = eval ( input, output, second_rule) ?
113
+ . ok_or ( Error :: TypeError ) ?
114
+ . try_bool ( ) ?;
115
+ Some ( Value :: Bool ( bool) )
116
+ } else {
117
+ None
118
+ }
119
+ }
120
+ Function :: And ( first_rule, second_rule) => {
121
+ let a = eval ( input, output, first_rule) ?
122
+ . ok_or ( Error :: TypeError ) ?
123
+ . try_bool ( ) ?;
124
+ let b = eval ( input, output, second_rule) ?
125
+ . ok_or ( Error :: TypeError ) ?
126
+ . try_bool ( ) ?;
127
+
128
+ Some ( Value :: Bool ( a && b) )
129
+ }
130
+ Function :: Intersects ( first_rule, second_rule) => {
131
+ let a = eval ( input, output, first_rule) ?
132
+ . ok_or ( Error :: TypeError ) ?
133
+ . try_array ( ) ?;
134
+ let b = eval ( input, output, second_rule) ?
135
+ . ok_or ( Error :: TypeError ) ?
136
+ . try_array ( ) ?;
86
137
87
- let eval_if = eval ( input, output, first_rule) ?. try_bool ( ) ?;
138
+ Some ( Value :: Bool ( a. iter ( ) . any ( |x| b. contains ( x) ) ) )
139
+ }
140
+ Function :: Get ( key) => {
141
+ let input_value = input. get ( key) . ok_or ( Error :: UnknownVariable ) ?;
88
142
89
- if eval_if {
90
- let bool = eval ( input, output, second_rule) ?. try_bool ( ) ?;
91
- return Ok ( EvalValue :: Bool ( bool) ) ;
143
+ Some ( Value :: try_from ( input_value. clone ( ) ) ?)
92
144
}
93
- } else if let Some ( SerdeValue :: Array ( array) ) = rule. get ( "intersects" ) {
94
- // lists
95
- let ( first_rule, second_rule) = match array. get ( 0 ..=1 ) {
96
- Some ( & [ ref first_rule, ref second_rule] ) => ( first_rule, second_rule) ,
97
- _ => return Err ( Error :: TypeError ) ,
98
- } ;
145
+ } ;
146
+
147
+ Ok ( value)
148
+ }
149
+
150
+ #[ cfg( test) ]
151
+ mod test {
152
+ use super :: * ;
153
+
154
+ #[ test]
155
+ fn deserialzes_intersects_rule ( ) {
156
+ let json = r#"{"intersects": [{ "get": "adSlot.categories" }, ["News", "Bitcoin"]]}"# ;
157
+
158
+ let parsed_rule = serde_json:: from_str :: < Rule > ( json) . expect ( "Should deserialize" ) ;
99
159
100
- let a = eval ( input, output, first_rule) ?. try_array ( ) ?;
101
- let b = eval ( input, output, second_rule) ?. try_array ( ) ?;
160
+ let mut expected_map = SerdeMap :: new ( ) ;
161
+ expected_map. insert (
162
+ "get" . to_string ( ) ,
163
+ SerdeValue :: String ( "adSlot.categories" . to_string ( ) ) ,
164
+ ) ;
102
165
103
- return Ok ( EvalValue :: Bool ( a. iter ( ) . any ( |x| b. contains ( x) ) ) ) ;
166
+ let expected = Rule :: Function ( Function :: Intersects (
167
+ Box :: new ( Rule :: Function ( Function :: Get (
168
+ "adSlot.categories" . to_string ( ) ,
169
+ ) ) ) ,
170
+ Box :: new ( Rule :: Value ( Value :: Array ( vec ! [
171
+ Value :: String ( "News" . to_string( ) ) ,
172
+ Value :: String ( "Bitcoin" . to_string( ) ) ,
173
+ ] ) ) ) ,
174
+ ) ) ;
175
+
176
+ assert_eq ! ( expected, parsed_rule)
104
177
}
105
178
106
- Ok ( EvalValue :: Null )
179
+ /// ```json
180
+ /// {
181
+ /// "intersects": [
182
+ /// {
183
+ /// "get": "publisherId"
184
+ /// },
185
+ /// [
186
+ /// "0xd5860D6196A4900bf46617cEf088ee6E6b61C9d6",
187
+ /// "0xd5860D6196A4900bf46617cEf088ee6E6b61C9d3"
188
+ /// ]
189
+ /// ]
190
+ /// }
191
+ /// ```
192
+ #[ test]
193
+ fn test_simple_intersect_eval ( ) {
194
+ let input: Map = vec ! [ (
195
+ "publisherId" . to_string( ) ,
196
+ SerdeValue :: Array ( vec![ SerdeValue :: String (
197
+ "0xd5860D6196A4900bf46617cEf088ee6E6b61C9d6" . to_string( ) ,
198
+ ) ] ) ,
199
+ ) ]
200
+ . into_iter ( )
201
+ . collect ( ) ;
202
+ let mut output = SerdeMap :: new ( ) ;
203
+
204
+ let publishers = vec ! [
205
+ Value :: String ( "0xd5860D6196A4900bf46617cEf088ee6E6b61C9d6" . to_string( ) ) ,
206
+ Value :: String ( "0xd5860D6196A4900bf46617cEf088ee6E6b61C9d3" . to_string( ) ) ,
207
+ ] ;
208
+
209
+ let rules = Rule :: Function ( Function :: Intersects (
210
+ Box :: new ( Rule :: Function ( Function :: Get ( "publisherId" . to_string ( ) ) ) ) ,
211
+ Box :: new ( Rule :: Value ( Value :: Array ( publishers) ) ) ,
212
+ ) ) ;
213
+
214
+ let result = eval ( & input, & mut output, & rules) . expect ( "Should eval rules" ) ;
215
+
216
+ assert_eq ! ( Value :: Bool ( true ) , result. expect( "Sould be Some!" ) ) ;
217
+ }
107
218
}
0 commit comments