From 9310a29144588dd904c57d1d5e7feb3a2721de52 Mon Sep 17 00:00:00 2001 From: MrCroxx Date: Fri, 8 Nov 2024 09:23:59 +0000 Subject: [PATCH 1/2] feat: support intrusive_adapter! access nested field Signed-off-by: MrCroxx --- src/adapter.rs | 33 +++++++++++++++++++++------------ src/key_adapter.rs | 6 +++--- src/lib.rs | 14 +++++++------- src/linked_list.rs | 10 +++++----- src/rbtree.rs | 8 ++++---- src/singly_linked_list.rs | 10 +++++----- src/xor_linked_list.rs | 12 ++++++------ 7 files changed, 51 insertions(+), 42 deletions(-) diff --git a/src/adapter.rs b/src/adapter.rs index 9c21671..98f97d9 100644 --- a/src/adapter.rs +++ b/src/adapter.rs @@ -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 } }; @@ -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 @@ -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, @@ -150,9 +150,9 @@ macro_rules! container_of { /// link: LinkedListLink, /// link2: RBTreeLink, /// } -/// intrusive_adapter!(MyAdapter = Box: Test { link: LinkedListLink }); -/// intrusive_adapter!(pub MyAdapter2 = Box: Test { link2: RBTreeLink }); -/// intrusive_adapter!(pub(crate) MyAdapter3 = Box: Test { link2: RBTreeLink }); +/// intrusive_adapter!(MyAdapter = Box: Test { link => LinkedListLink }); +/// intrusive_adapter!(pub MyAdapter2 = Box: Test { link2 => RBTreeLink }); +/// intrusive_adapter!(pub(crate) MyAdapter3 = Box: Test { link2 => RBTreeLink }); /// /// pub struct Test2 /// where T: Clone + ?Sized @@ -160,13 +160,13 @@ macro_rules! container_of { /// link: LinkedListLink, /// val: T, /// } -/// intrusive_adapter!(MyAdapter4<'a, T> = &'a Test2: Test2 { link: LinkedListLink } where T: ?Sized + Clone + 'a); +/// intrusive_adapter!(MyAdapter4<'a, T> = &'a Test2: Test2 { 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])* @@ -207,13 +207,13 @@ macro_rules! intrusive_adapter { #[inline] unsafe fn get_value(&self, link: ::LinkPtr) -> *const ::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 ::Value) -> ::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] @@ -274,8 +274,17 @@ mod tests { link: LinkedListLink, } + struct Wrapper { + obj: Obj, + } + + intrusive_adapter! { + /// Test doc comment + ObjAdapter1 = Rc: Obj { link => LinkedListLink } + } + intrusive_adapter! { /// Test doc comment - ObjAdapter1 = Rc: Obj { link: LinkedListLink } + WrapperAdapter1 = Rc: Wrapper { obj.link => LinkedListLink } } } diff --git a/src/key_adapter.rs b/src/key_adapter.rs index fa5cd2a..82c325b 100644 --- a/src/key_adapter.rs +++ b/src/key_adapter.rs @@ -29,14 +29,14 @@ use crate::pointer_ops::PointerOps; /// } /// /// // Adapter which returns a key by value -/// intrusive_adapter!(MyAdapter = Box: S { link : RBTreeLink }); +/// intrusive_adapter!(MyAdapter = Box: 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 { link : RBTreeLink }); +/// intrusive_adapter!(MyAdapter2 = Box: S { link => RBTreeLink }); /// impl<'a> KeyAdapter<'a> for MyAdapter2 { /// type Key = &'a u32; /// fn get_key(&self, s: &'a S) -> &'a u32 { &s.key } @@ -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 { link : RBTreeLink }); +/// intrusive_adapter!(MyAdapter3 = Box: 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) } diff --git a/src/lib.rs b/src/lib.rs index 9063de6..fc3c299 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 { link: LinkedListLink }); +//! intrusive_adapter!(TestAdapter = Box: Test { link => LinkedListLink }); //! //! // Create a list and some objects //! let mut list = LinkedList::new(TestAdapter::new()); @@ -106,10 +106,10 @@ //! value: i32, //! } //! -//! intrusive_adapter!(MyAdapter = Rc: Test { link: LinkedListLink }); -//! intrusive_adapter!(MyAdapter2 = Rc: Test { link2: SinglyLinkedListLink }); -//! intrusive_adapter!(MyAdapter3 = Rc: Test { link3: XorLinkedListLink }); -//! intrusive_adapter!(MyAdapter4 = Rc: Test { link4: RBTreeLink }); +//! intrusive_adapter!(MyAdapter = Rc: Test { link => LinkedListLink }); +//! intrusive_adapter!(MyAdapter2 = Rc: Test { link2 => SinglyLinkedListLink }); +//! intrusive_adapter!(MyAdapter3 = Rc: Test { link3 => XorLinkedListLink }); +//! intrusive_adapter!(MyAdapter4 = Rc: Test { link4 => RBTreeLink }); //! impl<'a> KeyAdapter<'a> for MyAdapter4 { //! type Key = i32; //! fn get_key(&self, x: &'a Test) -> i32 { x.value } @@ -158,7 +158,7 @@ //! value: i32, //! } //! -//! intrusive_adapter!(ElementAdapter = Box: Element { link: RBTreeLink }); +//! intrusive_adapter!(ElementAdapter = Box: Element { link => RBTreeLink }); //! impl<'a> KeyAdapter<'a> for ElementAdapter { //! type Key = i32; //! fn get_key(&self, e: &'a Element) -> i32 { e.value } @@ -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 diff --git a/src/linked_list.rs b/src/linked_list.rs index 3d5c152..812ac15 100644 --- a/src/linked_list.rs +++ b/src/linked_list.rs @@ -1607,9 +1607,9 @@ mod tests { write!(f, "{}", self.value) } } - intrusive_adapter!(ObjAdapter1 = Rc: Obj { link1: Link }); - intrusive_adapter!(ObjAdapter2 = Rc: Obj { link2: Link }); - intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef: Obj { link1: Link }); + intrusive_adapter!(ObjAdapter1 = Rc: Obj { link1 => Link }); + intrusive_adapter!(ObjAdapter2 = Rc: Obj { link2 => Link }); + intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef: Obj { link1 => Link }); fn make_rc_obj(value: u32) -> Rc { Rc::new(make_obj(value)) @@ -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 { @@ -2033,7 +2033,7 @@ mod tests { link: Link, value: usize, } - intrusive_adapter!(ObjAdapter = $ptr: Obj { link: Link }); + intrusive_adapter!(ObjAdapter = $ptr: Obj { link => Link }); let a = $ptr::new(Obj { link: Link::new(), diff --git a/src/rbtree.rs b/src/rbtree.rs index 83d428e..18c9df4 100644 --- a/src/rbtree.rs +++ b/src/rbtree.rs @@ -2550,7 +2550,7 @@ mod tests { write!(f, "{}", self.value) } } - intrusive_adapter!(RcObjAdapter = Rc: Obj { link: Link }); + intrusive_adapter!(RcObjAdapter = Rc: Obj { link => Link }); impl<'a> KeyAdapter<'a> for RcObjAdapter { type Key = i32; @@ -2559,7 +2559,7 @@ mod tests { } } - intrusive_adapter!(UnsafeRefObjAdapter = UnsafeRef: Obj { link: Link }); + intrusive_adapter!(UnsafeRefObjAdapter = UnsafeRef: Obj { link => Link }); impl<'a> KeyAdapter<'a> for UnsafeRefObjAdapter { type Key = i32; @@ -3291,7 +3291,7 @@ mod tests { 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 { @@ -3321,7 +3321,7 @@ mod tests { link: Link, value: usize, } - intrusive_adapter!(RcObjAdapter = $ptr: Obj { link: Link }); + intrusive_adapter!(RcObjAdapter = $ptr: Obj { link => Link }); impl<'a> KeyAdapter<'a> for RcObjAdapter { type Key = usize; fn get_key(&self, value: &'a Obj) -> usize { diff --git a/src/singly_linked_list.rs b/src/singly_linked_list.rs index cf66418..bd9b96c 100644 --- a/src/singly_linked_list.rs +++ b/src/singly_linked_list.rs @@ -1299,9 +1299,9 @@ mod tests { write!(f, "{}", self.value) } } - intrusive_adapter!(RcObjAdapter1 = Rc: Obj { link1: Link }); - intrusive_adapter!(RcObjAdapter2 = Rc: Obj { link2: Link }); - intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef: Obj { link1: Link }); + intrusive_adapter!(RcObjAdapter1 = Rc: Obj { link1 => Link }); + intrusive_adapter!(RcObjAdapter2 = Rc: Obj { link2 => Link }); + intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef: Obj { link1 => Link }); fn make_rc_obj(value: u32) -> Rc { Rc::new(make_obj(value)) @@ -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 { @@ -1677,7 +1677,7 @@ mod tests { link: Link, value: usize, } - intrusive_adapter!(ObjAdapter = $ptr: Obj { link: Link }); + intrusive_adapter!(ObjAdapter = $ptr: Obj { link => Link }); let a = $ptr::new(Obj { link: Link::new(), diff --git a/src/xor_linked_list.rs b/src/xor_linked_list.rs index 4b8bd28..a130581 100644 --- a/src/xor_linked_list.rs +++ b/src/xor_linked_list.rs @@ -1790,9 +1790,9 @@ mod tests { write!(f, "{}", self.value) } } - intrusive_adapter!(RcObjAdapter1 = Rc: Obj { link1: Link }); - intrusive_adapter!(RcObjAdapter2 = Rc: Obj { link2: Link }); - intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef: Obj { link1: Link }); + intrusive_adapter!(RcObjAdapter1 = Rc: Obj { link1 => Link }); + intrusive_adapter!(RcObjAdapter2 = Rc: Obj { link2 => Link }); + intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef: Obj { link1 => Link }); fn make_rc_obj(value: u32) -> Rc { Rc::new(make_obj(value)) @@ -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 { @@ -2281,7 +2281,7 @@ mod tests { self.value.set(val + 1); } } - intrusive_adapter!(ObjAdapter<'a> = Box>: Obj<'a> {link: Link}); + intrusive_adapter!(ObjAdapter<'a> = Box>: Obj<'a> {link => Link}); let v = Cell::new(0); let obj = Obj { @@ -2314,7 +2314,7 @@ mod tests { link: Link, value: usize, } - intrusive_adapter!(ObjAdapter = $ptr: Obj { link: Link }); + intrusive_adapter!(ObjAdapter = $ptr: Obj { link => Link }); let a = $ptr::new(Obj { link: Link::new(), From 7c08f2f1b2aafb25158bb94e6479a6811970d879 Mon Sep 17 00:00:00 2001 From: MrCroxx Date: Sat, 9 Nov 2024 04:34:26 +0000 Subject: [PATCH 2/2] test: update CI MSRV to 1.82.0 Signed-off-by: MrCroxx --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 19bc32c..8bab958 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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