Abstracted slices and slice-likes types in Rust.
- Ergonomic: Practical (rather than for exotic combinations),
- Type-safe - hence complex, but robust,
- Large, but organized.
- Explicit and clear. For example, stdandno_stdfeatures are mutually exclusive, so users detect any conflicts as early as possible. -- TODO Hashed could be a value object (transparent wrapper). It would make it more "future-proof"/flexible - but not backwards-compatible with your/third party's existing API's. Hence, we implement it directly forstd::collections::HashMap(when usingstdfeature). That makes it work for any application that usesHashMap- easier to use. --size_for_array_only,allow_empty_arrays,disable_empty_arraysare crate features, rather than per-struct or per-object fields. See more below at Crate Features.
- Generic: Generics, constant generic parameters and associated generic types are essential to memory efficiency and type safety. The drawbacks are longer build times and larger binaries. We optimize it where worthwhile.
As of mid 2022, we need Rust nightly. Otherwise this couldn't be so ergonomic.
We test building for several of more supported (tier 2) no_std Rust targets.
See no_std at
https://doc.rust-lang.org/nightly/rustc/platform-support.html#tier-2.
- no_std(plus optionally- no_std_vecto support vector-based implementations & functions)
- stdto indicate a need for full functionality (which is the same as- no_std_vecplus- HashMap-based).
- no_std(and- no_std_vec) are mutually exclusive with- std
- libraries can use no_std_vecfeature forVec-based functionality, andstdfor full functionality (includingHashMap-based) with conditional compilation (controlled by their features). Then such libraries can be used in eitherstdorno_stdprojects. You can also use macroswith_heap, enum_cfg, match_cfgif your crate also defines those feature names.
See features in Cargo.toml and their respective test_crates.
Some full qualified trait/struct/module names repeat their parts. Better have
more granular module paths, and some name repetition in file paths and module
names (like slices::bool_slice), rather than long (source) files).
These data-carrying enums are: SliceStorage, SliceStorageClone, SliceStorageDefault, SliceStorageDefaultClone. They provide storage and
abstracted access and transformations.
Const generic param N is used by Array invariant only. However, it makes all
variants consume space. Hence N > 0 is suggested primarily for no-heap or
frequent instantiation on stack and for small sizes (N). If you run with heap,
and you have infrequent instantiation and/or large sizes, suggest passing 0
for N, and use Vec invariant instead.
Why don't we call this to SliceStorageCopy instead of SliceStorage and why
don't we rename the existing SliceStorageClone to SliceStorage? It could
lead to laziness/not noticing/forgetting to use SliceStorageCopy whenever
possible. Especially so because then any Copy type could be stored in either
SliceStorage or SliceStorageCopy. Storing Copy items in a Clone-friendly
storage would work, but it would be less efficient than storing them in a
specialized Copy storage. Even more so with default values (which, if
primitive and if stored in specialized Copy storage, could be optimized away -
so the virtual memory wouldn't be used until written to it later, if at all).
However, it's unlikely that anyone would use SliceStorageClone for Copy
items (even though they could).