Skip to content

Commit ad9a098

Browse files
authored
Merge pull request #59 from orxfun/support-for-self-referential-collections
support-for-self-referential-collections
2 parents 353794f + b3a0423 commit ad9a098

16 files changed

+1299
-41
lines changed

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "orx-split-vec"
3-
version = "3.8.0"
3+
version = "3.9.0"
44
edition = "2021"
55
authors = ["orxfun <[email protected]>"]
66
description = "An efficient constant access time vector with dynamic capacity and pinned elements."
@@ -11,7 +11,7 @@ categories = ["data-structures", "rust-patterns", "no-std"]
1111

1212
[dependencies]
1313
orx-pseudo-default = { version = "1.4", default-features = false }
14-
orx-pinned-vec = "3.8"
14+
orx-pinned-vec = "3.9"
1515

1616
[[bench]]
1717
name = "serial_access"
+258
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
use crate::{
2+
pointers::{Ptr, Ptrs},
3+
Fragment,
4+
};
5+
use core::iter::FusedIterator;
6+
7+
#[derive(Copy)]
8+
pub struct IterPtr<T> {
9+
ptrs: Ptrs<T>,
10+
current_f: usize,
11+
current: Ptr<T>,
12+
}
13+
14+
impl<T> Clone for IterPtr<T> {
15+
fn clone(&self) -> Self {
16+
Self {
17+
ptrs: self.ptrs.clone(),
18+
current_f: self.current_f,
19+
current: self.current.clone(),
20+
}
21+
}
22+
}
23+
24+
impl<'a, T> From<&'a [Fragment<T>]> for IterPtr<T> {
25+
fn from(value: &'a [Fragment<T>]) -> Self {
26+
let current_f = 0;
27+
let current = match value.get(current_f) {
28+
Some(fragment) => Ptr::from(fragment),
29+
None => Ptr::default(),
30+
};
31+
let ptrs = Ptrs::from(value);
32+
Self {
33+
ptrs,
34+
current,
35+
current_f,
36+
}
37+
}
38+
}
39+
40+
impl<T> Iterator for IterPtr<T> {
41+
type Item = *const T;
42+
43+
fn next(&mut self) -> Option<Self::Item> {
44+
match self.current.next() {
45+
Some(x) => Some(x),
46+
None => {
47+
self.current_f += 1;
48+
match unsafe { self.ptrs.get(self.current_f) } {
49+
Some(ptr) => {
50+
self.current = ptr;
51+
self.current.next()
52+
}
53+
None => None,
54+
}
55+
}
56+
}
57+
}
58+
}
59+
60+
impl<T> FusedIterator for IterPtr<T> {}
61+
62+
#[cfg(test)]
63+
mod tests {
64+
use super::*;
65+
use alloc::{
66+
string::{String, ToString},
67+
vec::Vec,
68+
};
69+
70+
#[test]
71+
fn ptr_zero_fragments() {
72+
let fragments: Vec<Fragment<String>> = Vec::with_capacity(4);
73+
let mut iter = IterPtr::from(fragments.as_slice());
74+
75+
assert!(iter.next().is_none());
76+
assert!(iter.next().is_none());
77+
assert!(iter.next().is_none());
78+
}
79+
80+
#[test]
81+
fn ptr_one_empty_fragment() {
82+
let fragment: Fragment<String> = Vec::with_capacity(2).into();
83+
let mut fragments: Vec<Fragment<String>> = Vec::with_capacity(4);
84+
fragments.push(fragment);
85+
86+
let mut iter = IterPtr::from(fragments.as_slice());
87+
assert!(iter.next().is_none());
88+
assert!(iter.next().is_none());
89+
assert!(iter.next().is_none());
90+
}
91+
92+
#[test]
93+
fn ptr_one_non_empty_fragment() {
94+
let mut fragment: Fragment<String> = Vec::with_capacity(3).into();
95+
fragment.push(0.to_string());
96+
fragment.push(1.to_string());
97+
98+
let mut fragments: Vec<Fragment<String>> = Vec::with_capacity(4);
99+
fragments.push(fragment);
100+
101+
let mut iter = IterPtr::from(fragments.as_slice());
102+
assert_eq!(iter.next().map(|p| unsafe { &*p }), Some(&0.to_string()));
103+
assert_eq!(iter.next().map(|p| unsafe { &*p }), Some(&1.to_string()));
104+
assert!(iter.next().is_none());
105+
assert!(iter.next().is_none());
106+
}
107+
108+
#[test]
109+
fn ptr_many_non_empty_fragments() {
110+
let mut fragments: Vec<Fragment<String>> = Vec::with_capacity(4);
111+
112+
let prior = 0;
113+
let n = 4;
114+
let mut fragment: Fragment<String> = Vec::with_capacity(n).into();
115+
for i in 0..n {
116+
fragment.push((prior + i).to_string());
117+
}
118+
fragments.push(fragment);
119+
120+
let prior = prior + n;
121+
let n = 8;
122+
let mut fragment: Fragment<String> = Vec::with_capacity(n).into();
123+
for i in 0..n {
124+
fragment.push((prior + i).to_string());
125+
}
126+
fragments.push(fragment);
127+
128+
let prior = prior + n;
129+
let n = 16;
130+
let mut fragment: Fragment<String> = Vec::with_capacity(n).into();
131+
for i in 0..n {
132+
fragment.push((prior + i).to_string());
133+
}
134+
fragments.push(fragment);
135+
136+
let mut iter = IterPtr::from(fragments.as_slice());
137+
let mut prior = 0;
138+
for f in 0..fragments.len() {
139+
for i in 0..fragments[f].len() {
140+
assert_eq!(
141+
iter.next().map(|p| unsafe { &*p }),
142+
Some(&(prior + i).to_string())
143+
);
144+
}
145+
prior += fragments[f].len();
146+
}
147+
assert_eq!(iter.next(), None);
148+
assert_eq!(iter.next(), None);
149+
}
150+
151+
#[test]
152+
fn ptr_many_non_empty_fragments_half_last() {
153+
let mut fragments: Vec<Fragment<String>> = Vec::with_capacity(4);
154+
155+
let prior = 0;
156+
let n = 4;
157+
let mut fragment: Fragment<String> = Vec::with_capacity(n).into();
158+
for i in 0..n {
159+
fragment.push((prior + i).to_string());
160+
}
161+
fragments.push(fragment);
162+
163+
let prior = prior + n;
164+
let n = 8;
165+
let mut fragment: Fragment<String> = Vec::with_capacity(n).into();
166+
for i in 0..n {
167+
fragment.push((prior + i).to_string());
168+
}
169+
fragments.push(fragment);
170+
171+
let prior = prior + n;
172+
let n = 16;
173+
let mut fragment: Fragment<String> = Vec::with_capacity(n).into();
174+
for i in 0..(n / 2) {
175+
fragment.push((prior + i).to_string());
176+
}
177+
fragments.push(fragment);
178+
179+
let mut iter = IterPtr::from(fragments.as_slice());
180+
let mut prior = 0;
181+
for f in 0..fragments.len() {
182+
for i in 0..fragments[f].len() {
183+
assert_eq!(
184+
iter.next().map(|p| unsafe { &*p }),
185+
Some(&(prior + i).to_string())
186+
);
187+
}
188+
prior += fragments[f].len();
189+
}
190+
assert_eq!(iter.next(), None);
191+
assert_eq!(iter.next(), None);
192+
}
193+
194+
#[test]
195+
fn ptr_mutate_nodes_while_iterating() {
196+
let mut fragments: Vec<Fragment<String>> = Vec::with_capacity(4);
197+
198+
let prior = 0;
199+
let n = 4;
200+
let mut fragment: Fragment<String> = Vec::with_capacity(n).into();
201+
for i in 0..n {
202+
fragment.push((prior + i).to_string());
203+
}
204+
fragments.push(fragment);
205+
206+
let prior = prior + n;
207+
let n = 8;
208+
let mut fragment: Fragment<String> = Vec::with_capacity(n).into();
209+
for i in 0..n {
210+
fragment.push((prior + i).to_string());
211+
}
212+
fragments.push(fragment);
213+
214+
let prior = prior + n;
215+
let n = 16;
216+
let mut fragment: Fragment<String> = Vec::with_capacity(n).into();
217+
for i in 0..(n / 2) {
218+
fragment.push((prior + i).to_string());
219+
}
220+
fragments.push(fragment);
221+
222+
let mut iter = IterPtr::from(fragments.as_slice());
223+
let mut prior = 0;
224+
for f in 0..fragments.len() {
225+
for i in 0..fragments[f].len() {
226+
assert_eq!(
227+
iter.next().map(|p| unsafe { &*p }),
228+
Some(&(prior + i).to_string())
229+
);
230+
231+
if f > 0 {
232+
let first = {
233+
let f = unsafe { &*fragments.as_ptr().add(f - 1) };
234+
let p = unsafe { f.as_ptr().add(0) } as *mut String;
235+
p
236+
};
237+
let second = {
238+
let f = unsafe { &*fragments.as_ptr().add(f) };
239+
let p = unsafe { f.as_ptr().add(i) } as *mut String;
240+
p
241+
};
242+
unsafe { first.swap(second) };
243+
}
244+
245+
// fragments[f][i] = 0.to_string(); => miri error!!! but below is OK
246+
let f = unsafe { &*fragments.as_ptr().add(f) };
247+
let p = unsafe { f.as_ptr().add(i) } as *mut String;
248+
let mut new_str = 0.to_string();
249+
let mut_ref = &mut new_str;
250+
let mut_ptr = mut_ref as *mut String;
251+
unsafe { p.swap(mut_ptr) };
252+
}
253+
prior += fragments[f].len();
254+
}
255+
assert_eq!(iter.next(), None);
256+
assert_eq!(iter.next(), None);
257+
}
258+
}

0 commit comments

Comments
 (0)