From d02c0222bc0109d0ad611a9d9f78d684b33a32fc Mon Sep 17 00:00:00 2001
From: Gavin Wood <gavin@parity.io>
Date: Tue, 27 Apr 2021 14:33:59 +0200
Subject: [PATCH] Introduce macro for building Contains impl based on a match
 (#8675)

* Introduce macro for building Contains impl based on a match

* Fixes
---
 substrate/frame/support/src/traits/members.rs | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/substrate/frame/support/src/traits/members.rs b/substrate/frame/support/src/traits/members.rs
index 35748ca9c0c..125f096fa92 100644
--- a/substrate/frame/support/src/traits/members.rs
+++ b/substrate/frame/support/src/traits/members.rs
@@ -31,6 +31,36 @@ impl<T: Ord> Contains<T> for All<T> {
 	fn contains(_: &T) -> bool { true }
 }
 
+/// Create a type which implements the `Contains` trait for a particular type with syntax similar
+/// to `matches!`.
+#[macro_export]
+macro_rules! match_type {
+	( pub type $n:ident: impl Contains<$t:ty> = { $phead:pat $( | $ptail:pat )* } ; ) => {
+		pub struct $n;
+		impl $crate::traits::Contains<$t> for $n {
+			fn contains(l: &$t) -> bool {
+				matches!(l, $phead $( | $ptail )* )
+			}
+		}
+	}
+}
+
+#[cfg(test)]
+mod tests {
+	use super::*;
+
+	match_type! {
+		pub type OneOrTenToTwenty: impl Contains<u8> = { 1 | 10..=20 };
+	}
+
+	#[test]
+	fn match_type_works() {
+		for i in 0..=255 {
+			assert_eq!(OneOrTenToTwenty::contains(&i), i == 1 || i >= 10 && i <= 20);
+		}
+	}
+}
+
 /// A trait for a set which can enumerate its members in order.
 pub trait SortedMembers<T: Ord> {
 	/// Get a vector of all members in the set, ordered.
-- 
GitLab