1 | // Copyright (c) 2018 The predicates-rs Project Developers. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
4 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
5 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
6 | // option. This file may not be copied, modified, or distributed |
7 | // except according to those terms. |
8 | |
9 | use std::fmt; |
10 | |
11 | use crate::reflection; |
12 | use crate::utils; |
13 | use crate::Predicate; |
14 | |
15 | /// Predicate that checks for empty strings. |
16 | /// |
17 | /// This is created by `predicates::str::is_empty`. |
18 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
19 | pub struct IsEmptyPredicate {} |
20 | |
21 | impl Predicate<str> for IsEmptyPredicate { |
22 | fn eval(&self, variable: &str) -> bool { |
23 | variable.is_empty() |
24 | } |
25 | |
26 | fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> { |
27 | utils::default_find_case(self, expected, variable) |
28 | .map(|case| case.add_product(reflection::Product::new("var" , variable.to_owned()))) |
29 | } |
30 | } |
31 | |
32 | impl reflection::PredicateReflection for IsEmptyPredicate {} |
33 | |
34 | impl fmt::Display for IsEmptyPredicate { |
35 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
36 | let palette = crate::Palette::current(); |
37 | write!( |
38 | f, |
39 | "{}.{}()" , |
40 | palette.var.paint("var" ), |
41 | palette.description.paint("is_empty" ), |
42 | ) |
43 | } |
44 | } |
45 | |
46 | /// Creates a new `Predicate` that ensures a str is empty |
47 | /// |
48 | /// # Examples |
49 | /// |
50 | /// ``` |
51 | /// use predicates::prelude::*; |
52 | /// |
53 | /// let predicate_fn = predicate::str::is_empty(); |
54 | /// assert_eq!(true, predicate_fn.eval("" )); |
55 | /// assert_eq!(false, predicate_fn.eval("Food World" )); |
56 | /// ``` |
57 | pub fn is_empty() -> IsEmptyPredicate { |
58 | IsEmptyPredicate {} |
59 | } |
60 | |
61 | /// Predicate checks start of str |
62 | /// |
63 | /// This is created by `predicates::str::starts_with`. |
64 | #[derive(Debug, Clone, PartialEq, Eq)] |
65 | pub struct StartsWithPredicate { |
66 | pattern: String, |
67 | } |
68 | |
69 | impl Predicate<str> for StartsWithPredicate { |
70 | fn eval(&self, variable: &str) -> bool { |
71 | variable.starts_with(&self.pattern) |
72 | } |
73 | |
74 | fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> { |
75 | utils::default_find_case(self, expected, variable) |
76 | .map(|case| case.add_product(reflection::Product::new("var" , variable.to_owned()))) |
77 | } |
78 | } |
79 | |
80 | impl reflection::PredicateReflection for StartsWithPredicate {} |
81 | |
82 | impl fmt::Display for StartsWithPredicate { |
83 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
84 | let palette = crate::Palette::current(); |
85 | write!( |
86 | f, |
87 | "{}.{}({:?})" , |
88 | palette.var.paint("var" ), |
89 | palette.description.paint("starts_with" ), |
90 | self.pattern |
91 | ) |
92 | } |
93 | } |
94 | |
95 | /// Creates a new `Predicate` that ensures a str starts with `pattern` |
96 | /// |
97 | /// # Examples |
98 | /// |
99 | /// ``` |
100 | /// use predicates::prelude::*; |
101 | /// |
102 | /// let predicate_fn = predicate::str::starts_with("Hello" ); |
103 | /// assert_eq!(true, predicate_fn.eval("Hello World" )); |
104 | /// assert_eq!(false, predicate_fn.eval("Goodbye World" )); |
105 | /// ``` |
106 | pub fn starts_with<P>(pattern: P) -> StartsWithPredicate |
107 | where |
108 | P: Into<String>, |
109 | { |
110 | StartsWithPredicate { |
111 | pattern: pattern.into(), |
112 | } |
113 | } |
114 | |
115 | /// Predicate checks end of str |
116 | /// |
117 | /// This is created by `predicates::str::ends_with`. |
118 | #[derive(Debug, Clone, PartialEq, Eq)] |
119 | pub struct EndsWithPredicate { |
120 | pattern: String, |
121 | } |
122 | |
123 | impl Predicate<str> for EndsWithPredicate { |
124 | fn eval(&self, variable: &str) -> bool { |
125 | variable.ends_with(&self.pattern) |
126 | } |
127 | |
128 | fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> { |
129 | utils::default_find_case(self, expected, variable) |
130 | .map(|case| case.add_product(reflection::Product::new("var" , variable.to_owned()))) |
131 | } |
132 | } |
133 | |
134 | impl reflection::PredicateReflection for EndsWithPredicate {} |
135 | |
136 | impl fmt::Display for EndsWithPredicate { |
137 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
138 | let palette = crate::Palette::current(); |
139 | write!( |
140 | f, |
141 | "{}.{}({:?})" , |
142 | palette.var.paint("var" ), |
143 | palette.description.paint("ends_with" ), |
144 | self.pattern |
145 | ) |
146 | } |
147 | } |
148 | |
149 | /// Creates a new `Predicate` that ensures a str ends with `pattern` |
150 | /// |
151 | /// # Examples |
152 | /// |
153 | /// ``` |
154 | /// use predicates::prelude::*; |
155 | /// |
156 | /// let predicate_fn = predicate::str::ends_with("World" ); |
157 | /// assert_eq!(true, predicate_fn.eval("Hello World" )); |
158 | /// assert_eq!(false, predicate_fn.eval("Hello Moon" )); |
159 | /// ``` |
160 | pub fn ends_with<P>(pattern: P) -> EndsWithPredicate |
161 | where |
162 | P: Into<String>, |
163 | { |
164 | EndsWithPredicate { |
165 | pattern: pattern.into(), |
166 | } |
167 | } |
168 | |
169 | /// Predicate that checks for patterns. |
170 | /// |
171 | /// This is created by `predicates::str:contains`. |
172 | #[derive(Debug, Clone, PartialEq, Eq)] |
173 | pub struct ContainsPredicate { |
174 | pattern: String, |
175 | } |
176 | |
177 | impl ContainsPredicate { |
178 | /// Require a specific count of matches. |
179 | /// |
180 | /// # Examples |
181 | /// |
182 | /// ``` |
183 | /// use predicates::prelude::*; |
184 | /// |
185 | /// let predicate_fn = predicate::str::contains("Two" ).count(2); |
186 | /// assert_eq!(true, predicate_fn.eval("One Two Three Two One" )); |
187 | /// assert_eq!(false, predicate_fn.eval("One Two Three" )); |
188 | /// ``` |
189 | pub fn count(self, count: usize) -> MatchesPredicate { |
190 | MatchesPredicate { |
191 | pattern: self.pattern, |
192 | count, |
193 | } |
194 | } |
195 | } |
196 | |
197 | impl Predicate<str> for ContainsPredicate { |
198 | fn eval(&self, variable: &str) -> bool { |
199 | variable.contains(&self.pattern) |
200 | } |
201 | |
202 | fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> { |
203 | utils::default_find_case(self, expected, variable) |
204 | .map(|case| case.add_product(reflection::Product::new("var" , variable.to_owned()))) |
205 | } |
206 | } |
207 | |
208 | impl reflection::PredicateReflection for ContainsPredicate {} |
209 | |
210 | impl fmt::Display for ContainsPredicate { |
211 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
212 | let palette = crate::Palette::current(); |
213 | write!( |
214 | f, |
215 | "{}.{}({})" , |
216 | palette.var.paint("var" ), |
217 | palette.description.paint("contains" ), |
218 | palette.expected.paint(&self.pattern), |
219 | ) |
220 | } |
221 | } |
222 | |
223 | /// Predicate that checks for repeated patterns. |
224 | /// |
225 | /// This is created by `predicates::str::contains(...).count`. |
226 | #[derive(Debug, Clone, PartialEq, Eq)] |
227 | pub struct MatchesPredicate { |
228 | pattern: String, |
229 | count: usize, |
230 | } |
231 | |
232 | impl Predicate<str> for MatchesPredicate { |
233 | fn eval(&self, variable: &str) -> bool { |
234 | variable.matches(&self.pattern).count() == self.count |
235 | } |
236 | |
237 | fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> { |
238 | let actual_count = variable.matches(&self.pattern).count(); |
239 | let result = self.count == actual_count; |
240 | if result == expected { |
241 | Some( |
242 | reflection::Case::new(Some(self), result) |
243 | .add_product(reflection::Product::new("var" , variable.to_owned())) |
244 | .add_product(reflection::Product::new("actual count" , actual_count)), |
245 | ) |
246 | } else { |
247 | None |
248 | } |
249 | } |
250 | } |
251 | |
252 | impl reflection::PredicateReflection for MatchesPredicate { |
253 | fn parameters<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Parameter<'a>> + 'a> { |
254 | let params = vec![reflection::Parameter::new("count" , &self.count)]; |
255 | Box::new(params.into_iter()) |
256 | } |
257 | } |
258 | |
259 | impl fmt::Display for MatchesPredicate { |
260 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
261 | let palette = crate::Palette::current(); |
262 | write!( |
263 | f, |
264 | "{}.{}({})" , |
265 | palette.var.paint("var" ), |
266 | palette.description.paint("contains" ), |
267 | palette.expected.paint(&self.pattern), |
268 | ) |
269 | } |
270 | } |
271 | |
272 | /// Creates a new `Predicate` that ensures a str contains `pattern` |
273 | /// |
274 | /// # Examples |
275 | /// |
276 | /// ``` |
277 | /// use predicates::prelude::*; |
278 | /// |
279 | /// let predicate_fn = predicate::str::contains("Two" ); |
280 | /// assert_eq!(true, predicate_fn.eval("One Two Three" )); |
281 | /// assert_eq!(false, predicate_fn.eval("Four Five Six" )); |
282 | /// ``` |
283 | pub fn contains<P>(pattern: P) -> ContainsPredicate |
284 | where |
285 | P: Into<String>, |
286 | { |
287 | ContainsPredicate { |
288 | pattern: pattern.into(), |
289 | } |
290 | } |
291 | |