Home > other >  Is there a trait in Rust representing integers, e.g. i32, i64, u8, u16, ...?
Is there a trait in Rust representing integers, e.g. i32, i64, u8, u16, ...?

Time:08-31

I am writing a radix sort function in Rust that can handle vectors containing i32, i64, u8, u16, or so on. I did not find any trait that can represent integers, so initially I tried T: Into<isize> From<isize>, but From<isize> is not implemented for u8 or for a bunch of other types. I wonder if there is one trait that is implemented by all the primitive integer types and can be used here? Or what should the bound be if there is none?

P.S. I also tried T: Div<isize> Rem<isize>, but the compiler said that the <T as Div>::Output and <T as Rem>::Output cannot be used as array index.

CodePudding user response:

I wonder if there is one trait that is implemented by all the primitive integer types and can be used here?

The num crate provides such a trait, but I'm not sure it would be terribly useful to you here. It sounds like at the end of your operation, you need a usize to be able to index an array, so you want to accept "some integer type," do some math with it, then get a usize out the other end.

You might be interested in the TryInto trait, which is like Into but specifies a possibly-fallible conversion. If you make your own function fallible, this would be an appropriate way to accept multiple integer types.

The Div and Rem bounds need to specify the output type, because right now the output is unbounded meaning you could get any type from their invocations; it wouldn't even have to be a numeric type.

However, assuming you need to keep isize as the intermediate type, you could just do something like this and forgo the Div and Rem bounds entirely:

enum FooError {
    IntConversion,
    OutOfSliceBounds,
}

fn foo<T: TryInto<isize>, V>(n: T, slice: &[V]) -> Result<&V, FooError>
{
    let n: isize = n.try_into().map_err(|_| FooError::IntConversion)?;
    
    // Do some math on n, then...
    let n: usize = n.try_into().map_err(|_| FooError::IntConversion)?;
    
    slice.get(n).ok_or(FooError::OutOfSliceBounds)
}

If isize is not large enough to be the intermediate type you could use a larger integer type, but to index a slice you have to be able to convert the final result to usize.

If the domain of usize is suitable for the math operations, you could just accept T: TryInto<usize> and then you don't need the second conversion at all.

  • Related