Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/slotmap/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/slotmap/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.lock":"94822af614b8763e4a8ea7fa8a4a76b793765e9a47ff28980584828be4ab0a3b","Cargo.toml":"ca8d3e1b9d2bc3de5e56718195aba29609f4b0a5ceb14811a55dfedef61566bc","LICENSE":"940d3c7339956aa9e8917518305b485ef2aed42df81adbf48ab3a97f0685849b","README.md":"bdce0b82cd3266b923a86f12b872caf66aa0cd5a563d8dc59004c0d73eff110a","RELEASES.md":"c0f3e7e1e54a3a1a2a699101dae4c1e5237294efc9baee8031fda5811863afc0","build.rs":"2ea8b8a95a2b88f845505c6d555dff45372b110d30f36d1ba2eb8d2ec0901839","examples/doubly_linked_list.rs":"aa3bca7a9351e8ae3d2b51de65288437ba5d1c838c7d741d9d10e753848793e8","examples/rand_meld_heap.rs":"a7ce796313981466e96ff471ad5c58b8af65b6cdc78806614c35d4d2bef85dbf","src/basic.rs":"e714da1358d7547d4fdb339f751328c09cdbbe3fa68ecc65dea5590b6895ee02","src/dense.rs":"c52218d1e35544f7a9f70a102e5e4df589eb73ea1c46aa31b1b3869c70cc53b2","src/hop.rs":"87bbb19f6bef1cd15ef9b42cdd5ff7a551541ad95aa743abc14ee037ef63b436","src/lib.rs":"f2784f1dca09ea8c2471921e3a04e7a00581dcb711b78e32025aa15142e9fe7e","src/secondary.rs":"7c86cf230a3f9efb2ad3daa99e2cf23eac90cb5d2d3dee1ceafa4151c5917345","src/sparse_secondary.rs":"2a0e8bc4c39dfc5ad4e8bc1f0eeea59de7681d8051832877644e36361f7303af","src/util.rs":"5023602a8c259d2506e087cf22dd2abb2602e77d4bb9cd39b0221c642d6f61f7"},"package":"dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a"}
|
||||
275
third-party/vendor/slotmap/Cargo.lock
generated
vendored
Normal file
275
third-party/vendor/slotmap/Cargo.lock
generated
vendored
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
|
||||
dependencies = [
|
||||
"log",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fxhash"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quickcheck"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a44883e74aa97ad63db83c4bf8ca490f02b2fc02f92575e720c8551e843c945f"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"log",
|
||||
"rand",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"thread_local",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.118"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.118"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slotmap"
|
||||
version = "1.0.7"
|
||||
dependencies = [
|
||||
"fxhash",
|
||||
"quickcheck",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb9bc092d0d51e76b2b19d9d85534ffc9ec2db959a2523cdae0697e2972cd447"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
64
third-party/vendor/slotmap/Cargo.toml
vendored
Normal file
64
third-party/vendor/slotmap/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "slotmap"
|
||||
version = "1.0.7"
|
||||
authors = ["Orson Peters <orsonpeters@gmail.com>"]
|
||||
description = "Slotmap data structure"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"slotmap",
|
||||
"storage",
|
||||
"allocator",
|
||||
"arena",
|
||||
"reference",
|
||||
]
|
||||
categories = [
|
||||
"data-structures",
|
||||
"memory-management",
|
||||
"caching",
|
||||
]
|
||||
license = "Zlib"
|
||||
repository = "https://github.com/orlp/slotmap"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
features = [
|
||||
"derive",
|
||||
"alloc",
|
||||
]
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.fxhash]
|
||||
version = "0.2.1"
|
||||
|
||||
[dev-dependencies.quickcheck]
|
||||
version = "0.9"
|
||||
|
||||
[dev-dependencies.serde]
|
||||
version = "1.0"
|
||||
|
||||
[dev-dependencies.serde_derive]
|
||||
version = "1.0"
|
||||
|
||||
[dev-dependencies.serde_json]
|
||||
version = "1.0"
|
||||
|
||||
[build-dependencies.version_check]
|
||||
version = "0.9"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = []
|
||||
unstable = []
|
||||
19
third-party/vendor/slotmap/LICENSE
vendored
Normal file
19
third-party/vendor/slotmap/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2021 Orson Peters <orsonpeters@gmail.com>
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty. In
|
||||
no event will the authors be held liable for any damages arising from the use of
|
||||
this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose, including
|
||||
commercial applications, and to alter it and redistribute it freely, subject to
|
||||
the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim
|
||||
that you wrote the original software. If you use this software in a product,
|
||||
an acknowledgment in the product documentation would be appreciated but is
|
||||
not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
50
third-party/vendor/slotmap/README.md
vendored
Normal file
50
third-party/vendor/slotmap/README.md
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# slotmap
|
||||
|
||||
A Rust library providing three containers with persistent unique keys to access
|
||||
stored values, `SlotMap`, `HopSlotMap` and `DenseSlotMap`. Upon insertion a key
|
||||
is returned that can be used to later access or remove the values. Insertion,
|
||||
deletion and access all take O(1) time with low overhead. Great for storing
|
||||
collections of objects that need stable, safe references but have no clear
|
||||
ownership otherwise, such as game entities or graph nodes. Two secondary maps,
|
||||
`SecondaryMap` and `SparseSecondaryMap` are also provided that allow you to map
|
||||
further objects to the keys created by one of the slot maps. Please refer to
|
||||
[**the documentation**](https://docs.rs/slotmap) for more information.
|
||||
|
||||
The minimum required stable Rust version for `slotmap` is 1.49. To start using
|
||||
`slotmap` add the following to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
slotmap = "1.0"
|
||||
```
|
||||
|
||||
# Example
|
||||
|
||||
A short example:
|
||||
|
||||
```rust
|
||||
use slotmap::{SlotMap, SecondaryMap};
|
||||
|
||||
let mut sm = SlotMap::new();
|
||||
let foo = sm.insert("foo"); // Key generated on insert.
|
||||
let bar = sm.insert("bar");
|
||||
assert_eq!(sm[foo], "foo");
|
||||
assert_eq!(sm[bar], "bar");
|
||||
|
||||
sm.remove(bar);
|
||||
let reuse = sm.insert("reuse"); // Space from bar reused.
|
||||
assert_eq!(sm.contains_key(bar), false); // After deletion a key stays invalid.
|
||||
|
||||
let mut sec = SecondaryMap::new();
|
||||
sec.insert(foo, "noun"); // We provide the key for secondary maps.
|
||||
sec.insert(reuse, "verb");
|
||||
|
||||
for (key, val) in sm {
|
||||
println!("{} is a {}", val, sec[key]);
|
||||
}
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
`slotmap` is released under the Zlib license, a permissive license. It is
|
||||
OSI and FSF approved and GPL compatible.
|
||||
147
third-party/vendor/slotmap/RELEASES.md
vendored
Normal file
147
third-party/vendor/slotmap/RELEASES.md
vendored
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
Version 1.0.7
|
||||
=============
|
||||
|
||||
- Added `clone_from` implementations for all slot maps.
|
||||
- Added `try_insert_with_key` methods that accept a fallible closure.
|
||||
- Improved performance of insertion and key hashing.
|
||||
- Made `new_key_type` resistant to shadowing.
|
||||
- Made iterators clonable regardless of item type clonability.
|
||||
|
||||
|
||||
Version 1.0.6
|
||||
=============
|
||||
|
||||
- Made `Key` trait unsafe, as it was erroneously safe to implement.
|
||||
|
||||
|
||||
Version 1.0.5
|
||||
=============
|
||||
|
||||
- Added fuzzing for extra testing.
|
||||
- Fixed an issue that could cause a segfault when using `HopSlotMap::retain`
|
||||
that had the same underlying cause as the fix in 1.0.4 but was missed.
|
||||
|
||||
|
||||
Version 1.0.4
|
||||
=============
|
||||
|
||||
- Fixed an issue that could cause a segfault when using `HopSlotMap::drain`.
|
||||
All versions 0.3+ are affected, and thus yanked.
|
||||
|
||||
|
||||
Version 1.0.3
|
||||
=============
|
||||
|
||||
- Made `get_disjoint_mut` available on stable Rust 1.51 and up.
|
||||
- Added unchecked variants for the getters on `SparseSecondaryMap`.
|
||||
|
||||
|
||||
Version 1.0.2
|
||||
=============
|
||||
|
||||
- Fixed the `new_key_type!` macro, it assumed the `Key` trait was in scope.
|
||||
- Updated code base with more stringent (clippy) warnings, and many small code
|
||||
quality and documentation changes.
|
||||
- Documented the minimum required stable Rust version, which is 1.49.
|
||||
|
||||
|
||||
Version 1.0.1
|
||||
=============
|
||||
|
||||
- Fixed an instance where an uninitialized `[u32; N]` was created. The
|
||||
uninitialized values were never read - the code always initialized them
|
||||
before reading - but simply having the variable be uninitialized (despite all
|
||||
bit patterns being valid) is technically undefined behavior.
|
||||
|
||||
|
||||
Version 1.0.0
|
||||
=============
|
||||
|
||||
- Removed all `Copy` trait restrictions of value types stable Rust! There are
|
||||
no longer any restrictions on the types you can store in any of the
|
||||
slot maps. For that reason `Slottable` was deprecated as well.
|
||||
|
||||
- `no_std` support was added, use it by opting out of the default feature `std`.
|
||||
|
||||
- Added `sm.get_disjoint_mut([k1, k2, ...])` which allows you to get mutable
|
||||
references from multiple disjoint keys at the same time. This requires
|
||||
`min-const-generics` to be stabilized, so until Rust 1.51 comes out this is
|
||||
only available on nightly by setting the `unstable` feature.
|
||||
|
||||
- Added an `Entry` API to the secondary maps.
|
||||
|
||||
- Added `derive(Clone)` for iterators where possible.
|
||||
|
||||
- Replaced `Into<KeyData>` with `Key::data()`.
|
||||
|
||||
- `SecondaryMap` now uses minimal space overhead. Each slot now uses
|
||||
`max(sizeof(T), 4)` bytes.
|
||||
|
||||
- Moved `SlotMap` to the `basic` module.
|
||||
|
||||
|
||||
Version 0.4.1
|
||||
=============
|
||||
|
||||
- Backport of fix made in 1.0.4.
|
||||
|
||||
|
||||
Version 0.4.0
|
||||
=============
|
||||
|
||||
- Codebase moved to 2018 Edition.
|
||||
|
||||
- Reintroduce `DenseSlotMap` - an overzealous removal in 0.3.0.
|
||||
|
||||
- Added support for `try_reserve`.
|
||||
|
||||
- Added support for custom hashers in `SparseSecondaryMap`.
|
||||
|
||||
- `SparseSecondaryMap` and `SecondaryMap` can now be cloned.
|
||||
|
||||
- Keys have a more terse debug output.
|
||||
|
||||
- Fixed a bug that caused an overflowing left shift on 32-bit targets.
|
||||
|
||||
|
||||
Version 0.3.0
|
||||
=============
|
||||
|
||||
- Massive rework, with a focus on secondary maps and custom keys to prevent
|
||||
cross-slotmap key usage.
|
||||
|
||||
- Removed `DenseSlotMap` in favour of `HopSlotMap` as the latter performs
|
||||
better when secondary maps are in use.
|
||||
|
||||
- Unfortunately due to the redesign the first slot in a slot map must now
|
||||
always be empty. This means some deserializations of slot maps serialized
|
||||
with a version before 0.3.0 can fail.
|
||||
|
||||
- Added `SecondaryMap` and `SparseSecondaryMap`, which allows you to associate
|
||||
extra data with keys given by a slot map.
|
||||
|
||||
- Added `DefaultKey`, custom key types, and support for them on all slot maps
|
||||
and secondary maps. You must now always specify the key type you're using
|
||||
with a slot map, so `SlotMap<i32>` would be `SlotMap<DefaultKey, i32>`. It is
|
||||
recommended to make a custom key type with `new_key_type!` for any slot map
|
||||
you create, as this entirely prevents using the wrong key on the wrong slot
|
||||
map.
|
||||
|
||||
- `KeyData` now has `as_ffi` and `from_ffi` functions that convert the data
|
||||
that makes up a key to/from an `u64`. This allows you to use slot map keys
|
||||
as opaque handles in FFI code.
|
||||
|
||||
|
||||
Version 0.2.1
|
||||
=============
|
||||
|
||||
- Fixed a potential uninitialized memory vulnerability. No uninitialized memory
|
||||
was read or used directly, but Rust's assumptions could lead to it. Yanked
|
||||
all previous versions as they were all vulnerable.
|
||||
|
||||
- Made a `Key` member non-zero so that `Option<Key>` is optimized.
|
||||
|
||||
|
||||
Version 0.2.0
|
||||
=============
|
||||
Start of version history.
|
||||
17
third-party/vendor/slotmap/build.rs
vendored
Normal file
17
third-party/vendor/slotmap/build.rs
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
fn main() {
|
||||
let is_nightly = version_check::is_feature_flaggable() == Some(true);
|
||||
let is_at_least_1_49 = version_check::is_min_version("1.49.0").unwrap_or(false);
|
||||
let is_at_least_1_51 = version_check::is_min_version("1.51.0").unwrap_or(false);
|
||||
|
||||
if !is_at_least_1_49 {
|
||||
println!("cargo:warning=slotmap requires rustc => 1.49.0");
|
||||
}
|
||||
|
||||
if is_at_least_1_51 || is_nightly {
|
||||
println!("cargo:rustc-cfg=has_min_const_generics");
|
||||
}
|
||||
|
||||
if is_nightly {
|
||||
println!("cargo:rustc-cfg=nightly");
|
||||
}
|
||||
}
|
||||
135
third-party/vendor/slotmap/examples/doubly_linked_list.rs
vendored
Normal file
135
third-party/vendor/slotmap/examples/doubly_linked_list.rs
vendored
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
// A simple doubly linked list example using slotmap.
|
||||
|
||||
use slotmap::{new_key_type, Key, SlotMap};
|
||||
|
||||
new_key_type! {
|
||||
pub struct ListKey;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Node<T> {
|
||||
value: T,
|
||||
prev: ListKey,
|
||||
next: ListKey,
|
||||
}
|
||||
|
||||
pub struct List<T> {
|
||||
sm: SlotMap<ListKey, Node<T>>,
|
||||
head: ListKey,
|
||||
tail: ListKey,
|
||||
}
|
||||
|
||||
impl<T> List<T> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
sm: SlotMap::with_key(),
|
||||
head: ListKey::null(),
|
||||
tail: ListKey::null(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.sm.len()
|
||||
}
|
||||
|
||||
pub fn push_head(&mut self, value: T) -> ListKey {
|
||||
let k = self.sm.insert(Node {
|
||||
value,
|
||||
prev: ListKey::null(),
|
||||
next: self.head,
|
||||
});
|
||||
|
||||
if let Some(old_head) = self.sm.get_mut(self.head) {
|
||||
old_head.prev = k;
|
||||
} else {
|
||||
self.tail = k;
|
||||
}
|
||||
self.head = k;
|
||||
k
|
||||
}
|
||||
|
||||
pub fn push_tail(&mut self, value: T) -> ListKey {
|
||||
let k = self.sm.insert(Node {
|
||||
value,
|
||||
prev: self.tail,
|
||||
next: ListKey::null(),
|
||||
});
|
||||
|
||||
if let Some(old_tail) = self.sm.get_mut(self.tail) {
|
||||
old_tail.next = k;
|
||||
} else {
|
||||
self.head = k;
|
||||
}
|
||||
self.tail = k;
|
||||
k
|
||||
}
|
||||
|
||||
pub fn pop_head(&mut self) -> Option<T> {
|
||||
self.sm.remove(self.head).map(|old_head| {
|
||||
self.head = old_head.next;
|
||||
old_head.value
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pop_tail(&mut self) -> Option<T> {
|
||||
self.sm.remove(self.tail).map(|old_tail| {
|
||||
self.tail = old_tail.prev;
|
||||
old_tail.value
|
||||
})
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, key: ListKey) -> Option<T> {
|
||||
self.sm.remove(key).map(|node| {
|
||||
if let Some(prev_node) = self.sm.get_mut(node.prev) {
|
||||
prev_node.next = node.next;
|
||||
} else {
|
||||
self.head = node.next;
|
||||
}
|
||||
|
||||
if let Some(next_node) = self.sm.get_mut(node.next) {
|
||||
next_node.prev = node.prev;
|
||||
} else {
|
||||
self.tail = node.prev;
|
||||
}
|
||||
|
||||
node.value
|
||||
})
|
||||
}
|
||||
|
||||
pub fn head(&self) -> ListKey {
|
||||
self.head
|
||||
}
|
||||
|
||||
pub fn tail(&self) -> ListKey {
|
||||
self.tail
|
||||
}
|
||||
|
||||
pub fn get(&self, key: ListKey) -> Option<&T> {
|
||||
self.sm.get(key).map(|node| &node.value)
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, key: ListKey) -> Option<&mut T> {
|
||||
self.sm.get_mut(key).map(|node| &mut node.value)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut dll = List::new();
|
||||
dll.push_head(5);
|
||||
dll.push_tail(6);
|
||||
let k = dll.push_head(3);
|
||||
dll.push_tail(7);
|
||||
dll.push_head(4);
|
||||
|
||||
assert_eq!(dll.len(), 4);
|
||||
assert_eq!(dll.pop_head(), Some(4));
|
||||
assert_eq!(dll.pop_head(), Some(5));
|
||||
assert_eq!(dll.head(), k);
|
||||
dll.push_head(10);
|
||||
assert_eq!(dll.remove(k), Some(3));
|
||||
assert_eq!(dll.pop_tail(), Some(7));
|
||||
assert_eq!(dll.pop_tail(), Some(6));
|
||||
assert_eq!(dll.pop_head(), Some(10));
|
||||
assert_eq!(dll.pop_head(), None);
|
||||
assert_eq!(dll.pop_tail(), None);
|
||||
}
|
||||
174
third-party/vendor/slotmap/examples/rand_meld_heap.rs
vendored
Normal file
174
third-party/vendor/slotmap/examples/rand_meld_heap.rs
vendored
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
// Randomized meldable heap.
|
||||
// https://en.wikipedia.org/wiki/Randomized_meldable_heap
|
||||
|
||||
use slotmap::{new_key_type, Key, SlotMap};
|
||||
|
||||
new_key_type! {
|
||||
struct HeapKey;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct NodeHandle(HeapKey);
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Node<T> {
|
||||
value: T,
|
||||
children: [HeapKey; 2],
|
||||
parent: HeapKey,
|
||||
}
|
||||
|
||||
struct RandMeldHeap<T: Ord> {
|
||||
sm: SlotMap<HeapKey, Node<T>>,
|
||||
rng: std::num::Wrapping<u32>,
|
||||
root: HeapKey,
|
||||
}
|
||||
|
||||
impl<T: Ord + std::fmt::Debug> RandMeldHeap<T> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
sm: SlotMap::with_key(),
|
||||
rng: std::num::Wrapping(0xdead_beef),
|
||||
root: HeapKey::null(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn coinflip(&mut self) -> bool {
|
||||
// Simple LCG for top speed - random quality barely matters.
|
||||
self.rng += (self.rng << 8) + std::num::Wrapping(1);
|
||||
self.rng >> 31 > std::num::Wrapping(0)
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, value: T) -> NodeHandle {
|
||||
let k = self.sm.insert(Node {
|
||||
value,
|
||||
children: [HeapKey::null(), HeapKey::null()],
|
||||
parent: HeapKey::null(),
|
||||
});
|
||||
|
||||
let root = self.root;
|
||||
self.root = self.meld(k, root);
|
||||
|
||||
NodeHandle(k)
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Option<T> {
|
||||
self.sm.remove(self.root).map(|root| {
|
||||
self.root = self.meld(root.children[0], root.children[1]);
|
||||
if let Some(new_root) = self.sm.get_mut(self.root) {
|
||||
new_root.parent = HeapKey::null();
|
||||
}
|
||||
|
||||
root.value
|
||||
})
|
||||
}
|
||||
|
||||
pub fn remove_key(&mut self, node: NodeHandle) -> T {
|
||||
let node = node.0;
|
||||
self.unlink_node(node);
|
||||
self.sm.remove(node).unwrap().value
|
||||
}
|
||||
|
||||
pub fn update_key(&mut self, node: NodeHandle, value: T) {
|
||||
let node = node.0;
|
||||
|
||||
// Unlink and re-insert.
|
||||
self.unlink_node(node);
|
||||
self.sm[node] = Node {
|
||||
value,
|
||||
children: [HeapKey::null(), HeapKey::null()],
|
||||
parent: HeapKey::null(),
|
||||
};
|
||||
let root = self.root;
|
||||
self.root = self.meld(node, root);
|
||||
}
|
||||
|
||||
fn unlink_node(&mut self, node: HeapKey) {
|
||||
// Remove node from heap by merging children and placing them where
|
||||
// node used to be.
|
||||
let children = self.sm[node].children;
|
||||
let parent_key = self.sm[node].parent;
|
||||
|
||||
let melded_children = self.meld(children[0], children[1]);
|
||||
if let Some(mc) = self.sm.get_mut(melded_children) {
|
||||
mc.parent = parent_key;
|
||||
}
|
||||
|
||||
if let Some(parent) = self.sm.get_mut(parent_key) {
|
||||
if parent.children[0] == node {
|
||||
parent.children[0] = melded_children;
|
||||
} else {
|
||||
parent.children[1] = melded_children;
|
||||
}
|
||||
} else {
|
||||
self.root = melded_children;
|
||||
}
|
||||
}
|
||||
|
||||
fn meld(&mut self, mut a: HeapKey, mut b: HeapKey) -> HeapKey {
|
||||
if a.is_null() {
|
||||
return b;
|
||||
}
|
||||
if b.is_null() {
|
||||
return a;
|
||||
}
|
||||
|
||||
if self.sm[a].value > self.sm[b].value {
|
||||
std::mem::swap(&mut a, &mut b);
|
||||
}
|
||||
|
||||
let ret = a;
|
||||
|
||||
// From this point parent and trickle are assumed to be valid keys.
|
||||
let mut parent = a;
|
||||
let mut trickle = b;
|
||||
|
||||
loop {
|
||||
// If a child spot is free, put our trickle there.
|
||||
let children = self.sm[parent].children;
|
||||
if children[0].is_null() {
|
||||
self.sm[parent].children[0] = trickle;
|
||||
self.sm[trickle].parent = parent;
|
||||
break;
|
||||
} else if children[1].is_null() {
|
||||
self.sm[parent].children[1] = trickle;
|
||||
self.sm[trickle].parent = parent;
|
||||
break;
|
||||
}
|
||||
|
||||
// No spot free, choose a random child.
|
||||
let c = self.coinflip() as usize;
|
||||
let child = children[c];
|
||||
if self.sm[child].value > self.sm[trickle].value {
|
||||
self.sm[parent].children[c] = trickle;
|
||||
self.sm[trickle].parent = parent;
|
||||
parent = trickle;
|
||||
trickle = child;
|
||||
} else {
|
||||
parent = child;
|
||||
}
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.sm.len()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut rhm = RandMeldHeap::new();
|
||||
let the_answer = rhm.insert(-2);
|
||||
let big = rhm.insert(999);
|
||||
|
||||
for k in (0..10).rev() {
|
||||
rhm.insert(k * k);
|
||||
}
|
||||
|
||||
rhm.update_key(the_answer, 42);
|
||||
rhm.remove_key(big);
|
||||
|
||||
while rhm.len() > 0 {
|
||||
println!("{}", rhm.pop().unwrap());
|
||||
}
|
||||
}
|
||||
1541
third-party/vendor/slotmap/src/basic.rs
vendored
Normal file
1541
third-party/vendor/slotmap/src/basic.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
1397
third-party/vendor/slotmap/src/dense.rs
vendored
Normal file
1397
third-party/vendor/slotmap/src/dense.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
1684
third-party/vendor/slotmap/src/hop.rs
vendored
Normal file
1684
third-party/vendor/slotmap/src/hop.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
652
third-party/vendor/slotmap/src/lib.rs
vendored
Normal file
652
third-party/vendor/slotmap/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,652 @@
|
|||
#![doc(html_root_url = "https://docs.rs/slotmap/1.0.7")]
|
||||
#![crate_name = "slotmap"]
|
||||
#![cfg_attr(all(nightly, feature = "unstable"), feature(try_reserve))]
|
||||
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
|
||||
#![cfg_attr(all(nightly, doc), feature(doc_cfg))]
|
||||
#![warn(
|
||||
missing_debug_implementations,
|
||||
trivial_casts,
|
||||
trivial_numeric_casts,
|
||||
unused_lifetimes,
|
||||
unused_import_braces
|
||||
)]
|
||||
#![deny(missing_docs, unaligned_references)]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||
#![cfg_attr(
|
||||
feature = "cargo-clippy",
|
||||
allow(
|
||||
// Style differences.
|
||||
module_name_repetitions,
|
||||
redundant_closure_for_method_calls,
|
||||
unseparated_literal_suffix,
|
||||
|
||||
// I know what I'm doing and want these.
|
||||
wildcard_imports,
|
||||
inline_always,
|
||||
cast_possible_truncation,
|
||||
needless_pass_by_value,
|
||||
|
||||
// Very noisy.
|
||||
missing_errors_doc,
|
||||
must_use_candidate
|
||||
))]
|
||||
|
||||
//! # slotmap
|
||||
//!
|
||||
//! This library provides a container with persistent unique keys to access
|
||||
//! stored values, [`SlotMap`]. Upon insertion a key is returned that can be
|
||||
//! used to later access or remove the values. Insertion, removal and access all
|
||||
//! take O(1) time with low overhead. Great for storing collections of objects
|
||||
//! that need stable, safe references but have no clear ownership otherwise,
|
||||
//! such as game entities or graph nodes.
|
||||
//!
|
||||
//! The difference between a [`BTreeMap`] or [`HashMap`] and a slot map is
|
||||
//! that the slot map generates and returns the key when inserting a value. A
|
||||
//! key is always unique and will only refer to the value that was inserted.
|
||||
//! A slot map's main purpose is to simply own things in a safe and efficient
|
||||
//! manner.
|
||||
//!
|
||||
//! You can also create (multiple) secondary maps that can map the keys returned
|
||||
//! by [`SlotMap`] to other values, to associate arbitrary data with objects
|
||||
//! stored in slot maps, without hashing required - it's direct indexing under
|
||||
//! the hood.
|
||||
//!
|
||||
//! The minimum required stable Rust version for this crate is 1.49.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```
|
||||
//! # use slotmap::*;
|
||||
//! let mut sm = SlotMap::new();
|
||||
//! let foo = sm.insert("foo"); // Key generated on insert.
|
||||
//! let bar = sm.insert("bar");
|
||||
//! assert_eq!(sm[foo], "foo");
|
||||
//! assert_eq!(sm[bar], "bar");
|
||||
//!
|
||||
//! sm.remove(bar);
|
||||
//! let reuse = sm.insert("reuse"); // Space from bar reused.
|
||||
//! assert_eq!(sm.contains_key(bar), false); // After deletion a key stays invalid.
|
||||
//!
|
||||
//! let mut sec = SecondaryMap::new();
|
||||
//! sec.insert(foo, "noun"); // We provide the key for secondary maps.
|
||||
//! sec.insert(reuse, "verb");
|
||||
//!
|
||||
//! for (key, val) in sm {
|
||||
//! println!("{} is a {}", val, sec[key]);
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! # Serialization through [`serde`], [`no_std`] support and unstable features
|
||||
//!
|
||||
//! Both keys and the slot maps have full (de)seralization support through
|
||||
//! the [`serde`] library. A key remains valid for a slot map even after one or
|
||||
//! both have been serialized and deserialized! This makes storing or
|
||||
//! transferring complicated referential structures and graphs a breeze. Care has
|
||||
//! been taken such that deserializing keys and slot maps from untrusted sources
|
||||
//! is safe. If you wish to use these features you must enable the `serde`
|
||||
//! feature flag for `slotmap` in your `Cargo.toml`.
|
||||
//!
|
||||
//! ```text
|
||||
//! slotmap = { version = "1.0", features = ["serde"] }
|
||||
//! ```
|
||||
//!
|
||||
//! This crate also supports [`no_std`] environments, but does require the
|
||||
//! [`alloc`] crate to be available. To enable this you have to disable the
|
||||
//! `std` feature that is enabled by default:
|
||||
//!
|
||||
//! ```text
|
||||
//! slotmap = { version = "1.0", default-features = false }
|
||||
//! ```
|
||||
//!
|
||||
//! Unfortunately [`SparseSecondaryMap`] is not available in [`no_std`], because
|
||||
//! it relies on [`HashMap`]. Finally the `unstable` feature can be defined to
|
||||
//! enable the parts of `slotmap` that only work on nightly Rust.
|
||||
//!
|
||||
//! # Why not index a [`Vec`], or use [`slab`], [`stable-vec`], etc?
|
||||
//!
|
||||
//! Those solutions either can not reclaim memory from deleted elements or
|
||||
//! suffer from the ABA problem. The keys returned by `slotmap` are versioned.
|
||||
//! This means that once a key is removed, it stays removed, even if the
|
||||
//! physical storage inside the slotmap is reused for new elements. The key is a
|
||||
//! permanently unique<sup>*</sup> reference to the inserted value. Despite
|
||||
//! supporting versioning, a [`SlotMap`] is often not (much) slower than the
|
||||
//! alternative, by internally using carefully checked unsafe code. Finally,
|
||||
//! `slotmap` simply has a lot of features that make your life easy.
|
||||
//!
|
||||
//! # Performance characteristics and implementation details
|
||||
//!
|
||||
//! Insertion, access and deletion is all O(1) with low overhead by storing the
|
||||
//! elements inside a [`Vec`]. Unlike references or indices into a vector,
|
||||
//! unless you remove a key it is never invalidated. Behind the scenes each
|
||||
//! slot in the vector is a `(value, version)` tuple. After insertion the
|
||||
//! returned key also contains a version. Only when the stored version and
|
||||
//! version in a key match is a key valid. This allows us to reuse space in the
|
||||
//! vector after deletion without letting removed keys point to spurious new
|
||||
//! elements. <sup>*</sup>After 2<sup>31</sup> deletions and insertions to the
|
||||
//! same underlying slot the version wraps around and such a spurious reference
|
||||
//! could potentially occur. It is incredibly unlikely however, and in all
|
||||
//! circumstances is the behavior safe. A slot map can hold up to
|
||||
//! 2<sup>32</sup> - 2 elements at a time.
|
||||
//!
|
||||
//! The memory usage for each slot in [`SlotMap`] is `4 + max(sizeof(T), 4)`
|
||||
//! rounded up to the alignment of `T`. Similarly it is `4 + max(sizeof(T), 12)`
|
||||
//! for [`HopSlotMap`]. [`DenseSlotMap`] has an overhead of 8 bytes per element
|
||||
//! and 8 bytes per slot.
|
||||
//!
|
||||
//! # Choosing [`SlotMap`], [`HopSlotMap`] or [`DenseSlotMap`]
|
||||
//!
|
||||
//! A [`SlotMap`] is the fastest for most operations, except iteration. It can
|
||||
//! never shrink the size of its underlying storage, because it must remember
|
||||
//! for each storage slot what the latest stored version was, even if the slot
|
||||
//! is empty now. This means that iteration can be slow as it must iterate over
|
||||
//! potentially a lot of empty slots.
|
||||
//!
|
||||
//! [`HopSlotMap`] solves this by maintaining more information on
|
||||
//! insertion/removal, allowing it to iterate only over filled slots by 'hopping
|
||||
//! over' contiguous blocks of vacant slots. This can give it significantly
|
||||
//! better iteration speed. If you expect to iterate over all elements in a
|
||||
//! [`SlotMap`] a lot, and potentially have a lot of deleted elements, choose
|
||||
//! [`HopSlotMap`]. The downside is that insertion and removal is roughly twice
|
||||
//! as slow. Random access is the same speed for both.
|
||||
//!
|
||||
//! [`DenseSlotMap`] goes even further and stores all elements on a contiguous
|
||||
//! block of memory. It uses two indirections per random access; the slots
|
||||
//! contain indices used to access the contiguous memory. This means random
|
||||
//! access is slower than both [`SlotMap`] and [`HopSlotMap`], but iteration is
|
||||
//! significantly faster, as fast as a normal [`Vec`].
|
||||
//!
|
||||
//! # Choosing [`SecondaryMap`] or [`SparseSecondaryMap`]
|
||||
//!
|
||||
//! You want to associate extra data with objects stored in a slot map, so you
|
||||
//! use (multiple) secondary maps to map keys to that data.
|
||||
//!
|
||||
//! A [`SecondaryMap`] is simply a [`Vec`] of slots like slot map is, and
|
||||
//! essentially provides all the same guarantees as [`SlotMap`] does for its
|
||||
//! operations (with the exception that you provide the keys as produced by the
|
||||
//! primary slot map). This does mean that even if you associate data to only
|
||||
//! a single element from the primary slot map, you could need and have to
|
||||
//! initialize as much memory as the original.
|
||||
//!
|
||||
//! A [`SparseSecondaryMap`] is like a [`HashMap`] from keys to objects, however
|
||||
//! it automatically removes outdated keys for slots that had their space
|
||||
//! reused. You should use this variant if you expect to store some associated
|
||||
//! data for only a small portion of the primary slot map.
|
||||
//!
|
||||
//! # Custom key types
|
||||
//!
|
||||
//! If you have multiple slot maps it's an error to use the key of one slot map
|
||||
//! on another slot map. The result is safe, but unspecified, and can not be
|
||||
//! detected at runtime, so it can lead to a hard to find bug.
|
||||
//!
|
||||
//! To prevent this, slot maps allow you to specify what the type is of the key
|
||||
//! they return. You can construct new key types using the [`new_key_type!`]
|
||||
//! macro. The resulting type behaves exactly like [`DefaultKey`], but is a
|
||||
//! distinct type. So instead of simply using `SlotMap<DefaultKey, Player>` you
|
||||
//! would use:
|
||||
//!
|
||||
//! ```
|
||||
//! # use slotmap::*;
|
||||
//! # #[derive(Copy, Clone)]
|
||||
//! # struct Player;
|
||||
//! new_key_type! { struct PlayerKey; }
|
||||
//! let sm: SlotMap<PlayerKey, Player> = SlotMap::with_key();
|
||||
//! ```
|
||||
//!
|
||||
//! You can write code generic over any key type using the [`Key`] trait.
|
||||
//!
|
||||
//! [`Vec`]: std::vec::Vec
|
||||
//! [`BTreeMap`]: std::collections::BTreeMap
|
||||
//! [`HashMap`]: std::collections::HashMap
|
||||
//! [`serde`]: https://github.com/serde-rs/serde
|
||||
//! [`slab`]: https://crates.io/crates/slab
|
||||
//! [`stable-vec`]: https://crates.io/crates/stable-vec
|
||||
//! [`no_std`]: https://doc.rust-lang.org/1.7.0/book/no-stdlib.html
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
// So our macros can refer to these.
|
||||
#[doc(hidden)]
|
||||
pub mod __impl {
|
||||
#[cfg(feature = "serde")]
|
||||
pub use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
pub use core::convert::From;
|
||||
pub use core::result::Result;
|
||||
}
|
||||
|
||||
pub mod basic;
|
||||
pub mod dense;
|
||||
pub mod hop;
|
||||
pub mod secondary;
|
||||
#[cfg(feature = "std")]
|
||||
pub mod sparse_secondary;
|
||||
pub(crate) mod util;
|
||||
|
||||
use core::fmt::{self, Debug, Formatter};
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::num::NonZeroU32;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use crate::basic::SlotMap;
|
||||
#[doc(inline)]
|
||||
pub use crate::dense::DenseSlotMap;
|
||||
#[doc(inline)]
|
||||
pub use crate::hop::HopSlotMap;
|
||||
#[doc(inline)]
|
||||
pub use crate::secondary::SecondaryMap;
|
||||
#[cfg(feature = "std")]
|
||||
#[doc(inline)]
|
||||
pub use crate::sparse_secondary::SparseSecondaryMap;
|
||||
|
||||
// Keep Slottable for backwards compatibility, but warn about deprecation
|
||||
// and hide from documentation.
|
||||
#[doc(hidden)]
|
||||
#[deprecated(
|
||||
since = "1.0.0",
|
||||
note = "Slottable is not necessary anymore, slotmap now supports all types on stable."
|
||||
)]
|
||||
pub trait Slottable {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(deprecated)]
|
||||
impl<T> Slottable for T {}
|
||||
|
||||
/// The actual data stored in a [`Key`].
|
||||
///
|
||||
/// This implements [`Ord`](std::cmp::Ord) so keys can be stored in e.g.
|
||||
/// [`BTreeMap`](std::collections::BTreeMap), but the order of keys is
|
||||
/// unspecified.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct KeyData {
|
||||
idx: u32,
|
||||
version: NonZeroU32,
|
||||
}
|
||||
|
||||
impl KeyData {
|
||||
fn new(idx: u32, version: u32) -> Self {
|
||||
debug_assert!(version > 0);
|
||||
|
||||
Self {
|
||||
idx,
|
||||
version: unsafe { NonZeroU32::new_unchecked(version | 1) },
|
||||
}
|
||||
}
|
||||
|
||||
fn null() -> Self {
|
||||
Self::new(core::u32::MAX, 1)
|
||||
}
|
||||
|
||||
fn is_null(self) -> bool {
|
||||
self.idx == core::u32::MAX
|
||||
}
|
||||
|
||||
/// Returns the key data as a 64-bit integer. No guarantees about its value
|
||||
/// are made other than that passing it to [`from_ffi`](Self::from_ffi)
|
||||
/// will return a key equal to the original.
|
||||
///
|
||||
/// With this you can easily pass slot map keys as opaque handles to foreign
|
||||
/// code. After you get them back you can confidently use them in your slot
|
||||
/// map without worrying about unsafe behavior as you would with passing and
|
||||
/// receiving back references or pointers.
|
||||
///
|
||||
/// This is not a substitute for proper serialization, use [`serde`] for
|
||||
/// that. If you are not doing FFI, you almost surely do not need this
|
||||
/// function.
|
||||
///
|
||||
/// [`serde`]: crate#serialization-through-serde-no_std-support-and-unstable-features
|
||||
pub fn as_ffi(self) -> u64 {
|
||||
(u64::from(self.version.get()) << 32) | u64::from(self.idx)
|
||||
}
|
||||
|
||||
/// Iff `value` is a value received from `k.as_ffi()`, returns a key equal
|
||||
/// to `k`. Otherwise the behavior is safe but unspecified.
|
||||
pub fn from_ffi(value: u64) -> Self {
|
||||
let idx = value & 0xffff_ffff;
|
||||
let version = (value >> 32) | 1; // Ensure version is odd.
|
||||
Self::new(idx as u32, version as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for KeyData {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "{}v{}", self.idx, self.version.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for KeyData {
|
||||
fn default() -> Self {
|
||||
Self::null()
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for KeyData
|
||||
{
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
// A derived Hash impl would call write_u32 twice. We call write_u64
|
||||
// once, which is beneficial if the hasher implements write_u64
|
||||
// explicitly.
|
||||
state.write_u64(self.as_ffi())
|
||||
}
|
||||
}
|
||||
|
||||
/// Key used to access stored values in a slot map.
|
||||
///
|
||||
/// Do not use a key from one slot map in another. The behavior is safe but
|
||||
/// non-sensical (and might panic in case of out-of-bounds).
|
||||
///
|
||||
/// To prevent this, it is suggested to have a unique key type for each slot
|
||||
/// map. You can create new key types using [`new_key_type!`], which makes a
|
||||
/// new type identical to [`DefaultKey`], just with a different name.
|
||||
///
|
||||
/// This trait is intended to be a thin wrapper around [`KeyData`], and all
|
||||
/// methods must behave exactly as if we're operating on a [`KeyData`] directly.
|
||||
/// The internal unsafe code relies on this, therefore this trait is `unsafe` to
|
||||
/// implement. It is strongly suggested to simply use [`new_key_type!`] instead
|
||||
/// of implementing this trait yourself.
|
||||
pub unsafe trait Key:
|
||||
From<KeyData>
|
||||
+ Copy
|
||||
+ Clone
|
||||
+ Default
|
||||
+ Eq
|
||||
+ PartialEq
|
||||
+ Ord
|
||||
+ PartialOrd
|
||||
+ core::hash::Hash
|
||||
+ core::fmt::Debug
|
||||
{
|
||||
/// Creates a new key that is always invalid and distinct from any non-null
|
||||
/// key. A null key can only be created through this method (or default
|
||||
/// initialization of keys made with [`new_key_type!`], which calls this
|
||||
/// method).
|
||||
///
|
||||
/// A null key is always invalid, but an invalid key (that is, a key that
|
||||
/// has been removed from the slot map) does not become a null key. A null
|
||||
/// is safe to use with any safe method of any slot map instance.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use slotmap::*;
|
||||
/// let mut sm = SlotMap::new();
|
||||
/// let k = sm.insert(42);
|
||||
/// let nk = DefaultKey::null();
|
||||
/// assert!(nk.is_null());
|
||||
/// assert!(k != nk);
|
||||
/// assert_eq!(sm.get(nk), None);
|
||||
/// ```
|
||||
fn null() -> Self {
|
||||
KeyData::null().into()
|
||||
}
|
||||
|
||||
/// Checks if a key is null. There is only a single null key, that is
|
||||
/// `a.is_null() && b.is_null()` implies `a == b`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use slotmap::*;
|
||||
/// new_key_type! { struct MyKey; }
|
||||
/// let a = MyKey::null();
|
||||
/// let b = MyKey::default();
|
||||
/// assert_eq!(a, b);
|
||||
/// assert!(a.is_null());
|
||||
/// ```
|
||||
fn is_null(&self) -> bool {
|
||||
self.data().is_null()
|
||||
}
|
||||
|
||||
/// Gets the [`KeyData`] stored in this key.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use slotmap::*;
|
||||
/// new_key_type! { struct MyKey; }
|
||||
/// let dk = DefaultKey::null();
|
||||
/// let mk = MyKey::null();
|
||||
/// assert_eq!(dk.data(), mk.data());
|
||||
/// ```
|
||||
fn data(&self) -> KeyData;
|
||||
}
|
||||
|
||||
/// A helper macro to create new key types. If you use a new key type for each
|
||||
/// slot map you create you can entirely prevent using the wrong key on the
|
||||
/// wrong slot map.
|
||||
///
|
||||
/// The type constructed by this macro is defined exactly as [`DefaultKey`],
|
||||
/// but is a distinct type for the type checker and does not implicitly convert.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate slotmap;
|
||||
/// # use slotmap::*;
|
||||
/// new_key_type! {
|
||||
/// // A private key type.
|
||||
/// struct RocketKey;
|
||||
///
|
||||
/// // A public key type with a doc comment.
|
||||
/// /// Key for the user slot map.
|
||||
/// pub struct UserKey;
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let mut users = SlotMap::with_key();
|
||||
/// let mut rockets = SlotMap::with_key();
|
||||
/// let bob: UserKey = users.insert("bobby");
|
||||
/// let apollo: RocketKey = rockets.insert("apollo");
|
||||
/// // Now this is a type error because rockets.get expects an RocketKey:
|
||||
/// // rockets.get(bob);
|
||||
///
|
||||
/// // If for some reason you do end up needing to convert (e.g. storing
|
||||
/// // keys of multiple slot maps in the same data structure without
|
||||
/// // boxing), you can use KeyData as an intermediate representation. This
|
||||
/// // does mean that once again you are responsible for not using the wrong
|
||||
/// // key on the wrong slot map.
|
||||
/// let keys = vec![bob.data(), apollo.data()];
|
||||
/// println!("{} likes rocket {}",
|
||||
/// users[keys[0].into()], rockets[keys[1].into()]);
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! new_key_type {
|
||||
( $(#[$outer:meta])* $vis:vis struct $name:ident; $($rest:tt)* ) => {
|
||||
$(#[$outer])*
|
||||
#[derive(Copy, Clone, Default,
|
||||
Eq, PartialEq, Ord, PartialOrd,
|
||||
Hash, Debug)]
|
||||
#[repr(transparent)]
|
||||
$vis struct $name($crate::KeyData);
|
||||
|
||||
impl $crate::__impl::From<$crate::KeyData> for $name {
|
||||
fn from(k: $crate::KeyData) -> Self {
|
||||
$name(k)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl $crate::Key for $name {
|
||||
fn data(&self) -> $crate::KeyData {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
$crate::__serialize_key!($name);
|
||||
|
||||
$crate::new_key_type!($($rest)*);
|
||||
};
|
||||
|
||||
() => {}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! __serialize_key {
|
||||
( $name:ty ) => {
|
||||
impl $crate::__impl::Serialize for $name {
|
||||
fn serialize<S>(&self, serializer: S) -> $crate::__impl::Result<S::Ok, S::Error>
|
||||
where
|
||||
S: $crate::__impl::Serializer,
|
||||
{
|
||||
$crate::Key::data(self).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> $crate::__impl::Deserialize<'de> for $name {
|
||||
fn deserialize<D>(deserializer: D) -> $crate::__impl::Result<Self, D::Error>
|
||||
where
|
||||
D: $crate::__impl::Deserializer<'de>,
|
||||
{
|
||||
let key_data: $crate::KeyData =
|
||||
$crate::__impl::Deserialize::deserialize(deserializer)?;
|
||||
Ok(key_data.into())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "serde"))]
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! __serialize_key {
|
||||
( $name:ty ) => {};
|
||||
}
|
||||
|
||||
new_key_type! {
|
||||
/// The default slot map key type.
|
||||
pub struct DefaultKey;
|
||||
}
|
||||
|
||||
// Serialization with serde.
|
||||
#[cfg(feature = "serde")]
|
||||
mod serialize {
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct SerKey {
|
||||
idx: u32,
|
||||
version: u32,
|
||||
}
|
||||
|
||||
impl Serialize for KeyData {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let ser_key = SerKey {
|
||||
idx: self.idx,
|
||||
version: self.version.get(),
|
||||
};
|
||||
ser_key.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for KeyData {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let mut ser_key: SerKey = Deserialize::deserialize(deserializer)?;
|
||||
|
||||
// Ensure a.is_null() && b.is_null() implies a == b.
|
||||
if ser_key.idx == core::u32::MAX {
|
||||
ser_key.version = 1;
|
||||
}
|
||||
|
||||
ser_key.version |= 1; // Ensure version is odd.
|
||||
Ok(Self::new(ser_key.idx, ser_key.version))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// Intentionally no `use super::*;` because we want to test macro expansion
|
||||
// in the *users* scope, which might not have that.
|
||||
#[test]
|
||||
fn macro_expansion() {
|
||||
#![allow(dead_code)]
|
||||
use super::new_key_type;
|
||||
|
||||
// Clobber namespace with clashing names - should still work.
|
||||
trait Serialize { }
|
||||
trait Deserialize { }
|
||||
trait Serializer { }
|
||||
trait Deserializer { }
|
||||
trait Key { }
|
||||
trait From { }
|
||||
struct Result;
|
||||
struct KeyData;
|
||||
|
||||
new_key_type! {
|
||||
struct A;
|
||||
pub(crate) struct B;
|
||||
pub struct C;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_is_older_version() {
|
||||
use super::util::is_older_version;
|
||||
|
||||
let is_older = |a, b| is_older_version(a, b);
|
||||
assert!(!is_older(42, 42));
|
||||
assert!(is_older(0, 1));
|
||||
assert!(is_older(0, 1 << 31));
|
||||
assert!(!is_older(0, (1 << 31) + 1));
|
||||
assert!(is_older(u32::MAX, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iters_cloneable() {
|
||||
use super::*;
|
||||
|
||||
struct NoClone;
|
||||
|
||||
let mut sm = SlotMap::new();
|
||||
let mut hsm = HopSlotMap::new();
|
||||
let mut dsm = DenseSlotMap::new();
|
||||
let mut scm = SecondaryMap::new();
|
||||
let mut sscm = SparseSecondaryMap::new();
|
||||
scm.insert(sm.insert(NoClone), NoClone);
|
||||
sscm.insert(hsm.insert(NoClone), NoClone);
|
||||
dsm.insert(NoClone);
|
||||
|
||||
let _ = sm.keys().clone();
|
||||
let _ = sm.values().clone();
|
||||
let _ = sm.iter().clone();
|
||||
let _ = hsm.keys().clone();
|
||||
let _ = hsm.values().clone();
|
||||
let _ = hsm.iter().clone();
|
||||
let _ = dsm.keys().clone();
|
||||
let _ = dsm.values().clone();
|
||||
let _ = dsm.iter().clone();
|
||||
let _ = scm.keys().clone();
|
||||
let _ = scm.values().clone();
|
||||
let _ = scm.iter().clone();
|
||||
let _ = sscm.keys().clone();
|
||||
let _ = sscm.values().clone();
|
||||
let _ = sscm.iter().clone();
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn key_serde() {
|
||||
use super::*;
|
||||
|
||||
// Check round-trip through serde.
|
||||
let mut sm = SlotMap::new();
|
||||
let k = sm.insert(42);
|
||||
let ser = serde_json::to_string(&k).unwrap();
|
||||
let de: DefaultKey = serde_json::from_str(&ser).unwrap();
|
||||
assert_eq!(k, de);
|
||||
|
||||
// Even if a malicious entity sends up even (unoccupied) versions in the
|
||||
// key, we make the version point to the occupied version.
|
||||
let malicious: KeyData = serde_json::from_str(&r#"{"idx":0,"version":4}"#).unwrap();
|
||||
assert_eq!(malicious.version.get(), 5);
|
||||
}
|
||||
}
|
||||
1767
third-party/vendor/slotmap/src/secondary.rs
vendored
Normal file
1767
third-party/vendor/slotmap/src/secondary.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
1715
third-party/vendor/slotmap/src/sparse_secondary.rs
vendored
Normal file
1715
third-party/vendor/slotmap/src/sparse_secondary.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
46
third-party/vendor/slotmap/src/util.rs
vendored
Normal file
46
third-party/vendor/slotmap/src/util.rs
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
use core::fmt::Debug;
|
||||
use core::hint::unreachable_unchecked;
|
||||
|
||||
/// Internal stable replacement for !.
|
||||
#[derive(Debug)]
|
||||
pub enum Never {}
|
||||
|
||||
/// Returns if a is an older version than b, taking into account wrapping of
|
||||
/// versions.
|
||||
pub fn is_older_version(a: u32, b: u32) -> bool {
|
||||
let diff = a.wrapping_sub(b);
|
||||
diff >= (1 << 31)
|
||||
}
|
||||
|
||||
/// An unwrapper that checks on debug, doesn't check on release.
|
||||
/// UB if unwrapped on release mode when unwrap would panic.
|
||||
pub trait UnwrapUnchecked<T> {
|
||||
// Extra underscore because unwrap_unchecked is planned to be added to the stdlib.
|
||||
unsafe fn unwrap_unchecked_(self) -> T;
|
||||
}
|
||||
|
||||
impl<T> UnwrapUnchecked<T> for Option<T> {
|
||||
unsafe fn unwrap_unchecked_(self) -> T {
|
||||
if cfg!(debug_assertions) {
|
||||
self.unwrap()
|
||||
} else {
|
||||
match self {
|
||||
Some(x) => x,
|
||||
None => unreachable_unchecked(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E: Debug> UnwrapUnchecked<T> for Result<T, E> {
|
||||
unsafe fn unwrap_unchecked_(self) -> T {
|
||||
if cfg!(debug_assertions) {
|
||||
self.unwrap()
|
||||
} else {
|
||||
match self {
|
||||
Ok(x) => x,
|
||||
Err(_) => unreachable_unchecked(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue