Skip to content

Commit 047a931

Browse files
committed
feat: nested_soa attribute
1 parent 404a443 commit 047a931

File tree

10 files changed

+442
-86
lines changed

10 files changed

+442
-86
lines changed

soa-derive-internal/src/index.rs

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@ pub fn derive(input: &Input) -> TokenStream {
1212
let fields_names = input.fields.iter()
1313
.map(|field| field.ident.clone().unwrap())
1414
.collect::<Vec<_>>();
15-
let fields_names_1 = &fields_names;
16-
let fields_names_2 = &fields_names;
15+
let unnested_fields_names = input.unnested_fields.iter()
16+
.map(|field| field.ident.clone().unwrap())
17+
.collect::<Vec<_>>();
18+
let nested_fields_names = input.nested_fields.iter()
19+
.map(|field| field.ident.clone().unwrap())
20+
.collect::<Vec<_>>();
1721
let first_field_name = &fields_names[0];
1822

1923
quote!{
@@ -33,14 +37,16 @@ pub fn derive(input: &Input) -> TokenStream {
3337
#[inline]
3438
unsafe fn get_unchecked(self, soa: &'a #vec_name) -> Self::RefOutput {
3539
#ref_name {
36-
#(#fields_names_1: soa.#fields_names_2.get_unchecked(self),)*
40+
#(#unnested_fields_names: soa.#unnested_fields_names.get_unchecked(self),)*
41+
#(#nested_fields_names: self.get_unchecked(& soa.#nested_fields_names),)*
3742
}
3843
}
3944

4045
#[inline]
4146
fn index(self, soa: &'a #vec_name) -> Self::RefOutput {
4247
#ref_name {
43-
#(#fields_names_1: & soa.#fields_names_2[self],)*
48+
#(#unnested_fields_names: & soa.#unnested_fields_names[self],)*
49+
#(#nested_fields_names: self.index(&soa.#nested_fields_names),)*
4450
}
4551
}
4652
}
@@ -60,14 +66,16 @@ pub fn derive(input: &Input) -> TokenStream {
6066
#[inline]
6167
unsafe fn get_unchecked_mut(self, soa: &'a mut #vec_name) -> Self::MutOutput {
6268
#ref_mut_name {
63-
#(#fields_names_1: soa.#fields_names_2.get_unchecked_mut(self),)*
69+
#(#unnested_fields_names: soa.#unnested_fields_names.get_unchecked_mut(self),)*
70+
#(#nested_fields_names: self.get_unchecked_mut(&mut soa.#nested_fields_names),)*
6471
}
6572
}
6673

6774
#[inline]
6875
fn index_mut(self, soa: &'a mut #vec_name) -> Self::MutOutput {
6976
#ref_mut_name {
70-
#(#fields_names_1: &mut soa.#fields_names_2[self],)*
77+
#(#unnested_fields_names: &mut soa.#unnested_fields_names[self],)*
78+
#(#nested_fields_names: self.index_mut(&mut soa.#nested_fields_names),)*
7179
}
7280
}
7381
}
@@ -90,14 +98,16 @@ pub fn derive(input: &Input) -> TokenStream {
9098
#[inline]
9199
unsafe fn get_unchecked(self, soa: &'a #vec_name) -> Self::RefOutput {
92100
#slice_name {
93-
#(#fields_names_1: soa.#fields_names_2.get_unchecked(self.clone()),)*
101+
#(#unnested_fields_names: soa.#unnested_fields_names.get_unchecked(self.clone()),)*
102+
#(#nested_fields_names: self.clone().get_unchecked(& soa.#nested_fields_names),)*
94103
}
95104
}
96105

