Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support intrusive_adapter! access nested field #1

Merged
merged 2 commits into from
Nov 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
strategy:
fail-fast: false
matrix:
rust: [1.56.1, stable, beta, nightly]
rust: [1.82.0, stable, beta, nightly]
steps:
- name: Checkout
uses: actions/checkout@v2
Expand Down
33 changes: 21 additions & 12 deletions src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ pub unsafe trait Adapter {
/// pointer to the specified field of some container type.
#[macro_export]
macro_rules! container_of {
($ptr:expr, $container:path, $field:ident) => {
($ptr:expr, $container:path, $($fields:expr)+) => {
#[allow(clippy::cast_ptr_alignment)]
{
($ptr as *const _ as *const u8).sub($crate::offset_of!($container, $field))
($ptr as *const _ as *const u8).sub($crate::offset_of!($container, $($fields)+))
as *const $container
}
};
Expand All @@ -114,7 +114,7 @@ macro_rules! container_of {
/// The basic syntax to create an adapter is:
///
/// ```rust,ignore
/// intrusive_adapter!(Adapter = Pointer: Value { link_field: LinkType });
/// intrusive_adapter!(Adapter = Pointer: Value { link_field => LinkType });
/// ```
///
/// You can create a new instance of an adapter using the `new` method or the
Expand All @@ -128,7 +128,7 @@ macro_rules! container_of {
/// intrusive_adapter!(
/// Adapter<'lifetime, Type, Type2> =
/// Pointer: Value {
/// link_field: LinkType
/// link_field => LinkType
/// }
/// where
/// Type: Copy,
Expand All @@ -150,23 +150,23 @@ macro_rules! container_of {
/// link: LinkedListLink,
/// link2: RBTreeLink,
/// }
/// intrusive_adapter!(MyAdapter = Box<Test>: Test { link: LinkedListLink });
/// intrusive_adapter!(pub MyAdapter2 = Box<Test>: Test { link2: RBTreeLink });
/// intrusive_adapter!(pub(crate) MyAdapter3 = Box<Test>: Test { link2: RBTreeLink });
/// intrusive_adapter!(MyAdapter = Box<Test>: Test { link => LinkedListLink });
/// intrusive_adapter!(pub MyAdapter2 = Box<Test>: Test { link2 => RBTreeLink });
/// intrusive_adapter!(pub(crate) MyAdapter3 = Box<Test>: Test { link2 => RBTreeLink });
///
/// pub struct Test2<T>
/// where T: Clone + ?Sized
/// {
/// link: LinkedListLink,
/// val: T,
/// }
/// intrusive_adapter!(MyAdapter4<'a, T> = &'a Test2<T>: Test2<T> { link: LinkedListLink } where T: ?Sized + Clone + 'a);
/// intrusive_adapter!(MyAdapter4<'a, T> = &'a Test2<T>: Test2<T> { link => LinkedListLink } where T: ?Sized + Clone + 'a);
/// ```
#[macro_export]
macro_rules! intrusive_adapter {
(@impl
$(#[$attr:meta])* $vis:vis $name:ident ($($args:tt),*)
= $pointer:ty: $value:path { $field:ident: $link:ty } $($where_:tt)*
= $pointer:ty: $value:path { $($fields:expr)+ => $link:ty } $($where_:tt)*
) => {
#[allow(explicit_outlives_requirements)]
$(#[$attr])*
Expand Down Expand Up @@ -207,13 +207,13 @@ macro_rules! intrusive_adapter {

#[inline]
unsafe fn get_value(&self, link: <Self::LinkOps as $crate::LinkOps>::LinkPtr) -> *const <Self::PointerOps as $crate::PointerOps>::Value {
$crate::container_of!(link.as_ptr(), $value, $field)
$crate::container_of!(link.as_ptr(), $value, $($fields)+)
}
#[inline]
unsafe fn get_link(&self, value: *const <Self::PointerOps as $crate::PointerOps>::Value) -> <Self::LinkOps as $crate::LinkOps>::LinkPtr {
// We need to do this instead of just accessing the field directly
// to strictly follow the stack borrow rules.
let ptr = (value as *const u8).add($crate::offset_of!($value, $field));
let ptr = (value as *const u8).add($crate::offset_of!($value, $($fields)+));
core::ptr::NonNull::new_unchecked(ptr as *mut _)
}
#[inline]
Expand Down Expand Up @@ -274,8 +274,17 @@ mod tests {
link: LinkedListLink,
}

struct Wrapper {
obj: Obj,
}

intrusive_adapter! {
/// Test doc comment
ObjAdapter1 = Rc<Obj>: Obj { link => LinkedListLink }
}

intrusive_adapter! {
/// Test doc comment
ObjAdapter1 = Rc<Obj>: Obj { link: LinkedListLink }
WrapperAdapter1 = Rc<Wrapper>: Wrapper { obj.link => LinkedListLink }
}
}
6 changes: 3 additions & 3 deletions src/key_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ use crate::pointer_ops::PointerOps;
/// }
///
/// // Adapter which returns a key by value
/// intrusive_adapter!(MyAdapter = Box<S>: S { link : RBTreeLink });
/// intrusive_adapter!(MyAdapter = Box<S>: S { link => RBTreeLink });
/// impl<'a> KeyAdapter<'a> for MyAdapter {
/// type Key = u32;
/// fn get_key(&self, s: &'a S) -> u32 { s.key }
/// }
///
/// // Adapter which returns a key by reference
/// intrusive_adapter!(MyAdapter2 = Box<S>: S { link : RBTreeLink });
/// intrusive_adapter!(MyAdapter2 = Box<S>: S { link => RBTreeLink });
/// impl<'a> KeyAdapter<'a> for MyAdapter2 {
/// type Key = &'a u32;
/// fn get_key(&self, s: &'a S) -> &'a u32 { &s.key }
Expand All @@ -51,7 +51,7 @@ use crate::pointer_ops::PointerOps;
///
/// // Adapter which returns a tuple as a key. When used in a RBTree, this will
/// // keep all elements sorted by `key1` first, then `key2` and finally `key3`.
/// intrusive_adapter!(MyAdapter3 = Box<U>: U { link : RBTreeLink });
/// intrusive_adapter!(MyAdapter3 = Box<U>: U { link => RBTreeLink });
/// impl<'a> KeyAdapter<'a> for MyAdapter3 {
/// type Key = (i32, &'a str, f64);
/// fn get_key(&self, u: &'a U) -> Self::Key { (u.key1, &u.key2, u.key3) }
Expand Down
14 changes: 7 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
//!
//! // The adapter describes how an object can be inserted into an intrusive
//! // collection. This is automatically generated using a macro.
//! intrusive_adapter!(TestAdapter = Box<Test>: Test { link: LinkedListLink });
//! intrusive_adapter!(TestAdapter = Box<Test>: Test { link => LinkedListLink });
//!
//! // Create a list and some objects
//! let mut list = LinkedList::new(TestAdapter::new());
Expand Down Expand Up @@ -106,10 +106,10 @@
//! value: i32,
//! }
//!
//! intrusive_adapter!(MyAdapter = Rc<Test>: Test { link: LinkedListLink });
//! intrusive_adapter!(MyAdapter2 = Rc<Test>: Test { link2: SinglyLinkedListLink });
//! intrusive_adapter!(MyAdapter3 = Rc<Test>: Test { link3: XorLinkedListLink });
//! intrusive_adapter!(MyAdapter4 = Rc<Test>: Test { link4: RBTreeLink });
//! intrusive_adapter!(MyAdapter = Rc<Test>: Test { link => LinkedListLink });
//! intrusive_adapter!(MyAdapter2 = Rc<Test>: Test { link2 => SinglyLinkedListLink });
//! intrusive_adapter!(MyAdapter3 = Rc<Test>: Test { link3 => XorLinkedListLink });
//! intrusive_adapter!(MyAdapter4 = Rc<Test>: Test { link4 => RBTreeLink });
//! impl<'a> KeyAdapter<'a> for MyAdapter4 {
//! type Key = i32;
//! fn get_key(&self, x: &'a Test) -> i32 { x.value }
Expand Down Expand Up @@ -158,7 +158,7 @@
//! value: i32,
//! }
//!
//! intrusive_adapter!(ElementAdapter = Box<Element>: Element { link: RBTreeLink });
//! intrusive_adapter!(ElementAdapter = Box<Element>: Element { link => RBTreeLink });
//! impl<'a> KeyAdapter<'a> for ElementAdapter {
//! type Key = i32;
//! fn get_key(&self, e: &'a Element) -> i32 { e.value }
Expand Down Expand Up @@ -197,7 +197,7 @@
//! }
//!
//! // Note that we use a plain reference as the pointer type for the collection.
//! intrusive_adapter!(ValueAdapter<'a> = &'a Value: Value { link: LinkedListLink });
//! intrusive_adapter!(ValueAdapter<'a> = &'a Value: Value { link => LinkedListLink });
//!
//! // Create an arena and a list. Note that since stack objects are dropped in
//! // reverse order, the Arena must be created before the LinkedList. This
Expand Down Expand Up @@ -267,7 +267,7 @@
#![warn(missing_docs)]
#![warn(rust_2018_idioms)]
#![no_std]
#![cfg_attr(feature = "nightly", feature(const_fn_trait_bound))]

Check warning on line 270 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Test (nightly)

the feature `const_fn_trait_bound` has been stable since 1.61.0 and no longer requires an attribute to enable

Check warning on line 270 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Test (nightly)

the feature `const_fn_trait_bound` has been stable since 1.61.0 and no longer requires an attribute to enable
#![allow(
clippy::declare_interior_mutable_const,
clippy::collapsible_if,
Expand Down
10 changes: 5 additions & 5 deletions src/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1607,9 +1607,9 @@ mod tests {
write!(f, "{}", self.value)
}
}
intrusive_adapter!(ObjAdapter1 = Rc<Obj>: Obj { link1: Link });
intrusive_adapter!(ObjAdapter2 = Rc<Obj>: Obj { link2: Link });
intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef<Obj>: Obj { link1: Link });
intrusive_adapter!(ObjAdapter1 = Rc<Obj>: Obj { link1 => Link });
intrusive_adapter!(ObjAdapter2 = Rc<Obj>: Obj { link2 => Link });
intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef<Obj>: Obj { link1 => Link });

fn make_rc_obj(value: u32) -> Rc<Obj> {
Rc::new(make_obj(value))
Expand Down Expand Up @@ -2009,7 +2009,7 @@ mod tests {
link: Link,
value: &'a T,
}
intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link: Link} where T: 'a);
intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link => Link} where T: 'a);

let v = 5;
let a = Obj {
Expand All @@ -2033,7 +2033,7 @@ mod tests {
link: Link,
value: usize,
}
intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link: Link });
intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link => Link });

let a = $ptr::new(Obj {
link: Link::new(),
Expand Down
8 changes: 4 additions & 4 deletions src/rbtree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2043,7 +2043,7 @@
/// Panics if the new element is already linked to a different intrusive
/// collection.
#[inline]
pub fn insert<'a>(&'a mut self, val: <A::PointerOps as PointerOps>::Pointer) -> CursorMut<'_, A>

Check warning on line 2046 in src/rbtree.rs

View workflow job for this annotation

GitHub Actions / Test (beta)

elided lifetime has a name

Check warning on line 2046 in src/rbtree.rs

View workflow job for this annotation

GitHub Actions / Test (beta)

elided lifetime has a name

Check warning on line 2046 in src/rbtree.rs

View workflow job for this annotation

GitHub Actions / Test (nightly)

elided lifetime has a name

Check warning on line 2046 in src/rbtree.rs

View workflow job for this annotation

GitHub Actions / Test (nightly)

elided lifetime has a name

Check warning on line 2046 in src/rbtree.rs

View workflow job for this annotation

GitHub Actions / Test (nightly)

elided lifetime has a name

Check warning on line 2046 in src/rbtree.rs

View workflow job for this annotation

GitHub Actions / Test (nightly)

elided lifetime has a name
where
<A as KeyAdapter<'a>>::Key: Ord,
{
Expand Down Expand Up @@ -2550,7 +2550,7 @@
write!(f, "{}", self.value)
}
}
intrusive_adapter!(RcObjAdapter = Rc<Obj>: Obj { link: Link });
intrusive_adapter!(RcObjAdapter = Rc<Obj>: Obj { link => Link });

impl<'a> KeyAdapter<'a> for RcObjAdapter {
type Key = i32;
Expand All @@ -2559,7 +2559,7 @@
}
}

intrusive_adapter!(UnsafeRefObjAdapter = UnsafeRef<Obj>: Obj { link: Link });
intrusive_adapter!(UnsafeRefObjAdapter = UnsafeRef<Obj>: Obj { link => Link });

impl<'a> KeyAdapter<'a> for UnsafeRefObjAdapter {
type Key = i32;
Expand Down Expand Up @@ -3291,7 +3291,7 @@
link: Link,
value: &'a T,
}
intrusive_adapter!(RcObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link: Link} where T: 'a);
intrusive_adapter!(RcObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link => Link} where T: 'a);
impl<'a, 'b, T: 'a + 'b> KeyAdapter<'a> for RcObjAdapter<'b, T> {
type Key = &'a T;
fn get_key(&self, value: &'a Obj<'b, T>) -> &'a T {
Expand Down Expand Up @@ -3321,7 +3321,7 @@
link: Link,
value: usize,
}
intrusive_adapter!(RcObjAdapter = $ptr<Obj>: Obj { link: Link });
intrusive_adapter!(RcObjAdapter = $ptr<Obj>: Obj { link => Link });
impl<'a> KeyAdapter<'a> for RcObjAdapter {
type Key = usize;
fn get_key(&self, value: &'a Obj) -> usize {
Expand Down
10 changes: 5 additions & 5 deletions src/singly_linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1299,9 +1299,9 @@ mod tests {
write!(f, "{}", self.value)
}
}
intrusive_adapter!(RcObjAdapter1 = Rc<Obj>: Obj { link1: Link });
intrusive_adapter!(RcObjAdapter2 = Rc<Obj>: Obj { link2: Link });
intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef<Obj>: Obj { link1: Link });
intrusive_adapter!(RcObjAdapter1 = Rc<Obj>: Obj { link1 => Link });
intrusive_adapter!(RcObjAdapter2 = Rc<Obj>: Obj { link2 => Link });
intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef<Obj>: Obj { link1 => Link });

fn make_rc_obj(value: u32) -> Rc<Obj> {
Rc::new(make_obj(value))
Expand Down Expand Up @@ -1653,7 +1653,7 @@ mod tests {
link: Link,
value: &'a T,
}
intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link: Link} where T: 'a);
intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link => Link} where T: 'a);

