1use Row;
2use std::fmt;
3use std::borrow::Cow;
4use std::borrow::Borrow;
5
6#[derive(Clone, Debug)]
8pub enum Value<'a, T: Clone + 'a> {
9 Const(Cow<'a, T>),
11
12 Column(usize),
15}
16
17impl<'a, T: Clone + 'a> Value<'a, T> {
18 pub fn value<'b: 'a, R: Row<T> + ?Sized>(&'b self, row: &'b R) -> &'b T {
22 match *self {
23 Value::Column(i) => &row.index(i),
24 Value::Const(ref val) => val,
25 }
26 }
27
28 pub fn new<I: Into<T>>(t: I) -> Self {
30 Value::Const(Cow::Owned(t.into()))
31 }
32
33 pub fn using<I: Borrow<T>>(t: &'a I) -> Self {
35 Value::Const(Cow::Borrowed(t.borrow()))
36 }
37
38 pub fn column(c: usize) -> Self {
40 Value::Column(c)
41 }
42}
43
44#[derive(Clone, Debug)]
46pub enum Comparison<'a, T: Clone + 'a> {
47 Equal(Value<'a, T>),
49}
50
51impl<'a, T: Ord + Clone + 'a> Comparison<'a, T> {
52 pub fn matches<R: Row<T> + ?Sized>(&self, value: &T, row: &R) -> bool {
55 match *self {
56 Comparison::Equal(ref v) => value == v.value(row),
57 }
58 }
59}
60
61#[derive(Clone, Debug)]
63pub struct Condition<'a, T: Clone + 'a> {
64 pub column: usize,
66
67 pub cmp: Comparison<'a, T>,
69}
70
71impl<'a, T: Ord + Clone + 'a> Condition<'a, T> {
72 pub fn matches<R: Row<T> + ?Sized>(&self, row: &R) -> bool {
75 self.cmp.matches(&row.index(self.column), row)
76 }
77}
78
79impl<'a, T: fmt::Display + Clone + 'a> fmt::Display for Value<'a, T> {
80 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81 match *self {
82 Value::Column(i) => write!(f, "[{}]", i),
83 Value::Const(ref val) => write!(f, "{}", val),
84 }
85 }
86}
87
88impl<'a, T: fmt::Display + Clone + 'a> fmt::Display for Comparison<'a, T> {
89 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90 match *self {
91 Comparison::Equal(ref v) => write!(f, "= {}", v),
92 }
93 }
94}
95
96impl<'a, T: fmt::Display + Clone + 'a> fmt::Display for Condition<'a, T> {
97 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98 write!(f, "[{}] {}", self.column, self.cmp)
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn value() {
108 let a = &["a"];
109 let b = &["b"];
110 assert_eq!(Value::column(0).value(&a[..]), &"a");
111 assert_eq!(Value::new("a").value(&b[..]), &"a");
112 }
113
114 #[test]
115 fn cmp_eq() {
116 let a = &["a"];
117 let b = &["b"];
118 assert!(Comparison::Equal(Value::column(0)).matches(&"a", &a[..]));
119 assert!(!Comparison::Equal(Value::column(0)).matches(&"a", &b[..]));
120 assert!(Comparison::Equal(Value::new("a")).matches(&"a", &b[..]));
121 assert!(!Comparison::Equal(Value::new("b")).matches(&"a", &a[..]));
122 }
123
124 #[test]
125 fn borrowed_values() {
126 let a = vec!["a".to_string()];
127 let b = vec!["b".to_string()];
128 assert!(Comparison::Equal(Value::column(0)).matches(&a[0], &a));
129 assert!(!Comparison::Equal(Value::column(0)).matches(&a[0], &b));
130 assert!(Comparison::Equal(Value::using(&a[0])).matches(&a[0], &b));
131 assert!(!Comparison::Equal(Value::using(&b[0])).matches(&a[0], &a));
132 }
133
134 #[test]
135 fn through_deref() {
136 let a = vec!["a".to_string()];
137 let b = vec!["b".to_string()];
138 assert!(Comparison::Equal(Value::column(0)).matches(&a[0], &a));
139 assert!(!Comparison::Equal(Value::column(0)).matches(&a[0], &b));
140 assert!(Comparison::Equal(Value::new("a")).matches(&a[0], &b));
141 assert!(!Comparison::Equal(Value::new("b")).matches(&a[0], &a));
142 }
143
144 #[test]
145 fn cond_eq() {
146 let cmpf0 = Comparison::Equal(Value::column(0));
147 let cmpca = Comparison::Equal(Value::new("a"));
148 let cmpcb = Comparison::Equal(Value::new("b"));
149
150 let cf10 = Condition {
151 column: 1,
152 cmp: cmpf0,
153 };
154 let cca = Condition {
155 column: 0,
156 cmp: cmpca,
157 };
158 let ccb = Condition {
159 column: 0,
160 cmp: cmpcb,
161 };
162
163 let a = &["a"];
164 let b = &["b"];
165 let aa = &["a", "a"];
166 let ab = &["a", "b"];
167 assert!(cf10.matches(&aa[..]));
168 assert!(!cf10.matches(&ab[..]));
169 assert!(cca.matches(&a[..]));
170 assert!(!cca.matches(&b[..]));
171 assert!(ccb.matches(&b[..]));
172 assert!(!ccb.matches(&a[..]));
173 }
174
175 #[test]
176 fn display() {
177 let cf01: Condition<String> = Condition {
178 column: 0,
179 cmp: Comparison::Equal(Value::Column(1)),
180 };
181
182 let cca = Condition {
183 column: 0,
184 cmp: Comparison::Equal::<&str>(Value::new("a")),
185 };
186
187 assert_eq!(format!("{}", cf01), "[0] = [1]");
188 assert_eq!(format!("{}", cca), "[0] = a")
189 }
190}