Skip to content

Commit ae9f2fd

Browse files
committed
Refactor TryGet to Input::try_get
1 parent ad73d8c commit ae9f2fd

File tree

2 files changed

+93
-50
lines changed

2 files changed

+93
-50
lines changed

primitives/src/targeting.rs

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,73 @@ pub struct Input {
3535
pub ad_slot: Option<AdSlot>,
3636
}
3737

38+
impl Input {
39+
fn try_get(&self, key: &str) -> Result<Value, Error> {
40+
match key {
41+
"adView.secondsSinceShow" => self
42+
.ad_view
43+
.as_ref()
44+
.map(|ad_view| Value::Number(ad_view.seconds_since_show.into()))
45+
.ok_or(Error::UnknownVariable),
46+
"adView.hasCustomPreferences" => self
47+
.ad_view
48+
.as_ref()
49+
.map(|ad_view| Value::Bool(ad_view.has_custom_preferences))
50+
.ok_or(Error::UnknownVariable),
51+
"adSlotId" => Ok(Value::String(self.global.ad_slot_id.clone())),
52+
"adUnitId" => Ok(Value::String(self.global.ad_unit_id.clone())),
53+
"adUnitType" => Ok(Value::String(self.global.ad_unit_type.clone())),
54+
"publisherId" => Ok(Value::String(self.global.publisher_id.clone())),
55+
"advertiserId" => Ok(Value::String(self.global.advertiser_id.clone())),
56+
"country" => Ok(Value::String(self.global.country.clone())),
57+
"eventType" => Ok(Value::String(self.global.event_type.clone())),
58+
"campaignId" => Ok(Value::String(self.global.campiagn_id.clone())),
59+
"campaignTotalSpent" => Ok(Value::String(self.global.campaign_total_spent.clone())),
60+
"campaignSecondsActive" => {
61+
Ok(Value::Number(self.global.campaign_seconds_active.into()))
62+
}
63+
"campaignSecondsDuration" => {
64+
Ok(Value::Number(self.global.campaign_seconds_duration.into()))
65+
}
66+
"campaignBudget" => Ok(Value::BigNum(self.global.campaign_budget.clone())),
67+
"eventMinPrice" => Ok(Value::BigNum(self.global.event_min_price.clone())),
68+
"eventMaxPrice" => Ok(Value::BigNum(self.global.event_max_price.clone())),
69+
"publisherEarnedFromCampaign" => Ok(Value::BigNum(
70+
self.global.publisher_earned_from_campaign.clone(),
71+
)),
72+
"secondsSinceEpoch" => Ok(Value::Number(self.global.seconds_since_epoch.into())),
73+
"userAgentOS" => Ok(Value::String(self.global.user_agent_os.clone())),
74+
"userAgentBrowserFamily" => Ok(Value::String(self.global.user_agent_browser_family.clone())),
75+
"adSlot.categories" => self
76+
.ad_slot
77+
.as_ref()
78+
.map(|ad_slot| {
79+
let array = ad_slot
80+
.categories
81+
.iter()
82+
.map(|string| Value::String(string.clone()))
83+
.collect();
84+
Value::Array(array)
85+
})
86+
.ok_or(Error::UnknownVariable),
87+
"adSlot.hostname" => self
88+
.ad_slot
89+
.as_ref()
90+
.map(|ad_slot| Value::String(ad_slot.hostname.clone()))
91+
.ok_or(Error::UnknownVariable),
92+
"adSlot.alexaRank" => {
93+
let ad_slot = self.ad_slot.as_ref().ok_or(Error::UnknownVariable)?;
94+
95+
match serde_json::Number::from_f64(ad_slot.alexa_rank) {
96+
Some(number) => Ok(Value::Number(number)),
97+
None => Err(Error::TypeError)
98+
}
99+
}
100+
_unknown_field => Err(Error::UnknownVariable),
101+
}
102+
}
103+
}
104+
38105
#[derive(Debug, Serialize, Deserialize)]
39106
#[cfg_attr(test, derive(Default))]
40107
#[serde(rename_all = "camelCase")]
@@ -54,6 +121,7 @@ pub struct Global {
54121
pub advertiser_id: String,
55122
pub country: String,
56123
pub event_type: String,
124+
pub campiagn_id: String,
57125
pub campaign_total_spent: String,
58126
pub campaign_seconds_active: u64,
59127
pub campaign_seconds_duration: u64,
@@ -76,11 +144,6 @@ pub struct AdSlot {
76144
pub alexa_rank: f64,
77145
}
78146

79-
impl TryGet for Input {}
80-
impl TryGet for Global {}
81-
impl TryGet for AdView {}
82-
impl TryGet for AdSlot {}
83-
84147
#[derive(Debug)]
85148
pub struct Output {
86149
/// Whether to show the ad
@@ -115,8 +178,7 @@ mod test {
115178
.try_get("adView.secondsSinceShow")
116179
.expect("Should get the ad_view.seconds_since_show field");
117180

118-
let expected_number =
119-
serde_json::from_str::<serde_json::Number>("10").expect("Should create number");
181+
let expected_number = serde_json::Number::from(10);
120182

121183
assert_eq!(Value::Number(expected_number), ad_view_seconds_since_show);
122184

primitives/src/targeting/eval.rs

Lines changed: 24 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -52,45 +52,16 @@ impl Value {
5252
}
5353
}
5454

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-
8355
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
8456
#[serde(rename_all = "camelCase")]
57+
// TODO: https://github.com/AdExNetwork/adex-validator-stack-rust/issues/296
8558
pub enum Function {
8659
If(Box<Rule>, Box<Rule>),
8760
And(Box<Rule>, Box<Rule>),
8861
Intersects(Box<Rule>, Box<Rule>),
8962
Get(String),
90-
// TODO: set
91-
// TODO: Add: div, mul, mod, add, sub, max, min
92-
/// Bn (BigNum) function.
93-
Bn(Bn),
63+
/// Bn(Value) function.
64+
Bn(Value),
9465
}
9566

9667
impl From<Function> for Rule {
@@ -130,16 +101,7 @@ impl TryFrom<SerdeValue> for Value {
130101
match serde_value {
131102
SerdeValue::Bool(bool) => Ok(Self::Bool(bool)),
132103
SerdeValue::Number(number) => Ok(Self::Number(number)),
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-
}
104+
SerdeValue::String(string) => Ok(Value::String(string)),
143105
SerdeValue::Array(serde_array) => {
144106
let array = serde_array
145107
.into_iter()
@@ -220,7 +182,26 @@ fn eval(input: &Input, output: &mut Output, rule: &Rule) -> Result<Option<Value>
220182
Some(Value::Bool(a.iter().any(|x| b.contains(x))))
221183
}
222184
Function::Get(key) => Some(input.try_get(key)?),
223-
Function::Bn(bn) => Some(Value::BigNum(bn.big_num.clone())),
185+
Function::Bn(value) => {
186+
let big_num = match value {
187+
Value::String(string) => {
188+
let big_num =
189+
BigNum::from_str(string.as_str()).map_err(|_| Error::TypeError)?;
190+
191+
Value::BigNum(big_num)
192+
}
193+
Value::BigNum(big_num) => Value::BigNum(big_num.clone()),
194+
Value::Number(number) => {
195+
let big_num =
196+
BigNum::from_str(&number.to_string()).map_err(|_| Error::TypeError)?;
197+
198+
Value::BigNum(big_num)
199+
}
200+
_ => return Err(Error::TypeError),
201+
};
202+
203+
Some(big_num)
204+
}
224205
};
225206

226207
Ok(value)

0 commit comments

Comments
 (0)