Skip to content

Commit

Permalink
Implement rbtree iterators, increment version to 0.10.3
Browse files Browse the repository at this point in the history
  • Loading branch information
MrElectrify committed Mar 7, 2024
1 parent 820dedb commit ed2942b
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 10 deletions.
83 changes: 82 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ name = "eastl-rs"
authors = ["Andrew Buck"]
description = "EASTL binary-compatible Rust implementations"
documentation = "https://docs.rs/crate/eastl-rs"
version = "0.10.2"
version = "0.10.3"
edition = "2021"
license-file = "LICENSE"
readme = "README.md"
repository = "https://github.com/MrElectrify/EASTL-rs"
keywords = ["EASTL", "STL"]

[dependencies]
duplicate = "1.0"
moveit = "0.6.0"
superslice = "1.0"

Expand Down
33 changes: 33 additions & 0 deletions src/internal/rb_tree/iter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use crate::internal::rb_tree::node::Node;
use std::marker::PhantomData;

/// An iterator over a Red-Black tree's nodes.
pub struct Iter<'a, K, V> {
pub(super) node: *mut Node<K, V>,
pub(super) _marker: PhantomData<&'a ()>,
}

pub struct IterMut<'a, K, V> {
pub(super) node: *mut Node<K, V>,
pub(super) _marker: PhantomData<&'a mut ()>,
}

impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);

fn next(&mut self) -> Option<Self::Item> {
unsafe { self.node.as_ref() }
.and_then(Node::next)
.map(|node| (node.key(), node.val()))
}
}

impl<'a, K: 'a, V: 'a> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);

fn next(&mut self) -> Option<Self::Item> {
unsafe { self.node.as_mut() }
.and_then(Node::next_mut)
.map(|node| (&node.pair.0, &mut node.pair.1))
}
}
21 changes: 21 additions & 0 deletions src/internal/rb_tree/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use crate::internal::rb_tree::iter::{Iter, IterMut};
use crate::{
allocator::Allocator,
compare::{Compare, Less},
};
use duplicate::duplicate_item;
use std::marker::PhantomData;

use self::node::Node;

pub mod iter;
mod node;

#[repr(C)]
Expand Down Expand Up @@ -154,6 +158,23 @@ impl<K: Eq, V, A: Allocator, C: Compare<K>> RBTree<K, V, A, C> {
self.len() == 0
}

/// Returns an iterator over the elements in the tree.
///
/// # Safety
/// This iterator is not tested as trees are only partially implemented.
#[duplicate_item(
iter Self Iter;
[iter] [&Self] [Iter];
[iter_mut] [&mut Self] [IterMut];
)]
#[allow(clippy::needless_arbitrary_self_type)]
pub unsafe fn iter(self: Self) -> Iter<K, V> {
Iter {
node: self.parent,
_marker: PhantomData,
}
}

/// Returns the number of elements in the red-black tree
pub fn len(&self) -> usize {
self.size as usize
Expand Down
49 changes: 41 additions & 8 deletions src/internal/rb_tree/node.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::{fmt::Debug, marker::PhantomData};
use duplicate::duplicate_item;
use std::{fmt::Debug, marker::PhantomData, ptr};

/// The color of a red-black tree node
#[repr(C)]
Expand Down Expand Up @@ -87,8 +88,7 @@ pub(crate) struct Node<K, V> {
pub right: *mut Node<K, V>,
pub left: *mut Node<K, V>,
pub parent: ParentColor<K, V>,
key: K,
val: V,
pub(crate) pair: (K, V),
}

impl<K: Default, V: Default> Default for Node<K, V> {
Expand All @@ -97,8 +97,7 @@ impl<K: Default, V: Default> Default for Node<K, V> {
right: std::ptr::null_mut(),
left: std::ptr::null_mut(),
parent: ParentColor::default(),
key: K::default(),
val: V::default(),
pair: (K::default(), V::default()),
}
}
}
Expand Down Expand Up @@ -193,19 +192,53 @@ impl<K, V> Node<K, V> {
old_right
}

