Skip to content

Commit

Permalink
Added Interner::into_reader()
Browse files Browse the repository at this point in the history
  • Loading branch information
Kixiron committed Dec 31, 2020
1 parent 77f0220 commit a28a3ac
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 0 deletions.
102 changes: 102 additions & 0 deletions src/interface/boxed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use super::{Interner, Reader, Resolver};
use crate::{Key, LassoResult, RodeoResolver};
#[cfg(feature = "no-std")]
use alloc::boxed::Box;

impl<K, I> Interner<K> for Box<I>
where
K: Key,
I: Interner<K> + ?Sized + 'static,
{
#[cfg_attr(feature = "inline-more", inline)]
fn get_or_intern(&mut self, val: &str) -> K {
(&mut **self).get_or_intern(val)
}

#[cfg_attr(feature = "inline-more", inline)]
fn try_get_or_intern(&mut self, val: &str) -> LassoResult<K> {
(&mut **self).try_get_or_intern(val)
}

#[cfg_attr(feature = "inline-more", inline)]
fn get_or_intern_static(&mut self, val: &'static str) -> K {
(&mut **self).get_or_intern_static(val)
}

#[cfg_attr(feature = "inline-more", inline)]
fn try_get_or_intern_static(&mut self, val: &'static str) -> LassoResult<K> {
self.try_get_or_intern(val)
}

#[cfg_attr(feature = "inline-more", inline)]
#[must_use]
fn into_reader(self) -> Box<dyn Reader<K>>
where
Self: 'static,
{
I::into_reader_boxed(self)
}

#[cfg_attr(feature = "inline-more", inline)]
#[must_use]
fn into_reader_boxed(self: Box<Self>) -> Box<dyn Reader<K>>
where
Self: 'static,
{
(*self).into_reader()
}
}

impl<K, I> Reader<K> for Box<I>
where
K: Key,
I: Reader<K> + ?Sized + 'static,
{
#[cfg_attr(feature = "inline-more", inline)]
fn get(&self, val: &str) -> Option<K> {
(&**self).get(val)
}

#[cfg_attr(feature = "inline-more", inline)]
fn contains(&self, val: &str) -> bool {
(&**self).contains(val)
}

#[cfg_attr(feature = "inline-more", inline)]
#[must_use]
fn into_resolver(self) -> RodeoResolver<K> {
I::into_resolver_boxed(self)
}

#[cfg_attr(feature = "inline-more", inline)]
#[must_use]
fn into_resolver_boxed(self: Box<Self>) -> RodeoResolver<K> {
(*self).into_resolver()
}
}

impl<K, I> Resolver<K> for Box<I>
where
K: Key,
I: Resolver<K> + ?Sized + 'static,
{
#[cfg_attr(feature = "inline-more", inline)]
fn resolve<'a>(&'a self, key: &K) -> &'a str {
(&**self).resolve(key)
}

#[cfg_attr(feature = "inline-more", inline)]
fn try_resolve<'a>(&'a self, key: &K) -> Option<&'a str> {
(&**self).try_resolve(key)
}

#[cfg_attr(feature = "inline-more", inline)]
unsafe fn resolve_unchecked<'a>(&'a self, key: &K) -> &'a str {
(&**self).resolve_unchecked(key)
}

#[cfg_attr(feature = "inline-more", inline)]
fn contains_key(&self, key: &K) -> bool {
(&**self).contains_key(key)
}
}
27 changes: 27 additions & 0 deletions src/interface/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
mod boxed;
mod rodeo;
mod rodeo_reader;
mod rodeo_resolver;
mod tests;
mod threaded_rodeo;

use crate::{LassoResult, Rodeo, RodeoReader, RodeoResolver};
#[cfg(feature = "no-std")]
use alloc::boxed::Box;
use sealed::Sealed;

