Struct atom_table::AtomTable
source · pub struct AtomTable<T, I>where
I: From<usize>,{ /* private fields */ }
Expand description
A data structure that lets you use strongly typed indices/IDs instead of bulky values, performing a lookup in both directions.
T
is your value type, and I
is your index/ID type.
Typically I should be a “newtype” (tuple struct) wrapping usize
and with Copy
and From<usize>
implemented for it and From<I>
implemented for usize.
The derive_more
crate may be useful for implementing these traits.
Right now, the values must have an implementation of Clone
. This may be loosened
in the future if there is a straightforward and compelling way and reason to do so.
Values cannot be modified once inserted, because remaining the same is essential to providing the invariant (and, each value is stored twice within the structure at this time)
Implementations§
source§impl<V, I> AtomTable<V, I>where
I: From<usize>,
impl<V, I> AtomTable<V, I>where I: From<usize>,
sourcepub fn iter_enumerated(&self) -> impl Iterator<Item = (I, &V)>
pub fn iter_enumerated(&self) -> impl Iterator<Item = (I, &V)>
Iterate over the (ID, value) pairs.
sourcepub fn get(&self, id: I) -> Option<&V>where
usize: From<I>,
pub fn get(&self, id: I) -> Option<&V>where usize: From<I>,
Look up the ID and return the corresponding value, if any.
sourcepub fn get_or_create_id_for_owned_value(&mut self, value: V) -> Iwhere
V: Clone + Hash + Eq,
I: Copy,
pub fn get_or_create_id_for_owned_value(&mut self, value: V) -> Iwhere V: Clone + Hash + Eq, I: Copy,
Look up the provided, owned value, and either return the existing ID for it, or add it to the table and return the newly created ID for it.
- See
AtomTable::get_id
if you want to only get the ID if one already exists. - See
AtomTable::get_or_create_id
if you do not already own the value or are unwilling to transfer ownership - it will do an extra clone for you, as late as possible, if necessary.
Panics
Panics (assert) if an internal invariant is violated, which should not be possible.
sourcepub fn get_or_create_id<Q>(&mut self, value: &Q) -> Iwhere
I: Copy,
V: Clone + Hash + Eq + Borrow<Q>,
Q: ?Sized + Hash + Eq + ToOwned<Owned = V>,
pub fn get_or_create_id<Q>(&mut self, value: &Q) -> Iwhere I: Copy, V: Clone + Hash + Eq + Borrow<Q>, Q: ?Sized + Hash + Eq + ToOwned<Owned = V>,
Look up the provided value, and either return the existing ID for it, or add it to the table and return the newly created ID for it.
- See
AtomTable::get_id
if you want to only get the ID if one already exists. - See
AtomTable::get_or_create_id_for_owned_value
if you already own the value and are willing to transfer ownership: it will save one clone.
The generic type usage here is to allow usage of things that can be turned into owned values (generally by cloning), and which may be used without cloning to find an existing ID.
Panics
Panics (assert) if an internal invariant is violated, which should not be possible.
sourcepub fn get_id<Q>(&self, value: &Q) -> Option<I>where
I: Copy,
V: Hash + Eq + Borrow<Q>,
Q: Hash + Eq + ?Sized,
pub fn get_id<Q>(&self, value: &Q) -> Option<I>where I: Copy, V: Hash + Eq + Borrow<Q>, Q: Hash + Eq + ?Sized,
Look up the provided value and return the existing ID for it, if any.
The generic type usage here mirrors that used in HashMap<K, V>::get
, to allow e.g. &str
to be
passed here if the value type is String
.
source§impl<V, I> AtomTable<V, I>where
I: From<usize>,
impl<V, I> AtomTable<V, I>where I: From<usize>,
sourcepub fn try_transform<U: Hash + Eq + Clone>(
&self,
f: impl FnMut(&V) -> U
) -> Result<AtomTable<U, I>, NonUniqueTransformOutputError>where
I: Eq + Debug,
pub fn try_transform<U: Hash + Eq + Clone>( &self, f: impl FnMut(&V) -> U ) -> Result<AtomTable<U, I>, NonUniqueTransformOutputError>where I: Eq + Debug,
Apply a function to all values to produce a new atom table with correspondence between the IDs.
Your function f
must return unique outputs when given the unique inputs,
so the returned AtomTable
may still support ID lookup from a value (data structure invariant).
Requires (default) feature “transform”
Errors
Returns an NonUniqueTransformOutputError
error if your function does not return
unique outputs for each input.
sourcepub fn try_transform_res<U: Hash + Eq + Clone, E>(
&self,
f: impl FnMut(&V) -> Result<U, E>
) -> Result<AtomTable<U, I>, TransformResError<E>>where
I: Eq + Debug,
pub fn try_transform_res<U: Hash + Eq + Clone, E>( &self, f: impl FnMut(&V) -> Result<U, E> ) -> Result<AtomTable<U, I>, TransformResError<E>>where I: Eq + Debug,
Apply a function returning Result<T, E>
to all values to produce a new atom table
with correspondence between the IDs.
(That is, new_table.get(id)
on the new table will return effectively old_table.get(id).map(p).ok().flatten()
)
Requires (default) feature “transform”
Errors
Returns an error if your transform function returns an error at any point.
Your error type will be wrapped by TransformResError
so that
NonUniqueTransformOutputError
may also be returned, if your function does not return
unique outputs for each input, which would break the invariant of the data structure.
Panics
Panics if an internal invariant is somehow violated, which should not be possible.
Trait Implementations§
source§impl<V, I> Extend<V> for AtomTable<V, I>where
V: Hash + Eq + Clone,
I: From<usize> + Copy,
impl<V, I> Extend<V> for AtomTable<V, I>where V: Hash + Eq + Clone, I: From<usize> + Copy,
Allow extending from an iterator over values: duplicate values are silently ignored/discarded.
source§fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T)
fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T)
source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one
)source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one
)source§impl<V, I> FromIterator<V> for AtomTable<V, I>where
I: From<usize>,
V: Clone + Hash + Eq,
impl<V, I> FromIterator<V> for AtomTable<V, I>where I: From<usize>, V: Clone + Hash + Eq,
Allow creation from an iterator over values: duplicate values are silently ignored/discarded.
This is what allows us to use Iterator::collect
into an AtomTable
.
source§fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self
fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self
source§impl<V, I> IntoIterator for AtomTable<V, I>where
I: From<usize>,
impl<V, I> IntoIterator for AtomTable<V, I>where I: From<usize>,
Provide into_iter()
which iterates only over the values.
source§impl<V, I> PartialEq<AtomTable<V, I>> for AtomTable<V, I>where
I: From<usize>,
V: PartialEq,
impl<V, I> PartialEq<AtomTable<V, I>> for AtomTable<V, I>where I: From<usize>, V: PartialEq,
Equality comparison provided only when associated value type supports equality.