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