let v = 5;
let a = Obj {
Expand All @@ -1677,7 +1677,7 @@ mod tests {
link: Link,
value: usize,
}
intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link: Link });
intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link => Link });

let a = $ptr::new(Obj {
link: Link::new(),
Expand Down
12 changes: 6 additions & 6 deletions src/xor_linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1790,9 +1790,9 @@ mod tests {
write!(f, "{}", self.value)
}
}
intrusive_adapter!(RcObjAdapter1 = Rc<Obj>: Obj { link1: Link });
intrusive_adapter!(RcObjAdapter2 = Rc<Obj>: Obj { link2: Link });
intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef<Obj>: Obj { link1: Link });
intrusive_adapter!(RcObjAdapter1 = Rc<Obj>: Obj { link1 => Link });
intrusive_adapter!(RcObjAdapter2 = Rc<Obj>: Obj { link2 => Link });
intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef<Obj>: Obj { link1 => Link });

fn make_rc_obj(value: u32) -> Rc<Obj> {
Rc::new(make_obj(value))
Expand Down Expand Up @@ -2253,7 +2253,7 @@ mod tests {
link: Link,
value: &'a T,
}
intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link: Link} where T: 'a);
intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link => Link} where T: 'a);

let v = 5;
let a = Obj {
Expand Down Expand Up @@ -2281,7 +2281,7 @@ mod tests {
self.value.set(val + 1);
}
}
intrusive_adapter!(ObjAdapter<'a> = Box<Obj<'a>>: Obj<'a> {link: Link});
intrusive_adapter!(ObjAdapter<'a> = Box<Obj<'a>>: Obj<'a> {link => Link});

let v = Cell::new(0);
let obj = Obj {
Expand Down Expand Up @@ -2314,7 +2314,7 @@ mod tests {
link: Link,
value: usize,
}
intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link: Link });
intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link => Link });

let a = $ptr::new(Obj {
link: Link::new(),
Expand Down
Loading