Lasso

CI Security Audit Coverage LoC Docs.rs Crates.io

A concurrent string interner that allows strings to be cached with a minimal memory footprint, associating them with a unique [key] that can be used to retrieve them at any time. [Lassos] allow O(1) internment and resolution and can be turned into a [ReadOnlyLasso] to allow for contention-free resolutions with both key to str and str to key operations. It can also be turned into a [ResolverLasso] with only key to str operations for the lowest possible memory usage

Which Interner do I use?

No matter which interner you decide to use, you must start with a [Lasso], as that is the only way to intern strings and the only way to get the other two interner types. As your program progresses though you may not need to intern strings anymore, and at that point you may choose either a [ReadOnlyLasso] or a [ResolverLasso]. If you need to go from str to key you should use a [ReadOnlyLasso], but anything else should use a [ResolverLasso].

| Interner | Thread-safe | Intern String | key to str | str to key | Contention Free | Relative Memory Usage | | ----------------- | :----------------: | :----------------: | :----------------: | :----------------: | :----------------: | :-------------------: | | [Lasso] | :whitecheckmark: | :whitecheckmark: | :whitecheckmark: | :whitecheckmark: | :x: | Most | | [ReadOnlyLasso] | :whitecheckmark: | :x: | :whitecheckmark: | :whitecheckmark: | :whitecheckmark: | Middle | | [ResolverLasso] | :whitecheckmark: | :x: | :whitecheckmark: | :x: | :whitecheckmark: | Least |

Example: Interning Strings across threads

```rust use lasso::Lasso; use std::{thread, sync::Arc};

let lasso = Arc::new(Lasso::default()); let hello = lasso.getorintern("Hello, ");

let l = Arc::clone(&lasso); let world = thread::spawn(move || { l.getorintern("World!".to_string()) }) .join() .unwrap();

let world2 = lasso.getor_intern("World!");

asserteq!("Hello, ", lasso.resolve(&hello)); asserteq!("World!", lasso.resolve(&world));

// These are the same because they interned the same string asserteq!(world, world2); asserteq!(lasso.resolve(&world), lasso.resolve(&world2)); ```

Example: Resolving Strings

```rust use lasso::Lasso;

let lasso = Lasso::default(); let key = lasso.intern("Hello, World!");

assert_eq!("Hello, World!", lasso.resolve(&key)); ```

Example: Creating a ReadOnlyLasso

```rust use lasso::Lasso; use std::{thread, sync::Arc};

let lasso = Lasso::default(); let key = lasso.intern("Contention free!");

// Can be used for resolving strings with zero contention, but not for interning new ones let readonlylasso = Arc::new(lasso.intoreadonly());

let lasso = Arc::clone(&readonlylasso); thread::spawn(move || { assert_eq!("Contention free!", lasso.resolve(&key)); });

asserteq!("Contention free!", readonly_lasso.resolve(&key)); ```

Example: Creating a ResolverLasso

```rust use lasso::Lasso; use std::{thread, sync::Arc};

let lasso = Lasso::default(); let key = lasso.intern("Contention free!");

// Can be used for resolving strings with zero contention and the lowest possible memory consumption, // but not for interning new ones let resolverlasso = Arc::new(lasso.intoresolver());

let lasso = Arc::clone(&resolverlasso); thread::spawn(move || { asserteq!("Contention free!", lasso.resolve(&key)); });

asserteq!("Contention free!", resolverlasso.resolve(&key)); ```

Cargo Features