1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! Implement a generic filter operator to support filter such as `name="John"` as a combination of `(key, operator, value)`
//! Supported operators are `=`, `<`, `<=`, `>`, `>=`
use super::*;
use value::Value;

pub enum Operator {
  Equal,
  Lower,
  LowerEqual,
  Greater,
  GreaterEqual,
}

impl std::fmt::Display for Operator {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    match self {
      Operator::Equal        => write!(f, "="),
      Operator::Lower        => write!(f, "<"),
      Operator::LowerEqual   => write!(f, "<="),
      Operator::Greater      => write!(f, ">"),
      Operator::GreaterEqual => write!(f, ">="),
    }
  }
}

pub struct Filter<T> 
where T: std::fmt::Display
{
  key: String,
  value: Value<T>,
  operator: Operator,
}

impl<T> std::convert::From<(String, Operator, Value<T>)> for Filter<T> 
where T: std::fmt::Display
{
  fn from((key, operator, value): (String, Operator, Value<T>)) -> Self {
    Filter { key, value, operator }
  }
}

impl<T> std::convert::From<(&str, Operator, Value<T>)> for Filter<T> 
where T: std::fmt::Display
{
  fn from((key, operator, value): (&str, Operator, Value<T>)) -> Self {
    Filter { key: key.to_string(), value, operator }
  }
}

impl<T> FilterTrait for Filter<T>
where T: std::fmt::Display
{
  fn filter(&self) -> String {
    format!("`{0}` {1} {2}", self.key, self.operator, self.value)
  }
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  fn it_outputs_correct_statement() -> std::result::Result<(), Box<dyn std::error::Error>> {
    let g: Filter<u32> = ("user_id", Operator::Equal, 1.into()).into();
    assert!(FilterTrait::filter(&g).eq("`user_id` = 1"));
    Ok(())
  }
}

/*
pub struct Generic<T> 
where T: std::fmt::Display
{
  filter: Option<Filter<T>>,
}

impl<T> std::convert::From<()> for Generic<T>
where T: std::fmt::Display
{
  fn from(_: ()) -> Self {
    Generic { filter: None, next: None }
  }
}

impl<T> std::convert::From<(String, Operator, Value<T>)> for Generic<T> 
where T: std::fmt::Display
{
  fn from((key, operator, value): (String, Operator, Value<T>)) -> Self {
    Generic { filter: Some(Filter { key, value, operator }), next: None }
  }
}

impl<T> std::convert::From<(&str, Operator, Value<T>)> for Generic<T> 
where T: std::fmt::Display
{
  fn from((key, operator, value): (&str, Operator, Value<T>)) -> Self {
    Generic { filter: Some(Filter { key: key.to_string(), value, operator }), next: None }
  }
}

impl<T> Filterable for Generic<T>
where T: std::fmt::Display
{
  fn filter(&self) -> Option<String> {
    self.filter
    .as_ref()
    .map(|v| format!("`{0}` {1} {2}", v.key, v.operator, v.value))
  }

  fn next(&self) -> &Option<Box<dyn Selectable>> { &self.next }
  fn and(mut self, next: Box<dyn Selectable>)  -> Self { self.next = Some(next); self }
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  fn it_outputs_correct_statement() -> std::result::Result<(), Box<dyn std::error::Error>> {
    let g: Generic<u32> = ("user_id", Operator::Equal, 1.into()).into();
    assert!(filter::Filterable::filter(&g).unwrap().eq("`user_id` = 1"));
    assert!(g.next().is_none());

    Ok(())
  }
}
*/