diff --git a/src/lib.rs b/src/lib.rs index 818baa6..dce7ed7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -192,9 +192,15 @@ impl<'a, T> Populator<'a, T> } } - /// Get a reference to an item at `idx` whether it exists or not. - #[inline] - pub fn get_ref(&self, idx: usize) -> Ref<'_, 'a, T> + + #[inline(always)] + fn bounds_okay(&self, idx: usize) -> bool + { + idx < self.populates.len() + } + + #[inline(always)] + fn bounds_check(&self, idx: usize) { #[inline(never)] #[cold] @@ -205,12 +211,34 @@ impl<'a, T> Populator<'a, T> if idx >= self.populates.len() { _panic_oob(idx, self.populates.len()) } + } + + /// Get a reference to an item at `idx` whether it exists or not. + /// + /// # Panics + /// If the index is out of bounds + #[inline] + pub fn get_ref(&self, idx: usize) -> Ref<'_, 'a, T> + { + self.bounds_check(idx); Ref { pop: self, idx } } - //TODO: get_into(Arc) -> OwnedRef + + /// Consume into a reference to a specific index in the populator, whether it exists or not. + /// + /// # Panics + /// If the index is out of bounds + #[inline] + pub fn into_ref(self: std::sync::Arc, idx: usize) -> OwnedRef<'a, T> + { + OwnedRef { + pop: self, + idx + } + } //TODO: get_excusive -> RefEx /// Try to get an exclusive, mutable reference to an item at `idx` if an item exists there. diff --git a/src/refer.rs b/src/refer.rs index df91100..957777c 100644 --- a/src/refer.rs +++ b/src/refer.rs @@ -1,5 +1,6 @@ //! Single-index references. use super::*; +use std::sync::Arc; #[derive(Debug)] // PartialEq, PartialOrd pub struct Ref<'re, 'a, T: 'a> @@ -10,6 +11,34 @@ pub struct Ref<'re, 'a, T: 'a> //TODO: OR: Hold a reference to the actual AtomicBool at `idx` itself? } +#[derive(Debug)] +pub struct OwnedRef<'a, T: 'a> // PartialEq, PartialOrd +{ + pub(super) pop: Arc>, + pub(super) idx: usize, +} + + +impl<'a, T: 'a> PartialEq for OwnedRef<'a, T> +{ + #[inline] + fn eq(&self, other: &Self) -> bool + { + address_eq(self.pop.as_ref(), other.pop.as_ref()) && self.idx == other.idx + } +} + +impl<'a, T: 'a> PartialOrd for OwnedRef<'a, T> +{ + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + if address_eq(self.pop.as_ref(), other.pop.as_ref()) { + self.idx.partial_cmp(&other.idx) + } else { + None + } + } +} impl<'re, 'a, T: 'a> PartialEq for Ref<'re, 'a, T> { @@ -63,8 +92,65 @@ impl<'re, 'a, T: 'a> Ref<'re, 'a, T> { self.pop.insert(self.idx, value) } - } -//TODO: OwnedRef: From Arc receiver of Arc> -//TODO: RefEx: Exclusive reference, holds &'ref mut Populator<'a, T> +impl<'a, T:'a> OwnedRef<'a, T> +{ + /// The index that this `Ref` refers to. + #[inline] + pub fn slot(&self) -> usize + { + self.idx + } + /// Checks if the references item currently exists. + #[inline] + pub fn exists(&self) -> bool + { + self.pop.exists(self.idx) + } + /// Try to insert `value` at the referred slot. + /// + /// If the slot already has a value, then `Err(value)` is returned, otherwise, `value` is inserted into the table and the number of items now populated is returned. + #[inline] + pub fn try_insert(&self, value: T) -> Result + { + self.pop.try_insert(self.idx, value) + } + /// Insert `value` at the referred slot. + /// + /// # Panics + /// If the slot has a value. + #[inline] + pub fn insert(&self, value: T) -> usize + { + self.pop.insert(self.idx, value) + } + + /// Consume into the inner populator + #[inline] + pub fn into_inner(self) -> Arc> + { + self.pop + } +} + +impl<'a, T: 'a> From<(Arc>, usize)> for OwnedRef<'a, T> +{ + #[inline] + fn from((pop, idx): (Arc>, usize)) -> Self + { + Self { pop, idx } + } +} + + +impl<'a, T: 'a> From> for (Arc>, usize) +{ + #[inline] + fn from(from: OwnedRef<'a, T>) -> Self + { + (from.pop, from.idx) + } +} + +//TODO: RefEx: Exclusive reference, holds &'re mut Populator<'a, T>