Skip to content

Commit 0fa76e1

Browse files
authored
Merge pull request #1 from foyer-rs/xx/offset-of-nested-field-access
feat: support intrusive_adapter! access nested field
2 parents 94c5eac + 7c08f2f commit 0fa76e1

File tree

8 files changed

+52
-43
lines changed

8 files changed

+52
-43
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
strategy:
99
fail-fast: false
1010
matrix:
11-
rust: [1.56.1, stable, beta, nightly]
11+
rust: [1.82.0, stable, beta, nightly]
1212
steps:
1313
- name: Checkout
1414
uses: actions/checkout@v2

src/adapter.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ pub unsafe trait Adapter {
9898
/// pointer to the specified field of some container type.
9999
#[macro_export]
100100
macro_rules! container_of {
101-
($ptr:expr, $container:path, $field:ident) => {
101+
($ptr:expr, $container:path, $($fields:expr)+) => {
102102
#[allow(clippy::cast_ptr_alignment)]
103103
{
104-
($ptr as *const _ as *const u8).sub($crate::offset_of!($container, $field))
104+
($ptr as *const _ as *const u8).sub($crate::offset_of!($container, $($fields)+))
105105
as *const $container
106106
}
107107
};
@@ -114,7 +114,7 @@ macro_rules! container_of {
114114
/// The basic syntax to create an adapter is:
115115
///
116116
/// ```rust,ignore
117-
/// intrusive_adapter!(Adapter = Pointer: Value { link_field: LinkType });
117+
/// intrusive_adapter!(Adapter = Pointer: Value { link_field => LinkType });
118118
/// ```
119119
///
120120
/// You can create a new instance of an adapter using the `new` method or the
@@ -128,7 +128,7 @@ macro_rules! container_of {
128128
/// intrusive_adapter!(
129129
/// Adapter<'lifetime, Type, Type2> =
130130
/// Pointer: Value {
131-
/// link_field: LinkType
131+
/// link_field => LinkType
132132
/// }
133133
/// where
134134
/// Type: Copy,
@@ -150,23 +150,23 @@ macro_rules! container_of {
150150
/// link: LinkedListLink,
151151
/// link2: RBTreeLink,
152152
/// }
153-
/// intrusive_adapter!(MyAdapter = Box<Test>: Test { link: LinkedListLink });
154-
/// intrusive_adapter!(pub MyAdapter2 = Box<Test>: Test { link2: RBTreeLink });
155-
/// intrusive_adapter!(pub(crate) MyAdapter3 = Box<Test>: Test { link2: RBTreeLink });
153+
/// intrusive_adapter!(MyAdapter = Box<Test>: Test { link => LinkedListLink });
154+
/// intrusive_adapter!(pub MyAdapter2 = Box<Test>: Test { link2 => RBTreeLink });
155+
/// intrusive_adapter!(pub(crate) MyAdapter3 = Box<Test>: Test { link2 => RBTreeLink });
156156
///
157157
/// pub struct Test2<T>
158158
/// where T: Clone + ?Sized
159159
/// {
160160
/// link: LinkedListLink,
161161
/// val: T,
162162
/// }
163-
/// intrusive_adapter!(MyAdapter4<'a, T> = &'a Test2<T>: Test2<T> { link: LinkedListLink } where T: ?Sized + Clone + 'a);
163+
/// intrusive_adapter!(MyAdapter4<'a, T> = &'a Test2<T>: Test2<T> { link => LinkedListLink } where T: ?Sized + Clone + 'a);
164164
/// ```
165165
#[macro_export]
166166
macro_rules! intrusive_adapter {
167167
(@impl
168168
$(#[$attr:meta])* $vis:vis $name:ident ($($args:tt),*)
169-
= $pointer:ty: $value:path { $field:ident: $link:ty } $($where_:tt)*
169+
= $pointer:ty: $value:path { $($fields:expr)+ => $link:ty } $($where_:tt)*
170170
) => {
171171
#[allow(explicit_outlives_requirements)]
172172
$(#[$attr])*
@@ -207,13 +207,13 @@ macro_rules! intrusive_adapter {
207207

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

277+
struct Wrapper {
278+
obj: Obj,
279+
}
280+
281+
intrusive_adapter! {
282+
/// Test doc comment
283+
ObjAdapter1 = Rc<Obj>: Obj { link => LinkedListLink }
284+
}
285+
277286
intrusive_adapter! {
278287
/// Test doc comment
279-
ObjAdapter1 = Rc<Obj>: Obj { link: LinkedListLink }
288+
WrapperAdapter1 = Rc<Wrapper>: Wrapper { obj.link => LinkedListLink }
280289
}
281290
}

src/key_adapter.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ use crate::pointer_ops::PointerOps;
2929
/// }
3030
///
3131
/// // Adapter which returns a key by value
32-
/// intrusive_adapter!(MyAdapter = Box<S>: S { link : RBTreeLink });
32+
/// intrusive_adapter!(MyAdapter = Box<S>: S { link => RBTreeLink });
3333
/// impl<'a> KeyAdapter<'a> for MyAdapter {
3434
/// type Key = u32;
3535
/// fn get_key(&self, s: &'a S) -> u32 { s.key }
3636
/// }
3737
///
3838
/// // Adapter which returns a key by reference
39-
/// intrusive_adapter!(MyAdapter2 = Box<S>: S { link : RBTreeLink });
39+
/// intrusive_adapter!(MyAdapter2 = Box<S>: S { link => RBTreeLink });
4040
/// impl<'a> KeyAdapter<'a> for MyAdapter2 {
4141
/// type Key = &'a u32;
4242
/// fn get_key(&self, s: &'a S) -> &'a u32 { &s.key }
@@ -51,7 +51,7 @@ use crate::pointer_ops::PointerOps;
5151
///
5252
/// // Adapter which returns a tuple as a key. When used in a RBTree, this will
5353
/// // keep all elements sorted by `key1` first, then `key2` and finally `key3`.
54-
/// intrusive_adapter!(MyAdapter3 = Box<U>: U { link : RBTreeLink });
54+
/// intrusive_adapter!(MyAdapter3 = Box<U>: U { link => RBTreeLink });
5555
/// impl<'a> KeyAdapter<'a> for MyAdapter3 {
5656
/// type Key = (i32, &'a str, f64);
5757
/// fn get_key(&self, u: &'a U) -> Self::Key { (u.key1, &u.key2, u.key3) }

src/lib.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
//!
3434
//! // The adapter describes how an object can be inserted into an intrusive
3535
//! // collection. This is automatically generated using a macro.
36-
//! intrusive_adapter!(TestAdapter = Box<Test>: Test { link: LinkedListLink });
36+
//! intrusive_adapter!(TestAdapter = Box<Test>: Test { link => LinkedListLink });
3737
//!
3838
//! // Create a list and some objects
3939
//! let mut list = LinkedList::new(TestAdapter::new());
@@ -106,10 +106,10 @@
106106
//! value: i32,
107107
//! }
108108
//!
109-
//! intrusive_adapter!(MyAdapter = Rc<Test>: Test { link: LinkedListLink });
110-
//! intrusive_adapter!(MyAdapter2 = Rc<Test>: Test { link2: SinglyLinkedListLink });
111-
//! intrusive_adapter!(MyAdapter3 = Rc<Test>: Test { link3: XorLinkedListLink });
112-
//! intrusive_adapter!(MyAdapter4 = Rc<Test>: Test { link4: RBTreeLink });
109+
//! intrusive_adapter!(MyAdapter = Rc<Test>: Test { link => LinkedListLink });
110+
//! intrusive_adapter!(MyAdapter2 = Rc<Test>: Test { link2 => SinglyLinkedListLink });
111+
//! intrusive_adapter!(MyAdapter3 = Rc<Test>: Test { link3 => XorLinkedListLink });
112+
//! intrusive_adapter!(MyAdapter4 = Rc<Test>: Test { link4 => RBTreeLink });
113113
//! impl<'a> KeyAdapter<'a> for MyAdapter4 {
114114
//! type Key = i32;
115115
//! fn get_key(&self, x: &'a Test) -> i32 { x.value }
@@ -158,7 +158,7 @@
158158
//! value: i32,
159159
//! }
160160
//!
161-
//! intrusive_adapter!(ElementAdapter = Box<Element>: Element { link: RBTreeLink });
161+
//! intrusive_adapter!(ElementAdapter = Box<Element>: Element { link => RBTreeLink });
162162
//! impl<'a> KeyAdapter<'a> for ElementAdapter {
163163
//! type Key = i32;
164164
//! fn get_key(&self, e: &'a Element) -> i32 { e.value }
@@ -197,7 +197,7 @@
197197
//! }
198198
//!
199199
//! // Note that we use a plain reference as the pointer type for the collection.
200-
//! intrusive_adapter!(ValueAdapter<'a> = &'a Value: Value { link: LinkedListLink });
200+
//! intrusive_adapter!(ValueAdapter<'a> = &'a Value: Value { link => LinkedListLink });
201201
//!
202202
//! // Create an arena and a list. Note that since stack objects are dropped in
203203
//! // reverse order, the Arena must be created before the LinkedList. This

src/linked_list.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,9 +1607,9 @@ mod tests {
16071607
write!(f, "{}", self.value)
16081608
}
16091609
}
1610-
intrusive_adapter!(ObjAdapter1 = Rc<Obj>: Obj { link1: Link });
1611-
intrusive_adapter!(ObjAdapter2 = Rc<Obj>: Obj { link2: Link });
1612-
intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef<Obj>: Obj { link1: Link });
1610+
intrusive_adapter!(ObjAdapter1 = Rc<Obj>: Obj { link1 => Link });
1611+
intrusive_adapter!(ObjAdapter2 = Rc<Obj>: Obj { link2 => Link });
1612+
intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef<Obj>: Obj { link1 => Link });
16131613

16141614
fn make_rc_obj(value: u32) -> Rc<Obj> {
16151615
Rc::new(make_obj(value))
@@ -2009,7 +2009,7 @@ mod tests {
20092009
link: Link,
20102010
value: &'a T,
20112011
}
2012-
intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link: Link} where T: 'a);
2012+
intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link => Link} where T: 'a);
20132013

20142014
let v = 5;
20152015
let a = Obj {
@@ -2033,7 +2033,7 @@ mod tests {
20332033
link: Link,
20342034
value: usize,
20352035
}
2036-
intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link: Link });
2036+
intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link => Link });
20372037

20382038
let a = $ptr::new(Obj {
20392039
link: Link::new(),

src/rbtree.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2550,7 +2550,7 @@ mod tests {
25502550
write!(f, "{}", self.value)
25512551
}
25522552
}
2553-
intrusive_adapter!(RcObjAdapter = Rc<Obj>: Obj { link: Link });
2553+
intrusive_adapter!(RcObjAdapter = Rc<Obj>: Obj { link => Link });
25542554

25552555
impl<'a> KeyAdapter<'a> for RcObjAdapter {
25562556
type Key = i32;
@@ -2559,7 +2559,7 @@ mod tests {
25592559
}
25602560
}
25612561

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

25642564
impl<'a> KeyAdapter<'a> for UnsafeRefObjAdapter {
25652565
type Key = i32;
@@ -3291,7 +3291,7 @@ mod tests {
32913291
link: Link,
32923292
value: &'a T,
32933293
}
3294-
intrusive_adapter!(RcObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link: Link} where T: 'a);
3294+
intrusive_adapter!(RcObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link => Link} where T: 'a);
32953295
impl<'a, 'b, T: 'a + 'b> KeyAdapter<'a> for RcObjAdapter<'b, T> {
32963296
type Key = &'a T;
32973297
fn get_key(&self, value: &'a Obj<'b, T>) -> &'a T {
@@ -3321,7 +3321,7 @@ mod tests {
33213321
link: Link,
33223322
value: usize,
33233323
}
3324-
intrusive_adapter!(RcObjAdapter = $ptr<Obj>: Obj { link: Link });
3324+
intrusive_adapter!(RcObjAdapter = $ptr<Obj>: Obj { link => Link });
33253325
impl<'a> KeyAdapter<'a> for RcObjAdapter {
33263326
type Key = usize;
33273327
fn get_key(&self, value: &'a Obj) -> usize {

src/singly_linked_list.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,9 +1299,9 @@ mod tests {
12991299
write!(f, "{}", self.value)
13001300
}
13011301
}
1302-
intrusive_adapter!(RcObjAdapter1 = Rc<Obj>: Obj { link1: Link });
1303-
intrusive_adapter!(RcObjAdapter2 = Rc<Obj>: Obj { link2: Link });
1304-
intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef<Obj>: Obj { link1: Link });
1302+
intrusive_adapter!(RcObjAdapter1 = Rc<Obj>: Obj { link1 => Link });
1303+
intrusive_adapter!(RcObjAdapter2 = Rc<Obj>: Obj { link2 => Link });
1304+
intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef<Obj>: Obj { link1 => Link });
13051305

13061306
fn make_rc_obj(value: u32) -> Rc<Obj> {
13071307
Rc::new(make_obj(value))
@@ -1653,7 +1653,7 @@ mod tests {
16531653
link: Link,
16541654
value: &'a T,
16551655
}
1656-
intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link: Link} where T: 'a);
1656+
intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link => Link} where T: 'a);
16571657

16581658
let v = 5;
16591659
let a = Obj {
@@ -1677,7 +1677,7 @@ mod tests {
16771677
link: Link,
16781678
value: usize,
16791679
}
1680-
intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link: Link });
1680+
intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link => Link });
16811681

16821682
let a = $ptr::new(Obj {
16831683
link: Link::new(),

src/xor_linked_list.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,9 +1790,9 @@ mod tests {
17901790
write!(f, "{}", self.value)
17911791
}
17921792
}
1793-
intrusive_adapter!(RcObjAdapter1 = Rc<Obj>: Obj { link1: Link });
1794-
intrusive_adapter!(RcObjAdapter2 = Rc<Obj>: Obj { link2: Link });
1795-
intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef<Obj>: Obj { link1: Link });
1793+
intrusive_adapter!(RcObjAdapter1 = Rc<Obj>: Obj { link1 => Link });
1794+
intrusive_adapter!(RcObjAdapter2 = Rc<Obj>: Obj { link2 => Link });
1795+
intrusive_adapter!(UnsafeRefObjAdapter1 = UnsafeRef<Obj>: Obj { link1 => Link });
17961796

17971797
fn make_rc_obj(value: u32) -> Rc<Obj> {
17981798
Rc::new(make_obj(value))
@@ -2253,7 +2253,7 @@ mod tests {
22532253
link: Link,
22542254
value: &'a T,
22552255
}
2256-
intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link: Link} where T: 'a);
2256+
intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link => Link} where T: 'a);
22572257

22582258
let v = 5;
22592259
let a = Obj {
@@ -2281,7 +2281,7 @@ mod tests {
22812281
self.value.set(val + 1);
22822282
}
22832283
}
2284-
intrusive_adapter!(ObjAdapter<'a> = Box<Obj<'a>>: Obj<'a> {link: Link});
2284+
intrusive_adapter!(ObjAdapter<'a> = Box<Obj<'a>>: Obj<'a> {link => Link});
22852285

22862286
let v = Cell::new(0);
22872287
let obj = Obj {
@@ -2314,7 +2314,7 @@ mod tests {
23142314
link: Link,
23152315
value: usize,
23162316
}
2317-
intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link: Link });
2317+
intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link => Link });
23182318

23192319
let a = $ptr::new(Obj {
23202320
link: Link::new(),

0 commit comments

Comments
 (0)