1use std::fmt;
13
14use crate::reflection;
15use crate::Predicate;
16
17pub struct BoxPredicate<Item: ?Sized>(Box<dyn Predicate<Item> + Send + Sync>);
20
21impl<Item> BoxPredicate<Item>
22where
23 Item: ?Sized,
24{
25 pub fn new<P>(inner: P) -> BoxPredicate<Item>
28 where
29 P: Predicate<Item> + Send + Sync + 'static,
30 {
31 BoxPredicate(Box::new(inner))
32 }
33}
34
35impl<Item> fmt::Debug for BoxPredicate<Item>
36where
37 Item: ?Sized,
38{
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 f.debug_struct("BoxPredicate").finish()
41 }
42}
43
44impl<Item> reflection::PredicateReflection for BoxPredicate<Item>
45where
46 Item: ?Sized,
47{
48 fn parameters<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Parameter<'a>> + 'a> {
49 self.0.parameters()
50 }
51
52 fn children<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Child<'a>> + 'a> {
53 self.0.children()
54 }
55}
56
57impl<Item> fmt::Display for BoxPredicate<Item>
58where
59 Item: ?Sized,
60{
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 self.0.fmt(f)
63 }
64}
65
66impl<Item> Predicate<Item> for BoxPredicate<Item>
67where
68 Item: ?Sized,
69{
70 fn eval(&self, variable: &Item) -> bool {
71 self.0.eval(variable)
72 }
73
74 fn find_case<'a>(&'a self, expected: bool, variable: &Item) -> Option<reflection::Case<'a>> {
75 self.0.find_case(expected, variable)
76 }
77}
78
79pub trait PredicateBoxExt<Item: ?Sized>
81where
82 Self: Predicate<Item>,
83{
84 fn boxed(self) -> BoxPredicate<Item>
109 where
110 Self: Sized + Send + Sync + 'static,
111 {
112 BoxPredicate::new(self)
113 }
114}
115
116impl<P, Item: ?Sized> PredicateBoxExt<Item> for P where P: Predicate<Item> {}
117
118#[cfg(test)]
119mod test {
120 use crate::prelude::*;
121
122 #[test]
123 fn unsized_boxed() {
124 let p = predicate::always().boxed();
125 p.eval("4");
126 }
127
128 #[test]
129 fn boxed_find_case() {
130 let p1 = predicate::gt(5);
131 let p2 = p1.boxed();
132 match (p1.find_case(false, &4), p2.find_case(false, &4)) {
133 (Some(c1), Some(c2)) => {
134 assert_eq!(format!("{c1:?}"), format!("{c2:?}"));
135 }
136 _ => {
137 panic!();
138 }
139 }
140 }
141}