Skip to content

Commit

Permalink
Consolidate Handle construction code.
Browse files Browse the repository at this point in the history
  • Loading branch information
jimblandy authored and kvark committed Sep 27, 2021
1 parent f91e95b commit d026577
Showing 1 changed file with 27 additions and 17 deletions.
44 changes: 27 additions & 17 deletions src/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,21 @@ impl<T> Handle<T> {
let index = self.index.get() - 1;
index as usize
}

/// Convert a `usize` index into a `Handle<T>`.
fn from_usize(index: usize) -> Self {
use std::convert::TryFrom;

let handle_index = u32::try_from(index + 1)
.and_then(Index::try_from)
.expect("Failed to insert into UniqueArena. Handle overflows");
Handle::new(handle_index)
}

/// Convert a `usize` index into a `Handle<T>`, without range checks.
unsafe fn from_usize_unchecked(index: usize) -> Self {
Handle::new(Index::new_unchecked((index + 1) as u32))
}
}

/// A strongly typed range of handles.
Expand Down Expand Up @@ -174,42 +189,38 @@ impl<T> Arena<T> {
/// Returns an iterator over the items stored in this arena, returning both
/// the item's handle and a reference to it.
pub fn iter(&self) -> impl DoubleEndedIterator<Item = (Handle<T>, &T)> {
self.data.iter().enumerate().map(|(i, v)| {
let position = i + 1;
let index = unsafe { Index::new_unchecked(position as u32) };
(Handle::new(index), v)
})
self.data
.iter()
.enumerate()
.map(|(i, v)| unsafe { (Handle::from_usize_unchecked(i), v) })
}

/// Returns a iterator over the items stored in this arena,
/// returning both the item's handle and a mutable reference to it.
pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = (Handle<T>, &mut T)> {
self.data.iter_mut().enumerate().map(|(i, v)| {
let position = i + 1;
let index = unsafe { Index::new_unchecked(position as u32) };
(Handle::new(index), v)
})
self.data
.iter_mut()
.enumerate()
.map(|(i, v)| unsafe { (Handle::from_usize_unchecked(i), v) })
}

/// Adds a new value to the arena, returning a typed handle.
pub fn append(&mut self, value: T, span: Span) -> Handle<T> {
#[cfg(not(feature = "span"))]
let _ = span;
let position = self.data.len() + 1;
let index =
Index::new(position as u32).expect("Failed to append to Arena. Handle overflows");
let index = self.data.len();
self.data.push(value);
#[cfg(feature = "span")]
self.span_info.push(span);
Handle::new(index)
Handle::from_usize(index)
}

/// Fetch a handle to an existing type.
pub fn fetch_if<F: Fn(&T) -> bool>(&self, fun: F) -> Option<Handle<T>> {
self.data
.iter()
.position(fun)
.map(|index| Handle::new(unsafe { Index::new_unchecked((index + 1) as u32) }))
.map(|index| unsafe { Handle::from_usize_unchecked(index) })
}

/// Adds a value with a custom check for uniqueness:
Expand All @@ -223,8 +234,7 @@ impl<T> Arena<T> {
fun: F,
) -> Handle<T> {
if let Some(index) = self.data.iter().position(|d| fun(d, &value)) {
let index = unsafe { Index::new_unchecked((index + 1) as u32) };
Handle::new(index)
unsafe { Handle::from_usize_unchecked(index) }
} else {
self.append(value, span)
}
Expand Down

0 comments on commit d026577

Please sign in to comment.