string_table/
structure.rs

1use nohash_hasher::NoHashHasher;
2use std::{collections::HashMap, hash::BuildHasherDefault};
3
4use crate::hash::string_hash;
5
6#[derive(Clone)]
7#[repr(transparent)]
8/// A HashMap for Strings implemented with a special hashing algorithm.
9/// See: https://doc.rust-lang.org/std/collections/struct.HashMap.html
10pub struct StringTable<T> {
11    inner: HashMap<u32, T, BuildHasherDefault<NoHashHasher<u32>>>,
12}
13
14impl<T> StringTable<T> {
15    /// Creates an empty `StringTable`.
16    /// 
17    /// The table is initially created with a capacity of zero, so it will not initialize with any items.
18    /// 
19    /// # Example
20    /// ```rust
21    /// # use string_table::prelude::*;
22    /// let table: StringTable<i32> = StringTable::new();
23    /// ```
24    pub fn new() -> Self {
25        StringTable {
26            inner: HashMap::with_hasher(BuildHasherDefault::default()),
27        }
28    }
29
30    /// Creates an empty `StringTable` with a specified capacity.
31    /// 
32    /// However, it will not initialize with any items.
33    /// 
34    /// # Example
35    /// ```rust
36    /// # use string_table::prelude::*;
37    /// let table: StringTable<i32> = StringTable::with_capacity(20);
38    /// ```
39    pub fn with_capacity(capacity: usize) -> Self {
40        StringTable {
41            inner: HashMap::with_capacity_and_hasher(capacity, BuildHasherDefault::default()),
42        }
43    }
44
45    /// Inserts a key-value pair into the table.
46    /// 
47    /// # Example
48    /// ```rust
49    /// # use string_table::prelude::*;
50    /// let mut table: StringTable<i32> = StringTable::with_capacity(20);
51    /// table.insert("five", 5);
52    /// table.insert("ten", 10);
53    /// ```
54    pub fn insert(&mut self, key: &str, value: T) {
55        self.inner.insert(string_hash(key), value);
56    }
57
58    /// Gets a key-value pair from the table.
59    /// 
60    /// # Example
61    /// ```rust
62    /// # use string_table::prelude::*;
63    /// let mut table: StringTable<i32> = StringTable::with_capacity(1);
64    /// table.insert("five", 5);
65    /// assert!(table.get("five") == Some(&5))
66    /// ```
67    pub fn get(&mut self, key: &str) -> Option<&T> {
68        self.inner.get(&string_hash(key))
69    }
70
71    /// Gets a mutable reference to a key-value pair in the table.
72    /// 
73    /// # Example
74    /// ```rust
75    /// # use string_table::prelude::*;
76    /// let mut table: StringTable<i32> = StringTable::new();
77    /// table.insert("five", 5);
78    /// assert!(table.get_mut("five") == Some(&mut 5))
79    /// ```
80    pub fn get_mut(&mut self, key: &str) -> Option<&mut T> {
81        self.inner.get_mut(&string_hash(key))
82    }
83
84    /// Gets a key-value pair from the table, without checking if it exists or not.
85    /// 
86    /// For a safe alternative, see `StringTable::get`.
87    /// 
88    /// # Safety
89    /// Invoking this function with a key that doesn't exist is undefined behavior.
90    /// 
91    /// # Example
92    /// ```rust
93    /// # use string_table::prelude::*;
94    /// let mut table: StringTable<i32> = StringTable::new();
95    /// table.insert("my_string", 10);
96    /// unsafe {
97    ///     assert!(table.get_unchecked("my_string") == &10);
98    /// }
99    /// ```
100    pub unsafe fn get_unchecked(&mut self, key: &str) -> &T {
101        self.inner.get(&string_hash(key)).unwrap_unchecked()
102    }
103}