//! The [`UniqueArena`] type and supporting definitions.
usecrate::{FastIndexSet, Span};
usesuper::handle::{BadHandle, Handle, Index};
use std::{fmt, hash, ops};
/// An arena whose elements are guaranteed to be unique. /// /// A `UniqueArena` holds a set of unique values of type `T`, each with an /// associated [`Span`]. Inserting a value returns a `Handle<T>`, which can be /// used to index the `UniqueArena` and obtain shared access to the `T` element. /// Access via a `Handle` is an array lookup - no hash lookup is necessary. /// /// The element type must implement `Eq` and `Hash`. Insertions of equivalent /// elements, according to `Eq`, all return the same `Handle`. /// /// Once inserted, elements may not be mutated. /// /// `UniqueArena` is similar to [`Arena`]: If `Arena` is vector-like, /// `UniqueArena` is `HashSet`-like. /// /// [`Arena`]: super::Arena #[derive(Clone)] pubstruct UniqueArena<T> {
set: FastIndexSet<T>,
/// Spans for the elements, indexed by handle. /// /// The length of this vector is always equal to `set.len()`. `FastIndexSet` /// promises that its elements "are indexed in a compact range, without /// holes in the range 0..set.len()", so we can always use the indices /// returned by insertion as indices into this vector.
span_info: Vec<Span>,
}
impl<T> UniqueArena<T> { /// Create a new arena with no initial capacity allocated. pubfn new() -> Self {
UniqueArena {
set: FastIndexSet::default(),
span_info: Vec::new(),
}
}
/// Return the current number of items stored in this arena. pubfn len(&self) -> usize { self.set.len()
}
/// Return `true` if the arena contains no elements. pubfn is_empty(&self) -> bool { self.set.is_empty()
}
/// Clears the arena, keeping all allocations. pubfn clear(&mutself) { self.set.clear(); self.span_info.clear();
}
/// Return the span associated with `handle`. /// /// If a value has been inserted multiple times, the span returned is the /// one provided with the first insertion. pubfn get_span(&self, handle: Handle<T>) -> Span {
*self
.span_info
.get(handle.index())
.unwrap_or(&Span::default())
}
impl<T: Eq + hash::Hash> UniqueArena<T> { /// Returns an iterator over the items stored in this arena, returning both /// the item's handle and a reference to it. pubfn iter(&self) -> impl DoubleEndedIterator<Item = (Handle<T>, &T)> { self.set.iter().enumerate().map(|(i, v)| { let index = unsafe { Index::new_unchecked(i as u32) };
(Handle::new(index), v)
})
}
/// Insert a new value into the arena. /// /// Return a [`Handle<T>`], which can be used to index this arena to get a /// shared reference to the element. /// /// If this arena already contains an element that is `Eq` to `value`, /// return a `Handle` to the existing element, and drop `value`. /// /// If `value` is inserted into the arena, associate `span` with /// it. An element's span can be retrieved with the [`get_span`] /// method. /// /// [`Handle<T>`]: Handle /// [`get_span`]: UniqueArena::get_span pubfn insert(&mutself, value: T, span: Span) -> Handle<T> { let (index, added) = self.set.insert_full(value);
if added {
debug_assert!(index == self.span_info.len()); self.span_info.push(span);
}
/// Replace an old value with a new value. /// /// # Panics /// /// - if the old value is not in the arena /// - if the new value already exists in the arena pubfn replace(&mutself, old: Handle<T>, new: T) { let (index, added) = self.set.insert_full(new);
assert!(added && index == self.set.len() - 1);
/// Return this arena's handle for `value`, if present. /// /// If this arena already contains an element equal to `value`, /// return its handle. Otherwise, return `None`. pubfn get(&self, value: &T) -> Option<Handle<T>> { self.set
.get_index_of(value)
.map(|index| unsafe { Handle::from_usize_unchecked(index) })
}
/// Return this arena's value at `handle`, if that is a valid handle. pubfn get_handle(&self, handle: Handle<T>) -> Result<&T, BadHandle> { self.set
.get_index(handle.index())
.ok_or_else(|| BadHandle::new(handle))
}
/// Assert that `handle` is valid for this arena. pubfn check_contains_handle(&self, handle: Handle<T>) -> Result<(), BadHandle> { if handle.index() < self.set.len() {
Ok(())
} else {
Err(BadHandle::new(handle))
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.