1use std::ops::*;
2
3use super::{MaybeOwned, MaybeOwnedMut};
4
5macro_rules! impl_op {
6 ($([$OP:ident : $op:ident, $OP_ASSIGN:ident : $op_assign: ident]),*) => ($(
7 impl<'min, L, R, OUT: 'min> $OP<MaybeOwned<'min, R>> for MaybeOwned<'min, L>
8 where L: $OP<R, Output=OUT> + $OP<&'min R, Output=OUT>,
9 &'min L: $OP<R, Output=OUT> + $OP<&'min R, Output=OUT>
10 {
11 type Output = OUT;
12
13 fn $op(self, rhs: MaybeOwned<'min, R>) -> Self::Output {
14 use self::MaybeOwned::*;
15 match (self, rhs) {
16 (Owned(l), Owned(r)) => l.$op(r),
17 (Owned(l), Borrowed(r)) => l.$op(r),
18 (Borrowed(l), Owned(r)) => l.$op(r),
19 (Borrowed(l), Borrowed(r)) => l.$op(r)
20 }
21 }
22 }
23
24 impl<'min, L, R, OUT: 'min> $OP<MaybeOwnedMut<'min, R>> for MaybeOwnedMut<'min, L>
28 where L: $OP<R, Output=OUT> + $OP<&'min R, Output=OUT>,
29 &'min L: $OP<R, Output=OUT> + $OP<&'min R, Output=OUT>
30 {
31 type Output = OUT;
32
33 fn $op(self, rhs: MaybeOwnedMut<'min, R>) -> Self::Output {
34 use self::MaybeOwnedMut::*;
35 match (self, rhs) {
36 (Owned(l), Owned(r)) => l.$op(r),
37 (Owned(l), Borrowed(r)) => l.$op(&*r),
38 (Borrowed(l), Owned(r)) => (&*l).$op(r),
39 (Borrowed(l), Borrowed(r)) => (&*l).$op(&*r)
40 }
41 }
42 }
43
44 impl<'min, L, R> $OP_ASSIGN<MaybeOwned<'min, R>> for MaybeOwned<'min, L>
45 where L: Clone + $OP_ASSIGN<R> + $OP_ASSIGN<&'min R>
46 {
47
48 fn $op_assign(&mut self, rhs: MaybeOwned<'min, R>) {
49 use self::MaybeOwned::*;
50 match rhs {
51 Owned(r) => self.make_owned().$op_assign(r),
52 Borrowed(r) => self.make_owned().$op_assign(r)
53 }
54 }
55 }
56
57 impl<'min, L, R> $OP_ASSIGN<MaybeOwnedMut<'min, R>> for MaybeOwnedMut<'min, L>
58 where L: $OP_ASSIGN<R> + $OP_ASSIGN<&'min R>
59 {
60
61 fn $op_assign(&mut self, rhs: MaybeOwnedMut<'min, R>) {
62 use self::MaybeOwnedMut::*;
63 match rhs {
64 Owned(r) => self.as_mut().$op_assign(r),
65 Borrowed(r) => self.as_mut().$op_assign(&*r)
66 }
67 }
68 }
69 )*);
70}
71
72impl_op! {
73 [Add: add, AddAssign: add_assign],
74 [Sub: sub, SubAssign: sub_assign],
75 [Mul: mul, MulAssign: mul_assign],
76 [Div: div, DivAssign: div_assign],
77 [Shl: shl, ShlAssign: shl_assign],
78 [Shr: shr, ShrAssign: shr_assign],
79 [BitAnd: bitand, BitAndAssign: bitand_assign],
80 [BitOr: bitor, BitOrAssign: bitor_assign ],
81 [BitXor: bitxor, BitXorAssign: bitxor_assign]
82}
83
84impl<'l, V, OUT> Neg for MaybeOwned<'l, V>
85where
86 V: Neg<Output = OUT>,
87 &'l V: Neg<Output = OUT>,
88{
89 type Output = OUT;
90
91 fn neg(self) -> Self::Output {
92 use self::MaybeOwned::*;
93
94 match self {
95 Owned(s) => s.neg(),
96 Borrowed(s) => s.neg(),
97 }
98 }
99}
100
101impl<'l, V, OUT> Neg for MaybeOwnedMut<'l, V>
102where
103 V: Neg<Output = OUT>,
104 &'l V: Neg<Output = OUT>,
105{
106 type Output = OUT;
107
108 fn neg(self) -> Self::Output {
109 use self::MaybeOwnedMut::*;
110
111 match self {
112 Owned(s) => s.neg(),
113 Borrowed(s) => (&*s).neg(),
114 }
115 }
116}
117
118impl<'l, V, OUT> Not for MaybeOwned<'l, V>
119where
120 V: Not<Output = OUT>,
121 &'l V: Not<Output = OUT>,
122{
123 type Output = V::Output;
124
125 fn not(self) -> Self::Output {
126 use self::MaybeOwned::*;
127
128 match self {
129 Owned(s) => s.not(),
130 Borrowed(s) => s.not(),
131 }
132 }
133}
134
135impl<'l, V, OUT> Not for MaybeOwnedMut<'l, V>
136where
137 V: Not<Output = OUT>,
138 &'l V: Not<Output = OUT>,
139{
140 type Output = V::Output;
141
142 fn not(self) -> Self::Output {
143 use self::MaybeOwnedMut::*;
144
145 match self {
146 Owned(s) => s.not(),
147 Borrowed(s) => (&*s).not(),
148 }
149 }
150}
151
152#[cfg(test)]
153mod test {
154 use super::*;
155 use std::ops::{Add, AddAssign, Neg, Not};
156
157 #[derive(Clone, PartialEq)]
160 struct Think {
161 x: u8,
162 }
163
164 impl Add<Think> for Think {
165 type Output = u8;
166
167 fn add(self, rhs: Think) -> Self::Output {
168 self.x + rhs.x
169 }
170 }
171 impl AddAssign<Think> for Think {
172 fn add_assign(&mut self, rhs: Think) {
173 self.x += rhs.x
174 }
175 }
176 impl<'a> Add<&'a Think> for Think {
177 type Output = u8;
178
179 fn add(self, rhs: &'a Think) -> Self::Output {
180 self.x + rhs.x
181 }
182 }
183 impl<'a> AddAssign<&'a Think> for Think {
184 fn add_assign(&mut self, rhs: &'a Think) {
185 self.x += rhs.x
186 }
187 }
188 impl<'a> Add<Think> for &'a Think {
189 type Output = u8;
190
191 fn add(self, rhs: Think) -> Self::Output {
192 self.x + rhs.x
193 }
194 }
195 impl<'a, 'b> Add<&'a Think> for &'b Think {
196 type Output = u8;
197
198 fn add(self, rhs: &'a Think) -> Self::Output {
199 self.x + rhs.x
200 }
201 }
202
203 impl Not for Think {
204 type Output = bool;
205
206 fn not(self) -> Self::Output {
207 self.x != 0
208 }
209 }
210
211 impl<'a> Not for &'a Think {
212 type Output = bool;
213
214 fn not(self) -> Self::Output {
215 self.x != 0
216 }
217 }
218
219 impl Neg for Think {
220 type Output = i8;
221
222 fn neg(self) -> Self::Output {
223 -(self.x as i8)
224 }
225 }
226
227 impl<'a> Neg for &'a Think {
228 type Output = i8;
229
230 fn neg(self) -> Self::Output {
231 -(self.x as i8)
232 }
233 }
234
235 #[test]
236 fn op_impls_exist() {
237 let a = MaybeOwned::from(Think { x: 12 });
238 let b = MaybeOwned::from(Think { x: 13 });
239 assert_eq!(a + b, 25u8);
240
241 let c = Think { x: 42 };
242 let c1: MaybeOwned<Think> = (&c).into();
243 let c2: MaybeOwned<Think> = (&c).into();
244
245 assert_eq!(c1 + c2, 84);
246 }
247
248 #[test]
249 fn op_impls_exist_for_mut() {
250 let a: MaybeOwnedMut<Think> = Think { x: 12 }.into();
251 let b: MaybeOwnedMut<Think> = Think { x: 13 }.into();
252 assert_eq!(a + b, 25u8);
253
254 let mut c0a = Think { x: 42 };
255 let mut c0b = Think { x: 8 };
256 let c1: MaybeOwnedMut<Think> = (&mut c0a).into();
257 let c2: MaybeOwnedMut<Think> = (&mut c0b).into();
258 assert_eq!(c1 + c2, 50);
259 }
260
261 #[test]
262 fn op_assign_impls_exist() {
263 let mut a = MaybeOwned::from(Think { x: 2 });
264 a += MaybeOwned::from(Think { x: 3 });
265 assert_eq!(a.x, 5);
266
267 let a = Think { x: 2 };
268 let mut a: MaybeOwned<Think> = (&a).into();
269 assert!(!a.is_owned());
270 a += MaybeOwned::from(Think { x: 5 });
271 assert!(a.is_owned());
272 assert_eq!(a.as_ref().x, 7);
273 }
274
275 #[test]
276 fn op_assign_impls_exist_mut() {
277 let mut a: MaybeOwnedMut<Think> = Think { x: 2 }.into();
278 a += MaybeOwnedMut::from(Think { x: 3 });
279 assert_eq!(a.x, 5);
280
281 let mut a = Think { x: 2 };
282 let mut a: MaybeOwnedMut<Think> = (&mut a).into();
283 assert!(!a.is_owned());
284 a += MaybeOwnedMut::from(Think { x: 5 });
285 assert!(!a.is_owned());
286 assert_eq!(a.as_ref().x, 7);
287 }
288
289 #[test]
290 fn not_and_neg_work_for_think_test_type() {
291 assert_eq!(!Think { x: 0 }, false);
292 assert_eq!(!Think { x: 1 }, true);
293 assert_eq!(!&Think { x: 0 }, false);
294 assert_eq!(!&Think { x: 1 }, true);
295 }
296
297 #[test]
298 fn not_and_neg_are_impl() {
299 let a = Think { x: 5 };
300 let a1: MaybeOwned<Think> = (&a).into();
301 let a2: MaybeOwned<Think> = (&a).into();
302 assert_eq!(!a1, true);
303 assert_eq!(-a2, -5i8);
304 }
305
306 #[test]
307 fn not_and_neg_are_impl_mut() {
308 let mut a = Think { x: 5 };
309 let mut b = Think { x: 0 };
310 let a1: MaybeOwnedMut<Think> = (&mut a).into();
311 let b1: MaybeOwnedMut<Think> = (&mut b).into();
312
313 assert_eq!(!a1, true);
314 assert_eq!(!b1, false);
315
316 let a2: MaybeOwnedMut<Think> = (&mut a).into();
317 assert_eq!(-a2, -5i8);
318 }
319}