Trait linked_list::unsafe_list::Adapter
source · pub unsafe trait Adapter {
type EntryType: ?Sized;
// Required method
fn to_links(obj: &Self::EntryType) -> &Links<Self::EntryType>;
}
Expand description
A linked-list adapter.
It is a separate type (as opposed to implemented by the type of the elements of the list) so that a given type can be inserted into multiple lists at the same time; in such cases, each list needs its own adapter that returns a different pointer to links.
It may, however, be implemented by the type itself to be inserted into lists, which makes it more readable.
Safety
Implementers must ensure that the links returned by Adapter::to_links
are unique to the
adapter. That is, different adapters must return different links for a given object.
The reason for this requirement is to avoid confusion that may lead to UB. In particular, if
two adapters were to use the same links, a user may have two lists (one for each adapter) and
try to insert the same object into both at the same time; although this clearly violates the
list safety requirements (e.g., those in List::push_back
), for users to notice it, they’d
have to dig into the details of the two adapters.
By imposing the requirement on the adapter, we make it easier for users to check compliance with the requirements when using the list.
Examples
struct Example {
a: u32,
b: u32,
links1: Links<Example>,
links2: Links<Example>,
}
// SAFETY: This adapter is the only one that uses `Example::links1`.
unsafe impl Adapter for Example {
type EntryType = Self;
fn to_links(obj: &Self) -> &Links<Self> {
&obj.links1
}
}
struct ExampleAdapter;
// SAFETY: This adapter is the only one that uses `Example::links2`.
unsafe impl Adapter for ExampleAdapter {
type EntryType = Example;
fn to_links(obj: &Example) -> &Links<Example> {
&obj.links2
}
}
static LIST1: List<Example> = List::new();
static LIST2: List<ExampleAdapter> = List::new();