How do I convert a usize to a u32 using TryFrom?

前端 未结 1 1027
野趣味
野趣味 2020-12-07 02:07

I want to convert a usize typed variable into a u32 typed variable in Rust. I am aware that the usize variable might contain a value l

相关标签:
1条回答
  • 2020-12-07 02:28

    Since this answer was created, it was decided to have the implementation of TryFrom<usize> always allow for the possibility of failure, regardless of the current platform. The original code now compiles successfully in Rust 1.34.

    Original answer

    having TryFrom<usize> for u32 is dependent on having From<usize> for u32, which seems somewhat strange to me

    This is because there's a blanket implementation of TryFrom for anything that implements From:

    impl<T, U> TryFrom<U> for T
    where
        T: From<U>,
    {
        type Error = !;
    }
    

    As you mentioned, since Rust supports platforms where the native integer length is 16, 32, or 64 bits, having such an implementation of From / Into would not be lossless on some of these platforms.

    This error occurs because there's no direct implementation of TryFrom / TryInto for these types. This is because users of these traits prefer that the implementations be infallible when platform-appropriate (The type Error = !).

    There is a separate tracking issue 49415 specifically for deciding this issue.

    I think that I can write my own function that does the conversion

    Yes, that is what you should do. Something like this untested piece of code:

    use std::u32;
    
    struct SomeError;
    
    // usize is a u16 or u32, which always fits in a u32
    #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
    fn my_thing(a: usize) -> Result<u32, SomeError> {
        Ok(a as u32)
    }
    
    // usize is a u64, which might be too big
    #[cfg(target_pointer_width = "64")]
    fn my_thing(a: usize) -> Result<u32, SomeError> {
        if a > u32::MAX as usize {
            Err(SomeError)
        } else {
            Ok(a as u32)
        }
    }
    

    I would be surprised if Rust doesn't have some idiomatic way to do this conversion. usize and u32 are two basic types, after all.

    The problem is that usize isn't really a "basic" type because it changes size depending on the target platform. Getting this correct, performant and ergonomic is not easy.

    0 讨论(0)
提交回复
热议问题