バイナリ形式との間でデータをエンコード/デコードするライブラリを書いています。形式の一部は数値で、Rustのネイティブプリミティブ型を使用しています(i8
、i64
、f32
など)。
これらのデータ型をバイナリとの間で変換する、つまりf64
/f32
/i64
/etcを変換する簡単な組み込みの方法はありますか? Vec<u8>
?同様に、4つのu8
s(Vec<u8>
内)をf32
に変換する方法はありますか?
残念ながら、現時点では、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);
}
}
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);
浮動小数点については、以前の方法に依拠する必要があります。
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つの変数のサイズが正確に等しいことを確認してください。
Nicholas Rishelの答え から構築。
Rust 1.32には以下が含まれます: {to,from}_{ne,le,be}_bytes
、 to_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
は 移植性の問題 を持つ可能性があります。
目的がバイトを出力すること、またはそれらをstr
表現で表現することである場合は、単に:b
ブレース形式の表記
fn main() {
println!("This is the binary of int {:b}", 4 as i32);
}
これはプリント
This is the binary of int 100