rust / expert
Snippet
Entwurf maßgeschneiderter dynamisch skalierter Typen
Dynamisch skalierte Typen (DSTs) wie benutzerdefinierte Slices oder Arrays mit vorangestelltem Header erfordern eine manuelle Speicherallokation und den Aufbau von Fat-Pointers in Rust. Wir erstellen das Speicherlayout dynamisch, allozieren rohen Speicher, schreiben die Komponenten mittels Makros wie `addr_of_mut!`, um ungültige Zwischenreferenzen zu vermeiden, und konvertieren das Ganze über rohe Zeiger in eine `Box` zurück.
snippet.rs
rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
use std::alloc::{alloc, handle_alloc_error, Layout};use std::ptr::addr_of_mut;#[repr(C)]struct CustomDst {header: u32,data: [u8],}impl CustomDst {unsafe fn new(header: u32, elements: &[u8]) -> Box<Self> {let count = elements.len();let layout = Layout::new::<u32>().extend(Layout::array::<u8>(count).unwrap()).unwrap().0.pad_to_align();let ptr = alloc(layout);if ptr.is_null() {handle_alloc_error(layout);}let fat_ptr = std::ptr::slice_from_raw_parts_mut(ptr, count) as *mut CustomDst;addr_of_mut!((*fat_ptr).header).write(header);let dst_data_ptr = addr_of_mut!((*fat_ptr).data) as *mut u8;std::ptr::copy_nonoverlapping(elements.as_ptr(), dst_data_ptr, count);Box::from_raw(fat_ptr)}}
Erklärung
1
struct CustomDst {
Definiert einen benutzerdefinierten DST, dessen letztes Feld eine unbestimmte Slice-Größe besitzt.
2
let layout = Layout::new::<u32>().extend(...)
Berechnet die dynamische Größe und Ausrichtung für den Header gefolgt von den Byte-Elementen.
3
let fat_ptr = std::ptr::slice_from_raw_parts_mut(ptr, count) as *mut CustomDst;
Synthetisiert einen Fat-Pointer auf das DST, indem ein Slice-Fat-Pointer gecastet wird.
4
addr_of_mut!((*fat_ptr).header).write(header);
Schreibt das Header-Feld direkt im rohen Speicher, um die Erstellung nicht-initialisierter Referenzen zu verhindern.