web-dev-qa-db-ja.com

数値プリミティブ(i32、f64など)をバイト表現に変換する

バイナリ形式との間でデータをエンコード/デコードするライブラリを書いています。形式の一部は数値で、Rustのネイティブプリミティブ型を使用しています(i8i64f32など)。

これらのデータ型をバイナリとの間で変換する、つまりf64/f32/i64/etcを変換する簡単な組み込みの方法はありますか? Vec<u8>?同様に、4つのu8s(Vec<u8>内)をf32に変換する方法はありますか?

29
Rory

残念ながら、現時点では、Rust)のバイト配列との間でプリミティブを読み書きするための安全な組み込みサポートはありません。ただし、そのためのいくつかのコミュニティライブラリがあります バイトオーダー は最もよく使われるものです:

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であり、エンディアンによりプラットフォームに依存するため、最後の手段としてのみ使用する必要があります。

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);
    }
}
21

Rust 1.32現在、{to,from}_{ne,le,be}_bytesは整数型です。

let begin = 1234_i32;
let bytes = begin.to_ne_bytes();
let and_back = i32::from_ne_bytes(bytes);

浮動小数点については、以前の方法に依拠する必要があります。

20
Nicholas Rishel

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);
    }
}

注: 2つの変数のサイズが正確に等しいことを確認してください。

15
F001

Nicholas Rishelの答え から構築。

Rust 1.32には以下が含まれます: {to,from}_{ne,le,be}_bytesto_bits 、および from_bits

整数をバイトに変換してから戻す:

let x = 65535_i32;
let x_bytes = x.to_ne_bytes();                  // x_bytes = [255, 255, 0, 0]
let original_x = i32::from_ne_bytes(x_bytes);   // original_x = 65535 = x

Floatをバイトに変換してから戻す:

let y = 255.255_f64;
let y_bytes = y.to_bits().to_ne_bytes();
let original_y = f64::from_bits(u64::from_ne_bytes(y_bytes)); // original_y = 255.255 = y

Rustドキュメンテーションfrom_bits移植性の問題 を持つ可能性があります。

8
Michael Crapse

目的がバイトを出力すること、またはそれらをstr表現で表現することである場合は、単に:bブレース形式の表記

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

これはプリント

This is the binary of int 100

1
Josh Weinstein