How to idiomatically convert between u32 and usize?

This code works and prints "b":

fn main() {
    let s = "abc";
    let ch = s.chars().nth(1).unwrap();
    println!("{}", ch);
}

      

On the other hand, this code results in a type mismatch error.

fn main() {
    let s = "abc";
    let n: u32 = 1;
    let ch = s.chars().nth(n).unwrap();
    println!("{}", ch);
}

      

error[E0308]: mismatched types
 --> src/main.rs:5:28
  |
5 |     let ch = s.chars().nth(n).unwrap();
  |                            ^ expected usize, found u32

      

For some external reason, I have to use the type u32

for the variable n

. How can I convert u32

to usize

and use it to nth()

?

+13


source to share


3 answers


The operator as

works for all types of numbers:

let ch = s.chars().nth(n as usize).unwrap();

      

Rust forces you to enter integers to make sure you are aware of signatures or overflows.

Integer constants can have a suffix like:



let n = 1u32;

      

Note, however, that negative constants such as -1i32

are internal -

1i32

.

Integer variables declared without an explicit type specification are displayed as {integer}

and will be correctly inferred from one of the method calls.

+17


source


The most careful thing you can do is use TryFrom

and panic when the value cannot fit in usize

:

use std::convert::TryFrom;

fn main() {
    let s = "abc";
    let n: u32 = 1;
    let n_us = usize::try_from(n).unwrap();
    let ch = s.chars().nth(n_us).unwrap();
    println!("{}", ch);
}

      



Blindly used, as

your code will mysteriously fail when run on a platform usize

less than 32-bit. For example, some microcontrollers use 16-bit integers as their own size:

fn main() {
    let n: u32 = 0x1_FF_FF;
    // Pretend that 'usize' is 16-bit
    let n_us: u16 = n as u16;

    println!("{}, {}", n, n_us); // 131071, 65535
}

      

+5


source


We now have a completely different answer when we try to compile your code by replacing the number 1

with a variable like i32

:

error[E0308]: mismatched types
 --> src/main.rs:5:28
  |
5 |     let ch = s.chars().nth(n).unwrap();
  |                            ^ expected usize, found i32
help: you can convert an 'i32' to 'usize' and panic if the converted value wouldn't fit
  |
5 |     let ch = s.chars().nth(n.try_into().unwrap()).unwrap();
  |    

      

This means that the compiler now recommends using n.try_into().unwrap()

that uses a trait TryInto

, which in turn relies on TryFrom

and returns Result<T, T::Error>

. This is why we need to extract the result with.unwrap()

TryInto

documentation

0


source







All Articles