Преобразование числовых примитивов (i32, f64 и т. д.) В байтовые представления


Я пишу библиотеку, которая кодирует / декодирует данные в / из двоичного формата. Часть формата-это числа, для которых я использую собственные примитивные типы Rust (например i8, i64, f32 и т.д.).

Существует ли простой, встроенный способ преобразования этих типов данных в / из двоичных, т. е. f64/f32/i64/и т.д. в Vec<u8>? Точно так же есть способ преобразовать 4 u8s (в Vec<u8> скажем) в f32?

3 11

3 ответа:

К сожалению, в настоящее время в Rust нет безопасной встроенной поддержки чтения/записи примитивов из/в байтовый массив. Для этого есть несколько библиотек сообщества, однако byteorder является наиболее используемым:

extern crate byteorder;

use byteorder::{LittleEndian, WriteBytesExt};
use std::mem;

fn main() {
    let i: i64 = 12345;
    let mut bs = [0u8; mem::size_of::<i64>()];
    bs.as_mut()
        .write_i64::<LittleEndian>(i)
        .expect("Unable to write");

    for i in &bs {
        println!("{:X}", i);
    }
}

Конечно, вы всегда можете использовать необработанные указатели. Например, вы можете превратить *const i64 в *const i8, а затем преобразовать его в соответствующий байтовый фрагмент &[u8]. Тем не менее, это легко получить неправильно, unsafe и зависит от платформы из-за endiannness, так что это должно быть используется только в крайнем случае:

use std::{mem, slice};

fn main() {
    let i: i64 = 12345;
    let ip: *const i64 = &i;
    let bp: *const u8 = ip as *const _;
    let bs: &[u8] = unsafe { slice::from_raw_parts(bp, mem::size_of::<i64>()) };

    for i in bs {
        println!("{:X}", i);
    }
}

std::mem::transmute можно использовать, хотя это unsafe:

fn main() {
    let var1 = 12345678_i64;
    let raw_bytes: [i8; 8] = unsafe { std::mem::transmute(var1) };
    for byte in &raw_bytes {
        println!("{}", byte);
    }
}

Примечание: пожалуйста, убедитесь, что размер двух переменных точно равен.

Если ваша цель состоит в том, чтобы напечатать байты или иметь их в представлении str, просто используйте нотацию :b в формате brace

fn main() {
    println!("This is the binary of int {:b}", 4 as i32);
}

Это печатает

This is the binary of int 100