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 //! Name predicate expressions.
10 
11 use std::fmt;
12 use std::marker::PhantomData;
13 
14 use crate::reflection;
15 use crate::Predicate;
16 
17 /// Augment an existing predicate with a name.
18 ///
19 /// This is created by the `PredicateNameExt::name` function.
20 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
21 pub struct NamePredicate<M, Item>
22 where
23     M: Predicate<Item>,
24     Item: ?Sized,
25 {
26     inner: M,
27     name: &'static str,
28     _phantom: PhantomData<Item>,
29 }
30 
31 unsafe impl<M, Item> Send for NamePredicate<M, Item>
32 where
33     M: Predicate<Item> + Send,
34     Item: ?Sized,
35 {
36 }
37 
38 unsafe impl<M, Item> Sync for NamePredicate<M, Item>
39 where
40     M: Predicate<Item> + Sync,
41     Item: ?Sized,
42 {
43 }
44 
45 impl<M, Item> Predicate<Item> for NamePredicate<M, Item>
46 where
47     M: Predicate<Item>,
48     Item: ?Sized,
49 {
eval(&self, item: &Item) -> bool50     fn eval(&self, item: &Item) -> bool {
51         self.inner.eval(item)
52     }
53 
find_case<'a>(&'a self, expected: bool, variable: &Item) -> Option<reflection::Case<'a>>54     fn find_case<'a>(&'a self, expected: bool, variable: &Item) -> Option<reflection::Case<'a>> {
55         self.inner
56             .find_case(expected, variable)
57             .map(|child_case| reflection::Case::new(Some(self), expected).add_child(child_case))
58     }
59 }
60 
61 impl<M, Item> reflection::PredicateReflection for NamePredicate<M, Item>
62 where
63     M: Predicate<Item>,
64     Item: ?Sized,
65 {
children<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Child<'a>> + 'a>66     fn children<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Child<'a>> + 'a> {
67         let params = vec![reflection::Child::new(self.name, &self.inner)];
68         Box::new(params.into_iter())
69     }
70 }
71 
72 impl<M, Item> fmt::Display for NamePredicate<M, Item>
73 where
74     M: Predicate<Item>,
75     Item: ?Sized,
76 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result77     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78         let palette = crate::Palette::new(f.alternate());
79         write!(f, "{}", palette.description(self.name))
80     }
81 }
82 
83 /// `Predicate` extension that adds naming predicate expressions.
84 pub trait PredicateNameExt<Item: ?Sized>
85 where
86     Self: Predicate<Item>,
87 {
88     /// Name a predicate expression.
89     ///
90     /// # Examples
91     ///
92     /// ```
93     /// use predicates::prelude::*;
94     ///
95     /// let predicate_fn = predicate::str::is_empty().not().name("non-empty");
96     /// println!("{}", predicate_fn);
97     /// ```
name(self, name: &'static str) -> NamePredicate<Self, Item> where Self: Sized,98     fn name(self, name: &'static str) -> NamePredicate<Self, Item>
99     where
100         Self: Sized,
101     {
102         NamePredicate {
103             inner: self,
104             name,
105             _phantom: PhantomData,
106         }
107     }
108 }
109 
110 impl<P, Item> PredicateNameExt<Item> for P
111 where
112     P: Predicate<Item>,
113     Item: ?Sized,
114 {
115 }
116