use crate::orm::Model;
use chrono::Timelike;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum LookupType {
Exact, IExact, Ne,
Contains, IContains, StartsWith, IStartsWith, EndsWith, IEndsWith, Regex, IRegex,
Gt, Gte, Lt, Lte, Range,
In, NotIn,
IsNull, IsNotNull, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum LookupValue {
String(String),
Int(i64),
Float(f64),
Bool(bool),
Array(Vec<LookupValue>),
Range(Box<LookupValue>, Box<LookupValue>),
Null,
}
impl From<String> for LookupValue {
fn from(s: String) -> Self {
LookupValue::String(s)
}
}
impl From<&str> for LookupValue {
fn from(s: &str) -> Self {
LookupValue::String(s.to_string())
}
}
impl From<i32> for LookupValue {
fn from(i: i32) -> Self {
LookupValue::Int(i as i64)
}
}
impl From<i64> for LookupValue {
fn from(i: i64) -> Self {
LookupValue::Int(i)
}
}
impl From<f32> for LookupValue {
fn from(f: f32) -> Self {
LookupValue::Float(f as f64)
}
}
impl From<f64> for LookupValue {
fn from(f: f64) -> Self {
LookupValue::Float(f)
}
}
impl From<bool> for LookupValue {
fn from(b: bool) -> Self {
LookupValue::Bool(b)
}
}
impl From<()> for LookupValue {
fn from(_: ()) -> Self {
LookupValue::Null
}
}
impl From<super::traits::DateTime> for LookupValue {
fn from(dt: super::traits::DateTime) -> Self {
LookupValue::Int(dt.timestamp)
}
}
impl From<super::traits::Date> for LookupValue {
fn from(date: super::traits::Date) -> Self {
let days = date.year * 10000 + (date.month as i32) * 100 + (date.day as i32);
LookupValue::Int(days as i64)
}
}
impl From<chrono::NaiveDateTime> for LookupValue {
fn from(dt: chrono::NaiveDateTime) -> Self {
LookupValue::Int(dt.and_utc().timestamp())
}
}
impl From<chrono::NaiveDate> for LookupValue {
fn from(date: chrono::NaiveDate) -> Self {
LookupValue::Int(
date.and_hms_opt(0, 0, 0)
.map(|dt| dt.and_utc().timestamp())
.unwrap_or(0),
)
}
}
impl From<chrono::NaiveTime> for LookupValue {
fn from(time: chrono::NaiveTime) -> Self {
LookupValue::Int(time.num_seconds_from_midnight() as i64)
}
}
impl<Tz: chrono::TimeZone> From<chrono::DateTime<Tz>> for LookupValue {
fn from(dt: chrono::DateTime<Tz>) -> Self {
LookupValue::Int(dt.timestamp())
}
}
impl<T: Into<LookupValue>> From<(T, T)> for LookupValue {
fn from((start, end): (T, T)) -> Self {
LookupValue::Range(Box::new(start.into()), Box::new(end.into()))
}
}
#[derive(Debug, Clone)]
pub struct Lookup<M: Model> {
pub(crate) field_path: Vec<String>,
pub(crate) lookup_type: LookupType,
pub(crate) value: LookupValue,
pub(crate) _phantom: std::marker::PhantomData<M>,
}
impl<M: Model> Lookup<M> {
pub fn new(field_path: Vec<String>, lookup_type: LookupType, value: LookupValue) -> Self {
Self {
field_path,
lookup_type,
value,
_phantom: std::marker::PhantomData,
}
}
pub fn field_path(&self) -> &[String] {
&self.field_path
}
pub fn lookup_type(&self) -> &LookupType {
&self.lookup_type
}
pub fn value(&self) -> &LookupValue {
&self.value
}
}