@@ -2,11 +2,13 @@ use crate::BigNum;
2
2
use serde:: { Deserialize , Serialize } ;
3
3
use serde_json:: { value:: Value as SerdeValue , Number } ;
4
4
use std:: convert:: TryFrom ;
5
- use std:: fmt;
5
+ use std:: { fmt, str :: FromStr } ;
6
6
7
7
pub type Map = serde_json:: value:: Map < String , SerdeValue > ;
8
8
9
- #[ derive( Debug ) ]
9
+ use super :: { Input , Output , TryGet } ;
10
+
11
+ #[ derive( Debug , Eq , PartialEq ) ]
10
12
pub enum Error {
11
13
TypeError ,
12
14
UnknownVariable ,
@@ -29,7 +31,7 @@ pub enum Rule {
29
31
}
30
32
31
33
impl Rule {
32
- pub fn eval ( & self , input : & Map , output : & mut Map ) -> Result < Option < Value > , Error > {
34
+ pub fn eval ( & self , input : & Input , output : & mut Output ) -> Result < Option < Value > , Error > {
33
35
eval ( input, output, self )
34
36
}
35
37
}
@@ -50,6 +52,34 @@ impl Value {
50
52
}
51
53
}
52
54
55
+ #[ derive( Debug , Serialize , Deserialize , Clone , PartialEq , Eq ) ]
56
+ #[ serde( from = "BigNum" ) ]
57
+ /// Bn (BigNum) function.
58
+ /// This struct is also used to parse the Input correctly for [`TryGet`](primitives::targeting::TryGet).
59
+ ///
60
+ /// This type will be:
61
+ /// - Deserialized from a normal `BigNum`
62
+ ///
63
+ /// ```json
64
+ /// { "some_big_num_field": "1000" }
65
+ /// ```
66
+ ///
67
+ /// - Serialized to:
68
+ ///
69
+ /// ```json
70
+ /// { "FUNC": { "bn": "1000" } }
71
+ /// ```
72
+ pub struct Bn {
73
+ #[ serde( rename = "bn" ) ]
74
+ pub big_num : BigNum ,
75
+ }
76
+
77
+ impl From < BigNum > for Bn {
78
+ fn from ( big_num : BigNum ) -> Self {
79
+ Self { big_num }
80
+ }
81
+ }
82
+
53
83
#[ derive( Debug , Serialize , Deserialize , Clone , PartialEq , Eq ) ]
54
84
#[ serde( rename_all = "camelCase" ) ]
55
85
pub enum Function {
@@ -58,8 +88,9 @@ pub enum Function {
58
88
Intersects ( Box < Rule > , Box < Rule > ) ,
59
89
Get ( String ) ,
60
90
// TODO: set
61
-
62
91
// TODO: Add: div, mul, mod, add, sub, max, min
92
+ /// Bn (BigNum) function.
93
+ Bn ( Bn ) ,
63
94
}
64
95
65
96
impl From < Function > for Rule {
@@ -99,7 +130,16 @@ impl TryFrom<SerdeValue> for Value {
99
130
match serde_value {
100
131
SerdeValue :: Bool ( bool) => Ok ( Self :: Bool ( bool) ) ,
101
132
SerdeValue :: Number ( number) => Ok ( Self :: Number ( number) ) ,
102
- SerdeValue :: String ( string) => Ok ( Self :: String ( string) ) ,
133
+ SerdeValue :: String ( string) => {
134
+ // we need to try and parse the String as a BigNum
135
+ // if it fails, then it's just a String
136
+ let big_num = BigNum :: from_str ( & string) ;
137
+
138
+ match big_num {
139
+ Ok ( big_num) => Ok ( Value :: BigNum ( big_num) ) ,
140
+ Err ( _) => Ok ( Value :: String ( string) ) ,
141
+ }
142
+ }
103
143
SerdeValue :: Array ( serde_array) => {
104
144
let array = serde_array
105
145
. into_iter ( )
@@ -137,7 +177,7 @@ impl Value {
137
177
/// - Array
138
178
/// - Mutates output
139
179
/// - Throws an error
140
- fn eval ( input : & Map , output : & mut Map , rule : & Rule ) -> Result < Option < Value > , Error > {
180
+ fn eval ( input : & Input , output : & mut Output , rule : & Rule ) -> Result < Option < Value > , Error > {
141
181
let function = match rule {
142
182
Rule :: Value ( value) => return Ok ( Some ( value. clone ( ) ) ) ,
143
183
Rule :: Function ( function) => function,
@@ -179,11 +219,8 @@ fn eval(input: &Map, output: &mut Map, rule: &Rule) -> Result<Option<Value>, Err
179
219
180
220
Some ( Value :: Bool ( a. iter ( ) . any ( |x| b. contains ( x) ) ) )
181
221
}
182
- Function :: Get ( key) => {
183
- let input_value = input. get ( key) . ok_or ( Error :: UnknownVariable ) ?;
184
-
185
- Some ( Value :: try_from ( input_value. clone ( ) ) ?)
186
- }
222
+ Function :: Get ( key) => Some ( input. try_get ( key) ?) ,
223
+ Function :: Bn ( bn) => Some ( Value :: BigNum ( bn. big_num . clone ( ) ) ) ,
187
224
} ;
188
225
189
226
Ok ( value)
@@ -192,6 +229,7 @@ fn eval(input: &Map, output: &mut Map, rule: &Rule) -> Result<Option<Value>, Err
192
229
#[ cfg( test) ]
193
230
mod test {
194
231
use super :: * ;
232
+ use crate :: targeting:: AdSlot ;
195
233
196
234
#[ test]
197
235
fn deserialzes_intersects_rule ( ) {
@@ -231,16 +269,18 @@ mod test {
231
269
/// ```
232
270
#[ test]
233
271
fn test_intersects_eval ( ) {
234
- let input: Map = vec ! [ (
235
- "adSlot.categories" . to_string( ) ,
236
- SerdeValue :: Array ( vec![
237
- SerdeValue :: String ( "Bitcoin" . to_string( ) ) ,
238
- SerdeValue :: String ( "Ethereum" . to_string( ) ) ,
239
- ] ) ,
240
- ) ]
241
- . into_iter ( )
242
- . collect ( ) ;
243
- let mut output = Map :: new ( ) ;
272
+ let mut input = Input :: default ( ) ;
273
+ input. ad_slot = Some ( AdSlot {
274
+ categories : vec ! [ "Bitcoin" . to_string( ) , "Ethereum" . to_string( ) ] ,
275
+ hostname : Default :: default ( ) ,
276
+ alexa_rank : 0.0 ,
277
+ } ) ;
278
+
279
+ let mut output = Output {
280
+ show : true ,
281
+ boost : 1.0 ,
282
+ price : Default :: default ( ) ,
283
+ } ;
244
284
245
285
let categories = vec ! [ Value :: new_string( "News" ) , Value :: new_string( "Bitcoin" ) ] ;
246
286
@@ -256,15 +296,12 @@ mod test {
256
296
result. expect( "Sould return Non-NULL result!" )
257
297
) ;
258
298
259
- let input: Map = vec ! [ (
260
- "adSlot.categories" . to_string( ) ,
261
- SerdeValue :: Array ( vec![
262
- SerdeValue :: String ( "Advertisement" . to_string( ) ) ,
263
- SerdeValue :: String ( "Programming" . to_string( ) ) ,
264
- ] ) ,
265
- ) ]
266
- . into_iter ( )
267
- . collect ( ) ;
299
+ let mut input = Input :: default ( ) ;
300
+ input. ad_slot = Some ( AdSlot {
301
+ categories : vec ! [ "Advertisement" . to_string( ) , "Programming" . to_string( ) ] ,
302
+ hostname : Default :: default ( ) ,
303
+ alexa_rank : 0.0 ,
304
+ } ) ;
268
305
269
306
let result = rules. eval ( & input, & mut output) . expect ( "Should eval rules" ) ;
270
307
0 commit comments