Advanced API
Relevant source files
This document covers the advanced API layer of the linked_list_r4l crate, which provides safe ownership management and flexible pointer wrapping capabilities. This API sits between the user-friendly interface (see User-Friendly API) and the low-level unsafe operations (see Low-Level API).
The advanced API is designed for users who need control over memory ownership models while maintaining memory safety guarantees. It centers around the List<G: GetLinksWrapped> type and the Wrapper trait system that abstracts over different pointer types like Box<T>, Arc<T>, and &T.
Core Trait System
The advanced API is built on two key traits that work together to provide type-safe ownership management:
Wrapper Trait
The Wrapper<T> trait abstracts over different pointer types and ownership models, providing a uniform interface for converting between owned objects and raw pointers.
flowchart TD WrapperTrait["Wrapper<T> trait"] IntoPointer["into_pointer() -> NonNull<T>"] FromPointer["from_pointer(NonNull<T>) -> Self"] AsRef["as_ref() -> &T"] BoxImpl["Box<T> impl"] ArcImpl["Arc<T> impl"] RefImpl["&T impl"] BoxIntoRaw["Box::into_raw()"] BoxFromRaw["Box::from_raw()"] ArcIntoRaw["Arc::into_raw()"] ArcFromRaw["Arc::from_raw()"] NonNullFrom["NonNull::from()"] PtrDeref["ptr.as_ptr() deref"] ArcImpl --> ArcFromRaw ArcImpl --> ArcIntoRaw ArcImpl --> WrapperTrait BoxImpl --> BoxFromRaw BoxImpl --> BoxIntoRaw BoxImpl --> WrapperTrait RefImpl --> NonNullFrom RefImpl --> PtrDeref RefImpl --> WrapperTrait WrapperTrait --> AsRef WrapperTrait --> FromPointer WrapperTrait --> IntoPointer
Wrapper Trait Implementations
The trait is implemented for three fundamental pointer types:
| Type | Ownership Model | Use Case |
|---|---|---|
| Box | Unique ownership | Single-threaded owned data |
| Arc | Shared ownership | Multi-threaded reference counting |
| &T | Borrowed reference | Temporary list membership |
Sources: src/linked_list.rs(L18 - L83)
GetLinksWrapped Trait
The GetLinksWrapped trait extends GetLinks to specify which wrapper type should be used for list elements:
flowchart TD GetLinksWrapped["GetLinksWrapped trait"] GetLinks["extends GetLinks"] WrappedType["type Wrapped: Wrapper<Self::EntryType>"] BoxGetLinksWrapped["Box<T> impl GetLinksWrapped"] ArcGetLinksWrapped["Arc<T> impl GetLinksWrapped"] BoxWrapped["type Wrapped = Box<T::EntryType>"] ArcWrapped["type Wrapped = Arc<T::EntryType>"] ArcGetLinksWrapped --> ArcWrapped ArcGetLinksWrapped --> GetLinksWrapped BoxGetLinksWrapped --> BoxWrapped BoxGetLinksWrapped --> GetLinksWrapped GetLinksWrapped --> GetLinks GetLinksWrapped --> WrappedType
Sources: src/linked_list.rs(L85 - L121)
List<G: GetLinksWrapped> Interface
The List<G: GetLinksWrapped> struct provides the main interface for ownership-managed linked lists. It wraps the lower-level RawList<G> and handles ownership transfer automatically.
Core Operations
List Creation and Basic Operations
| Method | Purpose | Safety |
|---|---|---|
| new() | Create empty list | Safe |
| push_back(data) | Add to end | Safe, auto-cleanup on failure |
| push_front(data) | Add to beginning | Safe, auto-cleanup on failure |
| pop_front() | Remove from beginning | Safe, returns ownership |
| is_empty() | Check if empty | Safe |
Sources: src/linked_list.rs(L131 - L147) src/linked_list.rs(L149 - L177) src/linked_list.rs(L210 - L217)
Advanced Operations
The interface also provides more sophisticated operations for precise list manipulation:
flowchart TD AdvancedOps["Advanced Operations"] InsertAfter["insert_after(existing, data)"] Remove["remove(data)"] CursorMut["cursor_front_mut()"] UnsafeBlock["unsafe block required"] AsRefCall["Wrapper::as_ref(existing)"] OwnershipReturn["Option<G::Wrapped>"] CursorMutStruct["CursorMut<'a, G>"] CurrentAccess["current()"] RemoveCurrent["remove_current()"] Navigation["move_next(), peek_next(), peek_prev()"] AdvancedOps --> CursorMut AdvancedOps --> InsertAfter AdvancedOps --> Remove CursorMut --> CursorMutStruct CursorMutStruct --> CurrentAccess CursorMutStruct --> Navigation CursorMutStruct --> RemoveCurrent InsertAfter --> AsRefCall InsertAfter --> UnsafeBlock Remove --> OwnershipReturn Remove --> UnsafeBlock
Unsafe Operations Requirements
| Method | Safety Requirement |
|---|---|
| insert_after(existing, data) | existingmust be valid entry on this list |
| remove(data) | datamust be on this list or no list |
Sources: src/linked_list.rs(L178 - L208)
Cursors and Iterators
The advanced API provides two mechanisms for list traversal with different capabilities:
CursorMut
The CursorMut<'a, G> provides mutable access and modification capabilities during traversal:
flowchart TD CursorMutStruct["CursorMut<'a, G>"] RawCursor["raw_list::CursorMut<'a, G>"] CurrentMethod["current() -> Option<&mut G::EntryType>"] RemoveCurrentMethod["remove_current() -> Option<G::Wrapped>"] PeekNext["peek_next() -> Option<&mut G::EntryType>"] PeekPrev["peek_prev() -> Option<&mut G::EntryType>"] MoveNext["move_next()"] OwnershipReturn["Returns owned object"] MutableAccess["Allows mutation"] CurrentMethod --> MutableAccess CursorMutStruct --> CurrentMethod CursorMutStruct --> MoveNext CursorMutStruct --> PeekNext CursorMutStruct --> PeekPrev CursorMutStruct --> RawCursor CursorMutStruct --> RemoveCurrentMethod RemoveCurrentMethod --> OwnershipReturn
Sources: src/linked_list.rs(L237 - L276)
Iterator
The Iterator<'a, G> provides immutable forward and backward traversal:
flowchart TD IteratorStruct["Iterator<'a, G>"] RawIterator["raw_list::Iterator<'a, G>"] StdIterator["impl Iterator"] DoubleEnded["impl DoubleEndedIterator"] NextMethod["next() -> Option<&G::EntryType>"] NextBackMethod["next_back() -> Option<&G::EntryType>"] ImmutableRef["Immutable reference"] DoubleEnded --> NextBackMethod IteratorStruct --> DoubleEnded IteratorStruct --> RawIterator IteratorStruct --> StdIterator NextBackMethod --> ImmutableRef NextMethod --> ImmutableRef StdIterator --> NextMethod
Sources: src/linked_list.rs(L278 - L303)
Ownership Management
The advanced API's key strength is its automatic ownership management across different pointer types:
Ownership Transfer Flow
flowchart TD
subgraph subGraph0["Memory Safety"]
ListStorage["List internal storage"]
RawPointers["NonNull<T> storage"]
AtomicOps["Atomic operations"]
end
UserCode["User Code"]
WrappedObject["G::Wrapped object"]
IntoPointer["into_pointer()"]
RemovalOp["Removal operation"]
FromPointer["from_pointer()"]
ReturnedObject["Owned object returned"]
InsertionFail["Insertion failure"]
AutoCleanup["Automatic cleanup"]
AutoCleanup --> FromPointer
FromPointer --> ReturnedObject
InsertionFail --> AutoCleanup
IntoPointer --> ListStorage
ListStorage --> RawPointers
ListStorage --> RemovalOp
RawPointers --> AtomicOps
RemovalOp --> FromPointer
UserCode --> WrappedObject
WrappedObject --> InsertionFail
WrappedObject --> IntoPointer
Ownership Transfer Guarantees
| Scenario | Behavior | Memory Safety |
|---|---|---|
| Successful insertion | Ownership transferred to list | Guaranteed byinto_pointer() |
| Failed insertion | Object automatically reconstructed | Ensured byfrom_pointer()call |
| Successful removal | Ownership returned to caller | Guaranteed byfrom_pointer() |
| List drop | All elements properly dropped | Handled byDropimplementation |
Sources: src/linked_list.rs(L153 - L162) src/linked_list.rs(L168 - L176) src/linked_list.rs(L231 - L235)
Drop Behavior
The List<G> implements Drop to ensure all remaining elements are properly cleaned up:
flowchart TD DropImpl["List<G> Drop"] PopLoop["while pop_front().is_some()"] FromPointer["G::Wrapped::from_pointer()"] WrapperDrop["Wrapper's Drop impl"] BoxDrop["Box: heap deallocation"] ArcDrop["Arc: reference count decrement"] RefDrop["&T: no action needed"] DropImpl --> PopLoop FromPointer --> WrapperDrop PopLoop --> FromPointer WrapperDrop --> ArcDrop WrapperDrop --> BoxDrop WrapperDrop --> RefDrop
Sources: src/linked_list.rs(L231 - L235)
Thread Safety Considerations
While the advanced API provides memory safety guarantees, thread safety depends on the underlying RawList implementation and the specific wrapper type used:
| Wrapper Type | Thread Safety Notes |
|---|---|
| Box | Single-threaded ownership, no inherent thread safety |
| Arc | Reference counting is thread-safe, but list operations are not |
| &T | Depends on the referenced data's thread safety |
For multi-threaded usage, external synchronization (e.g., Mutex, RwLock) around the List<G> is required.
Sources: src/linked_list.rs(L50 - L66)