Moldagem

A Rust não fornece nenhuma conversão (coerção) de tipo implícita entre tipos primitivos. Mas, a conversão (moldagem) de tipo explícita pode ser realizada usando a palavra-chave as.

As regras para converter entre tipos integrais segue geralmente as convenções da C, exceto em casos onde a C tem comportamento não definido. O comportamento de todos os moldes entre tipos integrais é bem definido na Rust.

// Suprimir todos os avisos dos moldes que transbordam.
#![allow(overflowing_literals)]

fn main() {
    let decimal = 65.4321_f32;

    // Error! Sem conversão implícita
    let integer: u8 = decimal;
    // FIXME ^ Comente esta linha

    // Conversão explícita
    let integer = decimal as u8;
    let character = integer as char;

    // Error! Existem limitações nas regras de conversão.
    // Um flutuante não pode ser diretamente convertido à um carácter.
    let character = decimal as char;
    // FIXME ^ Comente esta linha

    println!("Casting: {} -> {} -> {}", decimal, integer, character);

    // quando moldamos qualquer valor à um tipo sem sinal, T,
    // T::MAX + 1 é adicionado ou subtraído até o valor caber num novo tipo

    // 1000 já cabe num u16
    println!("1000 as a u16 is: {}", 1000 as u16);

    // 1000 - 256 - 256 - 256 = 232
    // Nos bastidores, o primeiro os bits menos significativos de 8 são mantidos,
    // enquanto o resto perto do bit mais significativo é truncado.
    println!("1000 as a u8 is : {}", 1000 as u8);
    // -1 + 256 = 255
    println!("  -1 as a u8 is : {}", (-1i8) as u8);

    // Para os números positivos, isto é o mesmo que modulus
    println!("1000 mod 256 is : {}", 1000 % 256);

    // Quando moldamos à um tipo com sinal, o resultado (bitwise) é o mesmo que
    // a primeira moldagem ao tipo sem sinal correspondente.
    // Se o bit mais significativo deste valor for 1, então o valor é negativo.

    // A menos que já caiba, claro.
    println!(" 128 as a i16 is: {}", 128 as i16);

    // 128 as u8 -> 128,
    // cujo valor na representação de complemento dos dois de 8-bit é:
    println!(" 128 as a i8 is : {}", 128 as i8);

    // repetindo o exemplo acima
    // 1000 as u8 -> 232
    println!("1000 as a u8 is : {}", 1000 as u8);
    // e o valor de 232 na representação de complemento dos dois de 8-bit é -24
    println!(" 232 as a i8 is : {}", 232 as i8);

    // Desde a Rust 1.45, a palavra-chave `as` realiza um *molde de saturação*
    // quando moldamos de flutuante à inteiro. Se o valor de ponto flutuante
    // excede o saldo máximo ou é menos do que o saldo mínimo, o valor
    // retornado será igual ao salto cruzado.

    // 300.0 as u8 é 255
    println!(" 300.0 as u8 is : {}", 300.0_f32 as u8);
    // -100.0 as u8 é 0
    println!("-100.0 as u8 is : {}", -100.0_f32 as u8);
    // nan as u8 é 0
    println!("   nan as u8 is : {}", f32::NAN as u8);

    // Este comportamento incorre num pequeno custo de execução e
    // pode ser evitado com métodos inseguros, no entanto o resultado pode
    // transbordar e retornar **valores incertos**. Use estes métodos sabiamente:
    unsafe {
        // 300.0 as u8 é 44
        println!(" 300.0 as u8 is : {}", 300.0_f32.to_int_unchecked::<u8>());
        // -100.0 as u8 é 156
        println!("-100.0 as u8 is : {}", (-100.0_f32).to_int_unchecked::<u8>());
        // nan as u8 é 0
        println!("   nan as u8 is : {}", f32::NAN.to_int_unchecked::<u8>());
    }
}