Struct BiHashMap

Source
pub struct BiHashMap<T: BiHashItem, S = DefaultHashBuilder, A: Allocator = Global> { /* private fields */ }
Expand description

A 1:1 (bijective) map for two keys and a value.

The storage mechanism is a fast hash table of integer indexes to items, with these indexes stored in two hash tables. This allows for efficient lookups by either of the two keys and prevents duplicates.

§Examples

use iddqd::{BiHashItem, BiHashMap, bi_upcast};

// Define a struct with two keys and a value.
#[derive(Debug, PartialEq, Eq)]
struct MyItem {
    id: u32,
    name: &'static str,
    value: i32,
}

// Implement BiHashItem for the struct.
impl BiHashItem for MyItem {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        self.name
    }

    bi_upcast!();
}

// Create a new BiHashMap and insert items.
let mut map = BiHashMap::new();
map.insert_unique(MyItem { id: 1, name: "foo", value: 42 }).unwrap();
map.insert_unique(MyItem { id: 2, name: "bar", value: 99 }).unwrap();

// Look up by the first key.
assert_eq!(map.get1(&1).unwrap().value, 42);
assert_eq!(map.get1(&2).unwrap().value, 99);
assert!(map.get1(&3).is_none());

// Look up by the second key.
assert_eq!(map.get2(&"foo").unwrap().value, 42);
assert_eq!(map.get2(&"bar").unwrap().value, 99);
assert!(map.get2(&"baz").is_none());

Implementations§

Source§

impl<T: BiHashItem> BiHashMap<T>

Source

pub fn new() -> Self

Creates a new, empty BiHashMap.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let map: BiHashMap<Item> = BiHashMap::new();
assert!(map.is_empty());
assert_eq!(map.len(), 0);
Source

pub fn with_capacity(capacity: usize) -> Self

Creates a new BiHashMap with the given capacity.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let map: BiHashMap<Item> = BiHashMap::with_capacity(10);
assert!(map.capacity() >= 10);
assert!(map.is_empty());
Source§

impl<T: BiHashItem, S: Clone + BuildHasher> BiHashMap<T, S>

Source

pub fn with_hasher(hasher: S) -> Self

Creates a new BiHashMap with the given hasher.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};
use std::collections::hash_map::RandomState;

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let hasher = RandomState::new();
let map: BiHashMap<Item, RandomState> = BiHashMap::with_hasher(hasher);
assert!(map.is_empty());
Source

pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self

Creates a new BiHashMap with the given capacity and hasher.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};
use std::collections::hash_map::RandomState;

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let hasher = RandomState::new();
let map: BiHashMap<Item, _> =
    BiHashMap::with_capacity_and_hasher(10, hasher);
assert!(map.capacity() >= 10);
assert!(map.is_empty());
Source§

impl<T: BiHashItem, A: Clone + Allocator> BiHashMap<T, DefaultHashBuilder, A>

Source

pub fn new_in(alloc: A) -> Self

Creates a new empty BiHashMap using the given allocator.

Requires the allocator-api2 feature to be enabled.

§Examples

Using the bumpalo allocator:

