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}