@@ -25,13 +25,52 @@ pub trait Contains<T> {
2525 fn contains ( t : & T ) -> bool ;
2626}
2727
28+ #[ impl_trait_for_tuples:: impl_for_tuples( 1 , 30 ) ]
29+ impl < T > Contains < T > for Tuple {
30+ fn contains ( t : & T ) -> bool {
31+ for_tuples ! ( #(
32+ if Tuple :: contains( t) { return true }
33+ ) * ) ;
34+ false
35+ }
36+ }
37+
38+ /// A trait for querying whether a type can be said to "contain" a pair-value.
39+ pub trait ContainsPair < A , B > {
40+ /// Return `true` if this "contains" the pair-value `(a, b)`.
41+ fn contains ( a : & A , b : & B ) -> bool ;
42+ }
43+
44+ #[ impl_trait_for_tuples:: impl_for_tuples( 0 , 30 ) ]
45+ impl < A , B > ContainsPair < A , B > for Tuple {
46+ fn contains ( a : & A , b : & B ) -> bool {
47+ for_tuples ! ( #(
48+ if Tuple :: contains( a, b) { return true }
49+ ) * ) ;
50+ false
51+ }
52+ }
53+
54+ /// Converter `struct` to use a `ContainsPair` implementation for a `Contains` bound.
55+ pub struct FromContainsPair < CP > ( PhantomData < CP > ) ;
56+ impl < A , B , CP : ContainsPair < A , B > > Contains < ( A , B ) > for FromContainsPair < CP > {
57+ fn contains ( ( ref a, ref b) : & ( A , B ) ) -> bool {
58+ CP :: contains ( a, b)
59+ }
60+ }
61+
2862/// A [`Contains`] implementation that contains every value.
2963pub enum Everything { }
3064impl < T > Contains < T > for Everything {
3165 fn contains ( _: & T ) -> bool {
3266 true
3367 }
3468}
69+ impl < A , B > ContainsPair < A , B > for Everything {
70+ fn contains ( _: & A , _: & B ) -> bool {
71+ true
72+ }
73+ }
3574
3675/// A [`Contains`] implementation that contains no value.
3776pub enum Nothing { }
@@ -40,56 +79,125 @@ impl<T> Contains<T> for Nothing {
4079 false
4180 }
4281}
82+ impl < A , B > ContainsPair < A , B > for Nothing {
83+ fn contains ( _: & A , _: & B ) -> bool {
84+ false
85+ }
86+ }
4387
44- #[ deprecated = "Use `Everything` instead" ]
45- pub type AllowAll = Everything ;
46- #[ deprecated = "Use `Nothing` instead" ]
47- pub type DenyAll = Nothing ;
48- #[ deprecated = "Use `Contains` instead" ]
49- pub trait Filter < T > {
50- fn filter ( t : & T ) -> bool ;
88+ /// A [`Contains`] implementation that contains everything except the values in `Exclude`.
89+ pub struct EverythingBut < Exclude > ( PhantomData < Exclude > ) ;
90+ impl < T , Exclude : Contains < T > > Contains < T > for EverythingBut < Exclude > {
91+ fn contains ( t : & T ) -> bool {
92+ !Exclude :: contains ( t)
93+ }
5194}
52- #[ allow( deprecated) ]
53- impl < T , C : Contains < T > > Filter < T > for C {
54- fn filter ( t : & T ) -> bool {
55- Self :: contains ( t)
95+ impl < A , B , Exclude : ContainsPair < A , B > > ContainsPair < A , B > for EverythingBut < Exclude > {
96+ fn contains ( a : & A , b : & B ) -> bool {
97+ !Exclude :: contains ( a, b)
5698 }
5799}
58100
59- #[ impl_trait_for_tuples:: impl_for_tuples( 1 , 30 ) ]
60- impl < T > Contains < T > for Tuple {
101+ /// A [`Contains`] implementation that contains all members of `These` excepting any members in
102+ /// `Except`.
103+ pub struct TheseExcept < These , Except > ( PhantomData < ( These , Except ) > ) ;
104+ impl < T , These : Contains < T > , Except : Contains < T > > Contains < T > for TheseExcept < These , Except > {
61105 fn contains ( t : & T ) -> bool {
62- for_tuples ! ( #(
63- if Tuple :: contains( t) { return true }
64- ) * ) ;
65- false
106+ These :: contains ( t) && !Except :: contains ( t)
107+ }
108+ }
109+ impl < A , B , These : ContainsPair < A , B > , Except : ContainsPair < A , B > > ContainsPair < A , B >
110+ for TheseExcept < These , Except >
111+ {
112+ fn contains ( a : & A , b : & B ) -> bool {
113+ These :: contains ( a, b) && !Except :: contains ( a, b)
114+ }
115+ }
116+
117+ /// A [`Contains`] implementation which contains all members of `These` which are also members of
118+ /// `Those`.
119+ pub struct InsideBoth < These , Those > ( PhantomData < ( These , Those ) > ) ;
120+ impl < T , These : Contains < T > , Those : Contains < T > > Contains < T > for InsideBoth < These , Those > {
121+ fn contains ( t : & T ) -> bool {
122+ These :: contains ( t) && Those :: contains ( t)
123+ }
124+ }
125+ impl < A , B , These : ContainsPair < A , B > , Those : ContainsPair < A , B > > ContainsPair < A , B >
126+ for InsideBoth < These , Those >
127+ {
128+ fn contains ( a : & A , b : & B ) -> bool {
129+ These :: contains ( a, b) && Those :: contains ( a, b)
66130 }
67131}
68132
69133/// Create a type which implements the `Contains` trait for a particular type with syntax similar
70134/// to `matches!`.
71135#[ macro_export]
72- macro_rules! match_type {
73- ( pub type $n: ident: impl Contains <$t: ty> = { $phead: pat_param $( | $ptail: pat ) * } ; ) => {
136+ macro_rules! match_types {
137+ (
138+ pub type $n: ident: impl Contains <$t: ty> = {
139+ $phead: pat_param $( | $ptail: pat ) *
140+ } ;
141+ $( $rest: tt ) *
142+ ) => {
74143 pub struct $n;
75144 impl $crate:: traits:: Contains <$t> for $n {
76145 fn contains( l: & $t) -> bool {
77146 matches!( l, $phead $( | $ptail ) * )
78147 }
79148 }
149+ $crate:: match_types!( $( $rest ) * ) ;
150+ } ;
151+ (
152+ pub type $n: ident: impl ContainsPair <$a: ty, $b: ty> = {
153+ $phead: pat_param $( | $ptail: pat ) *
154+ } ;
155+ $( $rest: tt ) *
156+ ) => {
157+ pub struct $n;
158+ impl $crate:: traits:: ContainsPair <$a, $b> for $n {
159+ fn contains( a: & $a, b: & $b) -> bool {
160+ matches!( ( a, b) , $phead $( | $ptail ) * )
161+ }
162+ }
163+ $crate:: match_types!( $( $rest ) * ) ;
164+ } ;
165+ ( ) => { }
166+ }
167+
168+ /// Create a type which implements the `Contains` trait for a particular type with syntax similar
169+ /// to `matches!`.
170+ #[ macro_export]
171+ #[ deprecated = "Use `match_types!` instead" ]
172+ macro_rules! match_type {
173+ ( $( $x: tt ) * ) => { $crate:: match_types!( $( $x ) * ) ; }
174+ }
175+
176+ #[ deprecated = "Use `Everything` instead" ]
177+ pub type AllowAll = Everything ;
178+ #[ deprecated = "Use `Nothing` instead" ]
179+ pub type DenyAll = Nothing ;
180+ #[ deprecated = "Use `Contains` instead" ]
181+ pub trait Filter < T > {
182+ fn filter ( t : & T ) -> bool ;
183+ }
184+ #[ allow( deprecated) ]
185+ impl < T , C : Contains < T > > Filter < T > for C {
186+ fn filter ( t : & T ) -> bool {
187+ Self :: contains ( t)
80188 }
81189}
82190
83191#[ cfg( test) ]
84192mod tests {
85193 use super :: * ;
86194
87- match_type ! {
195+ match_types ! {
88196 pub type OneOrTenToTwenty : impl Contains <u8 > = { 1 | 10 ..=20 } ;
89197 }
90198
91199 #[ test]
92- fn match_type_works ( ) {
200+ fn match_types_works ( ) {
93201 for i in 0 ..=255 {
94202 assert_eq ! ( OneOrTenToTwenty :: contains( & i) , i == 1 || i >= 10 && i <= 20 ) ;
95203 }
0 commit comments