Phidelux
Phidelux

Reputation: 2271

Overloading like behavior using traits and generics

I have a simple Struct representing a 16Bit address:

pub struct Address(u16);

Now I would like to define a method, which allows we to check if an Address lies in a given range. This method either accepts a reference to another Address or a u16 value. Furthermore I would like to be able to call between like this:

let addr = Address{ 0x3fec };

let a1 = Address{ 0x3f00 };
let a2 = Address{ 0x4000 };

if addr.between(&a1, &a2) {
    println!("{} lays between {} and {}!", addr, a1, a2);
}

if addr.between(0x3f00, 0x4000) {
    println!("{} lays between {} and {}!", addr, a1, a2);
}

I am a complete rust beginner and got a bit lost in the jungle of Into, From, Borrow, AsRef, Generics and Traits. How would I implement such behavior? A special problem seems to be the second case as 0x3fff is actually an integer not an unsigned 16 bit value.

Is it possible to mimic this behavior by implementing generic traits for the same type?

Upvotes: 0

Views: 173

Answers (1)

Mathieu Rene
Mathieu Rene

Reputation: 994

You can implement From<u16> on your type, and use generic parameters in order to accept anything that can be converted to Address by adding a trait bound for Into<Address> (Into gets automatically implemented as soon as you have an implementation for From).

Note that I made the Address type Copy because it only holds a u16, this way you don't have to bother with references.


#[derive(Clone, Copy, Debug)]
pub struct Address(u16);

impl From<u16> for Address {
    fn from(addr: u16) -> Self {
        Self(addr)
    }
}

impl Address {
    pub fn between<T, U>(self, lower: T, upper: U) -> bool
    where
        T: Into<Address>,
        U: Into<Address>,
    {
        let lower = lower.into();
        let upper = upper.into();

        lower.0 < self.0 && self.0 < upper.0
    }
}

fn main() {
    let addr = Address(0x3fec);

    let a1 = Address(0x3f00);
    let a2 = Address(0x4000);

    if addr.between(a1, a2) {
        println!("{:?} lays between {:?} and {:?}!", addr, a1, a2);
    }

    if addr.between(0x3f00, 0x4000) {
        println!("{:?} lays between {:?} and {:?}!", addr, a1, a2);
    }
}

Upvotes: 2

Related Questions