title: “NonNull Patterns and FFI Usage” meta_description: “Common patterns using NonNull in intrusive data structures, arenas, and FFI with C libraries.” keywords: [“nonnull ffi”, “intrusive list rust”, “arena allocator”, “nonnull patterns”]
🌐 Reinventing from Scratch: NonNull<T>
Chapter 9 — “Patterns, Internals, and FFI”
“NonNull shines in intrusive data structures and C interop.”
🔗 9.1. Pattern: Intrusive Linked List
struct Node<T> {
value: T,
next: Option<NonNull<Node<T>>>,
prev: Option<NonNull<Node<T>>>,
}
pub struct IntrusiveList<T> {
head: Option<NonNull<Node<T>>>,
tail: Option<NonNull<Node<T>>>,
len: usize,
}
impl<T> IntrusiveList<T> {
pub fn push_back(&mut self, value: T) {
let node = Box::new(Node {
value,
next: None,
prev: self.tail,
});
let ptr = NonNull::from(Box::leak(node));
match self.tail {
Some(mut tail) => unsafe {
tail.as_mut().next = Some(ptr);
},
None => self.head = Some(ptr),
}
self.tail = Some(ptr);
self.len += 1;
}
}
Benefits: No separate allocation for links — embedded in nodes!
🏗️ 9.2. Pattern: Arena Allocator
pub struct Arena {
chunks: Vec<NonNull<u8>>,
current: NonNull<u8>,
remaining: usize,
}
impl Arena {
pub fn alloc<T>(&mut self, value: T) -> NonNull<T> {
let layout = Layout::new::<T>();
if layout.size() > self.remaining {
self.grow(layout.size());
}
unsafe {
let ptr = self.current.cast::<T>();
ptr.as_ptr().write(value);
self.current = NonNull::new_unchecked(
self.current.as_ptr().add(layout.size())
);
self.remaining -= layout.size();
ptr
}
}
}
🌉 9.3. FFI: C Interop
Passing to C
#[repr(C)]
struct CData {
value: i32,
next: Option<NonNull<CData>>, // C sees this as pointer
}
extern "C" {
fn process_list(head: *mut CData);
}
fn pass_to_c(head: NonNull<CData>) {
unsafe {
process_list(head.as_ptr());
}
}
Receiving from C
extern "C" {
fn get_data() -> *mut CData;
}
fn receive_from_c() -> Option<NonNull<CData>> {
unsafe {
let ptr = get_data();
NonNull::new(ptr) // Safe: handles null from C
}
}
🧠 9.4. Chapter Takeaways
NonNull is ideal for:
- ✅ Intrusive data structures
- ✅ Arena allocators
- ✅ FFI with C
- ✅ Manual memory management
Next: Chapter 10 — Tests, Miri, and Safety Checklist 🧪