Axle v0.14.1
Package

std/collections/hashmap

std/collections/hashmap — generic HashMap<K, V>, a pure-Axle
open-addressing SwissTable. Resolves by bare name through
use std::collections::HashMap; (the file it lives in does not
affect the import path).

C class HashMap<K, V>

get(K) : V | null returns null on a miss — null is a distinct
type, so V | null is a sound union over any V (a value-primitive
V carries a present flag alongside the payload, so 0 is never
confused with absence). Reach the value with get(k) ?? fallback or
an if (get(k) != null) guard. remove returns bool (whether a
binding was present) rather than the prior value.

K = f64 is unsupported: NaN-keys and float-precision-as-equality
are common footguns. Use i64 or string instead.

Pure-Axle SwissTable. Mirrors abseil flathashmap / hashbrown :

meta : i8[cap + 16] — meta byte per slot + 16-byte trailing
mirror so a wrap-around SIMD load
never reads past the buffer end.
keys : K[cap] — parallel key array
values : V[cap] — parallel value array

Meta encoding (low 7 bits = h2 hash; MSB = "control"):
0x00..0x7F occupied — low 7 bits are h2(key)
0x80 empty
0xFE tombstone (removed; probing must walk over it)

Hashing dispatches statically per K via the hash_key compiler
builtin — i32/i64 and user classes inline a double-keyed SplitMix64;
string routes to a keyed mix (hashStringSeeded). Both pull the
128-bit OS-CSPRNG @axle_hash_seed_lo/_hi key (HashDoS-safe).
Load factor target 7/8 (hashbrown convention) ; the sum of len and
tombstones counts toward the trigger so a churning workload
doesn't degrade to O(n) probe chains. Rehash doubles the
capacity and re-inserts every live entry (tombstones are
dropped).

Bit-twiddling on the SIMD match mask goes through cttz_i32
(compiler builtin → @llvm.cttz.i32 → one tzcnt on x86).

Constructors

TypeMethod and description
constructor() Build an empty map sized to one 16-slot SIMD group, its meta
array (plus 16-byte mirror) splatted to the empty sentinel.

Method detail

#constructor

constructor()

Build an empty map sized to one 16-slot SIMD group, its meta
array (plus 16-byte mirror) splatted to the empty sentinel.

Methods

TypeMethod and description
i32
size(self) : i32
bool
isEmpty(self) : bool
void
clear(mut self) : void
void
put(mut self, key : K, value : V) : void Insert or overwrite. Grows past the 7/8 load factor first, then
SIMD-probes for an existing key (overwrite) or the first hole
(insert), reclaiming a tombstone slot when one is chosen.
bool
containsKey(self, key : K) : bool
V | null
get(self, key : K) : V | null
V
getOrDefault(self, key : K, defaultValue : V) : V Single-probe variant of get — returns defaultValue on miss
instead of throwing. Matches the getOrDefault shape so
hot-path lookup loops can avoid the containsKey + get double
probe (the only safe way to use get without catching the
exception). Algorithm body is identical to get ; the only
difference is the miss branch.
bool
remove(mut self, key : K) : bool

Method detail

#size

size(self) : i32

#isEmpty

isEmpty(self) : bool

#clear

clear(mut self) : void

#put

put(mut self, key : K, value : V) : void

Insert or overwrite. Grows past the 7/8 load factor first, then
SIMD-probes for an existing key (overwrite) or the first hole
(insert), reclaiming a tombstone slot when one is chosen.

Parameters
key lookup key; == equality decides the target slot
value value bound to key, overwriting any prior binding

#containsKey

containsKey(self, key : K) : bool

#get

get(self, key : K) : V | null

#getOrDefault

getOrDefault(self, key : K, defaultValue : V) : V

Single-probe variant of get — returns defaultValue on miss
instead of throwing. Matches the getOrDefault shape so
hot-path lookup loops can avoid the containsKey + get double
probe (the only safe way to use get without catching the
exception). Algorithm body is identical to get ; the only
difference is the miss branch.

Parameters
key key to look up; matched by ==
defaultValue value returned unchanged when key is absent

#remove

remove(mut self, key : K) : bool