Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make string interner and backends compatible with more types #42

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ edition = "2021"
cfg-if = "1.0"
hashbrown = { version = "0.11", default-features = false, features = ["ahash"] }
serde = { version = "1.0", optional = true }
len-trait = {version = "0.6.1", optional = true}

[dev-dependencies]
serde_json = "1.0"
Expand Down Expand Up @@ -48,8 +49,7 @@ inline-more = ["hashbrown/inline-more"]
# the need for those present backends. Reduces compilation time of this crate.
#
# Enabled by default.
backends = []

backends = ["len-trait"]
# Enables testing of memory heap allocations.
#
# These tests are disabled by default since they are slow
Expand Down
11 changes: 5 additions & 6 deletions benches/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use string_interner::{
SimpleBackend,
StringBackend,
},
DefaultSymbol,
StringInterner,
};

Expand Down Expand Up @@ -90,7 +89,7 @@ type StringInternerWith<B> = StringInterner<B, FxBuildHasher>;

pub trait BackendBenchmark {
const NAME: &'static str;
type Backend: Backend;
type Backend: Backend<Str = str>;

fn setup() -> StringInternerWith<Self::Backend> {
<StringInternerWith<Self::Backend>>::new()
Expand Down Expand Up @@ -122,23 +121,23 @@ pub trait BackendBenchmark {
pub struct BenchBucket;
impl BackendBenchmark for BenchBucket {
const NAME: &'static str = "BucketBackend";
type Backend = BucketBackend<DefaultSymbol>;
type Backend = BucketBackend;
}

pub struct BenchSimple;
impl BackendBenchmark for BenchSimple {
const NAME: &'static str = "SimpleBackend";
type Backend = SimpleBackend<DefaultSymbol>;
type Backend = SimpleBackend;
}

pub struct BenchString;
impl BackendBenchmark for BenchString {
const NAME: &'static str = "StringBackend";
type Backend = StringBackend<DefaultSymbol>;
type Backend = StringBackend;
}

pub struct BenchBuffer;
impl BackendBenchmark for BenchBuffer {
const NAME: &'static str = "BufferBackend";
type Backend = BufferBackend<DefaultSymbol>;
type Backend = BufferBackend;
}
65 changes: 65 additions & 0 deletions src/backend/bucket/fixed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use std::{
ops::Deref,
ptr::NonNull,
};

use len_trait::{
Len,
WithCapacity,
};

/// Represents a container with a fixed initial capacity that
/// is capable of pushing elements of type `&S` into its internal buffer only if the
/// elements don't exceed its fixed capacity.
///
/// # Safety
///
/// It is Undefined Behaviour if any mutable or internally mutable operation
/// invalidates previously generated [`NonNull<S>`] pointers.
///
/// In other words, implementations must guarantee that no reallocations
/// occur after creating the container.
pub unsafe trait FixedContainer<S: ?Sized>:
Deref<Target = S> + WithCapacity + Len
{
/// Push the given string into the fixed string if there is enough capacity.
///
/// Returns a reference to the pushed string if there was enough capacity to
/// perform the operation. Otherwise returns `None`.
fn try_push_str(&mut self, string: &S) -> Option<NonNull<S>>;
}

unsafe impl FixedContainer<str> for String {
#[inline]
fn try_push_str(&mut self, string: &str) -> Option<NonNull<str>> {
let len = self.len();
if self.capacity() < len + string.len() {
return None
}
self.push_str(string);
debug_assert_eq!(self.len(), len + string.len());
Some(NonNull::from(
// SAFETY: We convert from bytes to utf8 from which we know through the
// input string that they must represent valid utf8.
unsafe {
core::str::from_utf8_unchecked(&self.as_bytes()[len..len + string.len()])
},
))
}
}

unsafe impl<T> FixedContainer<[T]> for Vec<T>
where
T: Clone,
{
#[inline]
fn try_push_str(&mut self, string: &[T]) -> Option<NonNull<[T]>> {
let len = self.len();
if self.capacity() < len + string.len() {
return None
}
self.extend_from_slice(string);
debug_assert_eq!(self.len(), len + string.len());
Some(NonNull::from(&self[len..len + string.len()]))
}
}
64 changes: 0 additions & 64 deletions src/backend/bucket/fixed_str.rs

This file was deleted.

56 changes: 0 additions & 56 deletions src/backend/bucket/interned_str.rs

This file was deleted.

Loading