use iddqd::{BiHashMap, BiHashItem, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

// Define a new allocator.
let bump = bumpalo::Bump::new();
// Create a new BiHashMap using the allocator.
let map: BiHashMap<Item, _, &bumpalo::Bump> = BiHashMap::new_in(&bump);
assert!(map.is_empty());
Source

pub fn with_capacity_in(capacity: usize, alloc: A) -> Self

Creates an empty BiHashMap with the specified capacity using the given allocator.

Requires the allocator-api2 feature to be enabled.

§Examples

Using the bumpalo allocator:

use iddqd::{BiHashMap, BiHashItem, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

// Define a new allocator.
let bump = bumpalo::Bump::new();
// Create a new BiHashMap with capacity using the allocator.
let map: BiHashMap<Item, _, &bumpalo::Bump> = BiHashMap::with_capacity_in(10, &bump);
assert!(map.capacity() >= 10);
assert!(map.is_empty());
Source§

impl<T: BiHashItem, S: Clone + BuildHasher, A: Clone + Allocator> BiHashMap<T, S, A>

Source

pub fn with_hasher_in(hasher: S, alloc: A) -> Self

Creates a new, empty BiHashMap with the given hasher and allocator.

Requires the allocator-api2 feature to be enabled.

§Examples

Using the bumpalo allocator:

use iddqd::{BiHashItem, BiHashMap, bi_upcast};
use std::collections::hash_map::RandomState;

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

// Define a new allocator.
let bump = bumpalo::Bump::new();
let hasher = RandomState::new();
// Create a new BiHashMap with hasher using the allocator.
let map: BiHashMap<Item, _, &bumpalo::Bump> =
    BiHashMap::with_hasher_in(hasher, &bump);
assert!(map.is_empty());
Source

pub fn with_capacity_and_hasher_in(capacity: usize, hasher: S, alloc: A) -> Self

Creates a new, empty BiHashMap with the given capacity, hasher, and allocator.

Requires the allocator-api2 feature to be enabled.

§Examples

Using the bumpalo allocator:

use iddqd::{BiHashItem, BiHashMap, bi_upcast};
use std::collections::hash_map::RandomState;

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

// Define a new allocator.
let bump = bumpalo::Bump::new();
let hasher = RandomState::new();
// Create a new BiHashMap with capacity and hasher using the allocator.
let map: BiHashMap<Item, _, &bumpalo::Bump> =
    BiHashMap::with_capacity_and_hasher_in(10, hasher, &bump);
assert!(map.capacity() >= 10);
assert!(map.is_empty());
Source§

impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> BiHashMap<T, S, A>

Source

pub fn allocator(&self) -> &A

Returns the allocator.

Requires the allocator-api2 feature to be enabled.

§Examples

Using the bumpalo allocator:

use iddqd::{BiHashMap, BiHashItem, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

// Define a new allocator.
let bump = bumpalo::Bump::new();
// Create a new BiHashMap using the allocator.
let map: BiHashMap<Item, _, &bumpalo::Bump> = BiHashMap::new_in(&bump);
let _allocator = map.allocator();
Source

pub fn capacity(&self) -> usize

Returns the currently allocated capacity of the map.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let map: BiHashMap<Item> = BiHashMap::with_capacity(10);
assert!(map.capacity() >= 10);

let empty_map: BiHashMap<Item> = BiHashMap::new();
assert!(empty_map.capacity() >= 0);
Source

pub fn is_empty(&self) -> bool

Returns true if the map contains no items.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
assert!(map.is_empty());

map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();
assert!(!map.is_empty());
Source

pub fn len(&self) -> usize

Returns the number of items in the map.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
assert_eq!(map.len(), 0);

map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();
map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
    .unwrap();
assert_eq!(map.len(), 2);
Source

pub fn iter(&self) -> Iter<'_, T>

Returns an iterator over all items in the map.

Similar to HashMap, the iteration order is arbitrary and not guaranteed to be stable.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();
map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
    .unwrap();

let mut values: Vec<i32> = map.iter().map(|item| item.value).collect();
values.sort();
assert_eq!(values, vec![42, 99]);
Source

pub fn iter_mut(&mut self) -> IterMut<'_, T, S, A>

Iterates over the items in the map, allowing for mutation.

Similar to HashMap, the iteration order is arbitrary and not guaranteed to be stable.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();
map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
    .unwrap();

for mut item in map.iter_mut() {
    item.value += 10;
}

assert_eq!(map.get1(&1).unwrap().value, 52);
assert_eq!(map.get1(&2).unwrap().value, 109);
Source

pub fn insert_overwrite(&mut self, value: T) -> Vec<T>

Inserts a value into the map, removing any conflicting items and returning a list of those items.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();
map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
    .unwrap();

// Insert an item with conflicting key1
let removed = map.insert_overwrite(Item {
    id: 1,
    name: "baz".to_string(),
    value: 100,
});
assert_eq!(removed.len(), 1);
assert_eq!(removed[0].name, "foo");
assert_eq!(removed[0].value, 42);

assert_eq!(map.len(), 2);
assert_eq!(map.get1(&1).unwrap().name, "baz");
Source

pub fn insert_unique(&mut self, value: T) -> Result<(), DuplicateItem<T, &T>>

Inserts a value into the set, returning an error if any duplicates were added.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();

// Successful insertion
assert!(
    map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
        .is_ok()
);
assert!(
    map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
        .is_ok()
);

// Duplicate key1
assert!(
    map.insert_unique(Item { id: 1, name: "baz".to_string(), value: 100 })
        .is_err()
);

// Duplicate key2
assert!(
    map.insert_unique(Item { id: 3, name: "foo".to_string(), value: 200 })
        .is_err()
);
Source

pub fn contains_key_unique<'a, Q1, Q2>(&'a self, key1: &Q1, key2: &Q2) -> bool
where Q1: Hash + Equivalent<T::K1<'a>> + ?Sized, Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,

Returns true if the map contains a single item that matches both key1 and key2.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 }).unwrap();