97106
#[inline]
98107
fn index(self, soa: &'a #vec_name) -> Self::RefOutput {
99108
#slice_name {
100-
#(#fields_names_1: & soa.#fields_names_2[self.clone()],)*
109+
#(#unnested_fields_names: & soa.#unnested_fields_names[self.clone()],)*
110+
#(#nested_fields_names: self.clone().index(&soa.#nested_fields_names),)*
101111
}
102112
}
103113
}
@@ -117,14 +127,16 @@ pub fn derive(input: &Input) -> TokenStream {
117127
#[inline]
118128
unsafe fn get_unchecked_mut(self, soa: &'a mut #vec_name) -> Self::MutOutput {
119129
#slice_mut_name {
120-
#(#fields_names_1: soa.#fields_names_2.get_unchecked_mut(self.clone()),)*
130+
#(#unnested_fields_names: soa.#unnested_fields_names.get_unchecked_mut(self.clone()),)*
131+
#(#nested_fields_names: self.clone().get_unchecked_mut(&mut soa.#nested_fields_names),)*
121132
}
122133
}
123134

124135
#[inline]
125136
fn index_mut(self, soa: &'a mut #vec_name) -> Self::MutOutput {
126137
#slice_mut_name {
127-
#(#fields_names_1: &mut soa.#fields_names_2[self.clone()],)*
138+
#(#unnested_fields_names: &mut soa.#unnested_fields_names[self.clone()],)*
139+
#(#nested_fields_names: self.clone().index_mut(&mut soa.#nested_fields_names),)*
128140
}
129141
}
130142
}
@@ -354,14 +366,16 @@ pub fn derive(input: &Input) -> TokenStream {
354366
#[inline]
355367
unsafe fn get_unchecked(self, slice: #slice_name<'a>) -> Self::RefOutput {
356368
#ref_name {
357-
#(#fields_names_1: slice.#fields_names_2.get_unchecked(self),)*
369+
#(#unnested_fields_names: slice.#unnested_fields_names.get_unchecked(self),)*
370+
#(#nested_fields_names: self.get_unchecked(slice.#nested_fields_names),)*
358371
}
359372
}
360373

361374
#[inline]
362375
fn index(self, slice: #slice_name<'a>) -> Self::RefOutput {
363376
#ref_name {
364-
#(#fields_names_1: & slice.#fields_names_2[self],)*
377+
#(#unnested_fields_names: & slice.#unnested_fields_names[self],)*
378+
#(#nested_fields_names: self.index(slice.#nested_fields_names),)*
365379
}
366380
}
367381
}
@@ -381,14 +395,16 @@ pub fn derive(input: &Input) -> TokenStream {
381395
#[inline]
382396
unsafe fn get_unchecked_mut(self, slice: #slice_mut_name<'a>) -> Self::MutOutput {
383397
#ref_mut_name {
384-
#(#fields_names_1: slice.#fields_names_2.get_unchecked_mut(self),)*
398+
#(#unnested_fields_names: slice.#unnested_fields_names.get_unchecked_mut(self),)*
399+
#(#nested_fields_names: self.get_unchecked_mut(slice.#nested_fields_names),)*
385400
}
386401
}
387402

388403
#[inline]
389404
fn index_mut(self, slice: #slice_mut_name<'a>) -> Self::MutOutput {
390405
#ref_mut_name {
391-
#(#fields_names_1: &mut slice.#fields_names_2[self],)*
406+
#(#unnested_fields_names: &mut slice.#unnested_fields_names[self],)*
407+
#(#nested_fields_names: self.index_mut(slice.#nested_fields_names),)*
392408
}
393409
}
394410
}
@@ -411,14 +427,16 @@ pub fn derive(input: &Input) -> TokenStream {
411427
#[inline]
412428
unsafe fn get_unchecked(self, slice: #slice_name<'a>) -> Self::RefOutput {
413429
#slice_name {
414-
#(#fields_names_1: slice.#fields_names_2.get_unchecked(self.clone()),)*
430+
#(#unnested_fields_names: slice.#unnested_fields_names.get_unchecked(self.clone()),)*
431+
#(#nested_fields_names: self.clone().get_unchecked(slice.#nested_fields_names),)*
415432
}
416433
}
417434

