use crate::expr::Expr;
use crate::query::condition::FilterValue;
use crate::{HeerId, RanjId};
impl From<String> for Expr<String> {
fn from(v: String) -> Self {
Self::from_literal(FilterValue::String(v))
}
}
impl From<&'static str> for Expr<String> {
fn from(v: &'static str) -> Self {
Self::from_literal(FilterValue::String(v.to_owned()))
}
}
impl From<i16> for Expr<i16> {
fn from(v: i16) -> Self {
Self::from_literal(FilterValue::I16(v))
}
}
impl From<i32> for Expr<i32> {
fn from(v: i32) -> Self {
Self::from_literal(FilterValue::I32(v))
}
}
impl From<i64> for Expr<i64> {
fn from(v: i64) -> Self {
Self::from_literal(FilterValue::I64(v))
}
}
impl From<f32> for Expr<f32> {
fn from(v: f32) -> Self {
Self::from_literal(FilterValue::F32(v))
}
}
impl From<f64> for Expr<f64> {
fn from(v: f64) -> Self {
Self::from_literal(FilterValue::F64(v))
}
}
impl From<bool> for Expr<bool> {
fn from(v: bool) -> Self {
Self::from_literal(FilterValue::Bool(v))
}
}
impl From<time::OffsetDateTime> for Expr<time::OffsetDateTime> {
fn from(v: time::OffsetDateTime) -> Self {
Self::from_literal(FilterValue::DateTime(v))
}
}
impl From<time::Date> for Expr<time::Date> {
fn from(v: time::Date) -> Self {
Self::from_literal(FilterValue::Date(v))
}
}
impl From<uuid::Uuid> for Expr<uuid::Uuid> {
fn from(v: uuid::Uuid) -> Self {
Self::from_literal(FilterValue::Uuid(v))
}
}
impl From<HeerId> for Expr<HeerId> {
fn from(v: HeerId) -> Self {
Self::from_literal(FilterValue::HeerId(v))
}
}
impl From<RanjId> for Expr<RanjId> {
fn from(v: RanjId) -> Self {
Self::from_literal(FilterValue::RanjId(v))
}
}
impl From<crate::types::HeerIdDesc> for Expr<crate::types::HeerIdDesc> {
fn from(v: crate::types::HeerIdDesc) -> Self {
Self::from_literal(FilterValue::HeerIdDesc(v))
}
}
impl From<crate::types::RanjIdDesc> for Expr<crate::types::RanjIdDesc> {
fn from(v: crate::types::RanjIdDesc) -> Self {
Self::from_literal(FilterValue::RanjIdDesc(v))
}
}
impl From<time::Duration> for crate::expr::Expr<time::Duration> {
fn from(d: time::Duration) -> Self {
use crate::expr::node::ExprNode;
let microseconds = saturating_micros(d);
crate::expr::Expr::from_node(ExprNode::IntervalLiteral { microseconds })
}
}
impl From<crate::Interval> for crate::expr::Expr<crate::Interval> {
fn from(v: crate::Interval) -> Self {
Self::from_literal(FilterValue::Interval(v))
}
}
pub(crate) fn saturating_micros(d: time::Duration) -> i64 {
let raw: i128 = d.whole_microseconds();
raw.clamp(i64::MIN as i128, i64::MAX as i128) as i64
}
#[cfg(test)]
mod tests {
use super::saturating_micros;
use crate::expr::node::ExprNode;
#[test]
fn duration_literal_saturates_max() {
let micros = saturating_micros(time::Duration::MAX);
assert_eq!(
micros,
i64::MAX,
"Duration::MAX must saturate to i64::MAX, not wrap"
);
let node = ExprNode::IntervalLiteral {
microseconds: micros,
};
if let ExprNode::IntervalLiteral { microseconds } = node {
assert_eq!(microseconds, i64::MAX);
} else {
panic!("expected IntervalLiteral");
}
}
#[test]
fn duration_literal_saturates_min() {
let micros = saturating_micros(time::Duration::MIN);
assert_eq!(
micros,
i64::MIN,
"Duration::MIN must saturate to i64::MIN, not wrap"
);
let node = ExprNode::IntervalLiteral {
microseconds: micros,
};
if let ExprNode::IntervalLiteral { microseconds } = node {
assert_eq!(microseconds, i64::MIN);
} else {
panic!("expected IntervalLiteral");
}
}
#[test]
fn duration_literal_in_range_is_exact() {
let d = time::Duration::days(30);
let expected_micros: i64 = 30 * 24 * 60 * 60 * 1_000_000;
let micros = saturating_micros(d);
assert_eq!(
micros, expected_micros,
"in-range Duration must produce exact microsecond count"
);
}
}