↑Programmieren in Rust
Bei der Serialisierung einer Zahl tut sich das Problem auf, dass die Byte-Reihenfolge von Computer-System zu Computer-System unterschiedlich sein kann.
Die Maschine, die das Programm ausführt, stellt eine Zahl in ihrem Arbeitsspeicher in einer bestimmten Form dar. Führt man nun eine sogenannte Transmutation aus, wo der Typ der Zahl als ein Array von Bytes uminterpretiert wird ohne eine Konvertierung vorzunehmen, enthüllt dies die interne Darstellung. Sendet die Maschine die Daten an eine andere, kommt es infolge zu einer Fehlinterpretation, sofern die Byte-Reihenfolgen der Maschinen unterschiedlich sind.
Zur Schaffung einer festen Schnittstelle, die zwischen unterschiedlichen Systemen vermittelt, einigt man sich bei einem Format auf eine feste Byte-Reihenfolge, – entweder Little-Endian oder Big-Endian.
Zur Umwandlung in das entsprechende Format gibt es zwei Möglichkeiten:
Die Standardbibliothek stellt für die Umwandlung bereits Funktionen zur Verfügung, so dass sich niemand mit Transmutationen befassen muss. Die folgende Tabelle listet die zur Verfügung gestellten Funktionen auf.
Serialisierung | Deserialisierung | |
---|---|---|
Little-Endian | to_le_bytes | from_le_bytes
|
Big-Endian | to_be_bytes | from_be_bytes
|
Nativ | to_ne_bytes | from_ne_bytes
|
Das nächste Programm serialisiert ein Array von
Zahlen des Typs u32
und schreibt
die daraus entstandenen Binärdaten in eine Datei.
Die Funktion to_le_bytes
wandelt die jeweilige Zahl
dabei in eine Bytesequenz der Reihenfolge Little-Endian um.
fn serialize_u32(a: &[u32]) -> Vec<u8> { let mut acc: Vec<u8> = Vec::with_capacity(4*a.len()); for x in a { acc.extend(&u32::to_le_bytes(*x)); } acc } fn main() { let a: &[u32] = &[1, 2, 3, 4]; let data = serialize_u32(a); std::fs::write("Datei.bin", &data).unwrap(); }
Betrachtet man Datei.bin
nun im Hex-Editor,
findet man vor:
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
Ein zweites Programm liest die Datei wieder ein und
deserialisiert die Daten. Die Funktion from_le_bytes
setzt dabei die jeweilige Zahl aus der im Little-Endian-Format
vorliegenden Bytesequenz zusammen.
fn main() { let bytes = std::fs::read("Datei.bin").unwrap(); for t in bytes.chunks_exact(4) { let value = u32::from_le_bytes([t[0], t[1], t[2], t[3]]); println!("{}", value); } }