rust / expert
Snippet
Selbstreferenzielle Typen mittels Pin und Pointer-Fixierung
Dieses Snippet demonstriert, wie man eine selbstreferenzielle Struktur in Rust unter Verwendung von `Pin` und `PhantomPinned` erstellt. Die Fixierung (Pinning) stellt sicher, dass die Struktur im Speicher nicht verschoben werden kann, sobald ihr interner Pointer initialisiert ist, was das Speichern und Dereferenzieren eines rohen Pointers auf eigene Felder sicher macht.
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
29
30
31
32
33
34
use std::marker::PhantomPinned;use std::pin::Pin;pub struct SelfReferential {value: String,pointer: *const String,_marker: PhantomPinned,}impl SelfReferential {pub fn new(val: &str) -> Self {Self {value: val.to_string(),pointer: std::ptr::null(),_marker: PhantomPinned,}}pub fn init(self: Pin<&mut Self>) {let val_ptr = &self.value as *const String;unsafe {let this = self.get_unchecked_mut();this.pointer = val_ptr;}}pub fn get_referred_value(&self) -> Option<&str> {if self.pointer.is_null() {None} else {unsafe { Some(&*self.pointer) }}}}
Erklärung
1
_marker: PhantomPinned
Verhindert, dass der Typ `Unpin` implementiert, wodurch er im Speicher fixiert bleibt, sobald er gepinnt wurde.
2
pub fn init(self: Pin<&mut Self>)
Erfordert, dass die Struktur vor der Initialisierung des selbstreferenziellen Pointers in eine `Pin`-Referenz verpackt wird.
3
let this = self.get_unchecked_mut()
Greift über unsicheren Code auf die veränderlichen Felder der gepinnten Struktur zu, um den rohen Pointer einzurichten.
4
this.pointer = val_ptr
Speichert die Speicheradresse des eigenen `value`-Felds der Struktur im `pointer`-Feld.
5
unsafe { Some(&*self.pointer) }
Dereferenziert den rohen Pointer sicher, da die Fixierung garantiert, dass sich die Adresse nicht geändert hat.