maybe_owned/
transitive_impl.rsuse std::ops::*;
use super::MaybeOwned;
macro_rules! impl_op {
($([$OP:ident : $op:ident, $OP_ASSIGN:ident : $op_assign: ident]),*) => ($(
impl<'min, L, R, OUT: 'min> $OP<MaybeOwned<'min, R>> for MaybeOwned<'min, L>
where L: $OP<R, Output=OUT> + $OP<&'min R, Output=OUT>,
&'min L: $OP<R, Output=OUT> + $OP<&'min R, Output=OUT>
{
type Output = OUT;
fn $op(self, rhs: MaybeOwned<'min, R>) -> Self::Output {
use self::MaybeOwned::*;
match (self, rhs) {
(Owned(l), Owned(r)) => l.$op(r),
(Owned(l), Borrowed(r)) => l.$op(r),
(Borrowed(l), Owned(r)) => l.$op(r),
(Borrowed(l), Borrowed(r)) => l.$op(r)
}
}
}
impl<'min, L, R> $OP_ASSIGN<MaybeOwned<'min, R>> for MaybeOwned<'min, L>
where L: Clone + $OP_ASSIGN<R> + $OP_ASSIGN<&'min R>
{
fn $op_assign(&mut self, rhs: MaybeOwned<'min, R>) {
use self::MaybeOwned::*;
match rhs {
Owned(r) => self.to_mut().$op_assign(r),
Borrowed(r) => self.to_mut().$op_assign(r)
}
}
}
)*);
}
impl_op! {
[Add: add, AddAssign: add_assign],
[Sub: sub, SubAssign: sub_assign],
[Mul: mul, MulAssign: mul_assign],
[Div: div, DivAssign: div_assign],
[Shl: shl, ShlAssign: shl_assign],
[Shr: shr, ShrAssign: shr_assign],
[BitAnd: bitand, BitAndAssign: bitand_assign],
[BitOr: bitor, BitOrAssign: bitor_assign ],
[BitXor: bitxor, BitXorAssign: bitxor_assign]
}
impl<'l, V, OUT> Neg for MaybeOwned<'l, V>
where V: Neg<Output=OUT>, &'l V: Neg<Output=OUT>
{
type Output = OUT;
fn neg(self) -> Self::Output {
use self::MaybeOwned::*;
match self {
Owned(s) => s.neg(),
Borrowed(s) => s.neg()
}
}
}
impl<'l, V, OUT> Not for MaybeOwned<'l, V>
where V: Not<Output=OUT>, &'l V: Not<Output=OUT>
{
type Output = V::Output;
fn not(self) -> Self::Output {
use self::MaybeOwned::*;
match self {
Owned(s) => s.not(),
Borrowed(s) => s.not()
}
}
}
#[cfg(test)]
mod test {
use std::ops::{Add, AddAssign, Not, Neg};
use super::*;
#[derive(Clone, PartialEq)]
struct Think { x: u8 }
impl Add<Think> for Think {
type Output = u8;
fn add(self, rhs: Think) -> Self::Output {
self.x + rhs.x
}
}
impl AddAssign<Think> for Think {
fn add_assign(&mut self, rhs: Think) {
self.x += rhs.x
}
}
impl<'a> Add<&'a Think> for Think {
type Output = u8;
fn add(self, rhs: &'a Think) -> Self::Output {
self.x + rhs.x
}
}
impl<'a> AddAssign<&'a Think> for Think {
fn add_assign(&mut self, rhs: &'a Think) {
self.x += rhs.x
}
}
impl<'a> Add<Think> for &'a Think {
type Output = u8;
fn add(self, rhs: Think) -> Self::Output {
self.x + rhs.x
}
}
impl<'a, 'b> Add<&'a Think> for &'b Think {
type Output = u8;
fn add(self, rhs: &'a Think) -> Self::Output {
self.x + rhs.x
}
}
impl Not for Think {
type Output = bool;
fn not(self) -> Self::Output {
self.x != 0
}
}
impl<'a> Not for &'a Think {
type Output = bool;
fn not(self) -> Self::Output {
self.x != 0
}
}
impl Neg for Think {
type Output = i8;
fn neg(self) -> Self::Output {
-(self.x as i8)
}
}
impl<'a> Neg for &'a Think {
type Output = i8;
fn neg(self) -> Self::Output {
-(self.x as i8)
}
}
#[test]
fn op_impls_exist() {
let a = MaybeOwned::from(Think { x: 12 });
let b = MaybeOwned::from(Think { x: 13 });
assert_eq!(a + b, 25u8);
let c = Think { x: 42 };
let c1: MaybeOwned<Think> = (&c).into();
let c2: MaybeOwned<Think> = (&c).into();
assert_eq!(c1 + c2, 84);
}
#[test]
fn op_assign_impls_exist() {
let mut a = MaybeOwned::from(Think { x: 2 });
a += MaybeOwned::from(Think { x: 3 });
assert_eq!(a.x, 5);
let a = Think { x: 2 };
let mut a: MaybeOwned<Think> = (&a).into();
assert!(!a.is_owned());
a += MaybeOwned::from(Think { x: 5 });
assert!(a.is_owned());
assert_eq!(a.as_ref().x, 7);
}
#[test]
fn not_and_neg_are_impl() {
let a = Think { x: 5 };
let b = Think { x: 0 };
let a1: MaybeOwned<Think> = (&a).into();
let a2: MaybeOwned<Think> = (&a).into();
assert_eq!(!a1, true);
assert_eq!(!b, false);
assert_eq!(-a2, -5i8);
}
}