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 {
eval(&self, variable: &str) -> bool22     fn eval(&self, variable: &str) -> bool {
23         variable.is_empty()
24     }
25 
find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>>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 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result35     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36         let palette = crate::Palette::new(f.alternate());
37         write!(
38             f,
39             "{}.{}()",
40             palette.var("var"),
41             palette.description("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 /// ```
is_empty() -> IsEmptyPredicate57 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 {
eval(&self, variable: &str) -> bool70     fn eval(&self, variable: &str) -> bool {
71         variable.starts_with(&self.pattern)
72     }
73 
find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>>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 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result83     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84         let palette = crate::Palette::new(f.alternate());
85         write!(
86             f,
87             "{}.{}({:?})",
88             palette.var("var"),
89             palette.description("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 /// ```
starts_with<P>(pattern: P) -> StartsWithPredicate where P: Into<String>,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 {
eval(&self, variable: &str) -> bool124     fn eval(&self, variable: &str) -> bool {
125         variable.ends_with(&self.pattern)
126     }
127 
find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>>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 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result137     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138         let palette = crate::Palette::new(f.alternate());
139         write!(
140             f,
141             "{}.{}({:?})",
142             palette.var("var"),
143             palette.description("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 /// ```
ends_with<P>(pattern: P) -> EndsWithPredicate where P: Into<String>,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     /// ```
count(self, count: usize) -> MatchesPredicate189     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 {
eval(&self, variable: &str) -> bool198     fn eval(&self, variable: &str) -> bool {
199         variable.contains(&self.pattern)
200     }
201 
find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>>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 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result211     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212         let palette = crate::Palette::new(f.alternate());
213         write!(
214             f,
215             "{}.{}({})",
216             palette.var("var"),
217             palette.description("contains"),
218             palette.expected(&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 {
eval(&self, variable: &str) -> bool233     fn eval(&self, variable: &str) -> bool {
234         variable.matches(&self.pattern).count() == self.count
235     }
236 
find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>>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 {
parameters<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Parameter<'a>> + 'a>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 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result260     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261         let palette = crate::Palette::new(f.alternate());
262         write!(
263             f,
264             "{}.{}({})",
265             palette.var("var"),
266             palette.description("contains"),
267             palette.expected(&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 /// ```
contains<P>(pattern: P) -> ContainsPredicate where P: Into<String>,283 pub fn contains<P>(pattern: P) -> ContainsPredicate
284 where
285     P: Into<String>,
286 {
287     ContainsPredicate {
288         pattern: pattern.into(),
289     }
290 }
291