@@ -7,11 +7,40 @@ use std::collections::HashMap;
7
7
8
8
pub use eval:: * ;
9
9
use serde_json:: Number ;
10
+ use serde:: { Serialize } ;
10
11
11
12
mod eval;
12
13
13
- #[ derive( Debug , Clone ) ]
14
- pub struct Input {
14
+ pub type InputMap = HashMap < String , Value > ;
15
+
16
+ #[ derive( Debug ) ]
17
+ pub enum Input {
18
+ Map {
19
+ inner : InputMap ,
20
+ deposit_asset : String ,
21
+ } ,
22
+ InputSource ( InputSource ) ,
23
+ }
24
+
25
+ impl Input {
26
+ pub fn get ( & self , key : & str ) -> Result < Value , Error > {
27
+ match self {
28
+ Input :: Map { inner, ..} => inner. get ( key) . ok_or ( Error :: UnknownVariable ) . map ( Clone :: clone) ,
29
+ Input :: InputSource ( input) => input. try_get ( key)
30
+ }
31
+ }
32
+
33
+ pub fn deposit_asset ( & self ) -> Value {
34
+ match self {
35
+ Input :: Map { deposit_asset, ..} => Value :: new_string ( deposit_asset) ,
36
+ Input :: InputSource ( input) => Value :: new_string ( & input. global . channel . deposit_asset )
37
+ }
38
+ }
39
+ }
40
+
41
+ #[ derive( Debug , Clone , Serialize ) ]
42
+ #[ serde( into = "InputMap" ) ]
43
+ pub struct InputSource {
15
44
/// AdView scope, accessible only on the AdView
16
45
pub ad_view : Option < AdView > ,
17
46
/// Global scope, accessible everywhere
@@ -20,7 +49,57 @@ pub struct Input {
20
49
pub ad_slot : Option < AdSlot > ,
21
50
}
22
51
23
- impl Input {
52
+ impl From < Input > for InputMap {
53
+ fn from ( input : Input ) -> Self {
54
+ let mut map = Self :: new ( ) ;
55
+
56
+ let fields = [
57
+ // AdView scope, accessible only on the AdView
58
+ "adView.secondsSinceCampaignImpression" ,
59
+ "adView.hasCustomPreferences" ,
60
+ "adView.navigatorLanguage" ,
61
+ // Global scope, accessible everywhere
62
+ "adSlotId" ,
63
+ "adSlotType" ,
64
+ "publisherId" ,
65
+ "country" ,
66
+ "eventType" ,
67
+ "secondsSinceEpoch" ,
68
+ "userAgentOS" ,
69
+ "userAgentBrowserFamily" ,
70
+ // Global scope, accessible everywhere, campaign-dependant
71
+ "adUnitId" ,
72
+ "advertiserId" ,
73
+ "campaignId" ,
74
+ "campaignTotalSpent" ,
75
+ "campaignSecondsActive" ,
76
+ "campaignSecondsDuration" ,
77
+ "campaignBudget" ,
78
+ "eventMinPrice" ,
79
+ "eventMaxPrice" ,
80
+ "publisherEarnedFromCampaign" ,
81
+ // adSlot scope, accessible on Supermarket and AdView
82
+ "adSlot.categories" ,
83
+ "adSlot.hostname" ,
84
+ "adSlot.alexaRank" ,
85
+ ] ;
86
+
87
+ for field in fields. iter ( ) {
88
+ match input. try_get ( field) {
89
+ Ok ( value) => {
90
+ // we don't care if there is an old value, there shouldn't be one!
91
+ map. insert ( field. to_string ( ) , value) ;
92
+ } ,
93
+ // if there is an Error, it will be `UnknownVariable` and we just skip it
94
+ Err ( _) => { } ,
95
+ }
96
+ }
97
+
98
+ map
99
+ }
100
+ }
101
+
102
+ impl InputSource {
24
103
fn try_get ( & self , key : & str ) -> Result < Value , Error > {
25
104
let spec = & self . global . channel . spec ;
26
105
@@ -107,6 +186,7 @@ impl Input {
107
186
108
187
Ok ( Value :: Number ( seconds. into ( ) ) )
109
188
}
189
+ "depositAsset" => Ok ( Value :: new_string ( & self . global . channel . deposit_asset ) ) ,
110
190
"campaignBudget" => Ok ( Value :: BigNum ( self . global . channel . deposit_amount . clone ( ) ) ) ,
111
191
"eventMinPrice" => {
112
192
let min = get_pricing_bounds ( & self . global . channel , & self . global . event_type ) . min ;
0 commit comments