diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md index 50fe6d64..67f51ea7 100644 --- a/docs/book/src/SUMMARY.md +++ b/docs/book/src/SUMMARY.md @@ -18,3 +18,4 @@ - [Big Integers Library](./bigint/index.md) - [Queue Library](./queue/index.md) - [Upgradability](./upgradability/index.md) +- [Hash Map](./hash_map/index.md) diff --git a/docs/book/src/hash_map/index.md b/docs/book/src/hash_map/index.md new file mode 100644 index 00000000..277a7f6b --- /dev/null +++ b/docs/book/src/hash_map/index.md @@ -0,0 +1,183 @@ +# HashMap Library + +A heap-allocated hash map implementation for the Sway language. This data structure exists only in memory during contract execution and does not persist to storage. It's primarily used in predicates (where storage is unavailable) but can also be used for temporary data storage in smart contracts. + +## Key Characteristics + +- **Heap-allocated**: All data exists only in memory during execution +- **Non-persistent**: Data is not saved to storage between transactions +- **Collision handling**: Uses linear probing with hash randomization +- **Auto-resizing**: Capacity doubles when full (starting from 1) +- **Generic**: Supports any types implementing `Eq + Hash` traits + +## When to Use + +✅ **Ideal for**: + +- Predicates (where storage is unavailable) +- Intermediate calculations in contracts +- Temporary data aggregation +- Caching frequently accessed computation results +- State machines during contract execution + +❌ **Not suitable for**: + +- Persistent data storage (use `StorageMap` instead) +- Large datasets exceeding block memory limits +- Long-term state management + +## Performance Note + +⚠️ Always use `with_capacity` when possible to pre-allocate memory. Reallocation during growth is expensive and involves repopulating the entire map. + +## Methods + +### `new() -> Self` + +Creates an empty `HashMap` with capacity 0. + +- Use Case: When the maximum size is unknown. For known sizes, with_capacity() is always preferred. +- Allocation Cost: Initial zero-allocation. First insertion triggers resize to capacity 1. + +```sway +{{#include ../../../../examples/hash_map/src/main.sw:new}} +``` + +### `with_capacity(capacity: u16) -> Self` + +Returns a new instance of a `HashMap` with a pre-allocated capacity to hold elements. This is the recommended function to use when creating a new `HashMap`. + +```sway +{{#include ../../../../examples/hash_map/src/main.sw:with_capacity}} +``` + +### `insert(&mut self, key: K, val: V) -> Option` + +Inserts a key-value pair. If the map did not have this key present, `None` is returned. Otherwise `Some(V)`. + +```sway +{{#include ../../../../examples/hash_map/src/main.sw:insert}} +``` + +### `try_insert(&mut self, key: K, val: V) -> Result>` + +Tries to insert a key-value pair into the map, and returns the value in the entry. If the map already had this key present, nothing is updated, and an error containing the occupied entry and the value is returned. + +```sway +{{#include ../../../../examples/hash_map/src/main.sw:try_insert}} +``` + +### `remove(&mut self, key: K) -> Option` + +Removes a key-value pair. Returns the value at the key if the key was previously in the map. + +```sway +{{#include ../../../../examples/hash_map/src/main.sw:remove}} +``` + +### `get(&self, key: K) -> Option` + +Returns the value associated with the key or `None`. + +```sway +{{#include ../../../../examples/hash_map/src/main.sw:get}} +``` + +### `contains_key(&self, key: K) -> bool` + +Checks if key exists in map. + +```sway +{{#include ../../../../examples/hash_map/src/main.sw:contains_key}} +``` + +### `keys(&self) -> Vec` + +Returns the list of keys present in the `HashMap`. The list return is unordered and is not guaranteed to be in the order inserted into the `HashMap`. + +```sway +{{#include ../../../../examples/hash_map/src/main.sw:keys}} +``` + +### `values(&self) -> Vec` + +Returns the list of values present in the `HashMap`. The list return is unordered and is not guaranteed to be in the order inserted into the `HashMap`. + +```sway +{{#include ../../../../examples/hash_map/src/main.sw:values}} +``` + +### `len(&self) -> u16` + +Returns number of elements. + +```sway +{{#include ../../../../examples/hash_map/src/main.sw:len}} +``` + +### `capacity(&self) -> u16` + +Returns current capacity. + +```sway +{{#include ../../../../examples/hash_map/src/main.sw:capacity}} +``` + +### `is_empty(&self) -> bool` + +Checks if map has no elements. + +```sway +{{#include ../../../../examples/hash_map/src/main.sw:is_empty}} +``` + +### `iter(&self) -> HashMapIter` + +Returns an iterator over key-value pairs. + +```sway +{{#include ../../../../examples/hash_map/src/main.sw:iter}} +``` + +## Iterators + +### `HashMapIter` + +Iterator over key-value pairs. + +```sway +{{#include ../../../../examples/hash_map/src/main.sw:for}} +``` + +## Error Types + +### `HashMapError` + +Error variants for hash map operations. + +#### Variants + +`OccupiedError(V)`: Returned by try_insert when key exists (contains existing value) + +## Memory Layout + +The map uses three contiguous memory regions: + +1. Keys: Array of keys +2. Values: Array of values +3. Indexes: Status array tracking + +Collisions are resolved using linear probing. + +## Limitations + +- Maximum capacity: `u16::MAX` (65,535 elements) +- No persistent storage +- Keys/values must implement Eq + Hash + +## Best Practices + +- Always use `with_capacity()` for known sizes +- Prefer `try_insert()` when checking for existing keys +- Use `iter()` for efficient traversal +- Avoid storing large datasets (heap memory constrained) diff --git a/docs/book/src/index.md b/docs/book/src/index.md index a2148cf5..4ba5fa4a 100644 --- a/docs/book/src/index.md +++ b/docs/book/src/index.md @@ -62,6 +62,10 @@ The [Big Integers](./bigint/index.md) Library is an interface to implement extre Data Structure Libraries are libraries which provide complex data structures which unlock additional functionality for Smart Contracts. +### [HashMap](./hash_map/index.md) + +The [HashMap](./hash_map/index.md) Library is a heap-allocated hash map implementation for the Sway language. + ### [Queue](./queue/index.md) The [Queue](./queue/index.md) Library is a linear data structure that provides First-In-First-Out (FIFO) operations. diff --git a/examples/Forc.lock b/examples/Forc.lock index 675fcad2..eb92936c 100644 --- a/examples/Forc.lock +++ b/examples/Forc.lock @@ -42,6 +42,19 @@ dependencies = [ "std", ] +[[package]] +name = "hash_map" +source = "path+from-root-D47FAF0E076933BB" +dependencies = ["std"] + +[[package]] +name = "hash_map_examples" +source = "member" +dependencies = [ + "hash_map", + "std", +] + [[package]] name = "merkle" source = "path+from-root-4197A95CF859C933" @@ -165,7 +178,8 @@ dependencies = [ [[package]] name = "std" -source = "git+https://github.com/fuellabs/sway?tag=v0.68.5#512bbfccdb15a0045576604ba97d7943c9b7520f" +version = "0.68.7" +source = "registry+std?0.68.7#QmXtvuy4DJqoVfTmMSygtwh5Zx9JvWsKfx2p83pXEGnZrC!" [[package]] name = "sway_libs" diff --git a/examples/Forc.toml b/examples/Forc.toml index 4b47a82b..29fd9859 100644 --- a/examples/Forc.toml +++ b/examples/Forc.toml @@ -14,4 +14,5 @@ members = [ "./signed_integers", "./big_integers", "./upgradability", + "./hash_map", ] diff --git a/examples/hash_map/Forc.toml b/examples/hash_map/Forc.toml new file mode 100644 index 00000000..20e1ff4c --- /dev/null +++ b/examples/hash_map/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "hash_map_examples" + +[dependencies] +hash_map = { path = "../../libs/hash_map" } diff --git a/examples/hash_map/src/main.sw b/examples/hash_map/src/main.sw new file mode 100644 index 00000000..ee44c4fe --- /dev/null +++ b/examples/hash_map/src/main.sw @@ -0,0 +1,156 @@ +library; + +use hash_map::*; + +fn new() { + // ANCHOR: new + let map: HashMap = HashMap::new(); + // ANCHOR_END: new +} + +fn with_capacity() { + // ANCHOR: with_capacity + let map: HashMap = HashMap::with_capacity(100); + // ANCHOR_END: with_capacity +} + +fn insert() { + let mut map: HashMap = HashMap::new(); + // ANCHOR: insert + // New insertion + let res = map.insert(1, 10); + assert(res.is_none()); + + // Updates + let res = map.insert(1, 20); + assert(res == Some(10)); + // ANCHOR_END: insert +} + +fn try_insert() { + let mut map: HashMap = HashMap::new(); + // ANCHOR: try_insert + // New insertion + let res = map.try_insert(1, 10); + assert(res.is_ok()); + + // Update + let res = map.try_insert(1, 20); + assert(res == Err(HashMapError::OccupiedError(10))); + // ANCHOR_END: try_insert +} + +fn remove() { + let mut map: HashMap = HashMap::new(); + + // ANCHOR: remove + map.insert(1, 10); + + let res = map.remove(1); + assert(res == Some(10)); + + let res = map.remove(1); + assert(res.is_none()); + // ANCHOR_END: remove +} + +fn get() { + let mut map: HashMap = HashMap::new(); + + // ANCHOR: get + map.insert(1, 10); + + let res = map.get(1); + assert(res == Some(10)); + + let res = map.get(2); + assert(res.is_none()); + // ANCHOR_END: get +} + +fn contains_key() { + let mut map: HashMap = HashMap::new(); + + // ANCHOR: contains_key + map.insert(1, 10); + + assert(map.contains_key(1)); + assert(!map.contains_key(2)); + // ANCHOR_END: contains_key +} + +fn keys() { + let mut map: HashMap = HashMap::new(); + + // ANCHOR: keys + map.insert(1, 10); + map.insert(2, 20); + + let keys: Vec = map.keys(); + assert(keys.len() == 2); + // ANCHOR_END: keys +} + +fn values() { + let mut map: HashMap = HashMap::new(); + + // ANCHOR: values + map.insert(1, 10); + map.insert(2, 20); + map.insert(3, 30); + + let values: Vec = map.values(); + assert(values.len() == 3); + // ANCHOR_END: values +} + +fn len() { + let mut map: HashMap = HashMap::new(); + + // ANCHOR: len + assert(map.len() == 0); + + map.insert(1, 10); + assert(map.len() == 1); + // ANCHOR_END: len +} + +fn capacity() { + // ANCHOR: capacity + let map: HashMap = HashMap::with_capacity(10); + assert(map.capacity() == 10); + // ANCHOR_END: capacity +} + +fn is_empty() { + let mut map: HashMap = HashMap::new(); + + // ANCHOR: is_empty + assert(map.is_empty()); + + map.insert(1, 10); + assert(!map.is_empty()); + // ANCHOR_END: is_empty +} + +fn iter() { + let mut map: HashMap = HashMap::new(); + + // ANCHOR: iter + map.insert(1, 10); + + let mut iter = map.iter(); + assert(iter.next() == Some((1, 10))); + assert(iter.next().is_none()); + // ANCHOR_END: iter +} + +fn for_loop() { + let mut map: HashMap = HashMap::new(); + + // ANCHOR: for + for (key, value) in map.iter() { + // Process pairs + } + // ANCHOR_END: for +} diff --git a/libs/hash_map/Forc.lock b/libs/hash_map/Forc.lock new file mode 100644 index 00000000..83dd9c07 --- /dev/null +++ b/libs/hash_map/Forc.lock @@ -0,0 +1,9 @@ +[[package]] +name = "hash_map" +source = "member" +dependencies = ["std"] + +[[package]] +name = "std" +version = "0.68.7" +source = "registry+std?0.68.7#QmXtvuy4DJqoVfTmMSygtwh5Zx9JvWsKfx2p83pXEGnZrC!" diff --git a/libs/hash_map/Forc.toml b/libs/hash_map/Forc.toml new file mode 100644 index 00000000..23612bdc --- /dev/null +++ b/libs/hash_map/Forc.toml @@ -0,0 +1,15 @@ +[project] +authors = ["Fuel Labs "] +entry = "hash_map.sw" +license = "Apache-2.0" +name = "hash_map" +version = "0.26.0" +description = "The Hash Map Library provides ." +homepage = "https://github.com/FuelLabs/sway-libs" +repository = "https://github.com/FuelLabs/sway-libs" +documentation = "https://github.com/FuelLabs/sway-libs" +organization = "FuelLabs" +categories = ["Data Structures", "Data Processing"] +keywords = ["library"] + +[dependencies] diff --git a/libs/hash_map/src/hash_map.sw b/libs/hash_map/src/hash_map.sw new file mode 100644 index 00000000..47f8d485 --- /dev/null +++ b/libs/hash_map/src/hash_map.sw @@ -0,0 +1,886 @@ +library; + +use std::{ + alloc::alloc, + hash::*, + iterator::Iterator, +}; + +pub enum HashMapError { + OccupiedError: V, +} + +impl PartialEq for HashMapError +where + V: PartialEq, +{ + fn eq(self, other: Self) -> bool { + match (self, other) { + (Self::OccupiedError(val_1), Self::OccupiedError(val_2)) => { + val_1 == val_2 + } + } + } +} + +impl Eq for HashMapError +where + V: Eq, +{} + +pub struct HashMap { + cap: u16, + len: u16, + values: raw_ptr, + keys: raw_ptr, + indexes: raw_ptr, +} + +impl HashMap +where + K: Eq, + K: Hash, +{ + // Internal use: Reads the key K at a given index + fn read_key(self, computed_index: u64) -> K { + if __is_reference_type::() { + asm(ptr: self.keys, offset: __size_of::() * computed_index, new) { + add new ptr offset; + new: K + } + } else if __size_of::() == 1 { + asm(ptr: self.keys, offset: computed_index, new, val) { + add new ptr offset; + lb val new i0; + val: K + } + } else { + asm(ptr: self.keys, offset: __size_of::() * computed_index, new, val) { + add new ptr offset; + lw val new i0; + val: K + } + } + } + + // Internal use: Writes a key K at a given index + fn write_key(ref mut self, computed_index: u64, key: K) { + if __is_reference_type::() { + asm( + ptr: self.keys, + val: key, + offset: __size_of::() * computed_index, + size: __size_of::(), + new, + ) { + add new ptr offset; + mcp new val size; + }; + } else if __size_of::() == 1 { + asm( + ptr: self.keys, + val: key, + offset: computed_index, + new, + ) { + add new ptr offset; + sb new val i0; + }; + } else { + asm( + ptr: self.keys, + val: key, + offset: __size_of::() * computed_index, + new, + ) { + add new ptr offset; + sw new val i0; + }; + } + } + + // Internal use: Reads the value V at a given index + fn read_value(self, computed_index: u64) -> V { + if __is_reference_type::() { + asm(ptr: self.values, offset: __size_of::() * computed_index, new) { + add new ptr offset; + new: V + } + } else if __size_of::() == 1 { + asm(ptr: self.values, offset: computed_index, new, val) { + add new ptr offset; + lb val new i0; + val: V + } + } else { + asm(ptr: self.values, offset: __size_of::() * computed_index, new, val) { + add new ptr offset; + lw val new i0; + val: V + } + } + } + + // Internal use: Writes a value V at a given index + fn write_value(ref mut self, computed_index: u64, val: V) { + if __is_reference_type::() { + asm( + ptr: self.values, + val: val, + offset: __size_of::() * computed_index, + size: __size_of::(), + new, + ) { + add new ptr offset; + mcp new val size; + }; + } else if __size_of::() == 1 { + asm( + ptr: self.values, + val: val, + offset: computed_index, + new, + ) { + add new ptr offset; + sb new val i0; + }; + } else { + asm( + ptr: self.values, + val: val, + offset: __size_of::() * computed_index, + new, + ) { + add new ptr offset; + sw new val i0; + }; + } + } + + // Internal use: Computes a hash for a given key. + fn get_hash(self, key: K) -> u64 { + let hash = sha256(key); + let (r0, r1, r2, r3) = asm(ptr: __addr_of(hash)) { + ptr: (u64, u64, u64, u64) + }; + let result = r0 ^ r1 ^ r2 ^ r3; + result + } + + // Internal use: Returns the key found at a given index and whether the index had been used before + fn key_at_index(self, computed_index: u64) -> (Option, bool) { + let value_set = asm(ptr: self.indexes, offset: computed_index, new, val) { + add new ptr offset; + lb val new i0; + val: u8 + }; + + match value_set { + 0u8 => (None, true), + 1u8 => (Some(self.read_key(computed_index)), false), + _ => (None, false), + } + } + + // Internal use: Returns a computed index and a bool as to whether the key is present. Will skip over free indexes if a value has been removed. + fn compute_index(self, key: K, skip_removed_indexes: bool) -> Option<(u64, bool)> { + let mut salt = 0; + let capacity = asm(val: self.cap) { + val: u64 + }; + if capacity == 0 { + return None; + } + + let mut computed_index = self.get_hash(key) % capacity; + let (mut key_at_index, mut index_free) = self.key_at_index(computed_index); + // Collision handling + while key_at_index != Some(key) { + salt += 1; + + if salt > capacity { + return None + } else if skip_removed_indexes && key_at_index == None && index_free { + return Some((computed_index, false)); + } else if !skip_removed_indexes && key_at_index == None { + return Some((computed_index, false)); + } + computed_index = (self.get_hash(key) + salt) % capacity; + let result = self.key_at_index(computed_index); + key_at_index = result.0; + index_free = result.1; + } + + Some((computed_index, true)) + } + + // Internal use: Grows the HashMap in size + fn grow(ref mut self) { + let old_capacity = asm(val: self.cap) { + val: u64 + }; + let old_values = self.values; + let old_keys = self.keys; + let old_indexes = self.indexes; + + let new_capacity = if old_capacity == 0 { + 1 + } else { + old_capacity * 2 + }; + + self.cap = asm(val: new_capacity) { + val: u16 + }; + self.keys = asm(size: __size_of::() * new_capacity, ptr) { + aloc size; + move ptr hp; + ptr: raw_ptr + }; + self.values = asm(size: __size_of::() * new_capacity, ptr) { + aloc size; + move ptr hp; + ptr: raw_ptr + }; + self.indexes = asm(size: new_capacity, ptr) { + aloc size; + move ptr hp; + ptr: raw_ptr + }; + + // Re-insert to fit new size + let mut iter = 0; + while iter < old_capacity { + if 0u8 == asm(ptr: old_indexes, offset: iter, new, val) { + add new ptr offset; + lb val new i0; + val: u8 + } { + iter += 1; + continue; + } + + let key = if __is_reference_type::() { + asm(ptr: old_keys, offset: __size_of::() * iter, new) { + add new ptr offset; + new: K + } + } else if __size_of::() == 1 { + asm(ptr: old_keys, offset: iter, new, val) { + add new ptr offset; + lb val new i0; + val: K + } + } else { + asm(ptr: old_keys, offset: __size_of::() * iter, new, val) { + add new ptr offset; + lw val new i0; + val: K + } + }; + + let value = if __is_reference_type::() { + asm(ptr: old_values, offset: __size_of::() * iter, new) { + add new ptr offset; + new: V + } + } else if __size_of::() == 1 { + asm(ptr: old_values, offset: iter, new, val) { + add new ptr offset; + lb val new i0; + val: V + } + } else { + asm(ptr: old_values, offset: __size_of::() * iter, new, val) { + add new ptr offset; + lw val new i0; + val: V + } + }; + + let (computed_index, result) = self.compute_index(key, false).unwrap(); + match result { + true => { + self.write_value(computed_index, value); + }, + false => { + self.write_key(computed_index, key); + self.write_value(computed_index, value); + asm(ptr: self.indexes, val: 1u8, offset: computed_index, new) { + add new ptr offset; + sb new val i0; + }; + }, + } + + iter += 1; + } + } + + // Internal use: Returns whether and index is set + fn is_index_set(self, index: u64) -> bool { + 0u8 != asm(ptr: self.indexes, offset: index, new, val) { + add new ptr offset; + lb val new i0; + val: u8 + } + } + + /// Returns a new instance of a `HashMap`. + /// + /// # Additional Information + /// + /// It is recommended to use the `with_capacity()` function to reduce execution costs while filling the map. + /// + /// # Returns + /// + /// * [HashMap] - A newly instantiated `HashMap`. + /// + /// # Examples + /// + /// ```sway + /// use hash_map::*; + /// + /// fn foo() { + /// let my_map: HashMap = HashMap::new(); + /// assert(my_map.is_empty()); + /// assert(my_map.capacity() == 100); + /// } + /// ``` + pub fn new() -> Self { + Self { + cap: 0, + len: 0, + keys: alloc::(0), + values: alloc::(0), + indexes: alloc::(0), + } + } + + /// Returns a new instance of a `HashMap` with a pre-allocated capacity to hold elements. + /// + /// # Additional Information + /// + /// This is the recommended function to use when creating a new `HashMap`. + /// + /// # Arguments + /// + /// * `capacity`: [u16] - The number of elements the `HashMap` should hold. + /// + /// # Returns + /// + /// * [HashMap] - A newly instantiated `HashMap`. + /// + /// # Examples + /// + /// ```sway + /// use hash_map::*; + /// + /// fn foo() { + /// let my_map: HashMap = HashMap::with_capacity(100); + /// assert(my_map.is_empty()); + /// assert(my_map.capacity() == 100); + /// } + /// ``` + pub fn with_capacity(capacity: u16) -> Self { + let cap = asm(val: capacity) { + val: u64 + }; + Self { + cap: capacity, + len: 0, + keys: asm(size: __size_of::() * cap, ptr) { + aloc size; + move ptr hp; + ptr: raw_ptr + }, + values: asm(size: __size_of::() * cap, ptr) { + aloc size; + move ptr hp; + ptr: raw_ptr + }, + indexes: asm(size: cap, ptr) { + aloc size; + move ptr hp; + ptr: raw_ptr + }, + } + } + + /// Inserts a key-value pair into the `HashMap`. + /// + /// # Arguments + /// + /// * `key`: [K] - The key of the key-value pair. + /// * `val`: [V] - The value of the key-value pair. + /// + /// # Returns + /// + /// * [Option] - If the map did not have this key present, `None` is returned. Otherwise `Some(V)`. + /// + /// # Examples + /// + /// ```sway + /// use hash_map::*; + /// + /// fn foo() { + /// let mut my_map: HashMap = HashMap::new(); + /// assert(my_map.insert(1, 2).is_none()); + /// assert(my_map.insert(1, 3) == Some(2)); + /// } + /// ``` + pub fn insert(ref mut self, key: K, val: V) -> Option { + let (computed_index, result) = match self.compute_index(key, false) { + Some(computed) => (computed.0, computed.1), + None => { + self.grow(); + self.compute_index(key, false).unwrap() + } + }; + + match result { + true => { + let old_val = self.read_value(computed_index); + self.write_value(computed_index, val); + + return Some(old_val); + }, + false => { + self.write_key(computed_index, key); + self.write_value(computed_index, val); + asm(ptr: self.indexes, val: 1u8, offset: computed_index, new) { + add new ptr offset; + sb new val i0; + }; + self.len += 1; + + return None; + }, + } + } + + /// Tries to insert a key-value pair into the map, and returns the value in the entry. + /// + /// # Arguments + /// + /// * `key`: [K] - The key of the key-value pair. + /// * `val`: [V] - The value of the key-value pair. + /// + /// # Returns + /// + /// * [Result>] - If the map already had this key present, nothing is updated, and an error containing the occupied entry and the value is returned. + /// + /// # Examples + /// + /// ```sway + /// use hash_map::*; + /// + /// fn foo() { + /// let mut my_map: HashMap = HashMap::new(); + /// assert(my_map.try_insert(1, 2).is_ok()); + /// assert(my_map.insert(1, 3) == Err(HashMapError::OccupiedError(2))); + /// } + /// ``` + pub fn try_insert(ref mut self, key: K, val: V) -> Result> { + let (computed_index, result) = match self.compute_index(key, false) { + Some(computed) => (computed.0, computed.1), + None => { + self.grow(); + self.compute_index(key, false).unwrap() + } + }; + + match result { + true => { + let existing_val = self.read_value(computed_index); + return Err(HashMapError::OccupiedError(existing_val)); + }, + false => { + self.write_key(computed_index, key); + self.write_value(computed_index, val); + asm(ptr: self.indexes, val: 1u8, offset: computed_index, new) { + add new ptr offset; + sb new val i0; + }; + self.len += 1; + + return Ok(val); + }, + } + } + + /// Removes an key-value pair from the `HashMap`. + /// + /// # Arguments + /// + /// * `key`: [K] - The key of the key-value pair. + /// + /// # Returns + /// + /// * [Option] - The value at the key if the key was previously in the map. + /// + /// # Examples + /// + /// ```sway + /// use hash_map::*; + /// + /// fn foo() { + /// let mut my_map: HashMap = HashMap::new(); + /// let _ = my_map.insert(1, 2); + /// assert(my_map.remove(1) == Some(2)); + /// assert(my_map.remove(1) == None); + /// } + /// ``` + pub fn remove(ref mut self, key: K) -> Option { + match self.compute_index(key, true) { + Some(computed) => { + match computed.1 { + true => { + asm(ptr: self.indexes, val: 2u8, offset: computed.0, new) { + add new ptr offset; + sb new val i0; + }; + self.len -= 1; + + Some(self.values.add::(computed.0).read::()) + }, + false => None, + } + }, + None => None, + } + } + + /// Returns a value from the map given a key. + /// + /// # Arguments + /// + /// * `key`: [K] - The key of the key-value pair. + /// + /// # Returns + /// + /// * [Option] - The value associated with the key or `None`. + /// + /// # Examples + /// + /// ```sway + /// use hash_map::*; + /// + /// fn foo () { + /// let mut my_map: HashMap = HashMap::new(); + /// let _ = my_map.insert(1, 2); + /// assert(my_map.get(1) == Some(2)); + /// assert(my_map.get(3) == None); + /// } + /// ``` + pub fn get(self, key: K) -> Option { + match self.compute_index(key, true) { + Some(computed) => { + match computed.1 { + true => Some(self.read_value(computed.0)), + false => None, + } + }, + None => None, + } + } + + /// Returns whether a key is present in the `HashMap`. + /// + /// # Arguments + /// + /// * `key`: [K] - The key of the key-value pair. + /// + /// # Returns + /// + /// * [bool] - `true` if the key is present, otherwise `false`. + /// + /// # Examples + /// + /// ```sway + /// use hash_map::*; + /// + /// fn foo() { + /// let mut my_map = HashMap::new(); + /// let _ = my_map.insert(1, 2); + /// assert(my_map.contains_key(1)); + /// assert(!my_map.contains_key(3)); + /// } + /// ``` + pub fn contains_key(self, key: K) -> bool { + match self.compute_index(key, true) { + Some(computed) => computed.1, + None => false, + } + } + + /// Returns the list of keys present in the `HashMap`. + /// + /// # Additional Information + /// + /// The list return is unordered and is not guaranteed to be in the order inserted into the `HashMap`. + /// + /// # Returns + /// + /// * [Vec] - The list of keys present in the `HashMap`. + /// + /// # Examples + /// + /// ```sway + /// use hash_map::*; + /// + /// fn foo() { + /// let mut my_map: HashMap = HashMap::new(); + /// assert(my_map.keys().len() == 0); + /// let _ = my_map.insert(1, 2); + /// let _ = my_map.insert(2, 3); + /// let keys = my_map.keys(); + /// assert(keys.len() == 2); + /// } + /// ``` + pub fn keys(self) -> Vec { + let mut result_vec = Vec::with_capacity(asm(val: self.len) { val: u64 }); + let mut iter = 0; + while iter < asm(val: self.cap) { val: u64 } { + if 1u8 != asm(ptr: self.indexes, offset: iter, new, val) { + add new ptr offset; + lb val new i0; + val: u8 + } { + iter += 1; + continue; + } + + result_vec.push(self.read_key(iter)); + iter += 1; + } + + result_vec + } + + /// Returns the list of values present in the `HashMap`. + /// + /// # Additional Information + /// + /// The list return is unordered and is not guaranteed to be in the order inserted into the `HashMap`. + /// + /// # Returns + /// + /// * [Vec] - The list of values present in the `HashMap`. + /// + /// # Examples + /// + /// ```sway + /// use hash_map::*; + /// + /// fn foo() { + /// let mut my_map: HashMap = HashMap::new(); + /// assert(my_map.values().len() == 0); + /// let _ = my_map.insert(1, 2); + /// let _ = my_map.insert(2, 3); + /// let values = my_map.values(); + /// assert(values.len() == 2); + /// } + /// ``` + pub fn values(self) -> Vec { + let mut result_vec = Vec::with_capacity(asm(val: self.len) { val: u64 }); + let mut iter = 0; + while iter < asm(val: self.cap) { val: u64 } { + if 1u8 != asm(ptr: self.indexes, offset: iter, new, val) { + add new ptr offset; + lb val new i0; + val: u8 + } { + iter += 1; + continue; + } + + result_vec.push(self.read_value(iter)); + iter += 1; + } + + result_vec + } + + /// Returns the number of elements in the `HashMap`. + /// + /// # Returns + /// + /// * [u16] - The number of elements. + /// + /// # Examples + /// + /// ```sway + /// use hash_map::*; + /// + /// fn foo() { + /// let mut map_map: HashMap = HashMap::new(); + /// assert(my_map.len() == 0); + /// let _ = my_map.insert(1, 2); + /// let _ = my_map.insert(2, 3); + /// assert(my_map.len() == 2); + /// } + /// ``` + pub fn len(self) -> u16 { + self.len + } + + /// Returns the number of elements the `HashMap` can hold. + /// + /// # Additional Information + /// + /// The capacity is always doubled when space runs out. + /// + /// # Returns + /// + /// * [u16] - The number of elements the `HashMap` can hold. + /// + /// # Examples + /// + /// ```sway + /// use hash_map::*; + /// + /// fn foo() { + /// let mut map_map: HashMap = HashMap::new(); + /// assert(my_map.capacity() == 0); + /// let _ = my_map.insert(1, 2); + /// let _ = my_map.insert(2, 3); + /// let _ = my_map.insert(3, 4); + /// assert(my_map.capacity() == 4); + /// } + /// ``` + pub fn capacity(self) -> u16 { + self.cap + } + + /// Returns whether the `HashMap` contains elements. + /// + /// # Returns + /// + /// * [bool] - `true` is there are no elements present in the `HashMap`, otherwise `false`. + /// + /// # Examples + /// + /// ```sway + /// use hash_map::*; + /// + /// fn foo() { + /// let mut my_map: HashMap = HashMap::new(); + /// assert(my_map.is_empty()); + /// let _ = my_map.insert(1, 2); + /// assert(!my_map.is_empty()); + /// } + /// ``` + pub fn is_empty(self) -> bool { + self.len == 0 + } + + /// Returns a `HashMapIter` that can be iterated over. + /// + /// # Returns + /// + /// * [HashMapIter] - The `HashMapIter`. + /// + /// # Examples + /// + /// ```sway + /// use hash_map::*; + /// + /// fn foo() { + /// let mut my_map: HashMap = HashMap::new(); + /// let _ = my_map.insert(1, 2); + /// let iterator = my_map.iter(); + /// assert(iterator.next() == Some((1, 2))); + /// assert(iterator.next() == None); + /// } + /// ``` + pub fn iter(self) -> HashMapIter { + HashMapIter { + values: self.values, + keys: self.keys, + indexes: self.indexes, + cap: asm(val: self.cap) { val: u64 }, + index: 0, + } + } +} + +pub struct HashMapIter { + values: raw_ptr, + keys: raw_ptr, + indexes: raw_ptr, + cap: u64, + index: u64, +} + +impl Iterator for HashMapIter { + type Item = (K, V); + fn next(ref mut self) -> Option { + // BEWARE: If the original hashmap gets modified during the iteration + // (e.g., elements are removed or added), this modification will not + // be reflected in `self.len`. + // + // But since modifying the hashmap during iteration is + // considered undefined behavior, this implementation, + // that always checks against the length at the time + // the iterator got created is perfectly valid. + if self.index >= self.cap { + return None + } + + while self.index < self.cap { + if 1u8 != asm(ptr: self.indexes, offset: self.index, new, val) { + add new ptr offset; + lb val new i0; + val: u8 + } { + self.index += 1; + continue; + } + + let key = if __is_reference_type::() { + asm(ptr: self.keys, offset: __size_of::() * self.index, new) { + add new ptr offset; + new: K + } + } else if __size_of::() == 1 { + asm(ptr: self.keys, offset: self.index, new, val) { + add new ptr offset; + lb val new i0; + val: K + } + } else { + asm(ptr: self.keys, offset: __size_of::() * self.index, new, val) { + add new ptr offset; + lw val new i0; + val: K + } + }; + + let value = if __is_reference_type::() { + asm(ptr: self.values, offset: __size_of::() * self.index, new) { + add new ptr offset; + new: V + } + } else if __size_of::() == 1 { + asm(ptr: self.values, offset: self.index, new, val) { + add new ptr offset; + lb val new i0; + val: V + } + } else { + asm(ptr: self.values, offset: __size_of::() * self.index, new, val) { + add new ptr offset; + lw val new i0; + val: V + } + }; + + self.index += 1; + + return Some((key, value)); + } + + return None; + } +} diff --git a/tests/src/hash_map/Forc.lock b/tests/src/hash_map/Forc.lock new file mode 100644 index 00000000..def4ebd7 --- /dev/null +++ b/tests/src/hash_map/Forc.lock @@ -0,0 +1,17 @@ +[[package]] +name = "hash_map" +source = "path+from-root-048D550467276A6A" +dependencies = ["std"] + +[[package]] +name = "hash_map_test" +source = "member" +dependencies = [ + "hash_map", + "std", +] + +[[package]] +name = "std" +version = "0.68.7" +source = "registry+std?0.68.7#QmXtvuy4DJqoVfTmMSygtwh5Zx9JvWsKfx2p83pXEGnZrC!" diff --git a/tests/src/hash_map/Forc.toml b/tests/src/hash_map/Forc.toml new file mode 100644 index 00000000..2a4fe5df --- /dev/null +++ b/tests/src/hash_map/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "hash_map_test" + +[dependencies] +hash_map = { path = "../../../libs/hash_map" } diff --git a/tests/src/hash_map/src/main.sw b/tests/src/hash_map/src/main.sw new file mode 100644 index 00000000..d4907f60 --- /dev/null +++ b/tests/src/hash_map/src/main.sw @@ -0,0 +1,2181 @@ +library; + +use hash_map::*; + +#[test] +fn hash_map_new() { + let new_map: HashMap = HashMap::new(); + + assert(new_map.len() == 0); + assert(new_map.capacity() == 0); + assert(new_map.keys().len() == 0); + assert(new_map.values().len() == 0); +} + +#[test] +fn hash_map_with_capacity() { + let new_map_1: HashMap = HashMap::with_capacity(0); + assert(new_map_1.len() == 0); + assert(new_map_1.capacity() == 0); + assert(new_map_1.keys().len() == 0); + assert(new_map_1.values().len() == 0); + + let new_map_2: HashMap = HashMap::with_capacity(1); + assert(new_map_2.len() == 0); + assert(new_map_2.capacity() == 1); + assert(new_map_2.keys().len() == 0); + assert(new_map_2.values().len() == 0); + + let new_map_3: HashMap = HashMap::with_capacity(u16::max()); + assert(new_map_3.len() == 0); + assert(new_map_3.capacity() == u16::max()); + assert(new_map_3.keys().len() == 0); + assert(new_map_3.values().len() == 0); +} + +#[test] +fn hash_map_insert() { + let mut maps: HashMap = HashMap::new(); + + assert(maps.get(1).is_none()); + let res = maps.insert(1, 10); + assert(res == None); + assert(maps.get(1).unwrap() == 10); + + assert(maps.get(2).is_none()); + let res = maps.insert(2, 11); + assert(res == None); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + + assert(maps.get(3).is_none()); + let res = maps.insert(3, 12); + assert(res == None); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + + assert(maps.get(4).is_none()); + let res = maps.insert(4, 13); + assert(res == None); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + + assert(maps.get(5).is_none()); + let res = maps.insert(5, 13); + assert(res == None); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + + assert(maps.get(6).is_none()); + let res = maps.insert(6, 0); + assert(res == None); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + + assert(maps.get(1).is_some()); + let res = maps.insert(1, 0); + assert(res == Some(10)); + assert(maps.get(1).unwrap() == 0); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + + assert(maps.get(u64::max()).is_none()); + let res = maps.insert(u64::max(), u64::max()); + assert(res == None); + assert(maps.get(1).unwrap() == 0); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).unwrap() == u64::max()); + + assert(maps.get(0).is_none()); + let res = maps.insert(0, 0); + assert(res == None); + assert(maps.get(1).unwrap() == 0); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).unwrap() == u64::max()); + assert(maps.get(0).unwrap() == 0); +} + +#[test] +fn hash_map_insert_reference_type() { + let mut maps: HashMap = HashMap::new(); + + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .is_none(), + ); + let res = maps.insert( + 0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d, + 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert(res == None); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .is_none(), + ); + let res = maps.insert( + 0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f, + 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert(res == None); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .is_none(), + ); + let res = maps.insert( + 0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f, + 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert(res == None); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .is_none(), + ); + let res = maps.insert( + 0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5, + 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert(res == None); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .is_none(), + ); + let res = maps.insert( + 0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f, + 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert(res == None); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + + assert( + maps + .get(0xe0cef4b9cb0706c1a4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .is_none(), + ); + let res = maps.insert( + 0xe0cef4b9cb0706c1a4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f, + b256::zero(), + ); + assert(res == None); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706c1a4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == b256::zero(), + ); + + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .is_some(), + ); + let res = maps.insert( + 0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d, + b256::zero(), + ); + assert(res == Some(0x00000000000000000000000000000000000000000000000000000000000000a1)); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == b256::zero(), + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706c1a4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == b256::zero(), + ); + + assert(maps.get(b256::max()).is_none()); + let res = maps.insert(b256::max(), b256::max()); + assert(res == None); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == b256::zero(), + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706c1a4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == b256::zero(), + ); + assert(maps.get(b256::max()).unwrap() == b256::max()); + + assert(maps.get(b256::zero()).is_none()); + let res = maps.insert(b256::zero(), b256::zero()); + assert(res == None); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == b256::zero(), + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706c1a4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == b256::zero(), + ); + assert(maps.get(b256::max()).unwrap() == b256::max()); + assert(maps.get(b256::zero()).unwrap() == b256::zero()); +} + +#[test] +fn hash_map_insert_byte() { + let mut maps: HashMap = HashMap::new(); + + assert(maps.get(1u8).is_none()); + let res = maps.insert(1u8, 10u8); + assert(res == None); + assert(maps.get(1u8).unwrap() == 10u8); + + assert(maps.get(2u8).is_none()); + let res = maps.insert(2u8, 11u8); + assert(res == None); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + + assert(maps.get(3u8).is_none()); + let res = maps.insert(3u8, 12u8); + assert(res == None); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + + assert(maps.get(4u8).is_none()); + let res = maps.insert(4u8, 13u8); + assert(res == None); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + assert(maps.get(4u8).unwrap() == 13u8); + + assert(maps.get(5u8).is_none()); + let res = maps.insert(5u8, 13u8); + assert(res == None); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + assert(maps.get(4u8).unwrap() == 13u8); + assert(maps.get(5u8).unwrap() == 13u8); + + assert(maps.get(6u8).is_none()); + let res = maps.insert(6u8, 0u8); + assert(res == None); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + assert(maps.get(4u8).unwrap() == 13u8); + assert(maps.get(5u8).unwrap() == 13u8); + assert(maps.get(6u8).unwrap() == 0u8); + + assert(maps.get(1u8).is_some()); + let res = maps.insert(1u8, 0u8); + assert(res == Some(10u8)); + assert(maps.get(1u8).unwrap() == 0u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + assert(maps.get(4u8).unwrap() == 13u8); + assert(maps.get(5u8).unwrap() == 13u8); + assert(maps.get(6u8).unwrap() == 0u8); + + assert(maps.get(u8::max()).is_none()); + let res = maps.insert(u8::max(), u8::max()); + assert(res == None); + assert(maps.get(1u8).unwrap() == 0u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + assert(maps.get(4u8).unwrap() == 13u8); + assert(maps.get(5u8).unwrap() == 13u8); + assert(maps.get(6u8).unwrap() == 0u8); + assert(maps.get(u8::max()).unwrap() == u8::max()); + + assert(maps.get(0u8).is_none()); + let res = maps.insert(0u8, 0u8); + assert(res == None); + assert(maps.get(1u8).unwrap() == 0u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + assert(maps.get(4u8).unwrap() == 13u8); + assert(maps.get(5u8).unwrap() == 13u8); + assert(maps.get(6u8).unwrap() == 0u8); + assert(maps.get(u8::max()).unwrap() == u8::max()); + assert(maps.get(0u8).unwrap() == 0u8); +} + +#[test] +fn hash_map_try_insert() { + let mut maps: HashMap = HashMap::new(); + + assert(maps.get(1).is_none()); + let res = maps.try_insert(1, 10); + assert(res == Ok(10)); + assert(maps.get(1).unwrap() == 10); + + assert(maps.get(2).is_none()); + let res = maps.try_insert(2, 11); + assert(res == Ok(11)); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + + assert(maps.get(3).is_none()); + let res = maps.try_insert(3, 12); + assert(res == Ok(12)); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + + assert(maps.get(4).is_none()); + let res = maps.try_insert(4, 13); + assert(res == Ok(13)); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + + assert(maps.get(5).is_none()); + let res = maps.try_insert(5, 13); + assert(res == Ok(13)); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + + assert(maps.get(6).is_none()); + let res = maps.try_insert(6, 0); + assert(res == Ok(0)); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + + assert(maps.get(1).is_some()); + let res = maps.try_insert(1, 0); + assert(res == Err(HashMapError::OccupiedError(10))); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + + assert(maps.get(u64::max()).is_none()); + let res = maps.try_insert(u64::max(), u64::max()); + assert(res == Ok(u64::max())); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).unwrap() == u64::max()); + + assert(maps.get(0).is_none()); + let res = maps.try_insert(0, 0); + assert(res == Ok(0)); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).unwrap() == u64::max()); + assert(maps.get(0).unwrap() == 0); + + assert(maps.get(0).is_some()); + let res = maps.try_insert(0, 0); + assert(res == Err(HashMapError::OccupiedError(0))); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).unwrap() == u64::max()); + assert(maps.get(0).unwrap() == 0); + + assert(maps.get(u64::max()).is_some()); + let res = maps.try_insert(u64::max(), u64::max() - 1); + assert(res == Err(HashMapError::OccupiedError(u64::max()))); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).unwrap() == u64::max()); +} + +#[test] +fn hash_map_try_insert_reference_type() { + let mut maps: HashMap = HashMap::new(); + + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .is_none(), + ); + let res = maps.try_insert( + 0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d, + 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert(res == Ok(0x00000000000000000000000000000000000000000000000000000000000000a1)); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .is_none(), + ); + let res = maps.try_insert( + 0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f, + 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert(res == Ok(0x00000000000000000000000000000000000000000000000000000000000000a2)); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .is_none(), + ); + let res = maps.try_insert( + 0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f, + 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert(res == Ok(0x00000000000000000000000000000000000000000000000000000000000000a3)); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .is_none(), + ); + let res = maps.try_insert( + 0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5, + 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert(res == Ok(0x00000000000000000000000000000000000000000000000000000000000000a4)); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .is_none(), + ); + let res = maps.try_insert( + 0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f, + 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert(res == Ok(0x00000000000000000000000000000000000000000000000000000000000000a4)); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + + assert( + maps + .get(0xe0cef4b9cb0706c1a4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .is_none(), + ); + let res = maps.try_insert( + 0xe0cef4b9cb0706c1a4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f, + b256::zero(), + ); + assert(res == Ok(b256::zero())); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706c1a4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == b256::zero(), + ); + + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .is_some(), + ); + let res = maps.try_insert( + 0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d, + b256::zero(), + ); + assert( + res == Err(HashMapError::OccupiedError(0x00000000000000000000000000000000000000000000000000000000000000a1)), + ); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706c1a4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == b256::zero(), + ); + + assert(maps.get(b256::max()).is_none()); + let res = maps.try_insert(b256::max(), b256::max()); + assert(res == Ok(b256::max())); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706c1a4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == b256::zero(), + ); + assert(maps.get(b256::max()).unwrap() == b256::max()); + + assert(maps.get(b256::zero()).is_none()); + let res = maps.try_insert(b256::zero(), b256::zero()); + assert(res == Ok(b256::zero())); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706c1a4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == b256::zero(), + ); + assert(maps.get(b256::max()).unwrap() == b256::max()); + assert(maps.get(b256::zero()).unwrap() == b256::zero()); + + assert(maps.get(b256::zero()).is_some()); + let res = maps.try_insert(b256::zero(), b256::zero()); + assert(res == Err(HashMapError::OccupiedError(b256::zero()))); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706c1a4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == b256::zero(), + ); + assert(maps.get(b256::max()).unwrap() == b256::max()); + assert(maps.get(b256::zero()).unwrap() == b256::zero()); + + assert(maps.get(b256::max()).is_some()); + let res = maps.try_insert( + b256::max(), + b256::from( + u256::max() - 0x0000000000000000000000000000000000000000000000000000000000000001u256, + ), + ); + assert(res == Err(HashMapError::OccupiedError(b256::max()))); + assert( + maps + .get(0x38d1786f24d5547780e48992ad12c12d6aeb6b06ccf0aa699dea36aafccad94d) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a1, + ); + assert( + maps + .get(0xe0ced4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a2, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a3, + ); + assert( + maps + .get(0xa139623f3a64240ac2919443bd827e1f80a576c63311efd23423c91cbedb13c5) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706cfa4aa174e15fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == 0x00000000000000000000000000000000000000000000000000000000000000a4, + ); + assert( + maps + .get(0xe0cef4b9cb0706c1a4aa174e75fb006b8ddd2a0ecd6296a27c0a05dcb856f32f) + .unwrap() == b256::zero(), + ); + assert(maps.get(b256::max()).unwrap() == b256::max()); + assert(maps.get(b256::zero()).unwrap() == b256::zero()); +} + +#[test] +fn hash_map_try_insert_byte() { + let mut maps: HashMap = HashMap::new(); + + assert(maps.get(1u8).is_none()); + let res = maps.try_insert(1u8, 10u8); + assert(res == Ok(10u8)); + assert(maps.get(1u8).unwrap() == 10u8); + + assert(maps.get(2u8).is_none()); + let res = maps.try_insert(2u8, 11u8); + assert(res == Ok(11u8)); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + + assert(maps.get(3u8).is_none()); + let res = maps.try_insert(3u8, 12u8); + assert(res == Ok(12u8)); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + + assert(maps.get(4u8).is_none()); + let res = maps.try_insert(4u8, 13u8); + assert(res == Ok(13u8)); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + assert(maps.get(4u8).unwrap() == 13u8); + + assert(maps.get(5u8).is_none()); + let res = maps.try_insert(5u8, 13u8); + assert(res == Ok(13u8)); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + assert(maps.get(4u8).unwrap() == 13u8); + assert(maps.get(5u8).unwrap() == 13u8); + + assert(maps.get(6u8).is_none()); + let res = maps.try_insert(6u8, 0u8); + assert(res == Ok(0u8)); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + assert(maps.get(4u8).unwrap() == 13u8); + assert(maps.get(5u8).unwrap() == 13u8); + assert(maps.get(6u8).unwrap() == 0u8); + + assert(maps.get(1u8).is_some()); + let res = maps.try_insert(1u8, 0u8); + assert(res == Err(HashMapError::OccupiedError(10u8))); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + assert(maps.get(4u8).unwrap() == 13u8); + assert(maps.get(5u8).unwrap() == 13u8); + assert(maps.get(6u8).unwrap() == 0u8); + + assert(maps.get(u8::max()).is_none()); + let res = maps.try_insert(u8::max(), u8::max()); + assert(res == Ok(u8::max())); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + assert(maps.get(4u8).unwrap() == 13u8); + assert(maps.get(5u8).unwrap() == 13u8); + assert(maps.get(6u8).unwrap() == 0u8); + assert(maps.get(u8::max()).unwrap() == u8::max()); + + assert(maps.get(0u8).is_none()); + let res = maps.try_insert(0u8, 0u8); + assert(res == Ok(0u8)); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + assert(maps.get(4u8).unwrap() == 13u8); + assert(maps.get(5u8).unwrap() == 13u8); + assert(maps.get(6u8).unwrap() == 0u8); + assert(maps.get(u8::max()).unwrap() == u8::max()); + assert(maps.get(0u8).unwrap() == 0u8); + + assert(maps.get(0u8).is_some()); + let res = maps.try_insert(0u8, 0u8); + assert(res == Err(HashMapError::OccupiedError(0u8))); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + assert(maps.get(4u8).unwrap() == 13u8); + assert(maps.get(5u8).unwrap() == 13u8); + assert(maps.get(6u8).unwrap() == 0u8); + assert(maps.get(u8::max()).unwrap() == u8::max()); + assert(maps.get(0u8).unwrap() == 0u8); + + assert(maps.get(u8::max()).is_some()); + let res = maps.try_insert(u8::max(), u8::max() - 1); + assert(res == Err(HashMapError::OccupiedError(u8::max()))); + assert(maps.get(1u8).unwrap() == 10u8); + assert(maps.get(2u8).unwrap() == 11u8); + assert(maps.get(3u8).unwrap() == 12u8); + assert(maps.get(4u8).unwrap() == 13u8); + assert(maps.get(5u8).unwrap() == 13u8); + assert(maps.get(6u8).unwrap() == 0u8); + assert(maps.get(u8::max()).unwrap() == u8::max()); + assert(maps.get(0u8).unwrap() == 0u8); +} + +#[test] +fn hash_map_remove() { + let mut maps: HashMap = HashMap::new(); + + let res = maps.remove(1); + assert(res == None); + let _ = maps.insert(1, 10); + assert(maps.get(1).unwrap() == 10); + let res = maps.remove(1); + assert(res == Some(10)); + + let res = maps.remove(1); + assert(res == None); + let _ = maps.insert(1, 10); + + let res = maps.remove(2); + assert(res == None); + let _ = maps.insert(2, 11); + let res = maps.remove(2); + assert(res == Some(11)); + assert(maps.get(1).unwrap() == 10); + + let _ = maps.insert(2, 11); + let _ = maps.insert(3, 12); + let _ = maps.insert(4, 13); + let _ = maps.insert(5, 13); + let _ = maps.insert(6, 0); + let res = maps.remove(1); + assert(res == Some(10)); + assert(maps.get(1) == None); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + + let _ = maps.insert(1, 0); + assert(maps.get(1).unwrap() == 0); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + + let _ = maps.insert(u64::max(), u64::max()); + let _ = maps.insert(0, 0); + assert(maps.get(1).unwrap() == 0); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).unwrap() == u64::max()); + assert(maps.get(0).unwrap() == 0); + + let res = maps.remove(1); + assert(res == Some(0)); + assert(maps.get(1) == None); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).unwrap() == u64::max()); + assert(maps.get(0).unwrap() == 0); + + let res = maps.remove(2); + assert(res == Some(11)); + assert(maps.get(1) == None); + assert(maps.get(2) == None); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).unwrap() == u64::max()); + assert(maps.get(0).unwrap() == 0); + + let res = maps.remove(3); + assert(res == Some(12)); + assert(maps.get(1) == None); + assert(maps.get(2) == None); + assert(maps.get(3) == None); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).unwrap() == u64::max()); + assert(maps.get(0).unwrap() == 0); + + let res = maps.remove(4); + assert(res == Some(13)); + assert(maps.get(1) == None); + assert(maps.get(2) == None); + assert(maps.get(3) == None); + assert(maps.get(4) == None); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).unwrap() == u64::max()); + assert(maps.get(0).unwrap() == 0); + + let res = maps.remove(5); + assert(res == Some(13)); + assert(maps.get(1) == None); + assert(maps.get(2) == None); + assert(maps.get(3) == None); + assert(maps.get(4) == None); + assert(maps.get(5) == None); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).unwrap() == u64::max()); + assert(maps.get(0).unwrap() == 0); + + let res = maps.remove(6); + assert(res == Some(0)); + assert(maps.get(1) == None); + assert(maps.get(2) == None); + assert(maps.get(3) == None); + assert(maps.get(4) == None); + assert(maps.get(5) == None); + assert(maps.get(6) == None); + assert(maps.get(u64::max()).unwrap() == u64::max()); + assert(maps.get(0).unwrap() == 0); + + let res = maps.remove(u64::max()); + assert(res == Some(u64::max())); + assert(maps.get(1) == None); + assert(maps.get(2) == None); + assert(maps.get(3) == None); + assert(maps.get(4) == None); + assert(maps.get(5) == None); + assert(maps.get(6) == None); + assert(maps.get(u64::max()) == None); + assert(maps.get(0).unwrap() == 0); + + let res = maps.remove(0); + assert(res == Some(0)); + assert(maps.get(1) == None); + assert(maps.get(2) == None); + assert(maps.get(3) == None); + assert(maps.get(4) == None); + assert(maps.get(5) == None); + assert(maps.get(6) == None); + assert(maps.get(u64::max()) == None); + assert(maps.get(0) == None); + + let res = maps.remove(1); + assert(res == None); + let res = maps.remove(2); + assert(res == None); + let res = maps.remove(3); + assert(res == None); + let res = maps.remove(4); + assert(res == None); + let res = maps.remove(5); + assert(res == None); + let res = maps.remove(6); + assert(res == None); + let res = maps.remove(u64::max()); + assert(res == None); + let res = maps.remove(0); + assert(res == None); +} + +#[test] +fn hash_map_get() { + let mut maps: HashMap = HashMap::new(); + + assert(maps.get(1).is_none()); + assert(maps.get(2).is_none()); + assert(maps.get(3).is_none()); + assert(maps.get(4).is_none()); + assert(maps.get(5).is_none()); + assert(maps.get(6).is_none()); + assert(maps.get(u64::max()).is_none()); + assert(maps.get(0).is_none()); + let _ = maps.insert(1, 10); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).is_none()); + assert(maps.get(3).is_none()); + assert(maps.get(4).is_none()); + assert(maps.get(5).is_none()); + assert(maps.get(6).is_none()); + assert(maps.get(u64::max()).is_none()); + assert(maps.get(0).is_none()); + + assert(maps.get(2).is_none()); + assert(maps.get(3).is_none()); + assert(maps.get(4).is_none()); + assert(maps.get(5).is_none()); + assert(maps.get(6).is_none()); + assert(maps.get(u64::max()).is_none()); + assert(maps.get(0).is_none()); + let _ = maps.insert(2, 11); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).is_none()); + assert(maps.get(4).is_none()); + assert(maps.get(5).is_none()); + assert(maps.get(6).is_none()); + assert(maps.get(u64::max()).is_none()); + assert(maps.get(0).is_none()); + + assert(maps.get(3).is_none()); + assert(maps.get(4).is_none()); + assert(maps.get(5).is_none()); + assert(maps.get(6).is_none()); + assert(maps.get(u64::max()).is_none()); + assert(maps.get(0).is_none()); + let _ = maps.insert(3, 12); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).is_none()); + assert(maps.get(5).is_none()); + assert(maps.get(6).is_none()); + assert(maps.get(u64::max()).is_none()); + assert(maps.get(0).is_none()); + + assert(maps.get(4).is_none()); + assert(maps.get(5).is_none()); + assert(maps.get(6).is_none()); + assert(maps.get(u64::max()).is_none()); + assert(maps.get(0).is_none()); + let _ = maps.insert(4, 13); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).is_none()); + assert(maps.get(6).is_none()); + assert(maps.get(u64::max()).is_none()); + assert(maps.get(0).is_none()); + + assert(maps.get(5).is_none()); + assert(maps.get(6).is_none()); + assert(maps.get(u64::max()).is_none()); + let _ = maps.insert(5, 13); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).is_none()); + assert(maps.get(u64::max()).is_none()); + assert(maps.get(0).is_none()); + + assert(maps.get(6).is_none()); + assert(maps.get(u64::max()).is_none()); + assert(maps.get(0).is_none()); + let _ = maps.insert(6, 0); + assert(maps.get(1).unwrap() == 10); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).is_none()); + assert(maps.get(0).is_none()); + + assert(maps.get(1).is_some()); + assert(maps.get(u64::max()).is_none()); + assert(maps.get(0).is_none()); + let _ = maps.insert(1, 0); + assert(maps.get(1).unwrap() == 0); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).is_none()); + assert(maps.get(0).is_none()); + + assert(maps.get(u64::max()).is_none()); + assert(maps.get(0).is_none()); + let _ = maps.insert(u64::max(), u64::max()); + assert(maps.get(1).unwrap() == 0); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).unwrap() == u64::max()); + assert(maps.get(0).is_none()); + + assert(maps.get(0).is_none()); + let _ = maps.insert(0, 0); + assert(maps.get(1).unwrap() == 0); + assert(maps.get(2).unwrap() == 11); + assert(maps.get(3).unwrap() == 12); + assert(maps.get(4).unwrap() == 13); + assert(maps.get(5).unwrap() == 13); + assert(maps.get(6).unwrap() == 0); + assert(maps.get(u64::max()).unwrap() == u64::max()); + assert(maps.get(0).unwrap() == 0); +} + +#[test] +fn hash_map_contains_key() { + let mut maps: HashMap = HashMap::new(); + + assert(maps.contains_key(1) == false); + assert(maps.contains_key(2) == false); + assert(maps.contains_key(3) == false); + assert(maps.contains_key(4) == false); + assert(maps.contains_key(5) == false); + assert(maps.contains_key(6) == false); + assert(maps.contains_key(u64::max()) == false); + assert(maps.contains_key(0) == false); + let _ = maps.insert(1, 10); + assert(maps.contains_key(1) == true); + assert(maps.contains_key(2) == false); + assert(maps.contains_key(3) == false); + assert(maps.contains_key(4) == false); + assert(maps.contains_key(5) == false); + assert(maps.contains_key(6) == false); + assert(maps.contains_key(u64::max()) == false); + assert(maps.contains_key(0) == false); + + let _ = maps.insert(2, 11); + assert(maps.contains_key(1) == true); + assert(maps.contains_key(2) == true); + assert(maps.contains_key(3) == false); + assert(maps.contains_key(4) == false); + assert(maps.contains_key(5) == false); + assert(maps.contains_key(6) == false); + assert(maps.contains_key(u64::max()) == false); + assert(maps.contains_key(0) == false); + + let _ = maps.insert(3, 12); + assert(maps.contains_key(1) == true); + assert(maps.contains_key(2) == true); + assert(maps.contains_key(3) == true); + assert(maps.contains_key(4) == false); + assert(maps.contains_key(5) == false); + assert(maps.contains_key(6) == false); + assert(maps.contains_key(u64::max()) == false); + assert(maps.contains_key(0) == false); + + let _ = maps.insert(4, 13); + assert(maps.contains_key(1) == true); + assert(maps.contains_key(2) == true); + assert(maps.contains_key(3) == true); + assert(maps.contains_key(4) == true); + assert(maps.contains_key(5) == false); + assert(maps.contains_key(6) == false); + assert(maps.contains_key(u64::max()) == false); + assert(maps.contains_key(0) == false); + + let _ = maps.insert(5, 13); + assert(maps.contains_key(1) == true); + assert(maps.contains_key(2) == true); + assert(maps.contains_key(3) == true); + assert(maps.contains_key(4) == true); + assert(maps.contains_key(5) == true); + assert(maps.contains_key(6) == false); + assert(maps.contains_key(u64::max()) == false); + assert(maps.contains_key(0) == false); + + let _ = maps.insert(6, 0); + assert(maps.contains_key(1) == true); + assert(maps.contains_key(2) == true); + assert(maps.contains_key(3) == true); + assert(maps.contains_key(4) == true); + assert(maps.contains_key(5) == true); + assert(maps.contains_key(6) == true); + assert(maps.contains_key(u64::max()) == false); + assert(maps.contains_key(0) == false); + + let _ = maps.insert(1, 0); + assert(maps.contains_key(1) == true); + assert(maps.contains_key(2) == true); + assert(maps.contains_key(3) == true); + assert(maps.contains_key(4) == true); + assert(maps.contains_key(5) == true); + assert(maps.contains_key(6) == true); + assert(maps.contains_key(u64::max()) == false); + assert(maps.contains_key(0) == false); + + let _ = maps.insert(u64::max(), u64::max()); + assert(maps.contains_key(1) == true); + assert(maps.contains_key(2) == true); + assert(maps.contains_key(3) == true); + assert(maps.contains_key(4) == true); + assert(maps.contains_key(5) == true); + assert(maps.contains_key(6) == true); + assert(maps.contains_key(u64::max()) == true); + assert(maps.contains_key(0) == false); + + let _ = maps.insert(0, 0); + assert(maps.contains_key(1) == true); + assert(maps.contains_key(2) == true); + assert(maps.contains_key(3) == true); + assert(maps.contains_key(4) == true); + assert(maps.contains_key(5) == true); + assert(maps.contains_key(6) == true); + assert(maps.contains_key(u64::max()) == true); + assert(maps.contains_key(0) == true); + + let _ = maps.remove(1); + assert(maps.contains_key(1) == false); + assert(maps.contains_key(2) == true); + assert(maps.contains_key(3) == true); + assert(maps.contains_key(4) == true); + assert(maps.contains_key(5) == true); + assert(maps.contains_key(6) == true); + assert(maps.contains_key(u64::max()) == true); + assert(maps.contains_key(0) == true); + + let _ = maps.remove(2); + assert(maps.contains_key(1) == false); + assert(maps.contains_key(2) == false); + assert(maps.contains_key(3) == true); + assert(maps.contains_key(4) == true); + assert(maps.contains_key(5) == true); + assert(maps.contains_key(6) == true); + assert(maps.contains_key(u64::max()) == true); + assert(maps.contains_key(0) == true); + + let _ = maps.remove(3); + assert(maps.contains_key(1) == false); + assert(maps.contains_key(2) == false); + assert(maps.contains_key(3) == false); + assert(maps.contains_key(4) == true); + assert(maps.contains_key(5) == true); + assert(maps.contains_key(6) == true); + assert(maps.contains_key(u64::max()) == true); + assert(maps.contains_key(0) == true); + + let _ = maps.remove(4); + assert(maps.contains_key(1) == false); + assert(maps.contains_key(2) == false); + assert(maps.contains_key(3) == false); + assert(maps.contains_key(4) == false); + assert(maps.contains_key(5) == true); + assert(maps.contains_key(6) == true); + assert(maps.contains_key(u64::max()) == true); + assert(maps.contains_key(0) == true); + + let _ = maps.remove(5); + assert(maps.contains_key(1) == false); + assert(maps.contains_key(2) == false); + assert(maps.contains_key(3) == false); + assert(maps.contains_key(4) == false); + assert(maps.contains_key(5) == false); + assert(maps.contains_key(6) == true); + assert(maps.contains_key(u64::max()) == true); + assert(maps.contains_key(0) == true); + + let _ = maps.remove(6); + assert(maps.contains_key(1) == false); + assert(maps.contains_key(2) == false); + assert(maps.contains_key(3) == false); + assert(maps.contains_key(4) == false); + assert(maps.contains_key(5) == false); + assert(maps.contains_key(6) == false); + assert(maps.contains_key(u64::max()) == true); + assert(maps.contains_key(0) == true); + + let _ = maps.remove(u64::max()); + assert(maps.contains_key(1) == false); + assert(maps.contains_key(2) == false); + assert(maps.contains_key(3) == false); + assert(maps.contains_key(4) == false); + assert(maps.contains_key(5) == false); + assert(maps.contains_key(6) == false); + assert(maps.contains_key(u64::max()) == false); + assert(maps.contains_key(0) == true); + + let _ = maps.remove(0); + assert(maps.contains_key(1) == false); + assert(maps.contains_key(2) == false); + assert(maps.contains_key(3) == false); + assert(maps.contains_key(4) == false); + assert(maps.contains_key(5) == false); + assert(maps.contains_key(6) == false); + assert(maps.contains_key(u64::max()) == false); + assert(maps.contains_key(0) == false); +} + +#[test] +fn hash_map_keys() { + let keys = [1, 2, 3, 4, 5, 6, u64::max(), 0]; + let values = [10, 11, 12, 13, 14, 15, u64::max(), 0]; + + let mut maps: HashMap = HashMap::new(); + + let _ = maps.insert(keys[0], values[0]); + let result = maps.keys(); + assert(result.len() == 1); + for key in result.iter() { + let mut iter = 0; + let mut key_found = false; + while iter < 8 { + if keys[iter] == key { + key_found = true; + break; + } + iter += 1; + } + + assert(key_found); + } + + let _ = maps.insert(keys[1], values[1]); + let result = maps.keys(); + assert(result.len() == 2); + for key in result.iter() { + let mut iter = 0; + let mut key_found = false; + while iter < 8 { + if keys[iter] == key { + key_found = true; + break; + } + iter += 1; + } + + assert(key_found); + } + + let _ = maps.insert(keys[2], values[2]); + let result = maps.keys(); + assert(result.len() == 3); + for key in result.iter() { + let mut iter = 0; + let mut key_found = false; + while iter < 8 { + if keys[iter] == key { + key_found = true; + break; + } + iter += 1; + } + + assert(key_found); + } + + let _ = maps.insert(keys[3], values[3]); + let result = maps.keys(); + assert(result.len() == 4); + for key in result.iter() { + let mut iter = 0; + let mut key_found = false; + while iter < 8 { + if keys[iter] == key { + key_found = true; + break; + } + iter += 1; + } + + assert(key_found); + } + + let _ = maps.insert(keys[4], values[4]); + let result = maps.keys(); + assert(result.len() == 5); + for key in result.iter() { + let mut iter = 0; + let mut key_found = false; + while iter < 8 { + if keys[iter] == key { + key_found = true; + break; + } + iter += 1; + } + + assert(key_found); + } + + let _ = maps.insert(keys[5], values[5]); + let result = maps.keys(); + assert(result.len() == 6); + for key in result.iter() { + let mut iter = 0; + let mut key_found = false; + while iter < 8 { + if keys[iter] == key { + key_found = true; + break; + } + iter += 1; + } + + assert(key_found); + } + + let _ = maps.insert(keys[6], values[6]); + let result = maps.keys(); + assert(result.len() == 7); + for key in result.iter() { + let mut iter = 0; + let mut key_found = false; + while iter < 8 { + if keys[iter] == key { + key_found = true; + break; + } + iter += 1; + } + + assert(key_found); + } + + let _ = maps.insert(keys[7], values[7]); + let result = maps.keys(); + assert(result.len() == 8); + for key in result.iter() { + let mut iter = 0; + let mut key_found = false; + while iter < 8 { + if keys[iter] == key { + key_found = true; + break; + } + iter += 1; + } + + assert(key_found); + } + + let _ = maps.remove(keys[0]); + let _ = maps.remove(keys[1]); + let _ = maps.remove(keys[2]); + let _ = maps.remove(keys[3]); + let _ = maps.remove(keys[4]); + let _ = maps.remove(keys[5]); + let _ = maps.remove(keys[6]); + let _ = maps.remove(keys[7]); + let result = maps.keys(); + assert(result.len() == 0); +} + +#[test] +fn hash_map_values() { + let keys = [1, 2, 3, 4, 5, 6, u64::max(), 0]; + let values = [10, 11, 12, 13, 14, 15, u64::max(), 0]; + + let mut maps: HashMap = HashMap::new(); + + let _ = maps.insert(keys[0], values[0]); + let result = maps.values(); + assert(result.len() == 1); + for value in result.iter() { + let mut iter = 0; + let mut value_found = false; + while iter < 8 { + if values[iter] == value { + value_found = true; + break; + } + iter += 1; + } + + assert(value_found); + } + + let _ = maps.insert(keys[1], values[1]); + let result = maps.values(); + assert(result.len() == 2); + for value in result.iter() { + let mut iter = 0; + let mut value_found = false; + while iter < 8 { + if values[iter] == value { + value_found = true; + break; + } + iter += 1; + } + + assert(value_found); + } + + let _ = maps.insert(keys[2], values[2]); + let result = maps.values(); + assert(result.len() == 3); + for value in result.iter() { + let mut iter = 0; + let mut value_found = false; + while iter < 8 { + if values[iter] == value { + value_found = true; + break; + } + iter += 1; + } + + assert(value_found); + } + + let _ = maps.insert(keys[3], values[3]); + let result = maps.values(); + assert(result.len() == 4); + for value in result.iter() { + let mut iter = 0; + let mut value_found = false; + while iter < 8 { + if values[iter] == value { + value_found = true; + break; + } + iter += 1; + } + + assert(value_found); + } + + let _ = maps.insert(keys[4], values[4]); + let result = maps.values(); + assert(result.len() == 5); + for value in result.iter() { + let mut iter = 0; + let mut value_found = false; + while iter < 8 { + if values[iter] == value { + value_found = true; + break; + } + iter += 1; + } + + assert(value_found); + } + + let _ = maps.insert(keys[5], values[5]); + let result = maps.values(); + assert(result.len() == 6); + for value in result.iter() { + let mut iter = 0; + let mut value_found = false; + while iter < 8 { + if values[iter] == value { + value_found = true; + break; + } + iter += 1; + } + + assert(value_found); + } + + let _ = maps.insert(keys[6], values[6]); + let result = maps.values(); + assert(result.len() == 7); + for value in result.iter() { + let mut iter = 0; + let mut value_found = false; + while iter < 8 { + if values[iter] == value { + value_found = true; + break; + } + iter += 1; + } + + assert(value_found); + } + + let _ = maps.insert(keys[7], values[7]); + let result = maps.values(); + assert(result.len() == 8); + for value in result.iter() { + let mut iter = 0; + let mut value_found = false; + while iter < 8 { + if values[iter] == value { + value_found = true; + break; + } + iter += 1; + } + + assert(value_found); + } + + let _ = maps.remove(keys[0]); + let _ = maps.remove(keys[1]); + let _ = maps.remove(keys[2]); + let _ = maps.remove(keys[3]); + let _ = maps.remove(keys[4]); + let _ = maps.remove(keys[5]); + let _ = maps.remove(keys[6]); + let _ = maps.remove(keys[7]); + let result = maps.values(); + assert(result.len() == 0); +} + +#[test] +fn hash_map_len() { + let mut maps: HashMap = HashMap::new(); + + assert(maps.len() == 0); + let _ = maps.insert(1, 10); + assert(maps.len() == 1); + + let _ = maps.insert(2, 11); + assert(maps.len() == 2); + + let _ = maps.insert(3, 12); + assert(maps.len() == 3); + + let _ = maps.insert(4, 13); + assert(maps.len() == 4); + + let _ = maps.insert(5, 13); + assert(maps.len() == 5); + + let _ = maps.insert(6, 0); + assert(maps.len() == 6); + + let _ = maps.insert(1, 0); + assert(maps.len() == 6); + + let _ = maps.insert(u64::max(), u64::max()); + assert(maps.len() == 7); + + let _ = maps.insert(0, 0); + assert(maps.len() == 8); + + let _ = maps.remove(1); + assert(maps.len() == 7); + + let _ = maps.remove(1); + assert(maps.len() == 7); + + let _ = maps.remove(2); + assert(maps.len() == 6); + + let _ = maps.remove(3); + assert(maps.len() == 5); + + let _ = maps.remove(4); + assert(maps.len() == 4); + + let _ = maps.remove(5); + assert(maps.len() == 3); + + let _ = maps.remove(6); + assert(maps.len() == 2); + + let _ = maps.remove(u64::max()); + assert(maps.len() == 1); + + let _ = maps.remove(0); + assert(maps.len() == 0); +} + +#[test] +fn hash_map_capacity() { + let mut maps: HashMap = HashMap::new(); + + assert(maps.capacity() == 0); + let _ = maps.insert(1, 10); + assert(maps.capacity() == 1); + + let _ = maps.insert(2, 11); + assert(maps.capacity() == 2); + + let _ = maps.insert(3, 12); + assert(maps.capacity() == 4); + + let _ = maps.insert(4, 13); + assert(maps.capacity() == 4); + + let _ = maps.insert(5, 13); + assert(maps.capacity() == 8); + + let _ = maps.insert(6, 0); + assert(maps.capacity() == 8); + + let _ = maps.insert(1, 0); + assert(maps.capacity() == 8); + + let _ = maps.insert(u64::max(), u64::max()); + assert(maps.capacity() == 8); + + let _ = maps.insert(0, 0); + assert(maps.capacity() == 8); + + let _ = maps.remove(1); + assert(maps.capacity() == 8); + + let _ = maps.remove(1); + assert(maps.capacity() == 8); + + let _ = maps.remove(2); + assert(maps.capacity() == 8); + + let _ = maps.remove(3); + assert(maps.capacity() == 8); + + let _ = maps.remove(4); + assert(maps.capacity() == 8); + + let _ = maps.remove(5); + assert(maps.capacity() == 8); + + let _ = maps.remove(6); + assert(maps.capacity() == 8); + + let _ = maps.remove(u64::max()); + assert(maps.capacity() == 8); + + let _ = maps.remove(0); + assert(maps.capacity() == 8); +} + +#[test] +fn hash_map_is_empty() { + let mut maps: HashMap = HashMap::new(); + + assert(maps.is_empty() == true); + let _ = maps.insert(1, 10); + assert(maps.is_empty() == false); + + let _ = maps.remove(1); + assert(maps.is_empty() == true); + + let _ = maps.insert(1, 10); + assert(maps.is_empty() == false); + + let _ = maps.insert(2, 11); + assert(maps.is_empty() == false); + + let _ = maps.insert(3, 12); + assert(maps.is_empty() == false); + + let _ = maps.insert(4, 13); + assert(maps.is_empty() == false); + + let _ = maps.insert(5, 13); + assert(maps.is_empty() == false); + + let _ = maps.insert(6, 0); + assert(maps.is_empty() == false); + + let _ = maps.insert(1, 0); + assert(maps.is_empty() == false); + + let _ = maps.insert(u64::max(), u64::max()); + assert(maps.is_empty() == false); + + let _ = maps.insert(0, 0); + assert(maps.is_empty() == false); + + let _ = maps.remove(1); + assert(maps.is_empty() == false); + + let _ = maps.remove(1); + assert(maps.is_empty() == false); + + let _ = maps.remove(2); + assert(maps.is_empty() == false); + + let _ = maps.remove(3); + assert(maps.is_empty() == false); + + let _ = maps.remove(4); + assert(maps.is_empty() == false); + + let _ = maps.remove(5); + assert(maps.is_empty() == false); + + let _ = maps.remove(6); + assert(maps.is_empty() == false); + + let _ = maps.remove(u64::max()); + assert(maps.is_empty() == false); + + let _ = maps.remove(0); + assert(maps.is_empty() == true); +} + +#[test] +fn hash_map_iter() { + let keys = [1, 2, 3, 4, 5, 6, u64::max(), 0]; + let values = [10, 11, 12, 13, 14, 15, u64::max(), 0]; + + let mut maps: HashMap = HashMap::new(); + + let _ = maps.insert(keys[0], values[0]); + for (key, value) in maps.iter() { + let mut iter = 0; + let mut key_value_found = false; + while iter < 8 { + if values[iter] == value && keys[iter] == key { + key_value_found = true; + break; + } + iter += 1; + } + + assert(key_value_found); + } + + let _ = maps.insert(keys[1], values[1]); + for (key, value) in maps.iter() { + let mut iter = 0; + let mut key_value_found = false; + while iter < 8 { + if values[iter] == value && keys[iter] == key { + key_value_found = true; + break; + } + iter += 1; + } + + assert(key_value_found); + } + + let _ = maps.insert(keys[2], values[2]); + for (key, value) in maps.iter() { + let mut iter = 0; + let mut key_value_found = false; + while iter < 8 { + if values[iter] == value && keys[iter] == key { + key_value_found = true; + break; + } + iter += 1; + } + + assert(key_value_found); + } + + let _ = maps.insert(keys[3], values[3]); + for (key, value) in maps.iter() { + let mut iter = 0; + let mut key_value_found = false; + while iter < 8 { + if values[iter] == value && keys[iter] == key { + key_value_found = true; + break; + } + iter += 1; + } + + assert(key_value_found); + } + + let _ = maps.insert(keys[4], values[4]); + for (key, value) in maps.iter() { + let mut iter = 0; + let mut key_value_found = false; + while iter < 8 { + if values[iter] == value && keys[iter] == key { + key_value_found = true; + break; + } + iter += 1; + } + + assert(key_value_found); + } + + let _ = maps.insert(keys[5], values[5]); + for (key, value) in maps.iter() { + let mut iter = 0; + let mut key_value_found = false; + while iter < 8 { + if values[iter] == value && keys[iter] == key { + key_value_found = true; + break; + } + iter += 1; + } + + assert(key_value_found); + } + + let _ = maps.insert(keys[6], values[6]); + for (key, value) in maps.iter() { + let mut iter = 0; + let mut key_value_found = false; + while iter < 8 { + if values[iter] == value && keys[iter] == key { + key_value_found = true; + break; + } + iter += 1; + } + + assert(key_value_found); + } + + let _ = maps.insert(keys[7], values[7]); + for (key, value) in maps.iter() { + let mut iter = 0; + let mut key_value_found = false; + while iter < 8 { + if values[iter] == value && keys[iter] == key { + key_value_found = true; + break; + } + iter += 1; + } + + assert(key_value_found); + } + + let _ = maps.remove(keys[0]); + let _ = maps.remove(keys[1]); + let _ = maps.remove(keys[2]); + let _ = maps.remove(keys[3]); + let _ = maps.remove(keys[4]); + let _ = maps.remove(keys[5]); + let _ = maps.remove(keys[6]); + let _ = maps.remove(keys[7]); + + let mut iterator = maps.iter(); + assert(iterator.next() == None); +}