/// A generic interface over any underlying interner, allowing storing and accessing
Expand Down Expand Up @@ -39,6 +42,21 @@ pub trait Interner<K>: Reader<K> + Resolver<K> + Sealed {
///
/// This will not reallocate or copy the given string
fn try_get_or_intern_static(&mut self, val: &'static str) -> LassoResult<K>;

/// Consumes the current [`Interner`] and converts it into a [`RodeoReader`] to allow
/// contention-free access of the interner from multiple threads
#[must_use]
fn into_reader(self) -> Box<dyn Reader<K>>
where
Self: 'static;

/// An implementation detail to allow calling [`Interner::into_reader()`] on dynamically
/// dispatched interners
#[doc(hidden)]
#[must_use]
fn into_reader_boxed(self: Box<Self>) -> Box<dyn Reader<K>>
where
Self: 'static;
}

/// A generic interface that allows using any underlying interner for
Expand All @@ -53,7 +71,14 @@ pub trait Reader<K>: Resolver<K> + Sealed {

/// Consumes the current [`Reader`] and makes it into a [`RodeoResolver`], allowing
/// contention-free access from multiple threads with the lowest possible memory consumption
#[must_use]
fn into_resolver(self) -> RodeoResolver<K>;

/// An implementation detail to allow calling [`Reader::into_resolver()`] on dynamically
/// dispatched readers
#[doc(hidden)]
#[must_use]
fn into_resolver_boxed(self: Box<Self>) -> RodeoResolver<K>;
}

/// A generic interface that allows using any underlying interner only
Expand Down Expand Up @@ -99,4 +124,6 @@ mod sealed {

#[cfg(feature = "multi-threaded")]
impl<K, S> Sealed for crate::ThreadedRodeo<K, S> {}

impl<I: ?Sized> Sealed for Box<I> {}
}
24 changes: 24 additions & 0 deletions src/interface/rodeo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,24 @@ where
fn try_get_or_intern_static(&mut self, val: &'static str) -> LassoResult<K> {
self.try_get_or_intern_static(val)
}

#[cfg_attr(feature = "inline-more", inline)]
#[must_use]
fn into_reader(self) -> Box<dyn Reader<K>>
where
Self: 'static,
{
Box::new(self).into_reader_boxed()
}

#[cfg_attr(feature = "inline-more", inline)]
#[must_use]
fn into_reader_boxed(self: Box<Self>) -> Box<dyn Reader<K>>
where
Self: 'static,
{
Box::new(Rodeo::into_reader(*self))
}
}

impl<K, S> Reader<K> for Rodeo<K, S>
Expand All @@ -49,6 +67,12 @@ where
fn into_resolver(self) -> RodeoResolver<K> {
self.into_resolver()
}

#[cfg_attr(feature = "inline-more", inline)]
#[must_use]
fn into_resolver_boxed(self: Box<Self>) -> RodeoResolver<K> {
(*self).into_resolver()
}
}

impl<K, S> Resolver<K> for Rodeo<K, S>
Expand Down
6 changes: 6 additions & 0 deletions src/interface/rodeo_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ where
fn into_resolver(self) -> RodeoResolver<K> {
self.into_resolver()
}

#[cfg_attr(feature = "inline-more", inline)]
#[must_use]
fn into_resolver_boxed(self: Box<Self>) -> RodeoResolver<K> {
(*self).into_resolver()
}
}

impl<K, S> Resolver<K> for RodeoReader<K, S>
Expand Down
21 changes: 21 additions & 0 deletions src/interface/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,27 @@ fn interner_implementations() {
assert_eq!(interner.resolve_unchecked(&key), string);
}
}

let reader = interner.into_reader();
for (key, string) in INTERNED_STRINGS
.iter()
.chain(UNINTERNED_STRINGS.iter())
.copied()
.enumerate()
.map(|(i, s)| (Spur::try_from_usize(i).unwrap(), s))
{
assert!(reader.get(string).is_some());
assert!(reader.contains(string));

assert!(reader.contains_key(&key));
assert_eq!(reader.resolve(&key), string);
assert!(reader.try_resolve(&key).is_some());
assert_eq!(reader.try_resolve(&key), Some(string));

unsafe {
assert_eq!(reader.resolve_unchecked(&key), string);
}
}
}
}

Expand Down
24 changes: 24 additions & 0 deletions src/interface/threaded_rodeo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,24 @@ where
fn try_get_or_intern_static(&mut self, val: &'static str) -> LassoResult<K> {
(&*self).try_get_or_intern_static(val)
}

#[cfg_attr(feature = "inline-more", inline)]
#[must_use]
fn into_reader(self) -> Box<dyn Reader<K>>
where
Self: 'static,
{
Box::new(self).into_reader_boxed()
}

#[cfg_attr(feature = "inline-more", inline)]
#[must_use]
fn into_reader_boxed(self: Box<Self>) -> Box<dyn Reader<K>>
where
Self: 'static,
{
Box::new(ThreadedRodeo::into_reader(*self))
}
}

impl<K, S> Reader<K> for ThreadedRodeo<K, S>
Expand All @@ -50,6 +68,12 @@ where
fn into_resolver(self) -> RodeoResolver<K> {
self.into_resolver()
}

#[cfg_attr(feature = "inline-more", inline)]
#[must_use]
fn into_resolver_boxed(self: Box<Self>) -> RodeoResolver<K> {
(*self).into_resolver()
}
}

impl<K, S> Resolver<K> for ThreadedRodeo<K, S>
Expand Down

0 comments on commit a28a3ac

Please sign in to comment.