Safely Casting a “char” to an “i64” and an “i64” to a “char”

Where x is a char and “a” and y is an i64 and 97, I am aware that I can write x as i64 and y as char; but I want to safely cast them.

I tried what is in a Rust playground which has:

fn main() {
    let x = 'a';
    let y = 97i64;
    
    let x_as_an_i64: i64 = x.try_into().unwrap();
    let y_as_a_char: char = y.try_into().unwrap();
    
    assert_eq!(x_as_an_i64, y);
    assert_eq!(y_as_a_char, x);
}

But Cargo interestingly fails exiting with status 101 and saying:

   Compiling playground v0.0.1 (/playground)
error[E0425]: cannot find value `y_as_an_i64` in this scope
 --> src/main.rs:9:16
  |
9 |     assert_eq!(y_as_an_i64, x);
  |                ^^^^^^^^^^^ help: a local variable with a similar name exists: `x_as_an_i64`

error[E0277]: the trait bound `i64: TryFrom<char>` is not satisfied
 --> src/main.rs:5:30
  |
5 |     let x_as_an_i64: i64 = x.try_into().unwrap();
  |                              ^^^^^^^^ the trait `From<char>` is not implemented for `i64`
  |
  = help: the following other types implement trait `From<T>`:
            `i64` implements `From<bool>`
            `i64` implements `From<deranged::RangedI64<MIN, MAX>>`
            `i64` implements `From<i16>`
            `i64` implements `From<i32>`
            `i64` implements `From<i8>`
            `i64` implements `From<jiff::util::rangeint::ri128<MIN, MAX>>`
            `i64` implements `From<jiff::util::rangeint::ri16<MIN, MAX>>`
            `i64` implements `From<jiff::util::rangeint::ri32<MIN, MAX>>`
          and 9 others
  = note: required for `char` to implement `Into<i64>`
  = note: required for `i64` to implement `TryFrom<char>`
  = note: required for `char` to implement `TryInto<i64>`

error[E0277]: the trait bound `char: TryFrom<i64>` is not satisfied
 --> src/main.rs:6:31
  |
6 |     let y_as_a_char: char = y.try_into().unwrap();
  |                               ^^^^^^^^ the trait `From<i64>` is not implemented for `char`
  |
  = help: the following other types implement trait `From<T>`:
            `char` implements `From<Char>`
            `char` implements `From<u8>`
  = note: required for `i64` to implement `Into<char>`
  = note: required for `char` to implement `TryFrom<i64>`
  = note: required for `i64` to implement `TryInto<char>`

Some errors have detailed explanations: E0277, E0425.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `playground` (bin "playground") due to 3 previous errors

What is interesting is that a char is smaller than an i64 but it only implements From<Char> and From<u8> and an i64 implements traits from From<bool> to From<i32> but does not implement From<char>.

I am looking for the safest way that never panics. What would you suggest?

You can cast to u32 and then to char using TryFrom twice.

1 Like

And the other way, char to u32 to i64 is infallible with From/Into.

(Also, note that 'a' is 0x61 or 97 decimal, but you're testing 61 decimal.)

3 Likes
fn main() {
    let x = 'a';
    let y = 97i64;
    
    let x_as_an_i64: i64 = u32::from(x).into();

    let Ok(y_as_u32) = u32::try_from(y) else {
        println!("{y} is not representable as u32");
        return;
    };

    let Ok(y_as_a_char) = char::try_from(y_as_u32) else {
        println!("{y} is not representable as char");
        return;
    };
    
    assert_eq!(x_as_an_i64, y);
    assert_eq!(y_as_a_char, x);
}

playground

2 Likes

What is in a Rust playground works, thanks!

I forgot hexadecimal notation, thanks!

1 Like

What you're doing by calling unwrap is no different than using as -- it will panic if the conversion fails.

1 Like

AFAIK, as never panics, it silently truncates.

6 Likes

It was for the playground.

It would sometimes be useful if there was a tool that could look at all conversions and tell you the way to get from A to B. Maybe it could look at rustdoc json output and build a graph and do a graph search.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.