418435
#[inline]
419436
fn index(self, slice: #slice_name<'a>) -> Self::RefOutput {
420437
#slice_name {
421-
#(#fields_names_1: & slice.#fields_names_2[self.clone()],)*
438+
#(#unnested_fields_names: & slice.#unnested_fields_names[self.clone()],)*
439+
#(#nested_fields_names: self.clone().index(slice.#nested_fields_names),)*
422440
}
423441
}
424442
}
@@ -438,14 +456,16 @@ pub fn derive(input: &Input) -> TokenStream {
438456
#[inline]
439457
unsafe fn get_unchecked_mut(self, slice: #slice_mut_name<'a>) -> Self::MutOutput {
440458
#slice_mut_name {
441-
#(#fields_names_1: slice.#fields_names_2.get_unchecked_mut(self.clone()),)*
459+
#(#unnested_fields_names: slice.#unnested_fields_names.get_unchecked_mut(self.clone()),)*
460+
#(#nested_fields_names: self.clone().get_unchecked_mut(slice.#nested_fields_names),)*
442461
}
443462
}
444463

445464
#[inline]
446465
fn index_mut(self, slice: #slice_mut_name<'a>) -> Self::MutOutput {
447466
#slice_mut_name {
448-
#(#fields_names_1: &mut slice.#fields_names_2[self.clone()],)*
467+
#(#unnested_fields_names: &mut slice.#unnested_fields_names[self.clone()],)*
468+
#(#nested_fields_names: self.clone().index_mut(slice.#nested_fields_names),)*
449469
}
450470
}
451471
}

soa-derive-internal/src/input.rs

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::convert::TryInto;
33
use proc_macro2::Span;
44
use quote::quote;
55

6-
use syn::{Data, DeriveInput, Field, Ident, Path, Visibility};
6+
use syn::{Attribute, Data, DeriveInput, Field, Ident, Path, Visibility};
77
use syn::{Meta, MetaList, NestedMeta};
88

99
/// Representing the struct we are deriving
@@ -12,6 +12,10 @@ pub struct Input {
1212
pub name: Ident,
1313
/// The list of fields in the struct
1414
pub fields: Vec<Field>,
15+
/// The fields that has `#[nested_soa]` attribute
16+
pub nested_fields: Vec<Field>,
17+
/// The fields that without `#[nested_soa]` attribute
18+
pub unnested_fields: Vec<Field>,
1519
/// The struct overall visibility
1620
pub visibility: Visibility,
1721
/// Additional attributes requested with `#[soa_attr(...)]` or
@@ -147,15 +151,39 @@ fn create_derive_meta(path: Path) -> Meta {
147151
})
148152
}
149153

154+
fn contains_nested_soa(attrs: &[Attribute]) -> bool {
155+
for attr in attrs {
156+
if let Ok(meta) = attr.parse_meta() {
157+
match meta {
158+
Meta::Path(path) => {
159+
if path.is_ident("nested_soa") {
160+
return true;
161+
}
162+
}
163+
_ => (),
164+
}
165+
}
166+
}
167+
false
168+
}
169+
150170
impl Input {
151171
pub fn new(input: DeriveInput) -> Input {
152-
let fields = match input.data {
153-
Data::Struct(s) => s.fields.iter().cloned().collect::<Vec<_>>(),
172+
let mut fields = Vec::new();
173+
let mut nested_fields = Vec::new();
174+
let mut unnested_fields = Vec::new();
175+
match input.data {
176+
Data::Struct(s) => {
177+
for field in s.fields.iter().cloned() {
178+
fields.push(field.clone());
179+
if contains_nested_soa(&field.attrs) {
180+
nested_fields.push(field);
181+
} else {
182+
unnested_fields.push(field);
183+
}
184+
}
185+
}
154186
_ => panic!("#[derive(StructOfArray)] only supports struct"),
155-
};
156-
157-
if fields.is_empty() {
158-
panic!("#[derive(StructOfArray)] only supports struct with fields");
159187
}
160188

161189
let mut extra_attrs = ExtraAttributes::new();
@@ -182,7 +210,6 @@ impl Input {
182210
}
183211
}
184212
}
185-
186213
}
187214
_ => panic!(
188215
"expected #[soa_derive(Traits, To, Derive)], got #[{}]",
@@ -200,6 +227,8 @@ impl Input {
200227
fields: fields,
201228
visibility: input.vis,
202229
attrs: extra_attrs,
230+
nested_fields,
231+
unnested_fields,
203232
}
204233
}
205234

0 commit comments

Comments
 (0)