Implements a map from integer indices to data.
Rather than storing data for every index, internally, this maps entire ranges to the data.
To this end, the APIs all work on ranges, not on individual integers. Ranges are split as
necessary (e.g., when [0,5) is first associated with X, and then [1,2) is mutated).
Users must not depend on whether a range is coalesced or not, even though this is observable
via the iteration APIs.
This is a “monotonic FxHashMap”: A FxHashMap that, when shared, can be pushed to but not
otherwise mutated. We also box items in the map. This means we can safely provide
shared references into existing items in the FxHashMap, because they will not be dropped
(from being removed) or moved (because they are boxed).
The API is completely tailored to what memory.rs needs. It is still in
a separate file to minimize the amount of code that has to care about the unsafety.
Implements a map from allocation ranges to data. This is somewhat similar to RangeMap, but the
ranges and data are discrete and non-splittable – they represent distinct “objects”. An
allocation in the map will always have the same range until explicitly removed