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     }
29 }
30 
31 impl reflection::PredicateReflection for IsEmptyPredicate {}
32 
33 impl fmt::Display for IsEmptyPredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result34     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35         write!(f, "var.is_empty()")
36     }
37 }
38 
39 /// Creates a new `Predicate` that ensures a str is empty
40 ///
41 /// # Examples
42 ///
43 /// ```
44 /// use predicates::prelude::*;
45 ///
46 /// let predicate_fn = predicate::str::is_empty();
47 /// assert_eq!(true, predicate_fn.eval(""));
48 /// assert_eq!(false, predicate_fn.eval("Food World"));
49 /// ```
is_empty() -> IsEmptyPredicate50 pub fn is_empty() -> IsEmptyPredicate {
51     IsEmptyPredicate {}
52 }
53 
54 /// Predicate checks start of str
55 ///
56 /// This is created by `predicates::str::starts_with`.
57 #[derive(Debug, Clone, PartialEq, Eq)]
58 pub struct StartsWithPredicate {
59     pattern: String,
60 }
61 
62 impl Predicate<str> for StartsWithPredicate {
eval(&self, variable: &str) -> bool63     fn eval(&self, variable: &str) -> bool {
64         variable.starts_with(&self.pattern)
65     }
66 
find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>>67     fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> {
68         utils::default_find_case(self, expected, variable)
69     }
70 }
71 
72 impl reflection::PredicateReflection for StartsWithPredicate {}
73 
74 impl fmt::Display for StartsWithPredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result75     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76         write!(f, "var.starts_with({:?})", self.pattern)
77     }
78 }
79 
80 /// Creates a new `Predicate` that ensures a str starts with `pattern`
81 ///
82 /// # Examples
83 ///
84 /// ```
85 /// use predicates::prelude::*;
86 ///
87 /// let predicate_fn = predicate::str::starts_with("Hello");
88 /// assert_eq!(true, predicate_fn.eval("Hello World"));
89 /// assert_eq!(false, predicate_fn.eval("Goodbye World"));
90 /// ```
starts_with<P>(pattern: P) -> StartsWithPredicate where P: Into<String>,91 pub fn starts_with<P>(pattern: P) -> StartsWithPredicate
92 where
93     P: Into<String>,
94 {
95     StartsWithPredicate {
96         pattern: pattern.into(),
97     }
98 }
99 
100 /// Predicate checks end of str
101 ///
102 /// This is created by `predicates::str::ends_with`.
103 #[derive(Debug, Clone, PartialEq, Eq)]
104 pub struct EndsWithPredicate {
105     pattern: String,
106 }
107 
108 impl Predicate<str> for EndsWithPredicate {
eval(&self, variable: &str) -> bool109     fn eval(&self, variable: &str) -> bool {
110         variable.ends_with(&self.pattern)
111     }
112 
find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>>113     fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> {
114         utils::default_find_case(self, expected, variable)
115     }
116 }
117 
118 impl reflection::PredicateReflection for EndsWithPredicate {}
119 
120 impl fmt::Display for EndsWithPredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result121     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122         write!(f, "var.ends_with({:?})", self.pattern)
123     }
124 }
125 
126 /// Creates a new `Predicate` that ensures a str ends with `pattern`
127 ///
128 /// # Examples
129 ///
130 /// ```
131 /// use predicates::prelude::*;
132 ///
133 /// let predicate_fn = predicate::str::ends_with("World");
134 /// assert_eq!(true, predicate_fn.eval("Hello World"));
135 /// assert_eq!(false, predicate_fn.eval("Hello Moon"));
136 /// ```
ends_with<P>(pattern: P) -> EndsWithPredicate where P: Into<String>,137 pub fn ends_with<P>(pattern: P) -> EndsWithPredicate
138 where
139     P: Into<String>,
140 {
141     EndsWithPredicate {
142         pattern: pattern.into(),
143     }
144 }
145 
146 /// Predicate that checks for patterns.
147 ///
148 /// This is created by `predicates::str:contains`.
149 #[derive(Debug, Clone, PartialEq, Eq)]
150 pub struct ContainsPredicate {
151     pattern: String,
152 }
153 
154 impl ContainsPredicate {
155     /// Require a specific count of matches.
156     ///
157     /// # Examples
158     ///
159     /// ```
160     /// use predicates::prelude::*;
161     ///
162     /// let predicate_fn = predicate::str::contains("Two").count(2);
163     /// assert_eq!(true, predicate_fn.eval("One Two Three Two One"));
164     /// assert_eq!(false, predicate_fn.eval("One Two Three"));
165     /// ```
count(self, count: usize) -> MatchesPredicate166     pub fn count(self, count: usize) -> MatchesPredicate {
167         MatchesPredicate {
168             pattern: self.pattern,
169             count,
170         }
171     }
172 }
173 
174 impl Predicate<str> for ContainsPredicate {
eval(&self, variable: &str) -> bool175     fn eval(&self, variable: &str) -> bool {
176         variable.contains(&self.pattern)
177     }
178 
find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>>179     fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> {
180         utils::default_find_case(self, expected, variable)
181     }
182 }
183 
184 impl reflection::PredicateReflection for ContainsPredicate {}
185 
186 impl fmt::Display for ContainsPredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result187     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188         write!(f, "var.contains({:?})", self.pattern)
189     }
190 }
191 
192 /// Predicate that checks for repeated patterns.
193 ///
194 /// This is created by `predicates::str::contains(...).count`.
195 #[derive(Debug, Clone, PartialEq, Eq)]
196 pub struct MatchesPredicate {
197     pattern: String,
198     count: usize,
199 }
200 
201 impl Predicate<str> for MatchesPredicate {
eval(&self, variable: &str) -> bool202     fn eval(&self, variable: &str) -> bool {
203         variable.matches(&self.pattern).count() == self.count
204     }
205 
find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>>206     fn find_case<'a>(&'a self, expected: bool, variable: &str) -> Option<reflection::Case<'a>> {
207         let actual_count = variable.matches(&self.pattern).count();
208         let result = self.count == actual_count;
209         if result == expected {
210             Some(
211                 reflection::Case::new(Some(self), result)
212                     .add_product(reflection::Product::new("actual count", actual_count)),
213             )
214         } else {
215             None
216         }
217     }
218 }
219 
220 impl reflection::PredicateReflection for MatchesPredicate {
parameters<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Parameter<'a>> + 'a>221     fn parameters<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Parameter<'a>> + 'a> {
222         let params = vec![reflection::Parameter::new("count", &self.count)];
223         Box::new(params.into_iter())
224     }
225 }
226 
227 impl fmt::Display for MatchesPredicate {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result228     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229         write!(f, "var.contains({})", self.pattern)
230     }
231 }
232 
233 /// Creates a new `Predicate` that ensures a str contains `pattern`
234 ///
235 /// # Examples
236 ///
237 /// ```
238 /// use predicates::prelude::*;
239 ///
240 /// let predicate_fn = predicate::str::contains("Two");
241 /// assert_eq!(true, predicate_fn.eval("One Two Three"));
242 /// assert_eq!(false, predicate_fn.eval("Four Five Six"));
243 /// ```
contains<P>(pattern: P) -> ContainsPredicate where P: Into<String>,244 pub fn contains<P>(pattern: P) -> ContainsPredicate
245 where
246     P: Into<String>,
247 {
248     ContainsPredicate {
249         pattern: pattern.into(),
250     }
251 }
252