predicates/str/
basics.rs

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
9use std::fmt;
10
11use crate::reflection;
12use crate::utils;
13use 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)]
19pub struct IsEmptyPredicate {}
20
21impl 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    }
29}
30
31impl reflection::PredicateReflection for IsEmptyPredicate {}
32
33impl fmt::Display for IsEmptyPredicate {
34    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/// ```
50pub 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)]
58pub struct StartsWithPredicate {
59    pattern: String,
60}
61
62impl Predicate<str> for StartsWithPredicate {
63    fn eval(&self, variable: &str) -> bool {
64        variable.starts_with(&self.pattern)
65    }
66
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
72impl reflection::PredicateReflection for StartsWithPredicate {}
73
74impl fmt::Display for StartsWithPredicate {
75    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/// ```
91pub fn starts_with<P>(pattern: P) -> StartsWithPredicate
92where
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)]
104pub struct EndsWithPredicate {
105    pattern: String,
106}
107
108impl Predicate<str> for EndsWithPredicate {
109    fn eval(&self, variable: &str) -> bool {
110        variable.ends_with(&self.pattern)
111    }
112
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
118impl reflection::PredicateReflection for EndsWithPredicate {}
119
120impl fmt::Display for EndsWithPredicate {
121    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/// ```
137pub fn ends_with<P>(pattern: P) -> EndsWithPredicate
138where
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)]
150pub struct ContainsPredicate {
151    pattern: String,
152}
153
154impl 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    /// ```
166    pub fn count(self, count: usize) -> MatchesPredicate {
167        MatchesPredicate {
168            pattern: self.pattern,
169            count,
170        }
171    }
172}
173
174impl Predicate<str> for ContainsPredicate {
175    fn eval(&self, variable: &str) -> bool {
176        variable.contains(&self.pattern)
177    }
178
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
184impl reflection::PredicateReflection for ContainsPredicate {}
185
186impl fmt::Display for ContainsPredicate {
187    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)]
196pub struct MatchesPredicate {
197    pattern: String,
198    count: usize,
199}
200
201impl Predicate<str> for MatchesPredicate {
202    fn eval(&self, variable: &str) -> bool {
203        variable.matches(&self.pattern).count() == self.count
204    }
205
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
220impl reflection::PredicateReflection for MatchesPredicate {
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
227impl fmt::Display for MatchesPredicate {
228    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/// ```
244pub fn contains<P>(pattern: P) -> ContainsPredicate
245where
246    P: Into<String>,
247{
248    ContainsPredicate {
249        pattern: pattern.into(),
250    }
251}