maybe_owned/
transitive_impl.rs

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        // Note: With an additional macro level we could fold this with the
25        //       previous $OP implementation. But the additional read complexity
26        //       isn't really worth it.
27        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    //FIXME the test might need some cleanup.
158
159    #[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}