use crate::value::Value;
use super::common;
use super::evaluator::RbacBuiltinError;
pub(super) fn time_compare(
left: &Value,
right: &Value,
op: &str,
name: &'static str,
) -> Result<bool, RbacBuiltinError> {
let lhs = common::value_as_string(left, name)?;
let rhs = common::value_as_string(right, name)?;
let left_secs = common::parse_time_of_day(&lhs)?;
let right_secs = common::parse_time_of_day(&rhs)?;
Ok(match op {
"==" => left_secs == right_secs,
"<" => left_secs < right_secs,
"<=" => left_secs <= right_secs,
">" => left_secs > right_secs,
">=" => left_secs >= right_secs,
_ => false,
})
}
pub(super) fn time_in_range(
left: &Value,
right: &Value,
name: &'static str,
) -> Result<bool, RbacBuiltinError> {
let value = common::value_as_string(left, name)?;
let value_secs = common::parse_time_of_day(&value)?;
match *right {
Value::Array(ref list) => {
let start = list.first().ok_or_else(|| {
RbacBuiltinError::new("TimeOfDayInRange expects a 2-element array")
})?;
let end = list.get(1).ok_or_else(|| {
RbacBuiltinError::new("TimeOfDayInRange expects a 2-element array")
})?;
if list.len() != 2 {
return Err(RbacBuiltinError::new(
"TimeOfDayInRange expects a 2-element array",
));
}
let start = common::value_as_string(start, name)?;
let end = common::value_as_string(end, name)?;
let start_secs = common::parse_time_of_day(&start)?;
let end_secs = common::parse_time_of_day(&end)?;
Ok(value_secs >= start_secs && value_secs <= end_secs)
}
Value::Set(ref set) => {
let mut iter = set.iter();
let start = iter
.next()
.ok_or_else(|| RbacBuiltinError::new("TimeOfDayInRange expects 2 values"))?;
let end = iter
.next()
.ok_or_else(|| RbacBuiltinError::new("TimeOfDayInRange expects 2 values"))?;
let start_secs = common::parse_time_of_day(&common::value_as_string(start, name)?)?;
let end_secs = common::parse_time_of_day(&common::value_as_string(end, name)?)?;
Ok(value_secs >= start_secs && value_secs <= end_secs)
}
_ => time_compare(left, right, "==", name),
}
}