Skip to content

Commit fc777a1

Browse files
committed
Fix archived B-tree map iteration
Fixes rkyv#590
1 parent 57dfc4a commit fc777a1

3 files changed

Lines changed: 62 additions & 24 deletions

File tree

rkyv/src/collections/btree_map/iter.rs

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -196,32 +196,35 @@ impl<K, V, const E: usize> Iterator for RawIter<K, V, E> {
196196
match kind {
197197
NodeKind::Inner => {
198198
let inner = current.cast::<InnerNode<K, V, E>>();
199-
if next_i < E {
199+
let next = if next_i < E {
200200
// More values in the current node
201201
self.stack.push((current, next_i));
202202

203-
// Recurse to a lesser if valid
204-
let next_lesser =
205-
unsafe { addr_of_mut!((*inner).lesser_nodes[next_i]) };
206-
let next_lesser_is_invalid =
207-
unsafe { RelPtr::is_invalid_raw(next_lesser) };
208-
if !next_lesser_is_invalid {
209-
self.stack.push((
210-
unsafe { RelPtr::as_ptr_raw(next_lesser).cast() },
211-
0,
212-
));
213-
}
203+
// Next is a lesser node
204+
unsafe { addr_of_mut!((*inner).lesser_nodes[next_i]) }
214205
} else {
215-
// Recurse to a greater if valid
216-
let next_greater =
217-
unsafe { addr_of_mut!((*inner).greater_node) };
218-
let next_greater_is_invalid =
219-
unsafe { RelPtr::is_invalid_raw(next_greater) };
220-
if !next_greater_is_invalid {
221-
self.stack.push((
222-
unsafe { RelPtr::as_ptr_raw(next_greater).cast() },
223-
0,
224-
));
206+
// Next is a greater node
207+
unsafe { addr_of_mut!((*inner).greater_node) }
208+
};
209+
210+
let next_is_invalid = unsafe { RelPtr::is_invalid_raw(next) };
211+
if !next_is_invalid {
212+
// Recurse left on next node
213+
let mut current = unsafe { RelPtr::as_ptr_raw(next) };
214+
loop {
215+
self.stack.push((current, 0));
216+
let kind = unsafe { (*current).kind };
217+
match kind {
218+
NodeKind::Inner => {
219+
let inner =
220+
current.cast::<InnerNode<K, V, E>>();
221+
let lesser = unsafe {
222+
addr_of_mut!((*inner).lesser_nodes[0])
223+
};
224+
current = unsafe { RelPtr::as_ptr_raw(lesser) };
225+
}
226+
NodeKind::Leaf => break,
227+
}
225228
}
226229
}
227230
}

rkyv/src/impls/alloc/collections/btree_map.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,4 +272,41 @@ mod tests {
272272
assert_eq!(i.next(), None);
273273
});
274274
}
275+
276+
// MIRI can't run this test quickly enough
277+
#[cfg(not(miri))]
278+
#[test]
279+
fn size_matches_iter_len() {
280+
#[derive(Archive, Deserialize, Serialize)]
281+
#[rkyv(crate)]
282+
struct Container {
283+
transforms: BTreeMap<String, String>,
284+
}
285+
286+
impl Container {
287+
pub fn fill(count: usize) -> Self {
288+
let mut transforms = BTreeMap::new();
289+
for i in 0..count {
290+
transforms.insert(i.to_string(), i.to_string());
291+
}
292+
Container { transforms }
293+
}
294+
295+
pub fn check(&self, expected: usize) {
296+
to_archived(self, |archived| {
297+
assert_eq!(archived.transforms.len(), expected);
298+
let mut count = 0;
299+
for (..) in archived.transforms.iter() {
300+
count += 1;
301+
}
302+
assert_eq!(count, expected);
303+
});
304+
}
305+
}
306+
307+
for expected in 0..=200 {
308+
let container = Container::fill(expected);
309+
container.check(expected);
310+
}
311+
}
275312
}

rkyv/src/impls/std/collections/hash_map.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,6 @@ mod tests {
293293

294294
let encoded = to_bytes::<Error>(&map).unwrap();
295295

296-
eprintln!("{encoded:?}");
297-
298296
// This .unwrap() fails!
299297
let _decoded = access::<Archived<MyHashMap>, Panic>(&encoded).unwrap();
300298
}

0 commit comments

Comments
 (0)