Skip to content

Commit 628b9be

Browse files
committed
feat: soa_attr for Vec's field
1 parent b5c98a3 commit 628b9be

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

soa-derive-internal/src/input.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ pub struct Input {
1212
pub name: Ident,
1313
/// The list of fields in the struct
1414
pub fields: Vec<Field>,
15+
/// Additional attributes requested with `#[soa_attr(...)]` on fields
16+
pub field_attrs: Vec<ExtraAttributes>,
1517
/// The struct overall visibility
1618
pub visibility: Visibility,
1719
/// Additional attributes requested with `#[soa_attr(...)]` or
@@ -145,8 +147,23 @@ fn create_derive_meta(path: Path) -> Meta {
145147

146148
impl Input {
147149
pub fn new(input: DeriveInput) -> Input {
148-
let fields = match input.data {
149-
Data::Struct(s) => s.fields.iter().cloned().collect::<Vec<_>>(),
150+
let mut fields = Vec::new();
151+
let mut field_attrs = Vec::new();
152+
match input.data {
153+
Data::Struct(s) => {
154+
for field in s.fields.iter() {
155+
let mut extra_attrs = ExtraAttributes::new();
156+
fields.push(field.clone());
157+
for attr in &field.attrs {
158+
if let Ok(meta) = attr.parse_meta() {
159+
if meta.path().is_ident("soa_attr") {
160+
extra_attrs.parse(&meta);
161+
}
162+
}
163+
}
164+
field_attrs.push(extra_attrs);
165+
}
166+
}
150167
_ => panic!("#[derive(StructOfArray)] only supports struct"),
151168
};
152169

@@ -201,6 +218,7 @@ impl Input {
201218
visibility: input.vis,
202219
attrs: extra_attrs,
203220
derive_clone,
221+
field_attrs,
204222
}
205223
}
206224

soa-derive-internal/src/vec.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ pub fn derive(input: &Input) -> TokenStream {
3535
let fields_types = &input.fields.iter()
3636
.map(|field| &field.ty)
3737
.collect::<Vec<_>>();
38+
39+
let field_attrs = input.field_attrs.iter()
40+
.map(|attr| &attr.vec).collect::<Vec<_>>();
3841

3942
let mut generated = quote! {
4043
/// An analog to `
@@ -45,6 +48,7 @@ pub fn derive(input: &Input) -> TokenStream {
4548
#visibility struct #vec_name {
4649
#(
4750
#[doc = #fields_doc]
51+
#(#[#field_attrs])*
4852
pub #fields_names: Vec<#fields_types>,
4953
)*
5054
}

tests/soa_attr.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use serde::{Serialize, Deserialize};
12
use soa_derive::StructOfArray;
23

34
#[derive(Debug, Clone, PartialEq, StructOfArray)]
@@ -25,3 +26,30 @@ fn eq_test() {
2526
};
2627
assert_eq!(particles0, particles1);
2728
}
29+
30+
#[derive(StructOfArray)]
31+
#[soa_derive(PartialEq, Debug, Serialize, Deserialize)]
32+
pub struct Point {
33+
pub x: f32,
34+
pub y: f32,
35+
#[soa_attr(Vec, serde(skip))]
36+
pub meta: bool
37+
}
38+
39+
#[test]
40+
fn serde_skip_test() -> Result<(), serde_json::Error> {
41+
let mut soa = PointVec::new();
42+
soa.push(Point { x: 1.0, y: 2.0, meta: true });
43+
soa.push(Point { x: 3.0, y: 4.0, meta: false });
44+
45+
46+
let json = serde_json::to_string(&soa)?;
47+
assert_eq!(json, r#"{"x":[1.0,3.0],"y":[2.0,4.0]}"#);
48+
let soa2: PointVec = serde_json::from_str(&json)?;
49+
assert_eq!(&soa2, &PointVec {
50+
x: vec![1.0, 3.0],
51+
y: vec![2.0, 4.0],
52+
meta: vec![]
53+
});
54+
Ok(())
55+
}

0 commit comments

Comments
 (0)