serde_with_macros/
lazy_bool.rs
1use core::{
2 mem,
3 ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not},
4};
5
6#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
8pub enum LazyBool<T> {
9 #[default]
13 False,
14
15 True,
17
18 Lazy(T),
20}
21
22impl<T> From<bool> for LazyBool<T> {
23 fn from(value: bool) -> Self {
24 match value {
25 false => Self::False,
26 true => Self::True,
27 }
28 }
29}
30
31macro_rules! impl_op {
33 (
34 <
35 $trait:ident::$method:ident,
36 $assign_trait:ident::$assign_method:ident
37 >($matching:pat_param) {
38 $($pattern:pat => $body:expr),+ $(,)?
39 }
40 $(where $($bound:tt)+)?
41 ) => {
42 impl<L, R, T> $trait<LazyBool<R>> for LazyBool<L>
43 where
44 L: $trait<R, Output = T>,
45 LazyBool<L>: Into<LazyBool<T>>,
46 LazyBool<R>: Into<LazyBool<T>>,
47 $($($bound)+)?
48 {
49 type Output = LazyBool<T>;
50
51 fn $method(self, rhs: LazyBool<R>) -> Self::Output {
52 match (self, rhs) {
53 (LazyBool::Lazy(lhs), LazyBool::Lazy(rhs)) => LazyBool::Lazy(lhs.$method(rhs)),
54 ($matching, rhs) => rhs.into(),
55 (lhs, $matching) => lhs.into(),
56 $($pattern => $body),+
57 }
58 }
59 }
60
61 impl<'a, L, R, T> $trait<&'a LazyBool<R>> for LazyBool<L>
62 where
63 L: $trait<&'a R, Output = T>,
64 LazyBool<L>: Into<LazyBool<T>>,
65 LazyBool<R>: Into<LazyBool<T>> + Clone,
66 $($($bound)+)?
67 {
68 type Output = LazyBool<T>;
69
70 fn $method(self, rhs: &'a LazyBool<R>) -> Self::Output {
71 match (self, rhs) {
72 (LazyBool::Lazy(lhs), LazyBool::Lazy(rhs)) => LazyBool::Lazy(lhs.$method(rhs)),
73 ($matching, rhs) => rhs.clone().into(),
74 (lhs, $matching) => lhs.into(),
75 $($pattern => $body),+
76 }
77 }
78 }
79
80 impl<'a, L, R, T> $trait<LazyBool<R>> for &'a LazyBool<L>
81 where
82 LazyBool<R>: $trait<&'a LazyBool<L>, Output = LazyBool<T>>,
83 {
84 type Output = LazyBool<T>;
85
86 fn $method(self, rhs: LazyBool<R>) -> Self::Output {
87 rhs.$method(self)
88 }
89 }
90
91 impl<L, R> $assign_trait<LazyBool<R>> for LazyBool<L>
92 where
93 LazyBool<L>: $trait<LazyBool<R>, Output = LazyBool<L>>,
94 {
95 fn $assign_method(&mut self, rhs: LazyBool<R>) {
96 let lhs = mem::take(self);
97 *self = lhs.$method(rhs);
98 }
99 }
100 };
101}
102
103impl_op! { <BitAnd::bitand, BitAndAssign::bitand_assign>(LazyBool::True){ _ => LazyBool::False } }
104impl_op! { <BitOr::bitor, BitOrAssign::bitor_assign>(LazyBool::False) { _ => LazyBool::True } }
105impl_op! {
106 <BitXor::bitxor, BitXorAssign::bitxor_assign>(LazyBool::False) {
107 (LazyBool::True, rhs) => (!rhs).into(),
108 (lhs, LazyBool::True) => (!lhs).into(),
109 }
110 where
111 LazyBool<L>: Not<Output = LazyBool<L>>,
112 LazyBool<R>: Not<Output = LazyBool<R>>,
113}
114
115impl<T> Not for LazyBool<T>
116where
117 T: Not<Output = T>,
118{
119 type Output = Self;
120
121 fn not(self) -> Self::Output {
122 match self {
123 Self::False => Self::True,
124 Self::True => Self::False,
125 Self::Lazy(this) => Self::Lazy(!this),
126 }
127 }
128}
129
130impl<T> Not for &LazyBool<T>
131where
132 LazyBool<T>: Not<Output = LazyBool<T>> + Clone,
133{
134 type Output = LazyBool<T>;
135
136 fn not(self) -> Self::Output {
137 !self.clone()
138 }
139}