#key-value #hash-map #btree-map #pattern #key-hash #key-value-store #collection

automap

Simple pattern to implement key-value maps where the value type contains the key type

1 unstable release

0.1.0 Feb 26, 2021

#1817 in Data structures

Download history 488/week @ 2024-07-20 774/week @ 2024-07-27 892/week @ 2024-08-03 676/week @ 2024-08-10 724/week @ 2024-08-17 722/week @ 2024-08-24 687/week @ 2024-08-31 829/week @ 2024-09-07 863/week @ 2024-09-14 951/week @ 2024-09-21 1288/week @ 2024-09-28 1155/week @ 2024-10-05 912/week @ 2024-10-12 526/week @ 2024-10-19 847/week @ 2024-10-26 669/week @ 2024-11-02

3,159 downloads per month
Used in 28 crates (via holochain_types)

Apache-2.0

11KB
131 lines

automap

Simple pattern to implement key-value maps where the value type contains the key type. Implementations for HashMap and BTreeMap from std::collections are provided.

Example

use std::collections::HashMap;
use automap::{AutoHashMap, AutoMapped};

// Let's say we want a `Person` to be keyed by their `name` in a HashMap
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
struct Person {
    name: String,
    age: u16,
}

// We can specify how to derive the key from the value
// As long as the Key type meets the bounds for a normal HashMap key, we
// can use this value in an AutoHashMap.
// (Similarly for BTreeMap.)
impl AutoMapped for Person {
    type Key = String;

    fn key(&self) -> &Self::Key {
        &self.name
    }
}

// Then, we can simply use an `AutoHashMap` to insert values directly.
let mut map = AutoHashMap::new();
let michelle = Person { name: "Michelle".into(), age: 37 };
// We don't need to provide the key, because it is derived from the value.
map.insert(michelle.clone());

// You can access all other normal HashMap methods directly:
assert_eq!(map.get("Michelle".into()), Some(&michelle));
assert_eq!(map.remove("Michelle".into()), Some(michelle));

// We can also go From and Into a normal HashMap easily.
let inner: HashMap<_, _> = map.into();
let map: AutoHashMap<_> = inner.into();

Serde support

Set the "serde" feature in your dependencies to include de/serialization support.

Future improvements

  • Avoid cloning the key: ideally, the key would be borrowed from the value, but it wasn't immediately apparent how to do this while still providing serde deserialization. Perhaps a bespoke data structure could be written instead of leaning on std::collections.
    • This could also be implemented with a proc macro which splits the target struct into the key part and the remainder, so that the key is only stored once while still using a standard Map.
  • Allow a value type to have multiple Automapped implementations, specifying different keys for different situations

Dependencies

~0.8–1.4MB
~29K SLoC