composable-indexes

Crates.iocomposable-indexes
lib.rscomposable-indexes
version
sourcesrc
created_at2025-04-07 19:55:32.28742+00
updated_at2025-05-07 20:18:31.219405+00
descriptionIn-memory collections with composable indexes
homepage
repositoryhttps://github.com/utdemir/composable-indexes
max_upload_size
id1624664
Cargo.toml error:TOML parse error at line 17, column 1 | 17 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include`
size0
Utku Demir (utdemir)

documentation

README

composable-indexes

Crates.io Docs.rs codecov

A Rust library for collections with flexible and composable in-memory indexes. The indexes stay in sync with the collection without any extra effort.

Features

  • Batteries included - built-in indexes for common use cases.
  • Fast - indexes are backed by performant data structures.
  • Composable - build complex indexes from simple ones with combinators.
  • Extensible - write your own index and aggregations.
  • Safe: Small core, property-based tests, no unsafe.

Example

use composable_indexes::*;

struct Person { name: String, age: u32, ssn: String }

let mut collection = Collection::<Person, _>::new(
  index::zip!(
   // A hashtable for the ssn, for exact lookups
   index::premap(|p: &Person| p.ssn.clone(), index::hashtable()),
   
   // A btree index for age, for range lookups
   index::premap(|p: &Person| p.age, index::btree()),

   // Also keep track of the mean age
   index::premap(|p: &Person| p.age, aggregations::mean()),
  )
);

let alice = collection.insert(Person { name: "Alice".to_string(), /* ... */ });
collection.insert(Person { name: "Bob".to_string(), /* ... */ });
collection.adjust_mut(alice, |p| { p.age = 31; });
// ...

let q = collection.query();

// SSN lookup
let _found = q.0.get("123-45-6789");

// Query the oldest person
let _oldest = q.1.max_one();

// Query the mean age
let _mean_age = q.2;

Limitations

  • For performance reasons, we do not use boxing or dynamic dispatch. So the flexibility comes with the type signatures getting larger.

Future work

  • Operations on more than one collection (i.e., foreign keys, joins)
  • A "splat" operator that applies an index to more than one field in a single item.
    • This is implemented in the ud/splat branch, but it adds yet another type parameter to the 'Index' trait, and I'm not sure if the tradeoff is worth it.
Commit count: 0

cargo fmt