1use crate::{Memo, ReadSignal, RwSignal, SignalUpdate, SignalWith, WriteSignal};
2
3macro_rules! impl_unary_op {
5 ($signal_type:ident, $trait:ident, $method:ident, $op:tt, [$($extra:tt)*]) => {
6 impl<T: 'static $(+ $extra)*> std::ops::$trait for $signal_type<T>
7 where
8 for<'a> &'a T: std::ops::$trait<Output = T>,
9 {
10 type Output = T;
11
12 fn $method(self) -> Self::Output {
13 self.with(|val| $op val)
14 }
15 }
16 };
17}
18
19macro_rules! impl_bin_op {
20 ($signal_type:ident, $trait:ident, $method:ident, $op:tt, [$($extra:tt)*]) => {
21 impl<T: std::ops::$trait<Output = T> + 'static $(+ $extra)*> std::ops::$trait<T>
22 for $signal_type<T>
23 where
24 for<'a> &'a T: std::ops::$trait<T, Output = T>,
25 {
26 type Output = T;
27 fn $method(self, rhs: T) -> Self::Output {
28 self.with(|val| val $op rhs)
29 }
30 }
31 };
32}
33
34macro_rules! impl_assign_op {
35 ($signal_type:ident, $trait:ident, $method:ident, $op:tt, [$($extra:tt)*]) => {
36 impl<T: std::ops::$trait + 'static $(+ $extra)*> std::ops::$trait<T> for $signal_type<T> {
37 fn $method(&mut self, rhs: T) {
38 self.update(|val| *val $op rhs);
39 }
40 }
41 };
42}
43
44macro_rules! impl_partial_eq {
45 ($signal_type:ident, [$($extra:tt)*]) => {
46 impl<T: PartialEq + 'static $(+ $extra)*> PartialEq<T> for $signal_type<T> {
47 fn eq(&self, other: &T) -> bool {
48 self.with(|val| *val == *other)
49 }
50 }
51 };
52}
53
54macro_rules! impl_display {
55 ($signal_type:ident, [$($extra:tt)*]) => {
56 impl<T: std::fmt::Display + 'static $(+ $extra)*> std::fmt::Display for $signal_type<T> {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 self.with(|val| std::fmt::Display::fmt(val, f))
59 }
60 }
61 };
62}
63
64macro_rules! impl_with_ops {
65 ($signal_type:ident, [$($extra:tt)*]) => {
66 impl_bin_op!($signal_type, Add, add, +, [$($extra)*]);
67 impl_bin_op!($signal_type, Sub, sub, -, [$($extra)*]);
68 impl_bin_op!($signal_type, Mul, mul, *, [$($extra)*]);
69 impl_bin_op!($signal_type, Div, div, /, [$($extra)*]);
70 impl_bin_op!($signal_type, Rem, rem, %, [$($extra)*]);
71 impl_bin_op!($signal_type, BitAnd, bitand, &, [$($extra)*]);
72 impl_bin_op!($signal_type, BitOr, bitor, |, [$($extra)*]);
73 impl_bin_op!($signal_type, BitXor, bitxor, ^, [$($extra)*]);
74 impl_bin_op!($signal_type, Shl, shl, <<, [$($extra)*]);
75 impl_bin_op!($signal_type, Shr, shr, >>, [$($extra)*]);
76 impl_unary_op!($signal_type, Not, not, !, [$($extra)*]);
77 impl_unary_op!($signal_type, Neg, neg, -, [$($extra)*]);
78 impl_partial_eq!($signal_type, [$($extra)*]);
79 impl_display!($signal_type, [$($extra)*]);
80 };
81}
82
83macro_rules! impl_assign_ops {
84 ($signal_type:ident, [$($extra:tt)*]) => {
85 impl_assign_op!($signal_type, AddAssign, add_assign, +=, [$($extra)*]);
86 impl_assign_op!($signal_type, SubAssign, sub_assign, -=, [$($extra)*]);
87 impl_assign_op!($signal_type, MulAssign, mul_assign, *=, [$($extra)*]);
88 impl_assign_op!($signal_type, DivAssign, div_assign, /=, [$($extra)*]);
89 impl_assign_op!($signal_type, RemAssign, rem_assign, %=, [$($extra)*]);
90 impl_assign_op!($signal_type, BitAndAssign, bitand_assign, &=, [$($extra)*]);
91 impl_assign_op!($signal_type, BitOrAssign, bitor_assign, |=, [$($extra)*]);
92 impl_assign_op!($signal_type, BitXorAssign, bitxor_assign, ^=, [$($extra)*]);
93 impl_assign_op!($signal_type, ShlAssign, shl_assign, <<=, [$($extra)*]);
94 impl_assign_op!($signal_type, ShrAssign, shr_assign, >>=, [$($extra)*]);
95 };
96}
97
98macro_rules! impl_all_ops {
99 ($signal_type:ident, [$($extra:tt)*]) => {
100 impl_assign_ops!($signal_type, [$($extra)*]);
101 impl_with_ops!($signal_type, [$($extra)*]);
102 };
103}
104
105impl_all_ops!(RwSignal, []);
106impl_assign_ops!(WriteSignal, []);
107impl_with_ops!(ReadSignal, []);
108impl_with_ops!(Memo, [PartialEq]);