@@ -6,6 +6,7 @@ use chrono::Utc;
6
6
use std:: collections:: HashMap ;
7
7
8
8
pub use eval:: * ;
9
+ use serde_json:: Number ;
9
10
10
11
mod eval;
11
12
@@ -24,6 +25,7 @@ impl Input {
24
25
let spec = & self . global . channel . spec ;
25
26
26
27
match key {
28
+ // AdView scope, accessible only on the AdView
27
29
"adView.secondsSinceCampaignImpression" => self
28
30
. ad_view
29
31
. as_ref ( )
@@ -34,9 +36,22 @@ impl Input {
34
36
. as_ref ( )
35
37
. map ( |ad_view| Value :: Bool ( ad_view. has_custom_preferences ) )
36
38
. ok_or ( Error :: UnknownVariable ) ,
39
+ "adView.navigatorLanguage" => self
40
+ . ad_view
41
+ . as_ref ( )
42
+ . map ( |ad_view| Value :: String ( ad_view. navigator_language . clone ( ) ) )
43
+ . ok_or ( Error :: UnknownVariable ) ,
44
+ // Global scope, accessible everywhere
37
45
"adSlotId" => Ok ( Value :: String ( self . global . ad_slot_id . clone ( ) ) ) ,
38
46
"adSlotType" => Ok ( Value :: String ( self . global . ad_slot_type . clone ( ) ) ) ,
39
47
"publisherId" => Ok ( Value :: String ( self . global . publisher_id . to_checksum ( ) ) ) ,
48
+ "country" => self
49
+ . global
50
+ . country
51
+ . clone ( )
52
+ . ok_or ( Error :: UnknownVariable )
53
+ . map ( Value :: String ) ,
54
+ "eventType" => Ok ( Value :: String ( self . global . event_type . clone ( ) ) ) ,
40
55
"secondsSinceEpoch" => Ok ( Value :: Number ( self . global . seconds_since_epoch . into ( ) ) ) ,
41
56
"userAgentOS" => self
42
57
. global
@@ -50,7 +65,7 @@ impl Input {
50
65
. clone ( )
51
66
. map ( Value :: String )
52
67
. ok_or ( Error :: UnknownVariable ) ,
53
-
68
+ // Global scope, accessible everywhere, campaign-dependant
54
69
"adUnitId" => {
55
70
let ipfs = self
56
71
. global
@@ -112,6 +127,7 @@ impl Input {
112
127
113
128
Ok ( Value :: BigNum ( earned) )
114
129
}
130
+ // adSlot scope, accessible on Supermarket and AdView
115
131
"adSlot.categories" => self
116
132
. ad_slot
117
133
. as_ref ( )
@@ -213,6 +229,26 @@ pub struct Output {
213
229
pub price : HashMap < String , BigNum > ,
214
230
}
215
231
232
+ impl Output {
233
+ fn try_get ( & self , key : & str ) -> Result < Value , Error > {
234
+ match key {
235
+ "show" => Ok ( Value :: Bool ( self . show ) ) ,
236
+ "boost" => {
237
+ let boost = Number :: from_f64 ( self . boost ) . ok_or ( Error :: TypeError ) ?;
238
+ Ok ( Value :: Number ( boost) )
239
+ }
240
+ price_key if price_key. starts_with ( "price." ) => {
241
+ let price = self
242
+ . price
243
+ . get ( price_key. trim_start_matches ( "price." ) )
244
+ . ok_or ( Error :: UnknownVariable ) ?;
245
+ Ok ( Value :: BigNum ( price. clone ( ) ) )
246
+ }
247
+ _ => Err ( Error :: UnknownVariable ) ,
248
+ }
249
+ }
250
+ }
251
+
216
252
impl From < & Channel > for Output {
217
253
fn from ( channel : & Channel ) -> Self {
218
254
let price = match & channel. spec . pricing_bounds {
@@ -325,6 +361,26 @@ mod test {
325
361
assert ! ( input. try_get( "adSlot.alexaRank" ) . is_ok( ) ) ;
326
362
}
327
363
364
+ #[ test]
365
+ fn test_try_get_of_output ( ) {
366
+ let output = Output {
367
+ show : false ,
368
+ boost : 5.5 ,
369
+ price : vec ! [ ( "one" . to_string( ) , 100 . into( ) ) ] . into_iter ( ) . collect ( ) ,
370
+ } ;
371
+
372
+ assert_eq ! ( Ok ( Value :: Bool ( false ) ) , output. try_get( "show" ) ) ;
373
+ assert_eq ! (
374
+ Ok ( Value :: Number (
375
+ Number :: from_f64( 5.5 ) . expect( "Should make a number" )
376
+ ) ) ,
377
+ output. try_get( "boost" )
378
+ ) ;
379
+ assert_eq ! ( Ok ( Value :: BigNum ( 100 . into( ) ) ) , output. try_get( "price.one" ) ) ;
380
+ assert_eq ! ( Err ( Error :: UnknownVariable ) , output. try_get( "price.unknown" ) ) ;
381
+ assert_eq ! ( Err ( Error :: UnknownVariable ) , output. try_get( "unknown" ) ) ;
382
+ }
383
+
328
384
#[ test]
329
385
fn test_output_from_channel ( ) {
330
386
use crate :: channel:: { Pricing , PricingBounds } ;
0 commit comments