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 | { |
50 | fn eval(&self, item: &Item) -> bool { |
51 | self.inner.eval(item) |
52 | } |
53 | |
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 | { |
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 | { |
77 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
78 | let palette = crate::Palette::current(); |
79 | write!(f, "{}" , palette.description.paint(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 | /// ``` |
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 | |