use std::fmt::Debug;
#[derive(Debug, Clone)]
pub struct RangeFilter<T> {
pub field_name: String,
pub gte: Option<T>,
pub gt: Option<T>,
pub lte: Option<T>,
pub lt: Option<T>,
}
impl<T> RangeFilter<T>
where
T: Clone + Debug,
{
pub fn new(field_name: impl Into<String>) -> Self {
Self {
field_name: field_name.into(),
gte: None,
gt: None,
lte: None,
lt: None,
}
}
pub fn gte(mut self, value: T) -> Self {
self.gte = Some(value);
self
}
pub fn gt(mut self, value: T) -> Self {
self.gt = Some(value);
self
}
pub fn lte(mut self, value: T) -> Self {
self.lte = Some(value);
self
}
pub fn lt(mut self, value: T) -> Self {
self.lt = Some(value);
self
}
pub fn between(mut self, min: T, max: T) -> Self {
self.gte = Some(min);
self.lte = Some(max);
self
}
pub fn field_name(&self) -> &str {
&self.field_name
}
pub fn has_bounds(&self) -> bool {
self.gte.is_some() || self.gt.is_some() || self.lte.is_some() || self.lt.is_some()
}
}
#[derive(Debug, Clone)]
pub struct DateRangeFilter {
range: RangeFilter<String>,
}
impl DateRangeFilter {
pub fn new(field_name: impl Into<String>) -> Self {
Self {
range: RangeFilter::new(field_name),
}
}
pub fn after(mut self, date: impl Into<String>) -> Self {
self.range = self.range.gte(date.into());
self
}
pub fn before(mut self, date: impl Into<String>) -> Self {
self.range = self.range.lte(date.into());
self
}
pub fn range(mut self, start: impl Into<String>, end: impl Into<String>) -> Self {
self.range = self.range.between(start.into(), end.into());
self
}
pub fn field_name(&self) -> &str {
self.range.field_name()
}
pub fn inner(&self) -> &RangeFilter<String> {
&self.range
}
}
#[derive(Debug, Clone)]
pub struct NumericRangeFilter<T> {
range: RangeFilter<T>,
}
impl<T> NumericRangeFilter<T>
where
T: Clone + Debug,
{
pub fn new(field_name: impl Into<String>) -> Self {
Self {
range: RangeFilter::new(field_name),
}
}
pub fn min(mut self, value: T) -> Self {
self.range = self.range.gte(value);
self
}
pub fn max(mut self, value: T) -> Self {
self.range = self.range.lte(value);
self
}
pub fn range(mut self, min: T, max: T) -> Self {
self.range = self.range.between(min, max);
self
}
pub fn field_name(&self) -> &str {
self.range.field_name()
}
pub fn inner(&self) -> &RangeFilter<T> {
&self.range
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_range_filter_creation() {
let filter: RangeFilter<i32> = RangeFilter::new("age");
assert_eq!(filter.field_name(), "age");
assert!(!filter.has_bounds());
}
#[test]
fn test_range_filter_gte() {
let filter: RangeFilter<i32> = RangeFilter::new("price").gte(100);
assert_eq!(filter.gte, Some(100));
assert!(filter.has_bounds());
}
#[test]
fn test_range_filter_gt() {
let filter: RangeFilter<i32> = RangeFilter::new("price").gt(100);
assert_eq!(filter.gt, Some(100));
assert!(filter.has_bounds());
}
#[test]
fn test_range_filter_lte() {
let filter: RangeFilter<i32> = RangeFilter::new("price").lte(500);
assert_eq!(filter.lte, Some(500));
assert!(filter.has_bounds());
}
#[test]
fn test_range_filter_lt() {
let filter: RangeFilter<i32> = RangeFilter::new("price").lt(500);
assert_eq!(filter.lt, Some(500));
assert!(filter.has_bounds());
}
#[test]
fn test_range_filter_between() {
let filter: RangeFilter<i32> = RangeFilter::new("price").between(100, 500);
assert_eq!(filter.gte, Some(100));
assert_eq!(filter.lte, Some(500));
assert!(filter.has_bounds());
}
#[test]
fn test_range_filter_complex() {
let filter: RangeFilter<i32> = RangeFilter::new("price").gt(100).lt(500);
assert_eq!(filter.gt, Some(100));
assert_eq!(filter.lt, Some(500));
assert!(filter.has_bounds());
}
#[test]
fn test_date_range_filter_creation() {
let filter = DateRangeFilter::new("created_at");
assert_eq!(filter.field_name(), "created_at");
}
#[test]
fn test_date_range_filter_after() {
let filter = DateRangeFilter::new("created_at").after("2024-01-01");
assert_eq!(filter.inner().gte, Some("2024-01-01".to_string()));
}
#[test]
fn test_date_range_filter_before() {
let filter = DateRangeFilter::new("created_at").before("2024-12-31");
assert_eq!(filter.inner().lte, Some("2024-12-31".to_string()));
}
#[test]
fn test_date_range_filter_range() {
let filter = DateRangeFilter::new("created_at").range("2024-01-01", "2024-12-31");
assert_eq!(filter.inner().gte, Some("2024-01-01".to_string()));
assert_eq!(filter.inner().lte, Some("2024-12-31".to_string()));
}
#[test]
fn test_numeric_range_filter_creation() {
let filter: NumericRangeFilter<i32> = NumericRangeFilter::new("quantity");
assert_eq!(filter.field_name(), "quantity");
}
#[test]
fn test_numeric_range_filter_min() {
let filter: NumericRangeFilter<i32> = NumericRangeFilter::new("quantity").min(10);
assert_eq!(filter.inner().gte, Some(10));
}
#[test]
fn test_numeric_range_filter_max() {
let filter: NumericRangeFilter<i32> = NumericRangeFilter::new("quantity").max(100);
assert_eq!(filter.inner().lte, Some(100));
}
#[test]
fn test_numeric_range_filter_range() {
let filter: NumericRangeFilter<f64> = NumericRangeFilter::new("price").range(99.99, 999.99);
assert_eq!(filter.inner().gte, Some(99.99));
assert_eq!(filter.inner().lte, Some(999.99));
}
}