assert!(map.contains_key_unique(&1, &"foo"));
assert!(map.contains_key_unique(&2, &"bar"));
assert!(!map.contains_key_unique(&1, &"bar")); // key1 exists but key2 doesn't match
assert!(!map.contains_key_unique(&3, &"baz")); // neither key exists
Source

pub fn get_unique<'a, Q1, Q2>(&'a self, key1: &Q1, key2: &Q2) -> Option<&'a T>
where Q1: Hash + Equivalent<T::K1<'a>> + ?Sized, Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,

Gets a reference to the unique item associated with the given key1 and key2, if it exists.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();
map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 }).unwrap();

assert_eq!(map.get_unique(&1, &"foo").unwrap().value, 42);
assert_eq!(map.get_unique(&2, &"bar").unwrap().value, 99);
assert!(map.get_unique(&1, &"bar").is_none()); // key1 exists but key2 doesn't match
assert!(map.get_unique(&3, &"baz").is_none()); // neither key exists
Source

pub fn get_mut_unique<'a, Q1, Q2>( &'a mut self, key1: &Q1, key2: &Q2, ) -> Option<RefMut<'a, T, S>>
where Q1: Hash + Equivalent<T::K1<'a>> + ?Sized, Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,

Gets a mutable reference to the unique item associated with the given key1 and key2, if it exists.

Source

pub fn remove_unique<'a, Q1, Q2>( &'a mut self, key1: &Q1, key2: &Q2, ) -> Option<T>
where Q1: Hash + Equivalent<T::K1<'a>> + ?Sized, Q2: Hash + Equivalent<T::K2<'a>> + ?Sized,

Removes the item uniquely identified by key1 and key2, if it exists.

Source

pub fn contains_key1<'a, Q>(&'a self, key1: &Q) -> bool
where Q: Hash + Equivalent<T::K1<'a>> + ?Sized,

Returns true if the map contains the given key1.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();
map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
    .unwrap();

assert!(map.contains_key1(&1));
assert!(map.contains_key1(&2));
assert!(!map.contains_key1(&3));
Source

pub fn get1<'a, Q>(&'a self, key1: &Q) -> Option<&'a T>
where Q: Hash + Equivalent<T::K1<'a>> + ?Sized,

Gets a reference to the value associated with the given key1.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();
map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
    .unwrap();

assert_eq!(map.get1(&1).unwrap().value, 42);
assert_eq!(map.get1(&2).unwrap().value, 99);
assert!(map.get1(&3).is_none());
Source

pub fn get1_mut<'a, Q>(&'a mut self, key1: &Q) -> Option<RefMut<'a, T, S>>
where Q: Hash + Equivalent<T::K1<'a>> + ?Sized,

Gets a mutable reference to the value associated with the given key1.

Source

pub fn remove1<'a, Q>(&'a mut self, key1: &Q) -> Option<T>
where Q: Hash + Equivalent<T::K1<'a>> + ?Sized,

Removes an item from the map by its key1.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();
map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
    .unwrap();

