1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#![macro_use]

macro_rules! flags_ops {
	($flagset:ident: $ty:ty: $flags:ident: $($case:ident,)*) => (
		impl ::std::ops::BitOr<$flags> for $flags {
			type Output = $flagset;
			fn bitor(self, rhs: $flags) -> Self::Output {
				$flagset::from(self) | $flagset::from(rhs)
			}
		}

		impl $flagset {
			/// Construct empty set of flags.
			pub fn none() -> Self {
				$flagset(0)
			}
		}

		impl ::std::fmt::Debug for $flagset {
			fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
				write!(f, "[")?;
				$(
					if *self & $flags::$case {
						write!(f, "{:?},", $flags::$case)?;
					}
				)*
				write!(f, "]")
			}
		}

		impl ::std::default::Default for $flagset {
			fn default() -> Self {
				$flagset(0)
			}
		}

		impl ::std::convert::From<$flags> for $flagset {
			fn from(flag: $flags) -> Self {
				$flagset(1 << (flag as u8))
			}
		}

		impl ::std::convert::Into<$ty> for $flagset {
			fn into(self) -> $ty {
				self.0
			}
		}

		impl ::std::ops::BitOr<$flags> for $flagset {
			type Output = $flagset;
			fn bitor(self, rhs: $flags) -> Self::Output {
				self | $flagset::from(rhs)
			}
		}

		impl ::std::ops::BitOr<$flagset> for $flagset {
			type Output = $flagset;
			fn bitor(self, rhs: $flagset) -> Self::Output {
				$flagset(self.0 | rhs.0)
			}
		}

		impl<T> ::std::ops::BitOrAssign<T> for $flagset
		where $flagset: ::std::ops::BitOr<T, Output=$flagset> {
			fn bitor_assign(&mut self, rhs: T) {
				*self = *self | rhs;
			}
		}

		impl ::std::ops::BitAnd<$flags> for $flagset {
			type Output = bool;
			fn bitand(self, rhs: $flags) -> Self::Output {
				0 != (self.0 & $flagset::from(rhs).0)
			}
		}

		impl ::std::ops::BitAnd<$flagset> for $flags {
			type Output = bool;
			fn bitand(self, rhs: $flagset) -> Self::Output {
				0 != ($flagset::from(self).0 & rhs.0)
			}
		}
	);
}

macro_rules! flag_mapping {
	($flagset:ident: $flags:ident => $ty:ty:
		$($case:ident => $value:expr,)*
	) => (
		impl Into<$ty> for $flagset {
			fn into(self) -> $ty {
				$(
					(if self & $flags::$case {
						$value
					} else {
						0
					})
				|)*
				0
			}
		}

		impl From<$ty> for $flagset {
			fn from(value: $ty) -> Self {
				$(
					(if 0 != value & $value {
						$flags::$case.into()
					} else {
						$flagset::none()
					})
				|)*
				$flagset::none()
			}
		}
	);
}