2

Suppose I have my own type as a tuple struct

struct MyType(u8);

And would like to implement the From trait for the other integral types in a generic way, like

impl From<T> for MyType {
    fn from(num: T) -> Self {
        MyType((num & 0xff) as u8)
    }
}

Rust does not allow this because generic types T do not have the as operator. How can I constrain T to the integral types so that as can be used? something along the lines of

impl From<T: Integral> for MyType {...}
Miguel
  • 658
  • 1
  • 6
  • 19

1 Answers1

2

You can use the num-traits crate.

PrimInt is the relevant trait, which extends NumCast which allows conversion between the primitive numeric types.

EDIT: Here's an example implementation. It's a bit ugly because many of the relevant conversions return Option, since they don't know ahead of time that the values are in range.

impl<T: PrimInt> From<T> for MyType {
    fn from(num: T) -> Self {
        let clamped = num & T::from(0xFFu8).unwrap();
        Self(clamped.to_u8().unwrap())
    }
}
Tavian Barnes
  • 12,477
  • 4
  • 45
  • 118
  • You may also want to specifically reference the example they've given; where all integers implement `From`, and therefore `0xFF` can be converted to them. – Optimistic Peach Sep 26 '20 at 02:09
  • 1
    I don't quite like the `T::from` that returns an `Option`. In the standard `std::convert::From` it is stated that "Note: This trait must not fail. If the conversion can fail, use TryFrom.". This seems to go against that idea. But thanks for pointing to num-traits. – Miguel Sep 27 '20 at 11:57
  • @Miguel This `from()` method is not from the `From` trait, rather it's a method on `NumCast` with the same name. It is unfortunate that `from::` returns an option, but it makes sense for things like converting `u64` to `u32`. – Tavian Barnes Sep 27 '20 at 17:51
  • https://internals.rust-lang.org/t/pre-rfc-add-explicitly-named-numeric-conversion-apis/11395 would be a step in the right direction I think, with the `IntToInt` trait and `wrapping_to()` – Tavian Barnes Sep 27 '20 at 17:51