use crate::cache::delta::{Item, Tree}; /// Iteration impl Tree { /// Return an iterator over chunks of roots. Roots are not children themselves, they have no parents. pub fn iter_root_chunks(&mut self, chunk_size: usize) -> impl Iterator> + '_ { let roots = self.root_items.as_mut_slice(); let children = self.child_items.as_mut_slice(); roots.chunks_mut(chunk_size).map(move |c| Chunk { inner: c.iter_mut(), children: children as *mut [Item], }) } } /// A chunk returned by `iter_root_chunks`, which can be iterated over to get [`Node`]s. pub struct Chunk<'a, T> { inner: std::slice::IterMut<'a, Item>, children: *mut [Item], } // SAFETY: The raw pointer is uniquely materialized in `Node::into_child_iter`. #[allow(unsafe_code)] unsafe impl<'a, T> Send for Chunk<'a, T> where T: Send {} impl<'a, T> Iterator for Chunk<'a, T> { type Item = Node<'a, T>; fn next(&mut self) -> Option { self.inner.next().map(|item| Node { item, children: self.children, }) } } /// An item returned by `iter_root_chunks`, allowing access to the `data` stored alongside nodes in a [`Tree`]. pub struct Node<'a, T> { item: &'a mut Item, children: *mut [Item], } impl<'a, T> Node<'a, T> { /// Returns the offset into the pack at which the `Node`s data is located. pub fn offset(&self) -> u64 { self.item.offset } /// Returns the slice into the data pack at which the pack entry is located. pub fn entry_slice(&self) -> crate::data::EntryRange { self.item.offset..self.item.next_offset } /// Returns the node data associated with this node. pub fn data(&mut self) -> &mut T { &mut self.item.data } /// Transform this `Node` into an iterator over its children. /// /// Children are `Node`s referring to pack entries whose base object is this pack entry. pub fn into_child_iter(self) -> impl Iterator> + 'a { let children = self.children; self.item.children.iter().map(move |&index| { // SAFETY: The children array is alive by the 'a lifetime. // SAFETY: The index is a valid index into the children array. // SAFETY: The resulting mutable pointer cannot be yielded by any other node. #[allow(unsafe_code)] Node { item: unsafe { &mut *(children as *mut Item).add(index) }, children, } }) } }