diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..da7dea5
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,4 @@
+# Preserve authenticated upstream package bytes, including mixed line endings.
+vendor/bincode-2.0.1/** -text
+vendor/bincode_derive-2.0.1/** -text
+vendor/upstream/*.crate -text
diff --git a/Cargo.lock b/Cargo.lock
index 67cc9de..8b8f622 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
-version = 4
+version = 3
[[package]]
name = "ahash"
@@ -44,8 +44,6 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]]
name = "bincode"
version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740"
dependencies = [
"bincode_derive",
"serde",
@@ -55,8 +53,6 @@ dependencies = [
[[package]]
name = "bincode_derive"
version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09"
dependencies = [
"virtue",
]
@@ -135,18 +131,18 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.6.6"
+version = "4.5.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca"
+checksum = "52fa72306bb30daf11bc97773431628e5b4916e97aaa74b7d3f625d4d495da02"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
-version = "4.6.6"
+version = "4.5.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889"
+checksum = "2071365c5c56eae7d77414029dde2f4f4ba151cf68d5a3261c9a40de428ace93"
dependencies = [
"anstyle",
"clap_lex",
@@ -154,15 +150,15 @@ dependencies = [
[[package]]
name = "clap_lex"
-version = "1.1.0"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
+checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831"
[[package]]
name = "convert_case"
-version = "0.10.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9"
+checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7"
dependencies = [
"unicode-segmentation",
]
@@ -282,23 +278,22 @@ dependencies = [
[[package]]
name = "derive_more"
-version = "2.1.1"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134"
+checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
dependencies = [
"derive_more-impl",
]
[[package]]
name = "derive_more-impl"
-version = "2.1.1"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb"
+checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
dependencies = [
"convert_case",
"proc-macro2",
"quote",
- "rustc_version",
"syn 2.0.119",
]
@@ -406,24 +401,24 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.4.3"
+version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
+checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
dependencies = [
"cfg-if",
"libc",
"r-efi",
+ "wasip2",
]
[[package]]
name = "half"
-version = "2.7.1"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
+checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
dependencies = [
"cfg-if",
"crunchy",
- "zerocopy",
]
[[package]]
@@ -437,9 +432,9 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.17.1"
+version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
+checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
[[package]]
name = "hecs"
@@ -547,12 +542,12 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.14.1"
+version = "2.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb"
+checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
dependencies = [
"equivalent",
- "hashbrown 0.17.1",
+ "hashbrown 0.16.1",
]
[[package]]
@@ -583,11 +578,11 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "jobserver"
-version = "0.1.35"
+version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3"
+checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
dependencies = [
- "getrandom 0.4.3",
+ "getrandom 0.3.4",
"libc",
]
@@ -757,15 +752,15 @@ dependencies = [
[[package]]
name = "r-efi"
-version = "6.0.0"
+version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "rayon"
-version = "1.12.0"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
+checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
@@ -773,9 +768,9 @@ dependencies = [
[[package]]
name = "rayon-core"
-version = "1.13.0"
+version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
+checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
@@ -819,15 +814,6 @@ version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
-[[package]]
-name = "rustc_version"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
-dependencies = [
- "semver",
-]
-
[[package]]
name = "rustix"
version = "1.1.4"
@@ -862,12 +848,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
-[[package]]
-name = "semver"
-version = "1.0.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
-
[[package]]
name = "serde"
version = "1.0.229"
@@ -913,11 +893,11 @@ dependencies = [
[[package]]
name = "serde_spanned"
-version = "1.1.1"
+version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
+checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
dependencies = [
- "serde_core",
+ "serde",
]
[[package]]
@@ -1020,42 +1000,44 @@ dependencies = [
[[package]]
name = "toml"
-version = "1.1.5+spec-1.1.0"
+version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12c0ba9680044b4ce98d391a62094047eada0d64860b80166c39f4a6b5640785"
+checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
dependencies = [
- "indexmap",
- "serde_core",
+ "serde",
"serde_spanned",
"toml_datetime",
- "toml_parser",
- "toml_writer",
- "winnow",
+ "toml_edit",
]
[[package]]
name = "toml_datetime"
-version = "1.1.1+spec-1.1.0"
+version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
+checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
dependencies = [
- "serde_core",
+ "serde",
]
[[package]]
-name = "toml_parser"
-version = "1.1.3+spec-1.1.0"
+name = "toml_edit"
+version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56"
+checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_write",
"winnow",
]
[[package]]
-name = "toml_writer"
-version = "1.1.2+spec-1.1.0"
+name = "toml_write"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2"
+checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
[[package]]
name = "typenum"
@@ -1071,9 +1053,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "unicode-segmentation"
-version = "1.13.3"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
+checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]]
name = "unicode-width"
@@ -1115,6 +1097,15 @@ version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+[[package]]
+name = "wasip2"
+version = "1.0.0+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03fa2761397e5bd52002cd7e73110c71af2109aca4e521a9f40473fe685b0a24"
+dependencies = [
+ "wit-bindgen",
+]
+
[[package]]
name = "wasm-bindgen"
version = "0.2.127"
@@ -1218,9 +1209,18 @@ dependencies = [
[[package]]
name = "winnow"
-version = "1.0.4"
+version = "0.7.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.45.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81"
+checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36"
[[package]]
name = "zerocopy"
diff --git a/Cargo.toml b/Cargo.toml
index 7169ed1..9258245 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,11 @@
[workspace]
resolver = "2"
members = ["crates/*"]
+exclude = ["vendor/bincode-2.0.1", "vendor/bincode_derive-2.0.1"]
+
+[patch.crates-io]
+bincode = { path = "vendor/bincode-2.0.1" }
+bincode_derive = { path = "vendor/bincode_derive-2.0.1" }
[workspace.package]
version = "0.1.0"
@@ -12,11 +17,11 @@ rust-version = "1.75"
hecs = "0.10"
criterion = "0.5"
crossterm = "0.29"
-bincode = "2"
+bincode = "=2.0.1"
zstd = "0.13"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
-toml = "1"
+toml = "=0.8.23"
sha2 = "0.10"
[profile.release]
diff --git a/crates/hexwork-audio/Cargo.toml b/crates/hexwork-audio/Cargo.toml
index c911b78..c665d72 100644
--- a/crates/hexwork-audio/Cargo.toml
+++ b/crates/hexwork-audio/Cargo.toml
@@ -2,4 +2,5 @@
name = "hexwork-audio"
version = "0.1.0"
edition = "2021"
+rust-version.workspace = true
description = "Tiny terminal-bell synth, optional rodio feature-gated"
diff --git a/crates/hexwork-cli/Cargo.toml b/crates/hexwork-cli/Cargo.toml
index d4e3bf1..f1e786f 100644
--- a/crates/hexwork-cli/Cargo.toml
+++ b/crates/hexwork-cli/Cargo.toml
@@ -2,6 +2,7 @@
name = "hexwork-cli"
version = "0.1.0"
edition = "2021"
+rust-version.workspace = true
description = "HEXWORK binary: arg parsing, game loop, panic epitaph writer"
[[bin]]
diff --git a/crates/hexwork-cli/tests/routes.rs b/crates/hexwork-cli/tests/routes.rs
index c9acc5f..0c42512 100644
--- a/crates/hexwork-cli/tests/routes.rs
+++ b/crates/hexwork-cli/tests/routes.rs
@@ -209,7 +209,7 @@ fn grate_mother_death_inputs_from(seed: u64, town_start: Cell) -> Vec {
access,
blockers,
);
- inputs.extend(std::iter::repeat_n(Input::Confirm, 4));
+ inputs.extend([Input::Confirm; 4]);
inputs
}
diff --git a/crates/hexwork-content/Cargo.toml b/crates/hexwork-content/Cargo.toml
index 831ad85..301cc09 100644
--- a/crates/hexwork-content/Cargo.toml
+++ b/crates/hexwork-content/Cargo.toml
@@ -2,6 +2,7 @@
name = "hexwork-content"
version = "0.1.0"
edition = "2021"
+rust-version.workspace = true
description = "Data-file loading and validation: monsters, items, hymns, gods, contracts"
[dependencies]
diff --git a/crates/hexwork-content/src/load.rs b/crates/hexwork-content/src/load.rs
index 810157a..9562ac6 100644
--- a/crates/hexwork-content/src/load.rs
+++ b/crates/hexwork-content/src/load.rs
@@ -319,4 +319,94 @@ mod tests {
assert_eq!(err.line, Some(2), "error must point at line 2");
assert!(err.to_string().starts_with("bad-file.toml:2: "));
}
+
+ #[test]
+ fn canonical_items_parser_fixed_toml_diagnostics_preserve_literal_lines() {
+ struct DiagnosticCase {
+ name: &'static str,
+ input: &'static str,
+ expected_line: usize,
+ }
+
+ let cases = [
+ DiagnosticCase {
+ name: "unfinished_array_with_terminal_lf",
+ input: "# fixture\n[[item]]\nid = [\n",
+ expected_line: 4,
+ },
+ DiagnosticCase {
+ name: "unfinished_array_with_extra_blank_lines",
+ input: "# fixture\n[[item]]\nid = [\n\n\n",
+ expected_line: 6,
+ },
+ DiagnosticCase {
+ name: "unfinished_array_without_terminal_lf",
+ input: "# fixture\n[[item]]\nid = [",
+ expected_line: 3,
+ },
+ DiagnosticCase {
+ name: "incomplete_assignment",
+ input: "x =\n",
+ expected_line: 1,
+ },
+ DiagnosticCase {
+ name: "utf8_incomplete_array",
+ input: "x = [\"é\"",
+ expected_line: 1,
+ },
+ DiagnosticCase {
+ name: "unfinished_array_crlf",
+ input: "# fixture\r\n[[item]]\r\nid = [\r\n",
+ expected_line: 4,
+ },
+ DiagnosticCase {
+ name: "invalid_token_before_newline",
+ input: "x = ?\ny = 1\n",
+ expected_line: 1,
+ },
+ DiagnosticCase {
+ name: "trailing_comment_and_blank_line",
+ input: "x = [\n# trailing comment\n\n",
+ expected_line: 4,
+ },
+ DiagnosticCase {
+ name: "trailing_horizontal_layout",
+ input: "x = [\n \t\r\n",
+ expected_line: 3,
+ },
+ DiagnosticCase {
+ name: "unterminated_multiline_basic_string",
+ input: "x = \"\"\"\n# apparent comment\n",
+ expected_line: 3,
+ },
+ DiagnosticCase {
+ name: "unterminated_multiline_literal_string",
+ input: "x = '''\n# apparent comment\n",
+ expected_line: 3,
+ },
+ DiagnosticCase {
+ name: "array_after_valid_multiline_string",
+ input: "x = [\"\"\"alpha\n# content\n\"\"\"",
+ expected_line: 3,
+ },
+ DiagnosticCase {
+ name: "array_with_trailing_comment",
+ input: "x = [\n 1,\n # trailing\n",
+ expected_line: 4,
+ },
+ ];
+
+ for case in cases {
+ let err = parse_text::(case.input, "items-fixture.toml")
+ .expect_err("every fixed diagnostic input must be malformed TOML");
+ assert_eq!(err.file, "items-fixture.toml", "case {}", case.name);
+ assert_eq!(err.line, Some(case.expected_line), "case {}", case.name);
+ assert!(
+ err.to_string()
+ .starts_with(&format!("items-fixture.toml:{}: ", case.expected_line)),
+ "case {}",
+ case.name
+ );
+ }
+ }
}
diff --git a/crates/hexwork-content/tests/runtime_pack.rs b/crates/hexwork-content/tests/runtime_pack.rs
index 72ff2c6..14ee7a7 100644
--- a/crates/hexwork-content/tests/runtime_pack.rs
+++ b/crates/hexwork-content/tests/runtime_pack.rs
@@ -167,16 +167,159 @@ fn missing_root_error_names_first_manifest_path() {
fn malformed_temp_pack_preserves_file_and_line() {
let scratch = ScratchRoot::copy_of_real_pack("malformed");
let items_path = scratch.path().join("assets/data/items.toml");
- let malformed = "# malformed runtime-pack fixture\n[[item]]\nid = [\n";
+ let malformed = "# malformed runtime-pack fixture\n[[item]]\nid = ?\n";
fs::write(&items_path, malformed).expect("write malformed scratch items file");
let error = RuntimePack::load(scratch.path()).expect_err("malformed TOML must fail");
+ let expected_path = items_path.to_string_lossy().into_owned();
- assert!(error
- .file()
- .expect("parse error has a file")
- .ends_with("assets/data/items.toml"));
+ let load_error = match &error {
+ RuntimePackError::Load(load_error) => load_error,
+ other => panic!("expected a load error, got {other:?}"),
+ };
+ assert_eq!(load_error.file, expected_path);
+ assert_eq!(load_error.line, Some(3));
assert_eq!(error.line(), Some(3));
- assert!(error.to_string().contains(":3:"));
+ assert_eq!(error.file(), Some(expected_path.as_str()));
+ assert!(error
+ .to_string()
+ .starts_with(&format!("{expected_path}:3: ")));
+}
+
+#[test]
+fn unfinished_array_at_eof_preserves_file_and_parser_line() {
+ let scratch = ScratchRoot::copy_of_real_pack("unfinished-array-at-eof");
+ let items_path = scratch.path().join("assets/data/items.toml");
+ // TOML 0.8.23 anchors this unfinished EOF span at parser line 4, rather
+ // than the prior-token line 3 reported by the former TOML parser. Keep
+ // these original bytes and assert the pinned parser's observable result.
+ let malformed = "# malformed runtime-pack fixture\n[[item]]\nid = [\n";
+ fs::write(&items_path, malformed).expect("write unfinished-array fixture");
+ let error = RuntimePack::load(scratch.path()).expect_err("unfinished TOML must fail");
+ let expected_path = items_path.to_string_lossy().into_owned();
+
+ let load_error = match &error {
+ RuntimePackError::Load(load_error) => load_error,
+ other => panic!("expected a load error, got {other:?}"),
+ };
+ assert_eq!(load_error.file, expected_path);
+ assert_eq!(load_error.line, Some(4));
+ assert_eq!(error.line(), Some(4));
+ assert_eq!(error.file(), Some(expected_path.as_str()));
+ assert!(error
+ .to_string()
+ .starts_with(&format!("{expected_path}:4: ")));
+}
+
+#[test]
+fn runtime_pack_fixed_toml_diagnostics_preserve_literal_lines() {
+ struct DiagnosticCase {
+ name: &'static str,
+ input: &'static str,
+ expected_line: usize,
+ }
+
+ let cases = [
+ DiagnosticCase {
+ name: "unfinished_array_with_terminal_lf",
+ input: "# fixture\n[[item]]\nid = [\n",
+ expected_line: 4,
+ },
+ DiagnosticCase {
+ name: "unfinished_array_with_extra_blank_lines",
+ input: "# fixture\n[[item]]\nid = [\n\n\n",
+ expected_line: 6,
+ },
+ DiagnosticCase {
+ name: "unfinished_array_without_terminal_lf",
+ input: "# fixture\n[[item]]\nid = [",
+ expected_line: 3,
+ },
+ DiagnosticCase {
+ name: "incomplete_assignment",
+ input: "x =\n",
+ expected_line: 1,
+ },
+ DiagnosticCase {
+ name: "utf8_incomplete_array",
+ input: "x = [\"é\"",
+ expected_line: 1,
+ },
+ DiagnosticCase {
+ name: "unfinished_array_crlf",
+ input: "# fixture\r\n[[item]]\r\nid = [\r\n",
+ expected_line: 4,
+ },
+ DiagnosticCase {
+ name: "invalid_token_before_newline",
+ input: "x = ?\ny = 1\n",
+ expected_line: 1,
+ },
+ DiagnosticCase {
+ name: "trailing_comment_and_blank_line",
+ input: "x = [\n# trailing comment\n\n",
+ expected_line: 4,
+ },
+ DiagnosticCase {
+ name: "trailing_horizontal_layout",
+ input: "x = [\n \t\r\n",
+ expected_line: 3,
+ },
+ DiagnosticCase {
+ name: "unterminated_multiline_basic_string",
+ input: "x = \"\"\"\n# apparent comment\n",
+ expected_line: 3,
+ },
+ DiagnosticCase {
+ name: "unterminated_multiline_literal_string",
+ input: "x = '''\n# apparent comment\n",
+ expected_line: 3,
+ },
+ DiagnosticCase {
+ name: "array_after_valid_multiline_string",
+ input: "x = [\"\"\"alpha\n# content\n\"\"\"",
+ expected_line: 3,
+ },
+ DiagnosticCase {
+ name: "array_with_trailing_comment",
+ input: "x = [\n 1,\n # trailing\n",
+ expected_line: 4,
+ },
+ ];
+
+ for case in cases {
+ let scratch = ScratchRoot::copy_of_real_pack(case.name);
+ let items_path = scratch.path().join("assets/data/items.toml");
+ fs::write(&items_path, case.input).expect("write diagnostic fixture");
+ let error = RuntimePack::load(scratch.path())
+ .expect_err("every fixed diagnostic input must be malformed TOML");
+ let expected_path = items_path.to_string_lossy().into_owned();
+
+ let load_error = match &error {
+ RuntimePackError::Load(load_error) => load_error,
+ other => panic!("case {}: expected a load error, got {other:?}", case.name),
+ };
+ assert_eq!(load_error.file, expected_path, "case {}", case.name);
+ assert_eq!(
+ load_error.line,
+ Some(case.expected_line),
+ "case {}",
+ case.name
+ );
+ assert_eq!(error.line(), Some(case.expected_line), "case {}", case.name);
+ assert_eq!(
+ error.file(),
+ Some(expected_path.as_str()),
+ "case {}",
+ case.name
+ );
+ assert!(
+ error
+ .to_string()
+ .starts_with(&format!("{expected_path}:{}: ", case.expected_line)),
+ "case {}",
+ case.name
+ );
+ }
}
#[test]
diff --git a/crates/hexwork-save/Cargo.toml b/crates/hexwork-save/Cargo.toml
index 451e3c2..37216ff 100644
--- a/crates/hexwork-save/Cargo.toml
+++ b/crates/hexwork-save/Cargo.toml
@@ -2,6 +2,7 @@
name = "hexwork-save"
version = "0.1.0"
edition = "2021"
+rust-version.workspace = true
description = "Saves, lineage vault, .hexdemo replays (docs/04 §4.7)"
[dependencies]
diff --git a/crates/hexwork-save/src/artifact/mod.rs b/crates/hexwork-save/src/artifact/mod.rs
index a56ac2e..243010d 100644
--- a/crates/hexwork-save/src/artifact/mod.rs
+++ b/crates/hexwork-save/src/artifact/mod.rs
@@ -458,9 +458,10 @@ impl ArtifactStore {
milestone.clone(),
)?;
self.vault = candidate;
- create_managed_directory(&run_dir).inspect_err(|_error| {
+ if let Err(error) = create_managed_directory(&run_dir) {
self.close_terminal_barrier();
- })?;
+ return Err(error);
+ }
let token = RunAllocation {
lineage_id: self.vault.lineage_id,
run_id,
diff --git a/crates/hexwork-save/src/artifact/tests.rs b/crates/hexwork-save/src/artifact/tests.rs
index ef207bd..ea1080d 100644
--- a/crates/hexwork-save/src/artifact/tests.rs
+++ b/crates/hexwork-save/src/artifact/tests.rs
@@ -6,7 +6,8 @@ use hexwork_core::runtime::ActorIdentity;
use hexwork_core::state::State;
use std::collections::VecDeque;
use std::process::{Command, Stdio};
-use std::sync::atomic::{AtomicU64, Ordering};
+use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
+use std::sync::Arc;
use std::time::{Duration, Instant};
static NEXT_ROOT: AtomicU64 = AtomicU64::new(1);
@@ -113,6 +114,22 @@ impl durable::IoHooks for ScriptedHooks {
}
}
+struct DirectoryConflictHooks {
+ run_dir: PathBuf,
+ fired: Arc,
+}
+impl durable::IoHooks for DirectoryConflictHooks {
+ fn fail(&mut self, point: durable::FaultPoint, path: &Path) -> std::io::Result<()> {
+ if point == durable::FaultPoint::PublishedSyncFailed
+ && path.ends_with(VAULT_FILE_NAME)
+ && !self.fired.swap(true, Ordering::Relaxed)
+ {
+ fs::write(&self.run_dir, b"managed directory conflict")?;
+ }
+ Ok(())
+ }
+}
+
#[derive(Debug)]
struct BoundarySnapshot {
milestone: ArtifactMilestone,
@@ -863,6 +880,45 @@ fn allocation_before_and_after_publish_faults_preserve_or_adopt_counter_exactly(
assert_eq!(next.run_id().sequence(), 2);
}
+#[test]
+fn allocation_directory_failure_closes_barrier_after_durable_counter() {
+ let root = Scratch::new("allocation-directory-conflict");
+ let pack = pack();
+ let (mut store, _) = ArtifactStore::open(&root.0).unwrap();
+ store
+ .recover(&pack, RecoveryLimits::default(), None)
+ .unwrap();
+ let sequence = store.vault_view().unwrap().next_run_sequence;
+ let run_id = RunId::new(sequence).unwrap();
+ let run_dir = root.0.join(RUNS_DIRECTORY_NAME).join(run_id.to_string());
+ let fired = Arc::new(AtomicBool::new(false));
+ store.set_io_hooks(DirectoryConflictHooks {
+ run_dir: run_dir.clone(),
+ fired: fired.clone(),
+ });
+ let mut observer = CountingObserver::default();
+ let error = store.allocate_run_with_observer(&mut observer).unwrap_err();
+
+ assert!(fired.load(Ordering::Relaxed));
+ assert_eq!(error.class(), ArtifactErrorClass::Conflict);
+ assert_eq!(error.code(), "managed-type-conflict");
+ assert_eq!(error.context(), run_dir.to_str().unwrap());
+ assert!(run_dir.is_file());
+ assert_eq!(
+ crate::decode_vault(&fs::read(root.0.join(VAULT_FILE_NAME)).unwrap())
+ .unwrap()
+ .next_run_sequence,
+ sequence + 1
+ );
+ assert_eq!(store.vault_view().unwrap().next_run_sequence, sequence + 1);
+ assert!(store.allocations.is_empty());
+ assert_eq!(observer.0, 0);
+ assert!(!store.recovery_is_complete());
+ let next = store.allocate_run().unwrap_err();
+ assert_eq!(next.class(), ArtifactErrorClass::NotReady);
+ assert_eq!(next.code(), "managed-recovery-required");
+}
+
#[test]
fn live_observer_sees_each_durable_boundary_before_next_mutation() {
let root = Scratch::new("observer-boundaries");
diff --git a/crates/hexwork-term/Cargo.toml b/crates/hexwork-term/Cargo.toml
index 0eb1d19..8259230 100644
--- a/crates/hexwork-term/Cargo.toml
+++ b/crates/hexwork-term/Cargo.toml
@@ -2,6 +2,7 @@
name = "hexwork-term"
version = "0.1.0"
edition = "2021"
+rust-version.workspace = true
description = "Terminal abstraction: raw mode, input, resize, truecolor detect"
[dependencies]
diff --git a/crates/hexwork-ui/Cargo.toml b/crates/hexwork-ui/Cargo.toml
index d0ac7db..ec5d190 100644
--- a/crates/hexwork-ui/Cargo.toml
+++ b/crates/hexwork-ui/Cargo.toml
@@ -2,6 +2,7 @@
name = "hexwork-ui"
version = "0.1.0"
edition = "2021"
+rust-version.workspace = true
description = "Screens, HUD, log, menus, look mode, chargen"
[dependencies]
diff --git a/crates/hexwork-ui/src/transfer.rs b/crates/hexwork-ui/src/transfer.rs
index 774f460..906fe61 100644
--- a/crates/hexwork-ui/src/transfer.rs
+++ b/crates/hexwork-ui/src/transfer.rs
@@ -373,7 +373,7 @@ mod tests {
width: usize::MAX,
height: usize::MAX,
body_rows: std::iter::once(format!("visible\u{85}{combining}"))
- .chain(std::iter::repeat_n("unread row".to_owned(), MAX_HEIGHT))
+ .chain(std::iter::repeat("unread row".to_owned()).take(MAX_HEIGHT))
.chain(std::iter::once("hidden sentinel".to_owned()))
.collect(),
content_clipped: false,
diff --git a/crates/hexwork-worldgen/Cargo.toml b/crates/hexwork-worldgen/Cargo.toml
index fb0bbec..017fe7d 100644
--- a/crates/hexwork-worldgen/Cargo.toml
+++ b/crates/hexwork-worldgen/Cargo.toml
@@ -2,6 +2,7 @@
name = "hexwork-worldgen"
version = "0.1.0"
edition = "2021"
+rust-version.workspace = true
description = "Seeded floor and town generation: anchor rooms plus systemic fill"
[dependencies]
diff --git a/crates/hexwork-worldgen/src/runtime.rs b/crates/hexwork-worldgen/src/runtime.rs
index e28f9c1..65b85b3 100644
--- a/crates/hexwork-worldgen/src/runtime.rs
+++ b/crates/hexwork-worldgen/src/runtime.rs
@@ -499,11 +499,12 @@ fn validate_common(
if !is_supported_standing(writes, bounds, connector.access) {
return Err(invalid("connector access lacks landing support/headroom"));
}
- if map
- .get(&cell_key(connector.column))
- .is_none_or(|voxel| voxel.occ != 0)
- {
- return Err(invalid("connector endpoint is not physically carved"));
+ match map.get(&cell_key(connector.column)) {
+ None => return Err(invalid("connector endpoint is not physically carved")),
+ Some(voxel) if voxel.occ != 0 => {
+ return Err(invalid("connector endpoint is not physically carved"));
+ }
+ Some(_) => {}
}
let endpoint = connector.connector.from.map(|value| value as i32);
let other_endpoint = connector.connector.to.map(|value| value as i32);
@@ -602,7 +603,7 @@ impl WorldPlan {
)?;
for road in &self.roads {
if road.width == 0
- || road.width.is_multiple_of(2)
+ || road.width % 2 == 0
|| road.from[2] != road.to[2]
|| (road.from[0] != road.to[0] && road.from[1] != road.to[1])
{
@@ -1921,7 +1922,7 @@ fn carve_canonical_topology(
carve_line(map, [2, y.min(20), walk_z], [30, y.min(20), walk_z]);
}
let channel_y = 3 + (mode as i32 * 2 % 16);
- if mode.is_multiple_of(2) {
+ if mode % 2 == 0 {
paint_water_line(
map,
[3, channel_y, walk_z],
@@ -2150,7 +2151,7 @@ pub(crate) fn build_playable_floor(master_seed: u64, depth: u8) -> FloorPlan {
for index in 0..count {
let vent_position = [
14 + index as i32 * 2 + shift,
- if depth.is_multiple_of(2) { 5 } else { 16 },
+ if depth % 2 == 0 { 5 } else { 16 },
walk_z,
];
let vent_access = [vent_position[0] - 1, vent_position[1], walk_z];
diff --git a/crates/hexwork-worldgen/tests/runtime_plans.rs b/crates/hexwork-worldgen/tests/runtime_plans.rs
index 3abcdb8..a7c7c70 100644
--- a/crates/hexwork-worldgen/tests/runtime_plans.rs
+++ b/crates/hexwork-worldgen/tests/runtime_plans.rs
@@ -568,6 +568,15 @@ fn malformed_blocked_connector_column_is_rejected() {
assert!(plan.validate().is_err());
}
+#[test]
+fn malformed_missing_connector_column_is_rejected() {
+ let mut plan = playable_floor(26, 4);
+ let column = plan.connectors[0].column;
+ plan.writes.retain(|write| write.cell != column);
+ let error = plan.validate().unwrap_err();
+ assert_eq!(error.message, "connector endpoint is not physically carved");
+}
+
#[test]
fn all_counted_vertical_connectors_have_depth_and_real_pairs() {
let town = milthollow(30);
diff --git a/vendor/README.md b/vendor/README.md
new file mode 100644
index 0000000..343c208
--- /dev/null
+++ b/vendor/README.md
@@ -0,0 +1,63 @@
+# Exact-source bincode 2.0.1 compatibility backport
+
+HEXWORK maintains Rust 1.75 support metadata for the exact published `bincode`
+2.0.1 and `bincode_derive` 2.0.1 packages. This is a local maintenance claim,
+**not an upstream Rust 1.75 support claim**. Upstream declares Rust 1.85.0.
+The only changes to the extracted packages are the two `Cargo.toml`
+`rust-version` declarations and bincode's exact `=2.0.1` derive dependency pin.
+No implementation, unsafe code, allocation/claim behavior, decoding limit,
+feature definition, original author manifest, or package license is changed.
+
+## Provenance and licensing
+
+Both original `.crate` archives are retained under `upstream/`. Their SHA256
+checksums were authenticated against the registry entries in baseline
+`e4cfd4c:Cargo.lock` **before extraction**. `provenance.json` records those trust
+anchors, upstream/source identity, all 78 archived files and original SHA256
+values, and the exact permitted manifest deltas. The normalized manifests,
+`Cargo.toml.orig`, READMEs, tests/benches, and hidden release metadata are retained;
+no archived file was omitted. Registry-cache-only extraction markers are not
+part of these published archives. The two packages are MIT
+licensed: see each unchanged `LICENSE.md`. Source upstream is
+; the authenticated packages, rather than
+a moving upstream branch, are the comparison authority.
+
+## Verification and support boundary
+
+Run with Python 3.11 or newer (standard library only):
+
+```
+python3 vendor/verify.py --root vendor
+python3 vendor/verify.py --root vendor --self-test
+```
+
+The verifier reads archives without extraction, authenticates hardcoded baseline
+checksums, validates the complete original inventory, rejects unsafe archive
+members/symlinks and extra/missing package files, compares every non-manifest
+byte, and checks both textual and parsed manifest deltas. Self-tests use
+throwaway copies outside this tree. No production file is repaired by the tool.
+
+The scoped feature set is bincode's existing **default/std/alloc/derive** set;
+serde is not enabled. The diagnostic probe established feasibility on Rust
+1.75 with unchanged codec implementation, not project-wide certification.
+Acceptance additionally requires actual locked Rust 1.75 and stable builds,
+content/parser gates, unchanged genuine v4 save/replay fixture hashes and exact
+re-encoding, and bounded/contextual decoding tests. The root workspace excludes
+these vendor directories from project membership; upstream test suites are not
+silently adopted as workspace targets. Their complete sources remain retained.
+No global project lint suppression is authorized.
+
+Only executed local Linux gates may be claimed. Configured macOS CI does not
+certify an unexecuted macOS build; Windows, optional serde/no-std configurations,
+and other untested features/platforms are outside this repair's proof.
+Production Cargo commands must never bypass Rust-version enforcement.
+
+## Maintenance policy
+
+Monitor upstream issues and releases, including correctness/security reports.
+Do not automatically upgrade the codec, change codec sources, loosen pins, or
+regenerate fixtures. Any future change requires an explicit maintenance plan,
+archive/license/provenance review, exact save/replay byte and decoding-budget
+tests on supported compilers, and independent review. Stop and escalate if a
+compiler requires implementation changes or any fixture/budget drifts. Preserve
+the original archives and trust anchors when reviewing future changes.
diff --git a/vendor/bincode-2.0.1/.cargo_vcs_info.json b/vendor/bincode-2.0.1/.cargo_vcs_info.json
new file mode 100644
index 0000000..6d2c100
--- /dev/null
+++ b/vendor/bincode-2.0.1/.cargo_vcs_info.json
@@ -0,0 +1,6 @@
+{
+ "git": {
+ "sha1": "4673360aa638b2b907dff24538de54f258d157da"
+ },
+ "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/vendor/bincode-2.0.1/.mailmap b/vendor/bincode-2.0.1/.mailmap
new file mode 100644
index 0000000..d562adb
--- /dev/null
+++ b/vendor/bincode-2.0.1/.mailmap
@@ -0,0 +1,3 @@
+Ty Overby
+Ty Overby
+Zoey Riordan
diff --git a/vendor/bincode-2.0.1/.rustfmt.toml b/vendor/bincode-2.0.1/.rustfmt.toml
new file mode 100644
index 0000000..43d4840
--- /dev/null
+++ b/vendor/bincode-2.0.1/.rustfmt.toml
@@ -0,0 +1 @@
+newline_style = "Unix"
diff --git a/vendor/bincode-2.0.1/CODE_OF_CONDUCT.md b/vendor/bincode-2.0.1/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..5849b62
--- /dev/null
+++ b/vendor/bincode-2.0.1/CODE_OF_CONDUCT.md
@@ -0,0 +1,128 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, religion, or sexual identity
+and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the
+ overall community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or
+ advances of any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email
+ address, without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+abuse@dos.cafe.
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series
+of actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or
+permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within
+the community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.0, available at
+https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
+
+Community Impact Guidelines were inspired by [Mozilla's code of conduct
+enforcement ladder](https://github.com/mozilla/diversity).
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see the FAQ at
+https://www.contributor-covenant.org/faq. Translations are available at
+https://www.contributor-covenant.org/translations.
diff --git a/vendor/bincode-2.0.1/Cargo.lock b/vendor/bincode-2.0.1/Cargo.lock
new file mode 100644
index 0000000..cc5084e
--- /dev/null
+++ b/vendor/bincode-2.0.1/Cargo.lock
@@ -0,0 +1,991 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "aliasable"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"
+
+[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "anes"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
+
+[[package]]
+name = "anstyle"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
+
+[[package]]
+name = "autocfg"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+
+[[package]]
+name = "bincode"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "bincode"
+version = "2.0.1"
+dependencies = [
+ "bincode 1.3.3",
+ "bincode_derive",
+ "bumpalo",
+ "chrono",
+ "criterion",
+ "glam",
+ "ouroboros",
+ "rand",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "tempfile",
+ "unty",
+ "uuid",
+]
+
+[[package]]
+name = "bincode_derive"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09"
+dependencies = [
+ "virtue",
+]
+
+[[package]]
+name = "bitflags"
+version = "2.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
+
+[[package]]
+name = "bumpalo"
+version = "3.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
+
+[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
+name = "cast"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
+
+[[package]]
+name = "cc"
+version = "1.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c"
+dependencies = [
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "chrono"
+version = "0.4.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
+dependencies = [
+ "android-tzdata",
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "serde",
+ "wasm-bindgen",
+ "windows-link",
+]
+
+[[package]]
+name = "ciborium"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
+dependencies = [
+ "ciborium-io",
+ "ciborium-ll",
+ "serde",
+]
+
+[[package]]
+name = "ciborium-io"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
+
+[[package]]
+name = "ciborium-ll"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
+dependencies = [
+ "ciborium-io",
+ "half",
+]
+
+[[package]]
+name = "clap"
+version = "4.5.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767"
+dependencies = [
+ "clap_builder",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863"
+dependencies = [
+ "anstyle",
+ "clap_lex",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
+[[package]]
+name = "criterion"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
+dependencies = [
+ "anes",
+ "cast",
+ "ciborium",
+ "clap",
+ "criterion-plot",
+ "is-terminal",
+ "itertools",
+ "num-traits",
+ "once_cell",
+ "oorandom",
+ "plotters",
+ "rayon",
+ "regex",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "tinytemplate",
+ "walkdir",
+]
+
+[[package]]
+name = "criterion-plot"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
+dependencies = [
+ "cast",
+ "itertools",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
+
+[[package]]
+name = "crunchy"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
+
+[[package]]
+name = "either"
+version = "1.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d"
+
+[[package]]
+name = "errno"
+version = "0.3.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
+
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.13.3+wasi-0.2.2",
+ "windows-targets",
+]
+
+[[package]]
+name = "glam"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "half"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
+dependencies = [
+ "cfg-if",
+ "crunchy",
+]
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "hermit-abi"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "is-terminal"
+version = "0.4.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
+
+[[package]]
+name = "js-sys"
+version = "0.3.77"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.170"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
+
+[[package]]
+name = "log"
+version = "0.4.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.20.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
+
+[[package]]
+name = "oorandom"
+version = "11.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
+
+[[package]]
+name = "ouroboros"
+version = "0.18.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59"
+dependencies = [
+ "aliasable",
+ "ouroboros_macro",
+ "static_assertions",
+]
+
+[[package]]
+name = "ouroboros_macro"
+version = "0.18.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "proc-macro2-diagnostics",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "plotters"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
+dependencies = [
+ "num-traits",
+ "plotters-backend",
+ "plotters-svg",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "plotters-backend"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
+
+[[package]]
+name = "plotters-svg"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
+dependencies = [
+ "plotters-backend",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "proc-macro2-diagnostics"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "version_check",
+ "yansi",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom 0.2.15",
+]
+
+[[package]]
+name = "rayon"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
+dependencies = [
+ "crossbeam-deque",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
+[[package]]
+name = "rustix"
+version = "0.38.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
+
+[[package]]
+name = "ryu"
+version = "1.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.218"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.218"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.140"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
+dependencies = [
+ "itoa",
+ "memchr",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "syn"
+version = "2.0.99"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "getrandom 0.3.1",
+ "once_cell",
+ "rustix",
+ "windows-sys",
+]
+
+[[package]]
+name = "tinytemplate"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
+dependencies = [
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe"
+
+[[package]]
+name = "unty"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
+
+[[package]]
+name = "uuid"
+version = "1.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "virtue"
+version = "0.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
+
+[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasi"
+version = "0.13.3+wasi-0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
+dependencies = [
+ "wit-bindgen-rt",
+]
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
+dependencies = [
+ "bumpalo",
+ "log",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "web-sys"
+version = "0.3.77"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "winapi-util"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-link"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3"
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "wit-bindgen-rt"
+version = "0.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "yansi"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
+
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/vendor/bincode-2.0.1/Cargo.toml b/vendor/bincode-2.0.1/Cargo.toml
new file mode 100644
index 0000000..40ffeac
--- /dev/null
+++ b/vendor/bincode-2.0.1/Cargo.toml
@@ -0,0 +1,192 @@
+# 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 = "2021"
+rust-version = "1.75"
+name = "bincode"
+version = "2.0.1"
+authors = [
+ "Ty Overby ",
+ "Zoey Riordan ",
+ "Victor Koenders ",
+]
+build = false
+exclude = [
+ "logo.svg",
+ "examples/*",
+ ".gitignore",
+ ".github/",
+]
+publish = true
+autolib = false
+autobins = false
+autoexamples = false
+autotests = false
+autobenches = false
+description = "A binary serialization / deserialization strategy for transforming structs into bytes and vice versa!"
+documentation = "https://docs.rs/bincode"
+readme = "readme.md"
+keywords = [
+ "binary",
+ "encode",
+ "decode",
+ "serialize",
+ "deserialize",
+]
+categories = [
+ "encoding",
+ "network-programming",
+]
+license = "MIT"
+repository = "https://github.com/bincode-org/bincode"
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = [
+ "--cfg",
+ "docsrs",
+]
+
+[features]
+alloc = ["serde?/alloc"]
+default = [
+ "std",
+ "derive",
+]
+derive = ["bincode_derive"]
+std = [
+ "alloc",
+ "serde?/std",
+]
+
+[lib]
+name = "bincode"
+path = "src/lib.rs"
+
+[[test]]
+name = "alloc"
+path = "tests/alloc.rs"
+
+[[test]]
+name = "atomic"
+path = "tests/atomic.rs"
+
+[[test]]
+name = "basic_types"
+path = "tests/basic_types.rs"
+
+[[test]]
+name = "context"
+path = "tests/context.rs"
+
+[[test]]
+name = "derive"
+path = "tests/derive.rs"
+
+[[test]]
+name = "derive_rename"
+path = "tests/derive_rename.rs"
+
+[[test]]
+name = "error_size"
+path = "tests/error_size.rs"
+
+[[test]]
+name = "issues"
+path = "tests/issues.rs"
+
+[[test]]
+name = "serde"
+path = "tests/serde.rs"
+
+[[test]]
+name = "std"
+path = "tests/std.rs"
+
+[[test]]
+name = "utils"
+path = "tests/utils.rs"
+
+[[bench]]
+name = "inline"
+path = "benches/inline.rs"
+harness = false
+
+[[bench]]
+name = "string"
+path = "benches/string.rs"
+harness = false
+
+[[bench]]
+name = "varint"
+path = "benches/varint.rs"
+harness = false
+
+[dependencies.bincode_derive]
+version = "=2.0.1"
+optional = true
+
+[dependencies.serde]
+version = "1.0"
+optional = true
+default-features = false
+
+[dependencies.unty]
+version = "0.0.4"
+
+[dev-dependencies.bincode_1]
+version = "1.3"
+package = "bincode"
+
+[dev-dependencies.bumpalo]
+version = "3.16.0"
+features = ["collections"]
+
+[dev-dependencies.chrono]
+version = "0.4"
+features = ["serde"]
+
+[dev-dependencies.criterion]
+version = "0.5"
+
+[dev-dependencies.glam]
+version = "0.25"
+features = ["serde"]
+
+[dev-dependencies.ouroboros]
+version = "0.18.3"
+
+[dev-dependencies.rand]
+version = "0.8"
+
+[dev-dependencies.serde]
+version = "1.0"
+features = ["derive"]
+
+[dev-dependencies.serde_derive]
+version = "1.0"
+
+[dev-dependencies.serde_json]
+version = "1.0"
+default-features = false
+
+[dev-dependencies.tempfile]
+version = "3.2"
+
+[dev-dependencies.uuid]
+version = "1.1"
+features = ["serde"]
+
+[profile.bench]
+lto = true
+codegen-units = 1
+debug = 1
diff --git a/vendor/bincode-2.0.1/Cargo.toml.orig b/vendor/bincode-2.0.1/Cargo.toml.orig
new file mode 100644
index 0000000..528b904
--- /dev/null
+++ b/vendor/bincode-2.0.1/Cargo.toml.orig
@@ -0,0 +1,73 @@
+[workspace]
+members = ["derive", "compatibility"]
+
+[package]
+name = "bincode"
+version = "2.0.1" # remember to update html_root_url and bincode_derive
+authors = [
+ "Ty Overby ",
+ "Zoey Riordan ",
+ "Victor Koenders ",
+]
+exclude = ["logo.svg", "examples/*", ".gitignore", ".github/"]
+rust-version = "1.85.0"
+
+publish = true
+
+repository = "https://github.com/bincode-org/bincode"
+documentation = "https://docs.rs/bincode"
+readme = "./readme.md"
+categories = ["encoding", "network-programming"]
+keywords = ["binary", "encode", "decode", "serialize", "deserialize"]
+
+license = "MIT"
+description = "A binary serialization / deserialization strategy for transforming structs into bytes and vice versa!"
+
+edition = "2021"
+
+[features]
+default = ["std", "derive"]
+std = ["alloc", "serde?/std"]
+alloc = ["serde?/alloc"]
+derive = ["bincode_derive"]
+
+[dependencies]
+bincode_derive = { path = "derive", version = "2.0.1", optional = true }
+serde = { version = "1.0", default-features = false, optional = true }
+unty = "0.0.4"
+
+# Used for tests
+[dev-dependencies]
+ouroboros = "0.18.3"
+serde_derive = "1.0"
+serde_json = { version = "1.0", default-features = false }
+tempfile = "3.2"
+criterion = "0.5"
+rand = "0.8"
+uuid = { version = "1.1", features = ["serde"] }
+chrono = { version = "0.4", features = ["serde"] }
+glam = { version = "0.25", features = ["serde"] }
+bincode_1 = { version = "1.3", package = "bincode" }
+serde = { version = "1.0", features = ["derive"] }
+bumpalo = { version = "3.16.0", features = ["collections"] }
+
+[[bench]]
+name = "varint"
+harness = false
+
+[[bench]]
+name = "inline"
+harness = false
+
+[[bench]]
+name = "string"
+harness = false
+
+[profile.bench]
+codegen-units = 1
+debug = 1
+lto = true
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = ["--cfg", "docsrs"]
diff --git a/vendor/bincode-2.0.1/LICENSE.md b/vendor/bincode-2.0.1/LICENSE.md
new file mode 100644
index 0000000..26b1f00
--- /dev/null
+++ b/vendor/bincode-2.0.1/LICENSE.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Ty Overby
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/bincode-2.0.1/benches/inline.rs b/vendor/bincode-2.0.1/benches/inline.rs
new file mode 100644
index 0000000..56f5ade
--- /dev/null
+++ b/vendor/bincode-2.0.1/benches/inline.rs
@@ -0,0 +1,17 @@
+use bincode::config;
+use criterion::{black_box, criterion_group, criterion_main, Criterion};
+
+fn inline_decoder_claim_bytes_read(c: &mut Criterion) {
+ let config = config::standard().with_limit::<100000>();
+ let slice = bincode::encode_to_vec(vec![String::from("Hello world"); 1000], config).unwrap();
+
+ c.bench_function("inline_decoder_claim_bytes_read", |b| {
+ b.iter(|| {
+ let _: (Vec, usize) =
+ black_box(bincode::decode_from_slice(black_box(&slice), config).unwrap());
+ })
+ });
+}
+
+criterion_group!(benches, inline_decoder_claim_bytes_read);
+criterion_main!(benches);
diff --git a/vendor/bincode-2.0.1/benches/string.rs b/vendor/bincode-2.0.1/benches/string.rs
new file mode 100644
index 0000000..f565b4a
--- /dev/null
+++ b/vendor/bincode-2.0.1/benches/string.rs
@@ -0,0 +1,73 @@
+// https://github.com/bincode-org/bincode/issues/618
+
+use bincode::{Decode, Encode};
+use criterion::{black_box, criterion_group, criterion_main, Criterion};
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Default, Encode, Decode)]
+pub struct MyStruct {
+ pub v: Vec,
+ pub string: String,
+ pub number: usize,
+}
+
+impl MyStruct {
+ #[inline]
+ pub fn new(v: Vec, string: String, number: usize) -> Self {
+ Self { v, string, number }
+ }
+}
+
+fn build_data(size: usize) -> Vec {
+ (0..size)
+ .map(|i| {
+ let vec: Vec = (0..i).map(|i| i.to_string().repeat(100)).collect();
+ MyStruct::new(vec, size.to_string(), size)
+ })
+ .collect()
+}
+
+fn index_item_decode(c: &mut Criterion) {
+ let data = build_data(100);
+
+ c.bench_function("bench v1", |b| {
+ b.iter(|| {
+ let _ = black_box(bincode_1::serialize(black_box(&data))).unwrap();
+ });
+ });
+
+ let config = bincode::config::standard();
+ c.bench_function("bench v2 (standard)", |b| {
+ b.iter(|| {
+ let _ = black_box(bincode::encode_to_vec(black_box(&data), config)).unwrap();
+ });
+ });
+
+ let config = bincode::config::legacy();
+ c.bench_function("bench v2 (legacy)", |b| {
+ b.iter(|| {
+ let _ = black_box(bincode::encode_to_vec(black_box(&data), config)).unwrap();
+ });
+ });
+
+ let encodedv1 = bincode_1::serialize(&data).unwrap();
+ let encodedv2 = bincode::encode_to_vec(&data, config).unwrap();
+ assert_eq!(encodedv1, encodedv2);
+
+ c.bench_function("bench v1 decode", |b| {
+ b.iter(|| {
+ let _: Vec =
+ black_box(bincode_1::deserialize(black_box(&encodedv1))).unwrap();
+ });
+ });
+
+ c.bench_function("bench v2 decode (legacy)", |b| {
+ b.iter(|| {
+ let _: (Vec, _) =
+ black_box(bincode::decode_from_slice(black_box(&encodedv1), config)).unwrap();
+ });
+ });
+}
+
+criterion_group!(benches, index_item_decode);
+criterion_main!(benches);
diff --git a/vendor/bincode-2.0.1/benches/varint.rs b/vendor/bincode-2.0.1/benches/varint.rs
new file mode 100644
index 0000000..248ab0a
--- /dev/null
+++ b/vendor/bincode-2.0.1/benches/varint.rs
@@ -0,0 +1,152 @@
+use bincode::config;
+use criterion::{criterion_group, criterion_main, Criterion};
+use rand::distributions::Distribution;
+
+fn slice_varint_u8(c: &mut Criterion) {
+ let mut rng = rand::thread_rng();
+ let dist = rand::distributions::Uniform::from(0..u8::MAX);
+ let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng)))
+ .take(10_000)
+ .collect();
+ let config = config::standard();
+ let bytes = bincode::encode_to_vec(input, config).unwrap();
+
+ c.bench_function("slice_varint_u8", |b| {
+ b.iter(|| {
+ let _: (Vec, usize) = bincode::decode_from_slice(&bytes, config).unwrap();
+ })
+ });
+}
+
+fn slice_varint_u16(c: &mut Criterion) {
+ let mut rng = rand::thread_rng();
+ let dist = rand::distributions::Uniform::from(0..u16::MAX);
+ let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng)))
+ .take(10_000)
+ .collect();
+ let config = config::standard();
+ let bytes = bincode::encode_to_vec(input, config).unwrap();
+
+ c.bench_function("slice_varint_u16", |b| {
+ b.iter(|| {
+ let _: (Vec, usize) = bincode::decode_from_slice(&bytes, config).unwrap();
+ })
+ });
+}
+
+fn slice_varint_u32(c: &mut Criterion) {
+ let mut rng = rand::thread_rng();
+ let dist = rand::distributions::Uniform::from(0..u32::MAX);
+ let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng)))
+ .take(10_000)
+ .collect();
+ let config = config::standard();
+ let bytes = bincode::encode_to_vec(input, config).unwrap();
+
+ c.bench_function("slice_varint_u32", |b| {
+ b.iter(|| {
+ let _: (Vec, usize) = bincode::decode_from_slice(&bytes, config).unwrap();
+ })
+ });
+}
+
+fn slice_varint_u64(c: &mut Criterion) {
+ let mut rng = rand::thread_rng();
+ let dist = rand::distributions::Uniform::from(0..u64::MAX);
+ let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng)))
+ .take(10_000)
+ .collect();
+ let config = config::standard();
+ let bytes = bincode::encode_to_vec(input, config).unwrap();
+
+ c.bench_function("slice_varint_u64", |b| {
+ b.iter(|| {
+ let _: (Vec, usize) = bincode::decode_from_slice(&bytes, config).unwrap();
+ })
+ });
+}
+
+fn bufreader_varint_u8(c: &mut Criterion) {
+ let mut rng = rand::thread_rng();
+ let dist = rand::distributions::Uniform::from(0..u8::MAX);
+ let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng)))
+ .take(10_000)
+ .collect();
+ let config = config::standard();
+ let bytes = bincode::encode_to_vec(input, config).unwrap();
+
+ c.bench_function("bufreader_varint_u8", |b| {
+ b.iter(|| {
+ let _: Vec =
+ bincode::decode_from_reader(&mut std::io::BufReader::new(&bytes[..]), config)
+ .unwrap();
+ })
+ });
+}
+
+fn bufreader_varint_u16(c: &mut Criterion) {
+ let mut rng = rand::thread_rng();
+ let dist = rand::distributions::Uniform::from(0..u16::MAX);
+ let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng)))
+ .take(10_000)
+ .collect();
+ let config = config::standard();
+ let bytes = bincode::encode_to_vec(input, config).unwrap();
+
+ c.bench_function("bufreader_varint_u16", |b| {
+ b.iter(|| {
+ let _: Vec =
+ bincode::decode_from_reader(&mut std::io::BufReader::new(&bytes[..]), config)
+ .unwrap();
+ })
+ });
+}
+
+fn bufreader_varint_u32(c: &mut Criterion) {
+ let mut rng = rand::thread_rng();
+ let dist = rand::distributions::Uniform::from(0..u32::MAX);
+ let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng)))
+ .take(10_000)
+ .collect();
+ let config = config::standard();
+ let bytes = bincode::encode_to_vec(input, config).unwrap();
+
+ c.bench_function("bufreader_varint_u32", |b| {
+ b.iter(|| {
+ let _: Vec =
+ bincode::decode_from_reader(&mut std::io::BufReader::new(&bytes[..]), config)
+ .unwrap();
+ })
+ });
+}
+
+fn bufreader_varint_u64(c: &mut Criterion) {
+ let mut rng = rand::thread_rng();
+ let dist = rand::distributions::Uniform::from(0..u64::MAX);
+ let input: Vec = std::iter::from_fn(|| Some(dist.sample(&mut rng)))
+ .take(10_000)
+ .collect();
+ let config = config::standard();
+ let bytes = bincode::encode_to_vec(input, config).unwrap();
+
+ c.bench_function("bufreader_varint_u64", |b| {
+ b.iter(|| {
+ let _: Vec =
+ bincode::decode_from_reader(&mut std::io::BufReader::new(&bytes[..]), config)
+ .unwrap();
+ })
+ });
+}
+
+criterion_group!(
+ benches,
+ slice_varint_u8,
+ slice_varint_u16,
+ slice_varint_u32,
+ slice_varint_u64,
+ bufreader_varint_u8,
+ bufreader_varint_u16,
+ bufreader_varint_u32,
+ bufreader_varint_u64,
+);
+criterion_main!(benches);
diff --git a/vendor/bincode-2.0.1/docs/migration_guide.md b/vendor/bincode-2.0.1/docs/migration_guide.md
new file mode 100644
index 0000000..afcf80d
--- /dev/null
+++ b/vendor/bincode-2.0.1/docs/migration_guide.md
@@ -0,0 +1,116 @@
+# Migrating from bincode 1 to 2
+
+Bincode 2 now has an optional dependency on `serde`. You can either use `serde`, or use bincode's own `derive` feature and macros.
+
+## From `Options` to `Configuration`
+
+Bincode 1 had the [Options](https://docs.rs/bincode/1/bincode/config/trait.Options.html) trait. This has been replaced with the [Configuration](https://docs.rs/bincode/2/bincode/config/struct.Configuration.html) struct.
+
+If you're using `Options`, you can change it like this:
+
+```rust,ignore
+# old
+bincode_1::DefaultOptions::new().with_varint_encoding()
+
+# new
+bincode_2::config::legacy().with_variable_int_encoding()
+```
+
+If you want to be compatible with bincode 1, use the following table:
+
+| Bincode 1 | Bincode 2 |
+| ---------------------------------------------------------------------- | ----------------------------------------------- |
+| version 1.0 - 1.2 with `bincode_1::DefaultOptions::new().serialize(T)` | `config::legacy()` |
+| version 1.3+ with `bincode_1::DefaultOptions::new().serialize(T)` | `config::legacy().with_variable_int_encoding()` |
+| No explicit `Options`, e.g. `bincode::serialize(T)` | `config::legacy()` |
+
+If you do not care about compatibility with bincode 1, we recommend using `config::standard()`
+
+The following changes have been made:
+
+- `.with_limit(n)` has been changed to `.with_limit::()`.
+- `.with_native_endian()` has been removed. Use `.with_big_endian()` or `with_little_endian()` instead.
+- `.with_varint_encoding()` has been renamed to `.with_variable_int_encoding()`.
+- `.with_fixint_encoding()` has been renamed to `.with_fixed_int_encoding()`.
+- `.reject_trailing_bytes()` has been removed.
+- `.allow_trailing_bytes()` has been removed.
+- You can no longer (de)serialize from the `Options` trait directly. Use one of the `encode_` or `decode_` methods.
+
+Because of confusion with `Options` defaults in bincode 1, we have made `Configuration` mandatory in all calls in bincode 2.
+
+## Migrating with `serde`
+
+You may wish to stick with `serde` when migrating to bincode 2, for example if you are using serde-exclusive derive features such as `#[serde(deserialize_with)]`.
+
+If so, make sure to include bincode 2 with the `serde` feature enabled, and use the `bincode::serde::*` functions instead of `bincode::*` as described below:
+
+```toml
+[dependencies]
+bincode = { version = "2.0", features = ["serde"] }
+
+# Optionally you can disable the `derive` feature:
+# bincode = { version = "2.0", default-features = false, features = ["std", "serde"] }
+```
+
+Then replace the following functions: (`Configuration` is `bincode::config::legacy()` by default)
+
+| Bincode 1 | Bincode 2 |
+| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
+| `bincode::deserialize(&[u8])` | `bincode::serde::decode_from_slice(&[u8], Configuration)`
`bincode::serde::borrow_decode_from_slice(&[u8], Configuration)` |
+| `bincode::deserialize_from(std::io::Read)` | `bincode::serde::decode_from_std_read(std::io::Read, Configuration)` |
+| `bincode::deserialize_from_custom(BincodeRead)` | `bincode::serde::decode_from_reader(Reader, Configuration)` |
+| | |
+| `bincode::serialize(T)` | `bincode::serde::encode_to_vec(T, Configuration)`
`bincode::serde::encode_into_slice(T, &mut [u8], Configuration)` |
+| `bincode::serialize_into(std::io::Write, T)` | `bincode::serde::encode_into_std_write(T, std::io::Write, Configuration)` |
+| `bincode::serialized_size(T)` | Currently not implemented |
+
+## Migrating from `serde` to `bincode-derive`
+
+`bincode-derive` is enabled by default. If you're using `default-features = false`, make sure to add `features = ["derive"]` to your `Cargo.toml`.
+
+```toml,ignore
+[dependencies]
+bincode = "2.0"
+
+# If you need `no_std` with `alloc`:
+# bincode = { version = "2.0", default-features = false, features = ["derive", "alloc"] }
+
+# If you need `no_std` and no `alloc`:
+# bincode = { version = "2.0", default-features = false, features = ["derive"] }
+```
+
+Replace or add the following attributes. You are able to use both `serde-derive` and `bincode-derive` side-by-side.
+
+| serde-derive | bincode-derive |
+| ------------------------------- | ---------------------------- |
+| `#[derive(serde::Serialize)]` | `#[derive(bincode::Encode)]` |
+| `#[derive(serde::Deserialize)]` | `#[derive(bincode::Decode)]` |
+
+**note:** To implement these traits manually, see the documentation of [Encode](https://docs.rs/bincode/2/bincode/enc/trait.Encode.html) and [Decode](https://docs.rs/bincode/2/bincode/de/trait.Decode.html).
+
+**note:** For more information on using `bincode-derive` with external libraries, see [below](#bincode-derive-and-libraries).
+
+Then replace the following functions: (`Configuration` is `bincode::config::legacy()` by default)
+
+| Bincode 1 | Bincode 2 |
+| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
+| `bincode::deserialize(&[u8])` | `bincode::decode_from_slice(&bytes, Configuration)`
`bincode::borrow_decode_from_slice(&[u8], Configuration)` |
+| `bincode::deserialize_from(std::io::Read)` | `bincode::decode_from_std_read(std::io::Read, Configuration)` |
+| `bincode::deserialize_from_custom(BincodeRead)` | `bincode::decode_from_reader(Reader, Configuration)` |
+| | |
+| `bincode::serialize(T)` | `bincode::encode_to_vec(T, Configuration)`
`bincode::encode_into_slice(t: T, &mut [u8], Configuration)` |
+| `bincode::serialize_into(std::io::Write, T)` | `bincode::encode_into_std_write(T, std::io::Write, Configuration)` |
+| `bincode::serialized_size(T)` | Currently not implemented |
+
+### Bincode derive and libraries
+
+Currently not many libraries support the traits `Encode` and `Decode`. There are a couple of options if you want to use `#[derive(bincode::Encode, bincode::Decode)]`:
+
+- Enable the `serde` feature and add a `#[bincode(with_serde)]` above each field that implements `serde::Serialize/Deserialize` but not `Encode/Decode`
+- Enable the `serde` feature and wrap your field in [bincode::serde::Compat](https://docs.rs/bincode/2/bincode/serde/struct.Compat.html) or [bincode::serde::BorrowCompat](https://docs.rs/bincode/2/bincode/serde/struct.BorrowCompat.html)
+- Make a pull request to the library:
+ - Make sure to be respectful, most of the developers are doing this in their free time.
+ - Add a dependency `bincode = { version = "2.0", default-features = false, optional = true }` to the `Cargo.toml`
+ - Implement [Encode](https://docs.rs/bincode/2/bincode/enc/trait.Encode.html)
+ - Implement [Decode](https://docs.rs/bincode/2/bincode/de/trait.Decode.html)
+ - Make sure both of these implementations have a `#[cfg(feature = "bincode")]` attribute.
diff --git a/vendor/bincode-2.0.1/docs/spec.md b/vendor/bincode-2.0.1/docs/spec.md
new file mode 100644
index 0000000..5e29e72
--- /dev/null
+++ b/vendor/bincode-2.0.1/docs/spec.md
@@ -0,0 +1,335 @@
+# Serialization Specification
+
+_NOTE_: This specification is primarily defined in the context of Rust, but aims to be implementable across different programming languages.
+
+## Definitions
+
+- **Variant**: A specific constructor or case of an enum type.
+- **Variant Payload**: The associated data of a specific enum variant.
+- **Discriminant**: A unique identifier for an enum variant, typically represented as an integer.
+- **Basic Types**: Primitive types that have a direct, well-defined binary representation.
+
+## Endianness
+
+By default, this serialization format uses little-endian byte order for basic numeric types. This means multi-byte values are encoded with their least significant byte first.
+
+Endianness can be configured with the following methods, allowing for big-endian serialization when required:
+
+- [`with_big_endian`](https://docs.rs/bincode/2/bincode/config/struct.Configuration.html#method.with_big_endian)
+- [`with_little_endian`](https://docs.rs/bincode/2/bincode/config/struct.Configuration.html#method.with_little_endian)
+
+### Byte Order Considerations
+
+- Multi-byte values (integers, floats) are affected by endianness
+- Single-byte values (u8, i8) are not affected
+- Struct and collection serialization order is not changed by endianness
+
+## Basic Types
+
+### Boolean Encoding
+
+- Encoded as a single byte
+- `false` is represented by `0`
+- `true` is represented by `1`
+- During deserialization, values other than 0 and 1 will result in an error [`DecodeError::InvalidBooleanValue`](https://docs.rs/bincode/2/bincode/error/enum.DecodeError.html#variant.InvalidBooleanValue)
+
+### Numeric Types
+
+- Encoded based on the configured [IntEncoding](#intencoding)
+- Signed integers use 2's complement representation
+- Floating point types use IEEE 754-2008 standard
+ - `f32`: 4 bytes (binary32)
+ - `f64`: 8 bytes (binary64)
+
+#### Floating Point Special Values
+
+- Subnormal numbers are preserved
+ - Also known as denormalized numbers
+ - Maintain their exact bit representation
+- `NaN` values are preserved
+ - Both quiet and signaling `NaN` are kept as-is
+ - Bit pattern of `NaN` is maintained exactly
+- No normalization or transformation of special values occurs
+- Serialization and deserialization do not alter the bit-level representation
+- Consistent with IEEE 754-2008 standard for floating-point arithmetic
+
+### Character Encoding
+
+- `char` is encoded as a 32-bit unsigned integer representing its Unicode Scalar Value
+- Valid Unicode Scalar Value range:
+ - 0x0000 to 0xD7FF (Basic Multilingual Plane)
+ - 0xE000 to 0x10FFFF (Supplementary Planes)
+- Surrogate code points (0xD800 to 0xDFFF) are not valid
+- Invalid Unicode characters can be acquired via unsafe code, this is handled as:
+ - during serialization: data is written as-is
+ - during deserialization: an error is raised [`DecodeError::InvalidCharEncoding`](https://docs.rs/bincode/2/bincode/error/enum.DecodeError.html#variant.InvalidCharEncoding)
+- No additional metadata or encoding scheme beyond the raw code point value
+
+All tuples have no additional bytes, and are encoded in their specified order, e.g.
+
+```rust
+let tuple = (u32::min_value(), i32::max_value()); // 8 bytes
+let encoded = bincode::encode_to_vec(tuple, bincode::config::legacy()).unwrap();
+assert_eq!(encoded.as_slice(), &[
+ 0, 0, 0, 0, // 4 bytes for first type: u32
+ 255, 255, 255, 127 // 4 bytes for second type: i32
+]);
+```
+
+## IntEncoding
+
+Bincode currently supports 2 different types of `IntEncoding`. With the default config, `VarintEncoding` is selected.
+
+### VarintEncoding
+
+Encoding an unsigned integer v (of any type excepting u8/i8) works as follows:
+
+1. If `u < 251`, encode it as a single byte with that value.
+1. If `251 <= u < 2**16`, encode it as a literal byte 251, followed by a u16 with value `u`.
+1. If `2**16 <= u < 2**32`, encode it as a literal byte 252, followed by a u32 with value `u`.
+1. If `2**32 <= u < 2**64`, encode it as a literal byte 253, followed by a u64 with value `u`.
+1. If `2**64 <= u < 2**128`, encode it as a literal byte 254, followed by a u128 with value `u`.
+
+`usize` is being encoded/decoded as a `u64` and `isize` is being encoded/decoded as a `i64`.
+
+See the documentation of [VarintEncoding](https://docs.rs/bincode/2/bincode/config/struct.Configuration.html#method.with_variable_int_encoding) for more information.
+
+### FixintEncoding
+
+- Fixed size integers are encoded directly
+- Enum discriminants are encoded as u32
+- Lengths and usize are encoded as u64
+
+See the documentation of [FixintEncoding](https://docs.rs/bincode/2/bincode/config/struct.Configuration.html#method.with_fixed_int_encoding) for more information.
+
+## Enums
+
+Enums are encoded with their variant first, followed by optionally the variant fields. The variant index is based on the `IntEncoding` during serialization.
+
+Both named and unnamed fields are serialized with their values only, and therefore encode to the same value.
+
+```rust
+#[derive(bincode::Encode)]
+pub enum SomeEnum {
+ A,
+ B(u32),
+ C { value: u32 },
+}
+
+// SomeEnum::A
+let encoded = bincode::encode_to_vec(SomeEnum::A, bincode::config::legacy()).unwrap();
+assert_eq!(encoded.as_slice(), &[
+ 0, 0, 0, 0, // first variant, A
+ // no extra bytes because A has no fields
+]);
+
+// SomeEnum::B(0)
+let encoded = bincode::encode_to_vec(SomeEnum::B(0), bincode::config::legacy()).unwrap();
+assert_eq!(encoded.as_slice(), &[
+ 1, 0, 0, 0, // second variant, B
+ 0, 0, 0, 0 // B has 1 unnamed field, which is an u32, so 4 bytes
+]);
+
+// SomeEnum::C { value: 0u32 }
+let encoded = bincode::encode_to_vec(SomeEnum::C { value: 0u32 }, bincode::config::legacy()).unwrap();
+assert_eq!(encoded.as_slice(), &[
+ 2, 0, 0, 0, // third variant, C
+ 0, 0, 0, 0 // C has 1 named field which is a u32, so 4 bytes
+]);
+```
+
+### Options
+
+`Option` is always serialized using a single byte for the discriminant, even in `Fixint` encoding (which normally uses a `u32` for discriminant).
+
+```rust
+let data: Option = Some(123);
+let encoded = bincode::encode_to_vec(data, bincode::config::legacy()).unwrap();
+assert_eq!(encoded.as_slice(), &[
+ 1, 123, 0, 0, 0 // the Some(..) tag is the leading 1
+]);
+
+let data: Option = None;
+let encoded = bincode::encode_to_vec(data, bincode::config::legacy()).unwrap();
+assert_eq!(encoded.as_slice(), &[
+ 0 // the None tag is simply 0
+]);
+```
+
+# Collections
+
+## General Collection Serialization
+
+Collections are encoded with their length value first, followed by each entry of the collection. The length value is based on the configured `IntEncoding`.
+
+### Serialization Considerations
+
+- Length is always serialized first
+- Entries are serialized in the order they are returned from the iterator implementation.
+ - Iteration order depends on the collection type
+ - Ordered collections (e.g., `Vec`): Iteration from lowest to highest index
+ - Unordered collections (e.g., `HashMap`): Implementation-defined iteration order
+- Duplicate keys are not checked in bincode, but may be resulting in an error when decoding a container from a list of pairs.
+
+### Handling of Specific Collection Types
+
+#### Linear Collections (`Vec`, Arrays, etc.)
+
+- Serialized by iterating from lowest to highest index
+- Length prefixed
+- Each item serialized sequentially
+
+```rust
+let list = vec![0u8, 1u8, 2u8];
+let encoded = bincode::encode_to_vec(list, bincode::config::legacy()).unwrap();
+assert_eq!(encoded.as_slice(), &[
+ 3, 0, 0, 0, 0, 0, 0, 0, // length of 3u64
+ 0, // entry 0
+ 1, // entry 1
+ 2, // entry 2
+]);
+```
+
+#### Key-Value Collections (`HashMap`, etc.)
+
+- Serialized as a sequence of key-value pairs
+- Iteration order is implementation-defined
+- Each entry is a tuple of (key, value)
+
+### Special Collection Considerations
+
+- Bincode will serialize the entries based on the iterator order.
+- Deserialization is deterministic but the collection implementation might not guarantee the same order as serialization.
+
+**Note**: Fixed-length arrays do not have their length encoded. See [Arrays](#arrays) for details.
+
+# String and &str
+
+## Encoding Principles
+
+- Strings are encoded as UTF-8 byte sequences
+- No null terminator is added
+- No Byte Order Mark (BOM) is written
+- Unicode non-characters are preserved
+
+### Encoding Details
+
+- Length is encoded first using the configured `IntEncoding`
+- Raw UTF-8 bytes follow the length
+- Supports the full range of valid UTF-8 sequences
+- `U+0000` and other code points can appear freely within the string
+
+### Unicode Handling
+
+- During serialization, the string is encoded as a sequence of the given bytes.
+ - Rust strings are UTF-8 encoded by default, but this is not enforced by bincode
+- No normalization or transformation of text
+- If an invalid UTF-8 sequence is encountered during decoding, an [`DecodeError::Utf8`](https://docs.rs/bincode/2/bincode/error/enum.DecodeError.html#variant.Utf8) error is raised
+
+```rust
+let str = "Hello 🌍"; // Mixed ASCII and Unicode
+
+let encoded = bincode::encode_to_vec(str, bincode::config::legacy()).unwrap();
+assert_eq!(encoded.as_slice(), &[
+ 10, 0, 0, 0, 0, 0, 0, 0, // length of the string, 10 bytes
+ b'H', b'e', b'l', b'l', b'o', b' ', 0xF0, 0x9F, 0x8C, 0x8D // UTF-8 encoded string
+]);
+```
+
+### Comparison with Other Types
+
+- Treated similarly to `Vec` in serialization
+- See [Collections](#collections) for more information about length and entry encoding
+
+# Arrays
+
+Array length is never encoded.
+
+Note that `&[T]` is encoded as a [Collection](#collections).
+
+```rust
+let arr: [u8; 5] = [10, 20, 30, 40, 50];
+let encoded = bincode::encode_to_vec(arr, bincode::config::legacy()).unwrap();
+assert_eq!(encoded.as_slice(), &[
+ 10, 20, 30, 40, 50, // the bytes
+]);
+
+```
+
+This applies to any type `T` that implements `Encode`/`Decode`
+
+```rust
+#[derive(bincode::Encode)]
+struct Foo {
+ first: u8,
+ second: u8
+};
+
+let arr: [Foo; 2] = [
+ Foo {
+ first: 10,
+ second: 20,
+ },
+ Foo {
+ first: 30,
+ second: 40,
+ },
+];
+
+let encoded = bincode::encode_to_vec(&arr, bincode::config::legacy()).unwrap();
+assert_eq!(encoded.as_slice(), &[
+ 10, 20, // First Foo
+ 30, 40, // Second Foo
+]);
+```
+
+## TupleEncoding
+
+Tuple fields are serialized in first-to-last declaration order, with no additional metadata.
+
+- No length prefix is added
+- Fields are encoded sequentially
+- No padding or alignment adjustments are made
+- Order of serialization is deterministic and matches the tuple's declaration order
+
+## StructEncoding
+
+Struct fields are serialized in first-to-last declaration order, with no metadata representing field names.
+
+- No length prefix is added
+- Fields are encoded sequentially
+- No padding or alignment adjustments are made
+- Order of serialization is deterministic and matches the struct's field declaration order
+- Both named and unnamed fields are serialized identically
+
+## EnumEncoding
+
+Enum variants are encoded with a discriminant followed by optional variant payload.
+
+### Discriminant Allocation
+
+- Discriminants are automatically assigned by the derive macro in declaration order
+ - First variant starts at 0
+ - Subsequent variants increment by 1
+- Explicit discriminant indices are currently not supported
+- Discriminant is always represented as a `u32` during serialization. See [Discriminant Representation](#discriminant-representation) for more details.
+- Maintains the original enum variant semantics during encoding
+
+### Variant Payload Encoding
+
+- Tuple variants: Fields serialized in declaration order
+- Struct variants: Fields serialized in declaration order
+- Unit variants: No additional data encoded
+
+### Discriminant Representation
+
+- Always encoded as a `u32`
+- Encoding method depends on the configured `IntEncoding`
+ - `VarintEncoding`: Variable-length encoding
+ - `FixintEncoding`: Fixed 4-byte representation
+
+### Handling of Variant Payloads
+
+- Payload is serialized immediately after the discriminant
+- No additional metadata about field names or types
+- Payload structure matches the variant's definition
diff --git a/vendor/bincode-2.0.1/readme.md b/vendor/bincode-2.0.1/readme.md
new file mode 100644
index 0000000..d04ba09
--- /dev/null
+++ b/vendor/bincode-2.0.1/readme.md
@@ -0,0 +1,110 @@
+# Bincode
+
+
+[](https://github.com/bincode-org/bincode/actions)
+[](https://crates.io/crates/bincode)
+[](https://opensource.org/licenses/MIT)
+
+[](https://matrix.to/#/#bincode:matrix.org)
+
+A compact encoder / decoder pair that uses a binary zero-fluff encoding scheme.
+The size of the encoded object will be the same or smaller than the size that
+the object takes up in memory in a running Rust program.
+
+In addition to exposing two simple functions
+(one that encodes to `Vec`, and one that decodes from `&[u8]`),
+binary-encode exposes a Reader/Writer API that makes it work
+perfectly with other stream-based APIs such as Rust files, network streams,
+and the [flate2-rs](https://github.com/rust-lang/flate2-rs) compression
+library.
+
+## [API Documentation](https://docs.rs/bincode/)
+
+## Bincode in the Wild
+
+* [google/tarpc](https://github.com/google/tarpc): Bincode is used to serialize and deserialize networked RPC messages.
+* [servo/webrender](https://github.com/servo/webrender): Bincode records WebRender API calls for record/replay-style graphics debugging.
+* [servo/ipc-channel](https://github.com/servo/ipc-channel): IPC-Channel uses Bincode to send structs between processes using a channel-like API.
+* [ajeetdsouza/zoxide](https://github.com/ajeetdsouza/zoxide): zoxide uses Bincode to store a database of directories and their access frequencies on disk.
+
+## Example
+
+```rust
+use bincode::{config, Decode, Encode};
+
+#[derive(Encode, Decode, PartialEq, Debug)]
+struct Entity {
+ x: f32,
+ y: f32,
+}
+
+#[derive(Encode, Decode, PartialEq, Debug)]
+struct World(Vec);
+
+fn main() {
+ let config = config::standard();
+
+ let world = World(vec![Entity { x: 0.0, y: 4.0 }, Entity { x: 10.0, y: 20.5 }]);
+
+ let encoded: Vec = bincode::encode_to_vec(&world, config).unwrap();
+
+ // The length of the vector is encoded as a varint u64, which in this case gets collapsed to a single byte
+ // See the documentation on varint for more info for that.
+ // The 4 floats are encoded in 4 bytes each.
+ assert_eq!(encoded.len(), 1 + 4 * 4);
+
+ let (decoded, len): (World, usize) = bincode::decode_from_slice(&encoded[..], config).unwrap();
+
+ assert_eq!(world, decoded);
+ assert_eq!(len, encoded.len()); // read all bytes
+}
+```
+
+## Specification
+
+Bincode's format is specified in [docs/spec.md](https://github.com/bincode-org/bincode/blob/trunk/docs/spec.md).
+
+## FAQ
+
+### Is Bincode suitable for storage?
+
+The encoding format is stable, provided the same configuration is used.
+This should ensure that later versions can still read data produced by a previous versions of the library if no major version change
+has occurred.
+
+Bincode 1 and 2 are completely compatible if the same configuration is used.
+
+Bincode is invariant over byte-order, making an exchange between different
+architectures possible. It is also rather space efficient, as it stores no
+metadata like struct field names in the output format and writes long streams of
+binary data without needing any potentially size-increasing encoding.
+
+As a result, Bincode is suitable for storing data. Be aware that it does not
+implement any sort of data versioning scheme or file headers, as these
+features are outside the scope of this crate.
+
+### Is Bincode suitable for untrusted inputs?
+
+Bincode attempts to protect against hostile data. There is a maximum size
+configuration available (`Configuration::with_limit`), but not enabled in the
+default configuration. Enabling it causes pre-allocation size to be limited to
+prevent against memory exhaustion attacks.
+
+Deserializing any incoming data will not cause undefined behavior or memory
+issues, assuming that the deserialization code for the struct is safe itself.
+
+Bincode can be used for untrusted inputs in the sense that it will not create a
+security issues in your application, provided the configuration is changed to enable a
+maximum size limit. Malicious inputs will fail upon deserialization.
+
+### What is Bincode's MSRV (minimum supported Rust version)?
+
+Bincode 2.0 has an MSRV of 1.85.0. Any changes to the MSRV are considered a breaking change for semver purposes, except when certain features are enabled. Features affecting MSRV are documented in the crate root.
+
+### Why does bincode not respect `#[repr(u8)]`?
+
+Bincode will encode enum variants as a `u32`. If you're worried about storage size, we can recommend enabling `Configuration::with_variable_int_encoding()`. This option is enabled by default with the `standard` configuration. In this case enum variants will almost always be encoded as a `u8`.
+
+Currently we have not found a compelling case to respect `#[repr(...)]`. You're most likely trying to interop with a format that is similar-but-not-quite-bincode. We only support our own protocol ([spec](https://github.com/bincode-org/bincode/blob/trunk/docs/spec.md)).
+
+If you really want to use bincode to encode/decode a different protocol, consider implementing `Encode` and `Decode` yourself. `bincode-derive` will output the generated implementation in `target/generated/bincode/_Encode.rs` and `target/generated/bincode/_Decode.rs` which should get you started.
diff --git a/vendor/bincode-2.0.1/src/atomic.rs b/vendor/bincode-2.0.1/src/atomic.rs
new file mode 100644
index 0000000..003621f
--- /dev/null
+++ b/vendor/bincode-2.0.1/src/atomic.rs
@@ -0,0 +1,226 @@
+use crate::{de::Decode, enc::Encode, impl_borrow_decode};
+use core::sync::atomic::Ordering;
+
+#[cfg(target_has_atomic = "ptr")]
+use core::sync::atomic::{AtomicIsize, AtomicUsize};
+
+#[cfg(target_has_atomic = "8")]
+use core::sync::atomic::{AtomicBool, AtomicI8, AtomicU8};
+
+#[cfg(target_has_atomic = "16")]
+use core::sync::atomic::{AtomicI16, AtomicU16};
+
+#[cfg(target_has_atomic = "32")]
+use core::sync::atomic::{AtomicI32, AtomicU32};
+
+#[cfg(target_has_atomic = "64")]
+use core::sync::atomic::{AtomicI64, AtomicU64};
+
+#[cfg(target_has_atomic = "8")]
+impl Encode for AtomicBool {
+ fn encode(
+ &self,
+ encoder: &mut E,
+ ) -> Result<(), crate::error::EncodeError> {
+ self.load(Ordering::SeqCst).encode(encoder)
+ }
+}
+
+#[cfg(target_has_atomic = "8")]
+impl Decode for AtomicBool {
+ fn decode(decoder: &mut D) -> Result {
+ Ok(AtomicBool::new(Decode::decode(decoder)?))
+ }
+}
+#[cfg(target_has_atomic = "8")]
+impl_borrow_decode!(AtomicBool);
+
+#[cfg(target_has_atomic = "8")]
+impl Encode for AtomicU8 {
+ fn encode(
+ &self,
+ encoder: &mut E,
+ ) -> Result<(), crate::error::EncodeError> {
+ self.load(Ordering::SeqCst).encode(encoder)
+ }
+}
+
+#[cfg(target_has_atomic = "8")]
+impl Decode for AtomicU8 {
+ fn decode(decoder: &mut D) -> Result {
+ Ok(AtomicU8::new(Decode::decode(decoder)?))
+ }
+}
+#[cfg(target_has_atomic = "8")]
+impl_borrow_decode!(AtomicU8);
+
+#[cfg(target_has_atomic = "16")]
+impl Encode for AtomicU16 {
+ fn encode(
+ &self,
+ encoder: &mut E,
+ ) -> Result<(), crate::error::EncodeError> {
+ self.load(Ordering::SeqCst).encode(encoder)
+ }
+}
+
+#[cfg(target_has_atomic = "16")]
+impl Decode for AtomicU16 {
+ fn decode(decoder: &mut D) -> Result {
+ Ok(AtomicU16::new(Decode::decode(decoder)?))
+ }
+}
+#[cfg(target_has_atomic = "16")]
+impl_borrow_decode!(AtomicU16);
+
+#[cfg(target_has_atomic = "32")]
+impl Encode for AtomicU32 {
+ fn encode(
+ &self,
+ encoder: &mut E,
+ ) -> Result<(), crate::error::EncodeError> {
+ self.load(Ordering::SeqCst).encode(encoder)
+ }
+}
+
+#[cfg(target_has_atomic = "32")]
+impl Decode for AtomicU32 {
+ fn decode(decoder: &mut D) -> Result {
+ Ok(AtomicU32::new(Decode::decode(decoder)?))
+ }
+}
+#[cfg(target_has_atomic = "32")]
+impl_borrow_decode!(AtomicU32);
+
+#[cfg(target_has_atomic = "64")]
+impl Encode for AtomicU64 {
+ fn encode(
+ &self,
+ encoder: &mut E,
+ ) -> Result<(), crate::error::EncodeError> {
+ self.load(Ordering::SeqCst).encode(encoder)
+ }
+}
+
+#[cfg(target_has_atomic = "64")]
+impl Decode for AtomicU64 {
+ fn decode(decoder: &mut D) -> Result {
+ Ok(AtomicU64::new(Decode::decode(decoder)?))
+ }
+}
+#[cfg(target_has_atomic = "64")]
+impl_borrow_decode!(AtomicU64);
+
+#[cfg(target_has_atomic = "ptr")]
+impl Encode for AtomicUsize {
+ fn encode(
+ &self,
+ encoder: &mut E,
+ ) -> Result<(), crate::error::EncodeError> {
+ self.load(Ordering::SeqCst).encode(encoder)
+ }
+}
+
+#[cfg(target_has_atomic = "ptr")]
+impl Decode for AtomicUsize {
+ fn decode(decoder: &mut D) -> Result {
+ Ok(AtomicUsize::new(Decode::decode(decoder)?))
+ }
+}
+#[cfg(target_has_atomic = "ptr")]
+impl_borrow_decode!(AtomicUsize);
+
+#[cfg(target_has_atomic = "8")]
+impl Encode for AtomicI8 {
+ fn encode(
+ &self,
+ encoder: &mut E,
+ ) -> Result<(), crate::error::EncodeError> {
+ self.load(Ordering::SeqCst).encode(encoder)
+ }
+}
+
+#[cfg(target_has_atomic = "8")]
+impl Decode for AtomicI8 {
+ fn decode(decoder: &mut D) -> Result {
+ Ok(AtomicI8::new(Decode::decode(decoder)?))
+ }
+}
+#[cfg(target_has_atomic = "8")]
+impl_borrow_decode!(AtomicI8);
+
+#[cfg(target_has_atomic = "16")]
+impl Encode for AtomicI16 {
+ fn encode(
+ &self,
+ encoder: &mut E,
+ ) -> Result<(), crate::error::EncodeError> {
+ self.load(Ordering::SeqCst).encode(encoder)
+ }
+}
+
+#[cfg(target_has_atomic = "16")]
+impl Decode for AtomicI16 {
+ fn decode(decoder: &mut D) -> Result {
+ Ok(AtomicI16::new(Decode::decode(decoder)?))
+ }
+}
+#[cfg(target_has_atomic = "16")]
+impl_borrow_decode!(AtomicI16);
+
+#[cfg(target_has_atomic = "32")]
+impl Encode for AtomicI32 {
+ fn encode(
+ &self,
+ encoder: &mut E,
+ ) -> Result<(), crate::error::EncodeError> {
+ self.load(Ordering::SeqCst).encode(encoder)
+ }
+}
+
+#[cfg(target_has_atomic = "32")]
+impl Decode for AtomicI32 {
+ fn decode(decoder: &mut D) -> Result {
+ Ok(AtomicI32::new(Decode::decode(decoder)?))
+ }
+}
+#[cfg(target_has_atomic = "32")]
+impl_borrow_decode!(AtomicI32);
+
+#[cfg(target_has_atomic = "64")]
+impl Encode for AtomicI64 {
+ fn encode(
+ &self,
+ encoder: &mut E,
+ ) -> Result<(), crate::error::EncodeError> {
+ self.load(Ordering::SeqCst).encode(encoder)
+ }
+}
+
+#[cfg(target_has_atomic = "64")]
+impl Decode for AtomicI64 {
+ fn decode(decoder: &mut D) -> Result {
+ Ok(AtomicI64::new(Decode::decode(decoder)?))
+ }
+}
+#[cfg(target_has_atomic = "64")]
+impl_borrow_decode!(AtomicI64);
+
+#[cfg(target_has_atomic = "ptr")]
+impl Encode for AtomicIsize {
+ fn encode(
+ &self,
+ encoder: &mut E,
+ ) -> Result<(), crate::error::EncodeError> {
+ self.load(Ordering::SeqCst).encode(encoder)
+ }
+}
+
+#[cfg(target_has_atomic = "ptr")]
+impl Decode for AtomicIsize {
+ fn decode(decoder: &mut D) -> Result {
+ Ok(AtomicIsize::new(Decode::decode(decoder)?))
+ }
+}
+#[cfg(target_has_atomic = "ptr")]
+impl_borrow_decode!(AtomicIsize);
diff --git a/vendor/bincode-2.0.1/src/config.rs b/vendor/bincode-2.0.1/src/config.rs
new file mode 100644
index 0000000..3642677
--- /dev/null
+++ b/vendor/bincode-2.0.1/src/config.rs
@@ -0,0 +1,294 @@
+//! The config module is used to change the behavior of bincode's encoding and decoding logic.
+//!
+//! *Important* make sure you use the same config for encoding and decoding, or else bincode will not work properly.
+//!
+//! To use a config, first create a type of [Configuration]. This type will implement trait [Config] for use with bincode.
+//!
+//! ```
+//! let config = bincode::config::standard()
+//! // pick one of:
+//! .with_big_endian()
+//! .with_little_endian()
+//! // pick one of:
+//! .with_variable_int_encoding()
+//! .with_fixed_int_encoding();
+//! ```
+//!
+//! See [Configuration] for more information on the configuration options.
+
+pub(crate) use self::internal::*;
+use core::marker::PhantomData;
+
+/// The Configuration struct is used to build bincode configurations. The [Config] trait is implemented
+/// by this struct when a valid configuration has been constructed.
+///
+/// The following methods are mutually exclusive and will overwrite each other. The last call to one of these methods determines the behavior of the configuration:
+///
+/// - [with_little_endian] and [with_big_endian]
+/// - [with_fixed_int_encoding] and [with_variable_int_encoding]
+///
+///
+/// [with_little_endian]: #method.with_little_endian
+/// [with_big_endian]: #method.with_big_endian
+/// [with_fixed_int_encoding]: #method.with_fixed_int_encoding
+/// [with_variable_int_encoding]: #method.with_variable_int_encoding
+#[derive(Copy, Clone, Debug)]
+pub struct Configuration {
+ _e: PhantomData,
+ _i: PhantomData,
+ _l: PhantomData,
+}
+
+// When adding more features to configuration, follow these steps:
+// - Create 2 or more structs that can be used as a type (e.g. Limit and NoLimit)
+// - Add an `Internal...Config` to the `internal` module
+// - Make sure `Config` and `impl Config for T` extend from this new trait
+// - Add a generic to `Configuration`
+// - Add this generic to `impl<...> Default for Configuration<...>`
+// - Add this generic to `const fn generate<...>()`
+// - Add this generic to _every_ function in `Configuration`
+// - Add your new methods
+
+/// The default config for bincode 2.0. By default this will be:
+/// - Little endian
+/// - Variable int encoding
+pub const fn standard() -> Configuration {
+ generate()
+}
+
+/// Creates the "legacy" default config. This is the default config that was present in bincode 1.0
+/// - Little endian
+/// - Fixed int length encoding
+pub const fn legacy() -> Configuration {
+ generate()
+}
+
+impl Default for Configuration {
+ fn default() -> Self {
+ generate()
+ }
+}
+
+const fn generate() -> Configuration {
+ Configuration {
+ _e: PhantomData,
+ _i: PhantomData,
+ _l: PhantomData,
+ }
+}
+
+impl Configuration {
+ /// Makes bincode encode all integer types in big endian.
+ pub const fn with_big_endian(self) -> Configuration {
+ generate()
+ }
+
+ /// Makes bincode encode all integer types in little endian.
+ pub const fn with_little_endian(self) -> Configuration {
+ generate()
+ }
+
+ /// Makes bincode encode all integer types with a variable integer encoding.
+ ///
+ /// Encoding an unsigned integer v (of any type excepting u8) works as follows:
+ ///
+ /// 1. If `u < 251`, encode it as a single byte with that value.
+ /// 2. If `251 <= u < 2**16`, encode it as a literal byte 251, followed by a u16 with value `u`.
+ /// 3. If `2**16 <= u < 2**32`, encode it as a literal byte 252, followed by a u32 with value `u`.
+ /// 4. If `2**32 <= u < 2**64`, encode it as a literal byte 253, followed by a u64 with value `u`.
+ /// 5. If `2**64 <= u < 2**128`, encode it as a literal byte 254, followed by a u128 with value `u`.
+ ///
+ /// Then, for signed integers, we first convert to unsigned using the zigzag algorithm,
+ /// and then encode them as we do for unsigned integers generally. The reason we use this
+ /// algorithm is that it encodes those values which are close to zero in less bytes; the
+ /// obvious algorithm, where we encode the cast values, gives a very large encoding for all
+ /// negative values.
+ ///
+ /// The zigzag algorithm is defined as follows:
+ ///
+ /// ```rust
+ /// # type Signed = i32;
+ /// # type Unsigned = u32;
+ /// fn zigzag(v: Signed) -> Unsigned {
+ /// match v {
+ /// 0 => 0,
+ /// // To avoid the edge case of Signed::min_value()
+ /// // !n is equal to `-n - 1`, so this is:
+ /// // !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1
+ /// v if v < 0 => !(v as Unsigned) * 2 - 1,
+ /// v if v > 0 => (v as Unsigned) * 2,
+ /// # _ => unreachable!()
+ /// }
+ /// }
+ /// ```
+ ///
+ /// And works such that:
+ ///
+ /// ```rust
+ /// # let zigzag = |n: i64| -> u64 {
+ /// # match n {
+ /// # 0 => 0,
+ /// # v if v < 0 => !(v as u64) * 2 + 1,
+ /// # v if v > 0 => (v as u64) * 2,
+ /// # _ => unreachable!(),
+ /// # }
+ /// # };
+ /// assert_eq!(zigzag(0), 0);
+ /// assert_eq!(zigzag(-1), 1);
+ /// assert_eq!(zigzag(1), 2);
+ /// assert_eq!(zigzag(-2), 3);
+ /// assert_eq!(zigzag(2), 4);
+ /// // etc
+ /// assert_eq!(zigzag(i64::min_value()), u64::max_value());
+ /// ```
+ ///
+ /// Note that u256 and the like are unsupported by this format; if and when they are added to the
+ /// language, they may be supported via the extension point given by the 255 byte.
+ pub const fn with_variable_int_encoding(self) -> Configuration {
+ generate()
+ }
+
+ /// Fixed-size integer encoding.
+ ///
+ /// * Fixed size integers are encoded directly
+ /// * Enum discriminants are encoded as u32
+ /// * Lengths and usize are encoded as u64
+ pub const fn with_fixed_int_encoding(self) -> Configuration {
+ generate()
+ }
+
+ /// Sets the byte limit to `limit`.
+ pub const fn with_limit(self) -> Configuration> {
+ generate()
+ }
+
+ /// Clear the byte limit.
+ pub const fn with_no_limit(self) -> Configuration {
+ generate()
+ }
+}
+
+/// Indicates a type is valid for controlling the bincode configuration
+pub trait Config:
+ InternalEndianConfig + InternalIntEncodingConfig + InternalLimitConfig + Copy + Clone
+{
+ /// This configuration's Endianness
+ fn endianness(&self) -> Endianness;
+
+ /// This configuration's Integer Encoding
+ fn int_encoding(&self) -> IntEncoding;
+
+ /// This configuration's byte limit, or `None` if no limit is configured
+ fn limit(&self) -> Option;
+}
+
+impl Config for T
+where
+ T: InternalEndianConfig + InternalIntEncodingConfig + InternalLimitConfig + Copy + Clone,
+{
+ fn endianness(&self) -> Endianness {
+ ::ENDIAN
+ }
+
+ fn int_encoding(&self) -> IntEncoding {
+ ::INT_ENCODING
+ }
+
+ fn limit(&self) -> Option {
+ ::LIMIT
+ }
+}
+
+/// Encodes all integer types in big endian.
+#[derive(Copy, Clone)]
+pub struct BigEndian {}
+
+impl InternalEndianConfig for BigEndian {
+ const ENDIAN: Endianness = Endianness::Big;
+}
+
+/// Encodes all integer types in little endian.
+#[derive(Copy, Clone)]
+pub struct LittleEndian {}
+
+impl InternalEndianConfig for LittleEndian {
+ const ENDIAN: Endianness = Endianness::Little;
+}
+
+/// Use fixed-size integer encoding.
+#[derive(Copy, Clone)]
+pub struct Fixint {}
+
+impl InternalIntEncodingConfig for Fixint {
+ const INT_ENCODING: IntEncoding = IntEncoding::Fixed;
+}
+
+/// Use variable integer encoding.
+#[derive(Copy, Clone)]
+pub struct Varint {}
+
+impl InternalIntEncodingConfig for Varint {
+ const INT_ENCODING: IntEncoding = IntEncoding::Variable;
+}
+
+/// Sets an unlimited byte limit.
+#[derive(Copy, Clone)]
+pub struct NoLimit {}
+impl InternalLimitConfig for NoLimit {
+ const LIMIT: Option = None;
+}
+
+/// Sets the byte limit to N.
+#[derive(Copy, Clone)]
+pub struct Limit {}
+impl InternalLimitConfig for Limit {
+ const LIMIT: Option = Some(N);
+}
+
+/// Endianness of a `Configuration`.
+#[derive(PartialEq, Eq)]
+#[non_exhaustive]
+pub enum Endianness {
+ /// Little Endian encoding, see `LittleEndian`.
+ Little,
+ /// Big Endian encoding, see `BigEndian`.
+ Big,
+}
+
+/// Integer Encoding of a `Configuration`.
+#[derive(PartialEq, Eq)]
+#[non_exhaustive]
+pub enum IntEncoding {
+ /// Fixed Integer Encoding, see `Fixint`.
+ Fixed,
+ /// Variable Integer Encoding, see `Varint`.
+ Variable,
+}
+
+mod internal {
+ use super::{Configuration, Endianness, IntEncoding};
+
+ pub trait InternalEndianConfig {
+ const ENDIAN: Endianness;
+ }
+
+ impl InternalEndianConfig for Configuration {
+ const ENDIAN: Endianness = E::ENDIAN;
+ }
+
+ pub trait InternalIntEncodingConfig {
+ const INT_ENCODING: IntEncoding;
+ }
+
+ impl InternalIntEncodingConfig for Configuration {
+ const INT_ENCODING: IntEncoding = I::INT_ENCODING;
+ }
+
+ pub trait InternalLimitConfig {
+ const LIMIT: Option;
+ }
+
+ impl InternalLimitConfig for Configuration {
+ const LIMIT: Option = L::LIMIT;
+ }
+}
diff --git a/vendor/bincode-2.0.1/src/de/decoder.rs b/vendor/bincode-2.0.1/src/de/decoder.rs
new file mode 100644
index 0000000..8945130
--- /dev/null
+++ b/vendor/bincode-2.0.1/src/de/decoder.rs
@@ -0,0 +1,142 @@
+use super::{
+ read::{BorrowReader, Reader},
+ BorrowDecoder, Decoder,
+};
+use crate::{config::Config, error::DecodeError, utils::Sealed};
+
+/// A Decoder that reads bytes from a given reader `R`.
+///
+/// This struct should rarely be used.
+/// In most cases, prefer any of the `decode` functions.
+///
+/// The ByteOrder that is chosen will impact the endianness that
+/// is used to read integers out of the reader.
+///
+/// ```
+/// # let slice: &[u8] = &[0, 0, 0, 0];
+/// # let some_reader = bincode::de::read::SliceReader::new(slice);
+/// use bincode::de::{DecoderImpl, Decode};
+/// let mut context = ();
+/// let mut decoder = DecoderImpl::new(some_reader, bincode::config::standard(), &mut context);
+/// // this u32 can be any Decode
+/// let value = u32::decode(&mut decoder).unwrap();
+/// ```
+pub struct DecoderImpl {
+ reader: R,
+ config: C,
+ bytes_read: usize,
+ context: Context,
+}
+
+impl DecoderImpl {
+ /// Construct a new Decoder
+ pub fn new(reader: R, config: C, context: Context) -> DecoderImpl {
+ DecoderImpl {
+ reader,
+ config,
+ bytes_read: 0,
+ context,
+ }
+ }
+}
+
+impl Sealed for DecoderImpl {}
+
+impl<'de, R: BorrowReader<'de>, C: Config, Context> BorrowDecoder<'de>
+ for DecoderImpl
+{
+ type BR = R;
+
+ fn borrow_reader(&mut self) -> &mut Self::BR {
+ &mut self.reader
+ }
+}
+
+impl Decoder for DecoderImpl {
+ type R = R;
+
+ type C = C;
+ type Context = Context;
+
+ fn reader(&mut self) -> &mut Self::R {
+ &mut self.reader
+ }
+
+ fn config(&self) -> &Self::C {
+ &self.config
+ }
+
+ #[inline]
+ fn claim_bytes_read(&mut self, n: usize) -> Result<(), DecodeError> {
+ // C::LIMIT is a const so this check should get compiled away
+ if let Some(limit) = C::LIMIT {
+ // Make sure we don't accidentally overflow `bytes_read`
+ self.bytes_read = self
+ .bytes_read
+ .checked_add(n)
+ .ok_or(DecodeError::LimitExceeded)?;
+ if self.bytes_read > limit {
+ Err(DecodeError::LimitExceeded)
+ } else {
+ Ok(())
+ }
+ } else {
+ Ok(())
+ }
+ }
+
+ #[inline]
+ fn unclaim_bytes_read(&mut self, n: usize) {
+ // C::LIMIT is a const so this check should get compiled away
+ if C::LIMIT.is_some() {
+ // We should always be claiming more than we unclaim, so this should never underflow
+ self.bytes_read -= n;
+ }
+ }
+
+ fn context(&mut self) -> &mut Self::Context {
+ &mut self.context
+ }
+}
+
+pub struct WithContext<'a, D: ?Sized, C> {
+ pub(crate) decoder: &'a mut D,
+ pub(crate) context: C,
+}
+
+impl Sealed for WithContext<'_, D, C> {}
+
+impl Decoder for WithContext<'_, D, Context> {
+ type R = D::R;
+
+ type C = D::C;
+
+ type Context = Context;
+
+ fn context(&mut self) -> &mut Self::Context {
+ &mut self.context
+ }
+
+ fn reader(&mut self) -> &mut Self::R {
+ self.decoder.reader()
+ }
+
+ fn config(&self) -> &Self::C {
+ self.decoder.config()
+ }
+
+ fn claim_bytes_read(&mut self, n: usize) -> Result<(), DecodeError> {
+ self.decoder.claim_bytes_read(n)
+ }
+
+ fn unclaim_bytes_read(&mut self, n: usize) {
+ self.decoder.unclaim_bytes_read(n)
+ }
+}
+
+impl<'de, C, D: BorrowDecoder<'de>> BorrowDecoder<'de> for WithContext<'_, D, C> {
+ type BR = D::BR;
+ fn borrow_reader(&mut self) -> &mut Self::BR {
+ self.decoder.borrow_reader()
+ }
+}
diff --git a/vendor/bincode-2.0.1/src/de/impl_core.rs b/vendor/bincode-2.0.1/src/de/impl_core.rs
new file mode 100644
index 0000000..0478f83
--- /dev/null
+++ b/vendor/bincode-2.0.1/src/de/impl_core.rs
@@ -0,0 +1,186 @@
+#![allow(unused_unsafe)]
+
+//! Contains implementations for rust core that have not been stabilized
+//!
+//! Functions in this are expected to be properly peer reviewed by the community
+//!
+//! Any modifications done are purely to make the code compatible with bincode
+
+use core::mem::{self, MaybeUninit};
+
+/// Pulls `N` items from `iter` and returns them as an array. If the iterator
+/// yields fewer than `N` items, `None` is returned and all already yielded
+/// items are dropped.
+///
+/// Since the iterator is passed as a mutable reference and this function calls
+/// `next` at most `N` times, the iterator can still be used afterwards to
+/// retrieve the remaining items.
+///
+/// If `iter.next()` panicks, all items already yielded by the iterator are
+/// dropped.
+#[allow(clippy::while_let_on_iterator)]
+pub fn collect_into_array(iter: &mut I) -> Option>
+where
+ I: Iterator- >,
+{
+ if N == 0 {
+ // SAFETY: An empty array is always inhabited and has no validity invariants.
+ return unsafe { Some(Ok(mem::zeroed())) };
+ }
+
+ struct Guard<'a, T, const N: usize> {
+ array_mut: &'a mut [MaybeUninit; N],
+ initialized: usize,
+ }
+
+ impl Drop for Guard<'_, T, N> {
+ fn drop(&mut self) {
+ debug_assert!(self.initialized <= N);
+
+ // SAFETY: this slice will contain only initialized objects.
+ unsafe {
+ core::ptr::drop_in_place(slice_assume_init_mut(
+ self.array_mut.get_unchecked_mut(..self.initialized),
+ ));
+ }
+ }
+ }
+
+ let mut array = uninit_array::();
+ let mut guard = Guard {
+ array_mut: &mut array,
+ initialized: 0,
+ };
+
+ while let Some(item_rslt) = iter.next() {
+ let item = match item_rslt {
+ Err(err) => {
+ return Some(Err(err));
+ }
+ Ok(elem) => elem,
+ };
+
+ // SAFETY: `guard.initialized` starts at 0, is increased by one in the
+ // loop and the loop is aborted once it reaches N (which is
+ // `array.len()`).
+ unsafe {
+ guard
+ .array_mut
+ .get_unchecked_mut(guard.initialized)
+ .write(item);
+ }
+ guard.initialized += 1;
+
+ // Check if the whole array was initialized.
+ if guard.initialized == N {
+ mem::forget(guard);
+
+ // SAFETY: the condition above asserts that all elements are
+ // initialized.
+ let out = unsafe { array_assume_init(array) };
+ return Some(Ok(out));
+ }
+ }
+
+ // This is only reached if the iterator is exhausted before
+ // `guard.initialized` reaches `N`. Also note that `guard` is dropped here,
+ // dropping all already initialized elements.
+ None
+}
+
+/// Assuming all the elements are initialized, get a mutable slice to them.
+///
+/// # Safety
+///
+/// It is up to the caller to guarantee that the `MaybeUninit` elements
+/// really are in an initialized state.
+/// Calling this when the content is not yet fully initialized causes undefined behavior.
+///
+/// See [`assume_init_mut`] for more details and examples.
+///
+/// [`assume_init_mut`]: MaybeUninit::assume_init_mut
+// #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
+// #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")]
+#[inline(always)]
+pub unsafe fn slice_assume_init_mut(slice: &mut [MaybeUninit]) -> &mut [T] {
+ // SAFETY: similar to safety notes for `slice_get_ref`, but we have a
+ // mutable reference which is also guaranteed to be valid for writes.
+ unsafe { &mut *(slice as *mut [MaybeUninit] as *mut [T]) }
+}
+
+/// Create a new array of `MaybeUninit` items, in an uninitialized state.
+///
+/// Note: in a future Rust version this method may become unnecessary
+/// when Rust allows
+/// [inline const expressions](https://github.com/rust-lang/rust/issues/76001).
+/// The example below could then use `let mut buf = [const { MaybeUninit::::uninit() }; 32];`.
+///
+/// # Examples
+///
+/// ```ignore
+/// #![feature(maybe_uninit_uninit_array, maybe_uninit_extra, maybe_uninit_slice)]
+///
+/// use std::mem::MaybeUninit;
+///
+/// extern "C" {
+/// fn read_into_buffer(ptr: *mut u8, max_len: usize) -> usize;
+/// }
+///
+/// /// Returns a (possibly smaller) slice of data that was actually read
+/// fn read(buf: &mut [MaybeUninit]) -> &[u8] {
+/// unsafe {
+/// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len());
+/// MaybeUninit::slice_assume_init_ref(&buf[..len])
+/// }
+/// }
+///
+/// let mut buf: [MaybeUninit; 32] = MaybeUninit::uninit_array();
+/// let data = read(&mut buf);
+/// ```
+// #[unstable(feature = "maybe_uninit_uninit_array", issue = "none")]
+// #[rustc_const_unstable(feature = "maybe_uninit_uninit_array", issue = "none")]
+#[inline(always)]
+fn uninit_array() -> [MaybeUninit; LEN] {
+ // SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid.
+ unsafe { MaybeUninit::<[MaybeUninit; LEN]>::uninit().assume_init() }
+}
+
+/// Extracts the values from an array of `MaybeUninit` containers.
+///
+/// # Safety
+///
+/// It is up to the caller to guarantee that all elements of the array are
+/// in an initialized state.
+///
+/// # Examples
+///
+/// ```ignore
+/// #![feature(maybe_uninit_uninit_array)]
+/// #![feature(maybe_uninit_array_assume_init)]
+/// use std::mem::MaybeUninit;
+///
+/// let mut array: [MaybeUninit; 3] = MaybeUninit::uninit_array();
+/// array[0].write(0);
+/// array[1].write(1);
+/// array[2].write(2);
+///
+/// // SAFETY: Now safe as we initialised all elements
+/// let array = unsafe {
+/// MaybeUninit::array_assume_init(array)
+/// };
+///
+/// assert_eq!(array, [0, 1, 2]);
+/// ```
+// #[unstable(feature = "maybe_uninit_array_assume_init", issue = "80908")]
+#[inline(always)]
+pub unsafe fn array_assume_init(array: [MaybeUninit; N]) -> [T; N] {
+ // SAFETY:
+ // * The caller guarantees that all elements of the array are initialized
+ // * `MaybeUninit` and T are guaranteed to have the same layout
+ // * `MaybeUninit` does not drop, so there are no double-frees
+ // And thus the conversion is safe
+ unsafe {
+ // intrinsics::assert_inhabited::<[T; N]>();
+ (&array as *const _ as *const [T; N]).read()
+ }
+}
diff --git a/vendor/bincode-2.0.1/src/de/impl_tuples.rs b/vendor/bincode-2.0.1/src/de/impl_tuples.rs
new file mode 100644
index 0000000..f4c5dc9
--- /dev/null
+++ b/vendor/bincode-2.0.1/src/de/impl_tuples.rs
@@ -0,0 +1,54 @@
+use super::{BorrowDecode, BorrowDecoder, Decode, Decoder};
+use crate::error::DecodeError;
+
+macro_rules! impl_tuple {
+ () => {};
+ ($first:ident $(, $extra:ident)*) => {
+ impl<'de, $first $(, $extra)*, Context> BorrowDecode<'de, Context> for ($first, $($extra, )*)
+ where
+ $first: BorrowDecode<'de, Context>,
+ $(
+ $extra : BorrowDecode<'de, Context>,
+ )*
+ {
+ fn borrow_decode>(decoder: &mut BD) -> Result {
+ Ok((
+ $first::borrow_decode(decoder)?,
+ $($extra :: borrow_decode(decoder)?, )*
+ ))
+ }
+ }
+
+ impl Decode for ($first, $($extra, )*)
+ where
+ $first: Decode,
+ $(
+ $extra : Decode,
+ )*
+ {
+ fn decode>(decoder: &mut DE) -> Result {
+ Ok((
+ $first::decode(decoder)?,
+ $($extra :: decode(decoder)?, )*
+ ))
+ }
+ }
+ }
+}
+
+impl_tuple!(A);
+impl_tuple!(A, B);
+impl_tuple!(A, B, C);
+impl_tuple!(A, B, C, D);
+impl_tuple!(A, B, C, D, E);
+impl_tuple!(A, B, C, D, E, F);
+impl_tuple!(A, B, C, D, E, F, G);
+impl_tuple!(A, B, C, D, E, F, G, H);
+impl_tuple!(A, B, C, D, E, F, G, H, I);
+impl_tuple!(A, B, C, D, E, F, G, H, I, J);
+impl_tuple!(A, B, C, D, E, F, G, H, I, J, K);
+impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
+impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
+impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
+impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
+impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
diff --git a/vendor/bincode-2.0.1/src/de/impls.rs b/vendor/bincode-2.0.1/src/de/impls.rs
new file mode 100644
index 0000000..a9c4ab6
--- /dev/null
+++ b/vendor/bincode-2.0.1/src/de/impls.rs
@@ -0,0 +1,798 @@
+use super::{
+ read::{BorrowReader, Reader},
+ BorrowDecode, BorrowDecoder, Decode, Decoder,
+};
+use crate::{
+ config::{Endianness, IntEncoding, InternalEndianConfig, InternalIntEncodingConfig},
+ error::{DecodeError, IntegerType},
+ impl_borrow_decode,
+};
+use core::{
+ cell::{Cell, RefCell},
+ cmp::Reverse,
+ num::{
+ NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
+ NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping,
+ },
+ ops::{Bound, Range, RangeInclusive},
+ time::Duration,
+};
+
+impl Decode for bool {
+ fn decode>(decoder: &mut D) -> Result {
+ match u8::decode(decoder)? {
+ 0 => Ok(false),
+ 1 => Ok(true),
+ x => Err(DecodeError::InvalidBooleanValue(x)),
+ }
+ }
+}
+impl_borrow_decode!(bool);
+
+impl Decode for u8 {
+ #[inline]
+ fn decode>(decoder: &mut D) -> Result {
+ decoder.claim_bytes_read(1)?;
+ if let Some(buf) = decoder.reader().peek_read(1) {
+ let byte = buf[0];
+ decoder.reader().consume(1);
+ Ok(byte)
+ } else {
+ let mut bytes = [0u8; 1];
+ decoder.reader().read(&mut bytes)?;
+ Ok(bytes[0])
+ }
+ }
+}
+impl_borrow_decode!(u8);
+
+impl Decode for NonZeroU8 {
+ fn decode>(decoder: &mut D) -> Result {
+ NonZeroU8::new(u8::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero {
+ non_zero_type: IntegerType::U8,
+ })
+ }
+}
+impl_borrow_decode!(NonZeroU8);
+
+impl Decode for u16 {
+ fn decode>(decoder: &mut D) -> Result {
+ decoder.claim_bytes_read(2)?;
+ match D::C::INT_ENCODING {
+ IntEncoding::Variable => {
+ crate::varint::varint_decode_u16(decoder.reader(), D::C::ENDIAN)
+ }
+ IntEncoding::Fixed => {
+ let mut bytes = [0u8; 2];
+ decoder.reader().read(&mut bytes)?;
+ Ok(match D::C::ENDIAN {
+ Endianness::Little => u16::from_le_bytes(bytes),
+ Endianness::Big => u16::from_be_bytes(bytes),
+ })
+ }
+ }
+ }
+}
+impl_borrow_decode!(u16);
+
+impl Decode for NonZeroU16 {
+ fn decode>(decoder: &mut D) -> Result {
+ NonZeroU16::new(u16::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero {
+ non_zero_type: IntegerType::U16,
+ })
+ }
+}
+impl_borrow_decode!(NonZeroU16);
+
+impl Decode for u32 {
+ fn decode>(decoder: &mut D) -> Result {
+ decoder.claim_bytes_read(4)?;
+ match D::C::INT_ENCODING {
+ IntEncoding::Variable => {
+ crate::varint::varint_decode_u32(decoder.reader(), D::C::ENDIAN)
+ }
+ IntEncoding::Fixed => {
+ let mut bytes = [0u8; 4];
+ decoder.reader().read(&mut bytes)?;
+ Ok(match D::C::ENDIAN {
+ Endianness::Little => u32::from_le_bytes(bytes),
+ Endianness::Big => u32::from_be_bytes(bytes),
+ })
+ }
+ }
+ }
+}
+impl_borrow_decode!(u32);
+
+impl Decode for NonZeroU32 {
+ fn decode>(decoder: &mut D) -> Result {
+ NonZeroU32::new(u32::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero {
+ non_zero_type: IntegerType::U32,
+ })
+ }
+}
+impl_borrow_decode!(NonZeroU32);
+
+impl Decode for u64 {
+ fn decode>(decoder: &mut D) -> Result {
+ decoder.claim_bytes_read(8)?;
+ match D::C::INT_ENCODING {
+ IntEncoding::Variable => {
+ crate::varint::varint_decode_u64(decoder.reader(), D::C::ENDIAN)
+ }
+ IntEncoding::Fixed => {
+ let mut bytes = [0u8; 8];
+ decoder.reader().read(&mut bytes)?;
+ Ok(match D::C::ENDIAN {
+ Endianness::Little => u64::from_le_bytes(bytes),
+ Endianness::Big => u64::from_be_bytes(bytes),
+ })
+ }
+ }
+ }
+}
+impl_borrow_decode!(u64);
+
+impl Decode for NonZeroU64 {
+ fn decode>(decoder: &mut D) -> Result {
+ NonZeroU64::new(u64::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero {
+ non_zero_type: IntegerType::U64,
+ })
+ }
+}
+impl_borrow_decode!(NonZeroU64);
+
+impl Decode for u128 {
+ fn decode>(decoder: &mut D) -> Result {
+ decoder.claim_bytes_read(16)?;
+ match D::C::INT_ENCODING {
+ IntEncoding::Variable => {
+ crate::varint::varint_decode_u128(decoder.reader(), D::C::ENDIAN)
+ }
+ IntEncoding::Fixed => {
+ let mut bytes = [0u8; 16];
+ decoder.reader().read(&mut bytes)?;
+ Ok(match D::C::ENDIAN {
+ Endianness::Little => u128::from_le_bytes(bytes),
+ Endianness::Big => u128::from_be_bytes(bytes),
+ })
+ }
+ }
+ }
+}
+impl_borrow_decode!(u128);
+
+impl Decode for NonZeroU128 {
+ fn decode>(decoder: &mut D) -> Result {
+ NonZeroU128::new(u128::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero {
+ non_zero_type: IntegerType::U128,
+ })
+ }
+}
+impl_borrow_decode!(NonZeroU128);
+
+impl Decode for usize {
+ fn decode>(decoder: &mut D) -> Result {
+ decoder.claim_bytes_read(8)?;
+ match D::C::INT_ENCODING {
+ IntEncoding::Variable => {
+ crate::varint::varint_decode_usize(decoder.reader(), D::C::ENDIAN)
+ }
+ IntEncoding::Fixed => {
+ let mut bytes = [0u8; 8];
+ decoder.reader().read(&mut bytes)?;
+
+ let value = match D::C::ENDIAN {
+ Endianness::Little => u64::from_le_bytes(bytes),
+ Endianness::Big => u64::from_be_bytes(bytes),
+ };
+
+ value
+ .try_into()
+ .map_err(|_| DecodeError::OutsideUsizeRange(value))
+ }
+ }
+ }
+}
+impl_borrow_decode!(usize);
+
+impl Decode for NonZeroUsize {
+ fn decode>(decoder: &mut D) -> Result {
+ NonZeroUsize::new(usize::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero {
+ non_zero_type: IntegerType::Usize,
+ })
+ }
+}
+impl_borrow_decode!(NonZeroUsize);
+
+impl Decode for i8 {
+ fn decode>(decoder: &mut D) -> Result {
+ decoder.claim_bytes_read(1)?;
+ let mut bytes = [0u8; 1];
+ decoder.reader().read(&mut bytes)?;
+ Ok(bytes[0] as i8)
+ }
+}
+impl_borrow_decode!(i8);
+
+impl Decode for NonZeroI8 {
+ fn decode>(decoder: &mut D) -> Result {
+ NonZeroI8::new(i8::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero {
+ non_zero_type: IntegerType::I8,
+ })
+ }
+}
+impl_borrow_decode!(NonZeroI8);
+
+impl Decode for i16 {
+ fn decode>(decoder: &mut D) -> Result {
+ decoder.claim_bytes_read(2)?;
+ match D::C::INT_ENCODING {
+ IntEncoding::Variable => {
+ crate::varint::varint_decode_i16(decoder.reader(), D::C::ENDIAN)
+ }
+ IntEncoding::Fixed => {
+ let mut bytes = [0u8; 2];
+ decoder.reader().read(&mut bytes)?;
+ Ok(match D::C::ENDIAN {
+ Endianness::Little => i16::from_le_bytes(bytes),
+ Endianness::Big => i16::from_be_bytes(bytes),
+ })
+ }
+ }
+ }
+}
+impl_borrow_decode!(i16);
+
+impl Decode for NonZeroI16 {
+ fn decode>(decoder: &mut D) -> Result {
+ NonZeroI16::new(i16::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero {
+ non_zero_type: IntegerType::I16,
+ })
+ }
+}
+impl_borrow_decode!(NonZeroI16);
+
+impl Decode for i32 {
+ fn decode>(decoder: &mut D) -> Result {
+ decoder.claim_bytes_read(4)?;
+ match D::C::INT_ENCODING {
+ IntEncoding::Variable => {
+ crate::varint::varint_decode_i32(decoder.reader(), D::C::ENDIAN)
+ }
+ IntEncoding::Fixed => {
+ let mut bytes = [0u8; 4];
+ decoder.reader().read(&mut bytes)?;
+ Ok(match D::C::ENDIAN {
+ Endianness::Little => i32::from_le_bytes(bytes),
+ Endianness::Big => i32::from_be_bytes(bytes),
+ })
+ }
+ }
+ }
+}
+impl_borrow_decode!(i32);
+
+impl Decode for NonZeroI32 {
+ fn decode