/// Returns the next node in the tree, in increasing order.
///
/// # Safety
/// This method returns
#[duplicate_item(
next Self Node;
[next] [Self] [Node];
[next_mut] [mut Self] [mut Node]
)]
pub fn next(mut self: &Self) -> Option<&Node<K, V>> {
if let Some(mut right_node) = unsafe { self.right.as_mut() } {
// the successor lies in the right subtree. find the smallest value in the greater
// subtree, which is the left-most node.
while let Some(left_node) = unsafe { right_node.left.as_mut() } {
right_node = left_node
}

Some(right_node)
} else {
// the successor is contained within the ancestors. find the first node that is its
// parent's left node (meaning the parent is the first node greater than the node)
// safety: the parent of a node is always present, because the parent of the root node
// is inside the tree itself
let mut parent = unsafe { &mut *self.parent.ptr() };
while ptr::eq(self as *const _, parent.right as *const _) {
let parent_parent = unsafe { &mut *parent.parent.ptr() };
self = parent;
parent = parent_parent;
}

Some(parent)
}
}

/// The key stored in the node
pub fn key(&self) -> &K {
&self.key
&self.pair.0
}

/// The value stored in the node
pub fn val(&self) -> &V {
&self.val
&self.pair.1
}

/// The value stored in the node
pub fn val_mut(&mut self) -> &mut V {
&mut self.val
&mut self.pair.1
}
}

Expand Down
30 changes: 30 additions & 0 deletions src/map/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use crate::internal::rb_tree::iter::{Iter, IterMut};
use crate::{
allocator::Allocator,
compare::{Compare, Less},
internal::rb_tree::RBTree,
};
use duplicate::duplicate_item;
use std::fmt::{Debug, Formatter};

/// A map backed by a red-black tree that is always ordered.
/// Insertion, lookup, and removal are O(nlgn). If you do not
Expand Down Expand Up @@ -103,6 +106,20 @@ impl<K: Eq, V, A: Allocator, C: Compare<K>> Map<K, V, A, C> {
self.inner.is_empty()
}

/// Returns an iterator over the elements in the tree.
///
/// # Safety
/// This iterator is not tested as trees are only partially implemented.
#[duplicate_item(
iter Self Iter;
[iter] [&Self] [Iter];
[iter_mut] [&mut Self] [IterMut];
)]
#[allow(clippy::needless_arbitrary_self_type)]
pub unsafe fn iter(self: Self) -> Iter<K, V> {
self.inner.iter()
}

/// Returns the number of elements in the map
pub fn len(&self) -> usize {
self.inner.len()
Expand Down Expand Up @@ -130,6 +147,19 @@ impl<K: Eq, V, A: Allocator, C: Compare<K>> Map<K, V, A, C> {
}
}

impl<K: Eq + Debug, V: Debug, A: Allocator, C: Compare<K>> Debug for Map<K, V, A, C> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{{{}}}",
unsafe { self.iter() }
.map(|(k, v)| format!("{k:?}: {v:?}"))
.collect::<Vec<String>>()
.join(",")
)
}
}

unsafe impl<K: Eq + Send, V: Send, A: Allocator + Send, C: Compare<K> + Send> Send
for Map<K, V, A, C>
{
Expand Down
8 changes: 8 additions & 0 deletions src/set/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ impl<K: Eq, A: Allocator, C: Compare<K>> Set<K, A, C> {
self.inner._insert(key, ()).is_some()
}

/// Returns an iterator over the elements in the tree.
///
/// # Safety
/// This iterator is not tested as trees are only partially implemented.
pub unsafe fn iter(&self) -> impl Iterator<Item = &K> {
self.inner.iter().map(|(k, _)| k)
}

/// Returns true if the set contains no elements
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
Expand Down

0 comments on commit ed2942b

Please sign in to comment.