let removed = map.remove1(&1);
assert_eq!(removed.unwrap().value, 42);
assert_eq!(map.len(), 1);
assert!(map.get1(&1).is_none());
assert!(map.remove1(&3).is_none());
Source

pub fn contains_key2<'a, Q>(&'a self, key2: &Q) -> bool
where Q: Hash + Equivalent<T::K2<'a>> + ?Sized,

Returns true if the map contains the given key2.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();
map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
    .unwrap();

assert!(map.contains_key2(&"foo"));
assert!(map.contains_key2(&"bar"));
assert!(!map.contains_key2(&"baz"));
Source

pub fn get2<'a, Q>(&'a self, key2: &Q) -> Option<&'a T>
where Q: Hash + Equivalent<T::K2<'a>> + ?Sized,

Gets a reference to the value associated with the given key2.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();
map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
    .unwrap();

assert_eq!(map.get2(&"foo").unwrap().value, 42);
assert_eq!(map.get2(&"bar").unwrap().value, 99);
assert!(map.get2(&"baz").is_none());
Source

pub fn get2_mut<'a, Q>(&'a mut self, key2: &Q) -> Option<RefMut<'a, T, S>>
where Q: Hash + Equivalent<T::K2<'a>> + ?Sized,

Gets a mutable reference to the value associated with the given key2.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();

if let Some(mut item_ref) = map.get2_mut(&"foo") {
    item_ref.value = 100;
}

assert_eq!(map.get2(&"foo").unwrap().value, 100);
Source

pub fn remove2<'a, Q>(&'a mut self, key2: &Q) -> Option<T>
where Q: Hash + Equivalent<T::K2<'a>> + ?Sized,

Removes an item from the map by its key2.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();
map.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
    .unwrap();

let removed = map.remove2(&"foo");
assert_eq!(removed.unwrap().value, 42);
assert_eq!(map.len(), 1);
assert!(map.get2(&"foo").is_none());
assert!(map.remove2(&"baz").is_none());
Source

pub fn entry<'a>( &'a mut self, key1: T::K1<'_>, key2: T::K2<'_>, ) -> Entry<'a, T, S, A>

Retrieves an entry by its keys.

Due to borrow checker limitations, this always accepts owned keys rather than a borrowed form of them.

§Examples
use iddqd::{BiHashItem, BiHashMap, bi_hash_map, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();

// Get existing entry
match map.entry(1, "foo") {
    bi_hash_map::Entry::Occupied(entry) => {
        assert_eq!(entry.get().as_unique().unwrap().value, 42);
    }
    bi_hash_map::Entry::Vacant(_) => panic!("Should be occupied"),
}

// Try to get a non-existing entry
match map.entry(2, "bar") {
    bi_hash_map::Entry::Occupied(_) => panic!("Should be vacant"),
    bi_hash_map::Entry::Vacant(entry) => {
        entry.insert(Item { id: 2, name: "bar".to_string(), value: 99 });
    }
}

assert_eq!(map.len(), 2);

Trait Implementations§

Source§

impl<T: Clone + BiHashItem, S: Clone, A: Clone + Allocator> Clone for BiHashMap<T, S, A>

Source§

fn clone(&self) -> BiHashMap<T, S, A>

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a, T, S, A> Debug for BiHashMap<T, S, A>
where T: BiHashItem + Debug + 'a, T::K1<'a>: Debug, T::K2<'a>: Debug, A: Allocator,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: BiHashItem, S: Default, A: Allocator + Default> Default for BiHashMap<T, S, A>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> Extend<T> for BiHashMap<T, S, A>

The Extend implementation overwrites duplicates. In the future, there will also be an extend_unique method that will return an error.

§Examples

use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map = BiHashMap::new();
map.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 }).unwrap();

let new_items = vec![
    Item { id: 2, name: "bar".to_string(), value: 99 },
    Item { id: 1, name: "baz".to_string(), value: 100 }, // overwrites existing
];

map.extend(new_items);
assert_eq!(map.len(), 2);
assert_eq!(map.get1(&1).unwrap().name, "baz"); // overwritten
assert_eq!(map.get1(&1).unwrap().value, 100);
Source§

fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)

