(quote from the Readme)
Each primitive collection type is specialized per primitive type (i8 , i16 , i32 , i64 , f32 , f64 , bool , char ) — no boxing, no trait objects, contiguous memory layout. Generic object collections (ArrayList<T> , HashSet<T> , etc.) complement the primitive types for general-purpose use.
This indicates very very strong Java-isms to me. Rust does not share the property of Java of having 8 specific “primitive datatypes” and “objects” beyond that. AFAIK not even even languages much closer to Java, e.g. C#, would have this property.
Hence, APIs that look like this
are extremely unidiomatic, and it’s even weirder that this merely wraps a more generic API internally, anyway, e.g. I see things like
#[derive(Debug, Clone)]
pub struct F32F32HashMap {
inner: OpenHashMap<f32, f32>,
}
Taking a quick peek around some places in the API, I’m noticing it defines a trait
/// Trait for primitive types that can be used as hash table keys.
pub trait PrimitiveKey: Copy + Default {
fn hash_code(&self) -> u64;
fn key_eq(&self, other: &Self) -> bool;
}
which is highly unidiomatic, since the standard library already provides relevant traits (Hash and Eq) which would generally just be re-used for better compatibility with user types, instead of rolling your own one.
Finally, I was intrigued by the existence of an immutable module, and looked at ImmutableF32HashSet out of curiosity… but it looks like it’s completely fake [or at least terribly misnamed] (i.e. not at all a hash set)!
/// Immutable, cheaply cloneable set of `f32` values.
#[derive(Debug, Clone)]
pub struct ImmutableF32HashSet {
items: Arc<[f32]>,
}
impl ImmutableF32HashSet {
pub fn from_mutable(set: &F32HashSet) -> Self {
ImmutableF32HashSet {
items: Arc::from(set.to_vec().into_boxed_slice()),
}
}
pub fn of(values: &[f32]) -> Self {
let mut s = F32HashSet::new();
for &v in values {
s.add(v);
}
Self::from_mutable(&s)
}
pub fn contains(&self, value: f32) -> bool {
self.items.iter().any(|&v| v.to_bits() == value.to_bits())
}
pub fn len(&self) -> usize {
self.items.len()
}
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = f32> + '_ {
self.items.iter().copied()
}
…
and for this Immutable…HashSet kind of type, too - with about 30 or so identically structured, monomorphised versions in separate modules, features an outright insane amount of redundant code duplication. Admitted, these also contain a note they’re generated code
// Code generated by mapdb-codegen. DO NOT EDIT.
but I seem unable to find the actual codegen tool/template from this description (and such codegen isn’t needed for this use-case in Rust [nor is the resulting API surface desirable], anyway!!)
This is just me looking at 2 or 3 random things; I have not tried to understand or check the hashmap implementation at all, and not looked at most of the crate API either, but maybe it helps as a starting point for some of the most notable things from a Rust user’s point of view 