# generic_static_cache
Quoting the [Rust Reference](https://doc.rust-lang.org/reference/items/static-items.html#statics--generics):
> A static item defined in a generic scope (for example in a blanket or default implementation)
> will result in exactly one static item being defined, as if the static definition was pulled
> out of the current scope into the module. There will not be one item per monomorphization.
One way to work around this is to use a `HashMap<TypeId,Data>`. This is a simple & usually the best solution.
If lookup performance is important, you can skip hashing the `TypeId` for minor gains as it
[already contains](https://github.com/rust-lang/rust/blob/eeff92ad32c2627876112ccfe812e19d38494087/library/core/src/any.rs#L645)
a good-quality hash.
This crate aims to further speed up the lookup by allocating the storage using inline
assembly: Accessing a generic static provided by this crate is instant,
whereas using a hashmap takes more than 10×instant.
## ⚠ Caveats ⚠
This crate isn't as well-tested as is should be.
Supported targets are **x86-64**, **aarch64**, **arm** and **x86**;
on other targets, this crate falls back to a hashmap.
## Usage
The `generic_static` macro defines a static variable inside of a function,
with every instantiation of the function having it's own instance of the static:
```rust
fn numeric_type_id<T>() -> u32 {
static NEXT: AtomicU32 = AtomicU32::new(0);
generic_static!{
static ID: &u32 = &NEXT.fetch_add(1, Relaxed);
}
*ID
}
assert_eq!(numeric_type_id::<bool>(), 0);
assert_eq!(numeric_type_id::<String>(), 1);
assert_eq!(numeric_type_id::<i32>(), 2);
assert_eq!(numeric_type_id::<bool>(), 0);
```
Underlying this is the `global::<T>()` function,
which allocates a shared global static for each type it's used with.
## no_std
On supported platforms, `global` is always available.
With the `alloc` feature, `generic_static!` and `non_zeroable_global` become available.
With the `std` feature, everything also becomes available on unsupported platforms.