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

前端 未结 1 1032
野趣味
野趣味 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 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 for u32 is dependent on having From for u32, which seems somewhat strange to me

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

    impl TryFrom for T
    where
        T: From,
    {
        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 {
        Ok(a as u32)
    }
    
    // usize is a u64, which might be too big
    #[cfg(target_pointer_width = "64")]
    fn my_thing(a: usize) -> Result {
        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)
提交回复
热议问题