Skip to content

Commit 7182fd3

Browse files
mobiuskleinLuthaf
authored andcommitted
Add opt-in generic traits for generated SoA types (#73)
1 parent b78f582 commit 7182fd3

File tree

16 files changed

+1065
-22
lines changed

16 files changed

+1065
-22
lines changed

.github/workflows/tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
runs-on: ubuntu-20.04
1212
strategy:
1313
matrix:
14-
rust-version: ["1.63", stable, beta, nightly]
14+
rust-version: ["1.78", stable, beta, nightly]
1515
steps:
1616
- uses: actions/checkout@v3
1717
with:

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
Cargo.lock
22
target
3+
rust-toolchain.toml

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "soa_derive"
33
version = "0.13.0"
44
edition = "2018"
5-
rust-version = "1.63"
5+
rust-version = "1.78"
66

77
authors = ["Guillaume Fraux <[email protected]>"]
88
license = "MIT/Apache-2.0"
@@ -30,4 +30,4 @@ serde_json = "1"
3030

3131
[[bench]]
3232
name = "soa"
33-
harness = false
33+
harness = false

example/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ publish = false
88
edition = "2021"
99

1010
[dependencies]
11-
soa_derive = {path = ".."}
11+
soa_derive = { path = ".." }
1212

1313
[lib]
1414
path = "lib.rs"

soa-derive-internal/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ documentation = "https://docs.rs/soa_derive/"
1717
[lib]
1818
proc-macro = true
1919

20+
2021
[dependencies]
2122
syn = {version = "2", features = ["derive", "extra-traits"]}
2223
quote = "1"

soa-derive-internal/src/generic.rs

+351
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
use proc_macro2::TokenStream;
2+
use quote::quote;
3+
4+
use crate::input::Input;
5+
use crate::names;
6+
7+
8+
pub fn derive_slice(input: &Input) -> TokenStream {
9+
let name = &input.name;
10+
let slice_name = names::slice_name(name);
11+
let ref_name = names::ref_name(&input.name);
12+
let ptr_name = names::ptr_name(&input.name);
13+
let iter_name = names::iter_name(name);
14+
15+
let generated = quote! {
16+
impl<'a> ::soa_derive::SoASlice<#name> for #slice_name<'a> {
17+
type Ref<'t> = #ref_name<'t> where Self: 't, 'a: 't;
18+
type Slice<'t> = #slice_name<'t> where Self: 't, 'a: 't;
19+
type Iter<'t> = #iter_name<'t> where Self: 't, 'a: 't;
20+
type Ptr = #ptr_name;
21+
22+
fn len(&self) -> usize {
23+
self.len()
24+
}
25+
26+
fn is_empty(&self) -> bool {
27+
self.is_empty()
28+
}
29+
30+
fn as_slice<'c>(&'c self) -> Self::Slice<'c> {
31+
self.reborrow::<'c>()
32+
}
33+
34+
fn slice<'c, 'b: 'c>(&'c self, index: impl core::ops::RangeBounds<usize>) -> Self::Slice<'c> where Self: 'b {
35+
let start = match index.start_bound() {
36+
std::ops::Bound::Included(i) | std::ops::Bound::Excluded(i) => *i,
37+
std::ops::Bound::Unbounded => 0,
38+
};
39+
let n = self.len();
40+
let end = match index.end_bound() {
41+
std::ops::Bound::Included(i) => (*i + 1).min(n),
42+
std::ops::Bound::Excluded(i) => *i,
43+
std::ops::Bound::Unbounded => n,
44+
};
45+
self.index(start..end)
46+
}
47+
48+
fn get<'c>(&'c self, index: usize) -> Option<Self::Ref<'c>> {
49+
self.get(index)
50+
}
51+
52+
fn index<'c>(&'c self, index: usize) -> Self::Ref<'c> {
53+
self.index(index)
54+
}
55+
56+
fn iter<'c>(&'c self) -> Self::Iter<'c> {
57+
self.iter()
58+
}
59+
60+
fn as_ptr(&self) -> Self::Ptr {
61+
self.as_ptr()
62+
}
63+
}
64+
};
65+
66+
return generated
67+
}
68+
69+
pub fn derive_slice_mut(input: &Input) -> TokenStream {
70+
let name = &input.name;
71+
let slice_name = names::slice_name(name);
72+
let slice_mut_name = names::slice_mut_name(&input.name);
73+
let ref_name = names::ref_name(&input.name);
74+
let ref_mut_name = names::ref_mut_name(&input.name);
75+
let ptr_name = names::ptr_name(&input.name);
76+
let ptr_mut_name = names::ptr_mut_name(&input.name);
77+
let iter_name = names::iter_name(name);
78+
let iter_mut_name = names::iter_mut_name(name);
79+
80+
let generated = quote! {
81+
82+
impl<'a> ::soa_derive::SoASliceMut<#name> for #slice_mut_name<'a> {
83+
type Ref<'t> = #ref_name<'t> where Self: 't;
84+
type Slice<'t> = #slice_name<'t> where Self: 't;
85+
type Iter<'t> = #iter_name<'t> where Self: 't;
86+
type Ptr = #ptr_name;
87+
88+
type RefMut<'t> = #ref_mut_name<'t> where Self: 't;
89+
type SliceMut<'t> = #slice_mut_name<'t> where Self: 't;
90+
type IterMut<'t> = #iter_mut_name<'t> where Self: 't;
91+
type PtrMut = #ptr_mut_name;
92+
93+
fn len(&self) -> usize {
94+
self.len()
95+
}
96+
97+
fn is_empty(&self) -> bool {
98+
self.is_empty()
99+
}
100+
101+
fn as_slice<'c>(&'c self) -> Self::Slice<'c> {
102+
self.as_slice()
103+
}
104+
105+
fn slice<'c, 'b: 'c>(&'c self, index: impl core::ops::RangeBounds<usize>) -> Self::Slice<'c> where Self: 'b {
106+
let start = match index.start_bound() {
107+
std::ops::Bound::Included(i) | std::ops::Bound::Excluded(i) => *i,
108+
std::ops::Bound::Unbounded => 0,
109+
};
110+
let n = self.len();
111+
let end = match index.end_bound() {
112+
std::ops::Bound::Included(i) => (*i + 1).min(n),
113+
std::ops::Bound::Excluded(i) => *i,
114+
std::ops::Bound::Unbounded => n,
115+
};
116+
self.index(start..end)
117+
}
118+
119+
fn get<'c>(&'c self, index: usize) -> Option<Self::Ref<'c>> {
120+
self.get(index)
121+
}
122+
123+
fn index<'c>(&'c self, index: usize) -> Self::Ref<'c> {
124+
self.index(index)
125+
}
126+
127+
fn iter<'c>(&'c self) -> Self::Iter<'c> {
128+
self.as_ref().into_iter()
129+
}
130+
131+
fn as_mut_slice<'c: 'b, 'b>(&'c mut self) -> Self::SliceMut<'c> where Self: 'b {
132+
self.reborrow()
133+
}
134+
135+
fn slice_mut<'c>(&'c mut self, index: impl core::ops::RangeBounds<usize>) -> Self::SliceMut<'c> {
136+
let start = match index.start_bound() {
137+
std::ops::Bound::Included(i) | std::ops::Bound::Excluded(i) => *i,
138+
std::ops::Bound::Unbounded => 0,
139+
};
140+
let n = self.len();
141+
let end = match index.end_bound() {
142+
std::ops::Bound::Included(i) => (*i + 1).min(n),
143+
std::ops::Bound::Excluded(i) => *i,
144+
std::ops::Bound::Unbounded => n,
145+
};
146+
self.index_mut(start..end)
147+
}
148+
149+
fn get_mut<'c>(&'c mut self, index: usize) -> Option<Self::RefMut<'c>> {
150+
self.get_mut(index)
151+
}
152+
153+
fn index_mut<'c>(&'c mut self, index: usize) -> Self::RefMut<'c> {
154+
self.index_mut(index)
155+
}
156+
157+
fn iter_mut<'c>(&'c mut self) -> Self::IterMut<'c> {
158+
self.iter_mut()
159+
}
160+
161+
fn apply_index(&mut self, indices: &[usize]) {
162+
self.apply_permutation(&mut ::soa_derive::Permutation::oneline(indices).inverse());
163+
}
164+
165+
fn as_ptr(&self) -> Self::Ptr {
166+
self.as_ptr()
167+
}
168+
169+
fn as_mut_ptr(&mut self) -> Self::PtrMut {
170+
self.as_mut_ptr()
171+
}
172+
}
173+
};
174+
175+
return generated
176+
}
177+
178+
pub fn derive_vec(input: &Input) -> TokenStream {
179+
let name = &input.name;
180+
let vec_name = names::vec_name(&input.name);
181+
let slice_name = names::slice_name(name);
182+
let slice_mut_name = names::slice_mut_name(&input.name);
183+
let ref_name = names::ref_name(&input.name);
184+
let ref_mut_name = names::ref_mut_name(&input.name);
185+
let ptr_name = names::ptr_name(&input.name);
186+
let ptr_mut_name = names::ptr_mut_name(&input.name);
187+
let iter_name = names::iter_name(name);
188+
let iter_mut_name = names::iter_mut_name(name);
189+
190+
let generated = quote! {
191+
192+
impl ::soa_derive::SoAVec<#name> for #vec_name {
193+
type Ref<'t> = #ref_name<'t>;
194+
type Slice<'t> = #slice_name<'t>;
195+
type Iter<'t> = #iter_name<'t>;
196+
type Ptr = #ptr_name;
197+
198+
type RefMut<'t> = #ref_mut_name<'t>;
199+
type SliceMut<'t> = #slice_mut_name<'t>;
200+
type IterMut<'t> = #iter_mut_name<'t>;
201+
type PtrMut = #ptr_mut_name;
202+
203+
fn len(&self) -> usize {
204+
self.len()
205+
}
206+
207+
fn is_empty(&self) -> bool {
208+
self.is_empty()
209+
}
210+
211+
fn as_slice<'c, 'a: 'c>(&'c self) -> Self::Slice<'c> where Self: 'a {
212+
self.as_slice()
213+
}
214+
215+
fn slice<'c, 'a: 'c>(&'c self, index: impl core::ops::RangeBounds<usize>) -> Self::Slice<'c> where Self: 'a {
216+
let start = match index.start_bound() {
217+
std::ops::Bound::Included(i) | std::ops::Bound::Excluded(i) => *i,
218+
std::ops::Bound::Unbounded => 0,
219+
};
220+
let n = self.len();
221+
let end = match index.end_bound() {
222+
std::ops::Bound::Included(i) => (*i + 1).min(n),
223+
std::ops::Bound::Excluded(i) => *i,
224+
std::ops::Bound::Unbounded => n,
225+
};
226+
self.index(start..end)
227+
}
228+
229+
fn get<'c>(&'c self, index: usize) -> Option<Self::Ref<'c>> {
230+
self.get(index)
231+
}
232+
233+
fn index<'c>(&'c self, index: usize) -> Self::Ref<'c> {
234+
self.index(index)
235+
}
236+
237+
fn iter<'c>(&'c self) -> Self::Iter<'c> {
238+
self.iter()
239+
}
240+
241+
fn as_mut_slice<'c, 'a: 'c>(&'c mut self) -> Self::SliceMut<'c> where Self: 'a {
242+
self.as_mut_slice()
243+
}
244+
245+
fn slice_mut<'c>(&'c mut self, index: impl core::ops::RangeBounds<usize>) -> Self::SliceMut<'c> {
246+
let start = match index.start_bound() {
247+
std::ops::Bound::Included(i) | std::ops::Bound::Excluded(i) => *i,
248+
std::ops::Bound::Unbounded => 0,
249+
};
250+
let n = self.len();
251+
let end = match index.end_bound() {
252+
std::ops::Bound::Included(i) => (*i + 1).min(n),
253+
std::ops::Bound::Excluded(i) => *i,
254+
std::ops::Bound::Unbounded => n,
255+
};
256+
self.index_mut(start..end)
257+
}
258+
259+
fn get_mut<'c>(&'c mut self, index: usize) -> Option<Self::RefMut<'c>> {
260+
self.get_mut(index)
261+
}
262+
263+
fn index_mut<'c>(&'c mut self, index: usize) -> Self::RefMut<'c> {
264+
self.index_mut(index)
265+
}
266+
267+
fn iter_mut<'c>(&'c mut self) -> Self::IterMut<'c> {
268+
self.iter_mut()
269+
}
270+
271+
fn apply_index(&mut self, indices: &[usize]) {
272+
use ::soa_derive::SoASliceMut;
273+
self.as_mut_slice().apply_index(indices);
274+
}
275+
276+
fn new() -> Self {
277+
Self::new()
278+
}
279+
280+
fn with_capacity(capacity: usize) -> Self {
281+
Self::with_capacity(capacity)
282+
}
283+
284+
fn capacity(&self) -> usize {
285+
self.capacity()
286+
}
287+
288+
fn reserve(&mut self, additional: usize) {
289+
self.reserve(additional);
290+
}
291+
292+
fn reserve_exact(&mut self, additional: usize) {
293+
self.reserve_exact(additional);
294+
}
295+
296+
fn shrink_to_fit(&mut self) {
297+
self.shrink_to_fit();
298+
}
299+
300+
fn truncate(&mut self, len: usize) {
301+
self.truncate(len);
302+
}
303+
304+
fn push(&mut self, value: #name) {
305+
self.push(value);
306+
}
307+
308+
fn swap_remove(&mut self, index: usize) -> #name {
309+
self.swap_remove(index)
310+
}
311+
312+
fn insert(&mut self, index: usize, element: #name) {
313+
self.insert(index, element);
314+
}
315+
316+
fn replace(&mut self, index: usize, element: #name) -> #name {
317+
self.replace(index, element)
318+
}
319+
320+
fn remove(&mut self, index: usize) -> #name {
321+
self.remove(index)
322+
}
323+
324+
fn pop(&mut self) -> Option<#name> {
325+
self.pop()
326+
}
327+
328+
fn append(&mut self, other: &mut Self) {
329+
self.append(other);
330+
}
331+
332+
fn clear(&mut self) {
333+
self.clear();
334+
}
335+
336+
fn split_off(&mut self, at: usize) -> Self {
337+
self.split_off(at)
338+
}
339+
340+
fn as_ptr(&self) -> Self::Ptr {
341+
self.as_ptr()
342+
}
343+
344+
fn as_mut_ptr(&mut self) -> Self::PtrMut {
345+
self.as_mut_ptr()
346+
}
347+
}
348+
};
349+
350+
return generated
351+
}

0 commit comments

Comments
 (0)