Extends a collection with the contents of an iterator. Read more
Source§

fn extend_one(&mut self, item: A)

🔬This is a nightly-only experimental API. (extend_one)
Extends a collection with exactly one element.
Source§

fn extend_reserve(&mut self, additional: usize)

🔬This is a nightly-only experimental API. (extend_one)
Reserves capacity in a collection for the given number of additional elements. Read more
Source§

impl<T: BiHashItem, S: Clone + BuildHasher + Default, A: Default + Allocator> FromIterator<T> for BiHashMap<T, S, A>

The FromIterator implementation for BiHashMap overwrites duplicate items.

§Examples

use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let items = vec![
    Item { id: 1, name: "foo".to_string(), value: 42 },
    Item { id: 2, name: "bar".to_string(), value: 99 },
    Item { id: 1, name: "baz".to_string(), value: 100 }, // overwrites first item
];

let map: BiHashMap<Item> = items.into_iter().collect();
assert_eq!(map.len(), 2);
assert_eq!(map.get1(&1).unwrap().name, "baz"); // overwritten
assert_eq!(map.get1(&1).unwrap().value, 100);
assert_eq!(map.get1(&2).unwrap().value, 99);
Source§

fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self

Creates a value from an iterator. Read more
Source§

impl<'a, T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator for &'a BiHashMap<T, S, A>

Source§

type Item = &'a T

The type of the elements being iterated over.
Source§

type IntoIter = Iter<'a, T>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<'a, T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator for &'a mut BiHashMap<T, S, A>

Source§

type Item = RefMut<'a, T, S>

The type of the elements being iterated over.
Source§

type IntoIter = IterMut<'a, T, S, A>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<T: BiHashItem, S: Clone + BuildHasher, A: Allocator> IntoIterator for BiHashMap<T, S, A>

Source§

type Item = T

The type of the elements being iterated over.
Source§

type IntoIter = IntoIter<T, A>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<T: BiHashItem + PartialEq, S: Clone + BuildHasher, A: Allocator> PartialEq for BiHashMap<T, S, A>

The PartialEq implementation for BiHashMap checks that both maps have the same items, regardless of insertion order.

§Examples

use iddqd::{BiHashItem, BiHashMap, bi_upcast};

#[derive(Debug, PartialEq, Eq)]
struct Item {
    id: u32,
    name: String,
    value: i32,
}

impl BiHashItem for Item {
    type K1<'a> = u32;
    type K2<'a> = &'a str;

    fn key1(&self) -> Self::K1<'_> {
        self.id
    }
    fn key2(&self) -> Self::K2<'_> {
        &self.name
    }
    bi_upcast!();
}

let mut map1 = BiHashMap::new();
map1.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();
map1.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
    .unwrap();

let mut map2 = BiHashMap::new();
map2.insert_unique(Item { id: 2, name: "bar".to_string(), value: 99 })
    .unwrap();
map2.insert_unique(Item { id: 1, name: "foo".to_string(), value: 42 })
    .unwrap();

// Maps are equal even if items were inserted in different order
assert_eq!(map1, map2);

map2.insert_unique(Item { id: 3, name: "baz".to_string(), value: 200 })
    .unwrap();
assert_ne!(map1, map2);
Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<T: BiHashItem + Eq, S: Clone + BuildHasher, A: Allocator> Eq for BiHashMap<T, S, A>

Auto Trait Implementations§

§

impl<T, S, A> Freeze for BiHashMap<T, S, A>
where S: Freeze, A: Freeze,

§

impl<T, S, A> RefUnwindSafe for BiHashMap<T, S, A>

§

impl<T, S, A> Send for BiHashMap<T, S, A>
where S: Send, T: Send, A: Send,

§

impl<T, S, A> Sync for BiHashMap<T, S, A>
where S: Sync, T: Sync, A: Sync,

§

impl<T, S, A> Unpin for BiHashMap<T, S, A>
where S: Unpin, A: Unpin, T: Unpin,

§

impl<T, S, A> UnwindSafe for BiHashMap<T, S, A>
where S: UnwindSafe, A: UnwindSafe, T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.