indexmap::map::raw_entry_v1

Trait RawEntryApiV1

Source
pub trait RawEntryApiV1<K, V, S>: Sealed {
    // Required methods
    fn raw_entry_v1(&self) -> RawEntryBuilder<'_, K, V, S>;
    fn raw_entry_mut_v1(&mut self) -> RawEntryBuilderMut<'_, K, V, S>;
}
Expand description

Opt-in access to the experimental raw entry API.

See the raw_entry_v1 module documentation for more information.

Required Methods§

Source

fn raw_entry_v1(&self) -> RawEntryBuilder<'_, K, V, S>

Creates a raw immutable entry builder for the IndexMap.

Raw entries provide the lowest level of control for searching and manipulating a map. They must be manually initialized with a hash and then manually searched.

This is useful for

  • Hash memoization
  • Using a search key that doesn’t work with the Equivalent trait
  • Using custom comparison logic without newtype wrappers

Unless you are in such a situation, higher-level and more foolproof APIs like get should be preferred.

Immutable raw entries have very limited use; you might instead want raw_entry_mut_v1.

§Examples
use core::hash::{BuildHasher, Hash};
use indexmap::map::{IndexMap, RawEntryApiV1};

let mut map = IndexMap::new();
map.extend([("a", 100), ("b", 200), ("c", 300)]);

fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
    use core::hash::Hasher;
    let mut state = hash_builder.build_hasher();
    key.hash(&mut state);
    state.finish()
}

for k in ["a", "b", "c", "d", "e", "f"] {
    let hash = compute_hash(map.hasher(), k);
    let i = map.get_index_of(k);
    let v = map.get(k);
    let kv = map.get_key_value(k);
    let ikv = map.get_full(k);

    println!("Key: {} and value: {:?}", k, v);

    assert_eq!(map.raw_entry_v1().from_key(k), kv);
    assert_eq!(map.raw_entry_v1().from_hash(hash, |q| *q == k), kv);
    assert_eq!(map.raw_entry_v1().from_key_hashed_nocheck(hash, k), kv);
    assert_eq!(map.raw_entry_v1().from_hash_full(hash, |q| *q == k), ikv);
    assert_eq!(map.raw_entry_v1().index_from_hash(hash, |q| *q == k), i);
}
Source

fn raw_entry_mut_v1(&mut self) -> RawEntryBuilderMut<'_, K, V, S>

Creates a raw entry builder for the IndexMap.

Raw entries provide the lowest level of control for searching and manipulating a map. They must be manually initialized with a hash and then manually searched. After this, insertions into a vacant entry still require an owned key to be provided.

Raw entries are useful for such exotic situations as:

  • Hash memoization
  • Deferring the creation of an owned key until it is known to be required
  • Using a search key that doesn’t work with the Equivalent trait
  • Using custom comparison logic without newtype wrappers

Because raw entries provide much more low-level control, it’s much easier to put the IndexMap into an inconsistent state which, while memory-safe, will cause the map to produce seemingly random results. Higher-level and more foolproof APIs like entry should be preferred when possible.

Raw entries give mutable access to the keys. This must not be used to modify how the key would compare or hash, as the map will not re-evaluate where the key should go, meaning the keys may become “lost” if their location does not reflect their state. For instance, if you change a key so that the map now contains keys which compare equal, search may start acting erratically, with two keys randomly masking each other. Implementations are free to assume this doesn’t happen (within the limits of memory-safety).

§Examples
use core::hash::{BuildHasher, Hash};
use indexmap::map::{IndexMap, RawEntryApiV1};
use indexmap::map::raw_entry_v1::RawEntryMut;

let mut map = IndexMap::new();
map.extend([("a", 100), ("b", 200), ("c", 300)]);

fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
    use core::hash::Hasher;
    let mut state = hash_builder.build_hasher();
    key.hash(&mut state);
    state.finish()
}

// Existing key (insert and update)
match map.raw_entry_mut_v1().from_key("a") {
    RawEntryMut::Vacant(_) => unreachable!(),
    RawEntryMut::Occupied(mut view) => {
        assert_eq!(view.index(), 0);
        assert_eq!(view.get(), &100);
        let v = view.get_mut();
        let new_v = (*v) * 10;
        *v = new_v;
        assert_eq!(view.insert(1111), 1000);
    }
}

assert_eq!(map["a"], 1111);
assert_eq!(map.len(), 3);

// Existing key (take)
let hash = compute_hash(map.hasher(), "c");
match map.raw_entry_mut_v1().from_key_hashed_nocheck(hash, "c") {
    RawEntryMut::Vacant(_) => unreachable!(),
    RawEntryMut::Occupied(view) => {
        assert_eq!(view.index(), 2);
        assert_eq!(view.shift_remove_entry(), ("c", 300));
    }
}
assert_eq!(map.raw_entry_v1().from_key("c"), None);
assert_eq!(map.len(), 2);

// Nonexistent key (insert and update)
let key = "d";
let hash = compute_hash(map.hasher(), key);
match map.raw_entry_mut_v1().from_hash(hash, |q| *q == key) {
    RawEntryMut::Occupied(_) => unreachable!(),
    RawEntryMut::Vacant(view) => {
        assert_eq!(view.index(), 2);
        let (k, value) = view.insert("d", 4000);
        assert_eq!((*k, *value), ("d", 4000));
        *value = 40000;
    }
}
assert_eq!(map["d"], 40000);
assert_eq!(map.len(), 3);

match map.raw_entry_mut_v1().from_hash(hash, |q| *q == key) {
    RawEntryMut::Vacant(_) => unreachable!(),
    RawEntryMut::Occupied(view) => {
        assert_eq!(view.index(), 2);
        assert_eq!(view.swap_remove_entry(), ("d", 40000));
    }
}
assert_eq!(map.get("d"), None);
assert_eq!(map.len(), 2);

Implementors§

Source§

impl<K, V, S> RawEntryApiV1<K, V, S> for IndexMap<K, V, S>