How to implement std::ops traits for multiple rhs

Viewed 37

If I have:

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
struct Bytes(u64);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
struct Seconds(f64);

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
struct BytesPerSecond(f64);

is there a simple way to get something like:

let b = Bytes(1024);
let s = Seconds(2.0);
let bytes = b / b; // yields Bytes
let bps = b / s; // yields BytesPerSecond

The uom crate lets you do things like:

let l1 = Length::new::<meter>(15.0);
let t1 = Time::new::<second>(50.0);
let l2 = l1 / l1
let v1 = l1 / t1;

Since each trait (Div, in this case) can only have one method, it seems like I would have to use generics to create multiple impls. I'm not sure how that would work in practice, though (and I found uoms's source hard to decipher).

1 Answers

Simple, Div is generic over the right-hand operand type. It simply defaults to Self if left unspecified (done via Div<RhsType>). And the output type must be supplied regardless.

So implementing Bytes / Bytes = Bytes and Bytes / Seconds = BytesPerSecond would look like this:

impl Div for Bytes {
    type Output = Bytes;

    fn div(self, rhs: Bytes) -> Bytes {
        todo!()
    }
}

impl Div<Seconds> for Bytes {
    type Output = BytesPerSecond;

    fn div(self, rhs: Seconds) -> BytesPerSecond {
        todo!()
    }
}
Related