floem_reactive/
impls.rs

1use crate::{Memo, ReadSignal, RwSignal, SignalUpdate, SignalWith, WriteSignal};
2
3// Unary operation macro
4macro_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]);