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 + + +[![CI](https://github.com/bincode-org/bincode/workflows/CI/badge.svg)](https://github.com/bincode-org/bincode/actions) +[![](https://img.shields.io/crates/v/bincode.svg)](https://crates.io/crates/bincode) +[![](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) + +[![Matrix](https://img.shields.io/matrix/bincode:matrix.org?label=Matrix%20Chat)](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>(decoder: &mut D) -> Result { + NonZeroI32::new(i32::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { + non_zero_type: IntegerType::I32, + }) + } +} +impl_borrow_decode!(NonZeroI32); + +impl Decode for i64 { + fn decode>(decoder: &mut D) -> Result { + decoder.claim_bytes_read(8)?; + match D::C::INT_ENCODING { + IntEncoding::Variable => { + crate::varint::varint_decode_i64(decoder.reader(), D::C::ENDIAN) + } + IntEncoding::Fixed => { + let mut bytes = [0u8; 8]; + decoder.reader().read(&mut bytes)?; + Ok(match D::C::ENDIAN { + Endianness::Little => i64::from_le_bytes(bytes), + Endianness::Big => i64::from_be_bytes(bytes), + }) + } + } + } +} +impl_borrow_decode!(i64); + +impl Decode for NonZeroI64 { + fn decode>(decoder: &mut D) -> Result { + NonZeroI64::new(i64::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { + non_zero_type: IntegerType::I64, + }) + } +} +impl_borrow_decode!(NonZeroI64); + +impl Decode for i128 { + fn decode>(decoder: &mut D) -> Result { + decoder.claim_bytes_read(16)?; + match D::C::INT_ENCODING { + IntEncoding::Variable => { + crate::varint::varint_decode_i128(decoder.reader(), D::C::ENDIAN) + } + IntEncoding::Fixed => { + let mut bytes = [0u8; 16]; + decoder.reader().read(&mut bytes)?; + Ok(match D::C::ENDIAN { + Endianness::Little => i128::from_le_bytes(bytes), + Endianness::Big => i128::from_be_bytes(bytes), + }) + } + } + } +} +impl_borrow_decode!(i128); + +impl Decode for NonZeroI128 { + fn decode>(decoder: &mut D) -> Result { + NonZeroI128::new(i128::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { + non_zero_type: IntegerType::I128, + }) + } +} +impl_borrow_decode!(NonZeroI128); + +impl Decode for isize { + fn decode>(decoder: &mut D) -> Result { + decoder.claim_bytes_read(8)?; + match D::C::INT_ENCODING { + IntEncoding::Variable => { + crate::varint::varint_decode_isize(decoder.reader(), D::C::ENDIAN) + } + IntEncoding::Fixed => { + let mut bytes = [0u8; 8]; + decoder.reader().read(&mut bytes)?; + Ok(match D::C::ENDIAN { + Endianness::Little => i64::from_le_bytes(bytes), + Endianness::Big => i64::from_be_bytes(bytes), + } as isize) + } + } + } +} +impl_borrow_decode!(isize); + +impl Decode for NonZeroIsize { + fn decode>(decoder: &mut D) -> Result { + NonZeroIsize::new(isize::decode(decoder)?).ok_or(DecodeError::NonZeroTypeIsZero { + non_zero_type: IntegerType::Isize, + }) + } +} +impl_borrow_decode!(NonZeroIsize); + +impl Decode for f32 { + fn decode>(decoder: &mut D) -> Result { + decoder.claim_bytes_read(4)?; + let mut bytes = [0u8; 4]; + decoder.reader().read(&mut bytes)?; + Ok(match D::C::ENDIAN { + Endianness::Little => f32::from_le_bytes(bytes), + Endianness::Big => f32::from_be_bytes(bytes), + }) + } +} +impl_borrow_decode!(f32); + +impl Decode for f64 { + fn decode>(decoder: &mut D) -> Result { + decoder.claim_bytes_read(8)?; + let mut bytes = [0u8; 8]; + decoder.reader().read(&mut bytes)?; + Ok(match D::C::ENDIAN { + Endianness::Little => f64::from_le_bytes(bytes), + Endianness::Big => f64::from_be_bytes(bytes), + }) + } +} +impl_borrow_decode!(f64); + +impl> Decode for Wrapping { + fn decode>(decoder: &mut D) -> Result { + Ok(Wrapping(T::decode(decoder)?)) + } +} +impl<'de, Context, T: BorrowDecode<'de, Context>> BorrowDecode<'de, Context> for Wrapping { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + Ok(Wrapping(T::borrow_decode(decoder)?)) + } +} + +impl> Decode for Reverse { + fn decode>(decoder: &mut D) -> Result { + Ok(Reverse(T::decode(decoder)?)) + } +} + +impl<'de, Context, T: BorrowDecode<'de, Context>> BorrowDecode<'de, Context> for Reverse { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + Ok(Reverse(T::borrow_decode(decoder)?)) + } +} + +impl Decode for char { + fn decode>(decoder: &mut D) -> Result { + let mut array = [0u8; 4]; + + // Look at the first byte to see how many bytes must be read + decoder.reader().read(&mut array[..1])?; + + let width = utf8_char_width(array[0]); + if width == 0 { + return Err(DecodeError::InvalidCharEncoding(array)); + } + // Normally we have to `.claim_bytes_read` before reading, however in this + // case the amount of bytes read from `char` can vary wildly, and it should + // only read up to 4 bytes too much. + decoder.claim_bytes_read(width)?; + if width == 1 { + return Ok(array[0] as char); + } + + // read the remaining pain + decoder.reader().read(&mut array[1..width])?; + let res = core::str::from_utf8(&array[..width]) + .ok() + .and_then(|s| s.chars().next()) + .ok_or(DecodeError::InvalidCharEncoding(array))?; + Ok(res) + } +} +impl_borrow_decode!(char); + +impl<'a, 'de: 'a, Context> BorrowDecode<'de, Context> for &'a [u8] { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let len = super::decode_slice_len(decoder)?; + decoder.claim_bytes_read(len)?; + decoder.borrow_reader().take_bytes(len) + } +} + +impl<'a, 'de: 'a, Context> BorrowDecode<'de, Context> for &'a str { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let slice = <&[u8]>::borrow_decode(decoder)?; + core::str::from_utf8(slice).map_err(|inner| DecodeError::Utf8 { inner }) + } +} + +impl Decode for [T; N] +where + T: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + decoder.claim_bytes_read(core::mem::size_of::<[T; N]>())?; + + if unty::type_equal::() { + let mut buf = [0u8; N]; + decoder.reader().read(&mut buf)?; + let ptr = &mut buf as *mut _ as *mut [T; N]; + + // Safety: we know that T is a u8, so it is perfectly safe to + // translate an array of u8 into an array of T + let res = unsafe { ptr.read() }; + Ok(res) + } else { + let result = super::impl_core::collect_into_array(&mut (0..N).map(|_| { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::()); + T::decode(decoder) + })); + + // result is only None if N does not match the values of `(0..N)`, which it always should + // So this unwrap should never occur + result.unwrap() + } + } +} + +impl<'de, T, const N: usize, Context> BorrowDecode<'de, Context> for [T; N] +where + T: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + decoder.claim_bytes_read(core::mem::size_of::<[T; N]>())?; + + if unty::type_equal::() { + let mut buf = [0u8; N]; + decoder.reader().read(&mut buf)?; + let ptr = &mut buf as *mut _ as *mut [T; N]; + + // Safety: we know that T is a u8, so it is perfectly safe to + // translate an array of u8 into an array of T + let res = unsafe { ptr.read() }; + Ok(res) + } else { + let result = super::impl_core::collect_into_array(&mut (0..N).map(|_| { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::()); + T::borrow_decode(decoder) + })); + + // result is only None if N does not match the values of `(0..N)`, which it always should + // So this unwrap should never occur + result.unwrap() + } + } +} + +impl Decode for () { + fn decode>(_: &mut D) -> Result { + Ok(()) + } +} +impl_borrow_decode!(()); + +impl Decode for core::marker::PhantomData { + fn decode>(_: &mut D) -> Result { + Ok(core::marker::PhantomData) + } +} +impl_borrow_decode!(core::marker::PhantomData, T); + +impl Decode for Option +where + T: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + match super::decode_option_variant(decoder, core::any::type_name::>())? { + Some(_) => { + let val = T::decode(decoder)?; + Ok(Some(val)) + } + None => Ok(None), + } + } +} + +impl<'de, T, Context> BorrowDecode<'de, Context> for Option +where + T: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + match super::decode_option_variant(decoder, core::any::type_name::>())? { + Some(_) => { + let val = T::borrow_decode(decoder)?; + Ok(Some(val)) + } + None => Ok(None), + } + } +} + +impl Decode for Result +where + T: Decode, + U: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + let is_ok = u32::decode(decoder)?; + match is_ok { + 0 => { + let t = T::decode(decoder)?; + Ok(Ok(t)) + } + 1 => { + let u = U::decode(decoder)?; + Ok(Err(u)) + } + x => Err(DecodeError::UnexpectedVariant { + found: x, + allowed: &crate::error::AllowedEnumVariants::Range { max: 1, min: 0 }, + type_name: core::any::type_name::>(), + }), + } + } +} + +impl<'de, T, U, Context> BorrowDecode<'de, Context> for Result +where + T: BorrowDecode<'de, Context>, + U: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let is_ok = u32::decode(decoder)?; + match is_ok { + 0 => { + let t = T::borrow_decode(decoder)?; + Ok(Ok(t)) + } + 1 => { + let u = U::borrow_decode(decoder)?; + Ok(Err(u)) + } + x => Err(DecodeError::UnexpectedVariant { + found: x, + allowed: &crate::error::AllowedEnumVariants::Range { max: 1, min: 0 }, + type_name: core::any::type_name::>(), + }), + } + } +} + +impl Decode for Cell +where + T: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + let t = T::decode(decoder)?; + Ok(Cell::new(t)) + } +} + +impl<'de, T, Context> BorrowDecode<'de, Context> for Cell +where + T: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let t = T::borrow_decode(decoder)?; + Ok(Cell::new(t)) + } +} + +impl Decode for RefCell +where + T: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + let t = T::decode(decoder)?; + Ok(RefCell::new(t)) + } +} + +impl<'de, T, Context> BorrowDecode<'de, Context> for RefCell +where + T: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let t = T::borrow_decode(decoder)?; + Ok(RefCell::new(t)) + } +} + +impl Decode for Duration { + fn decode>(decoder: &mut D) -> Result { + const NANOS_PER_SEC: u64 = 1_000_000_000; + let secs: u64 = Decode::decode(decoder)?; + let nanos: u32 = Decode::decode(decoder)?; + if secs.checked_add(u64::from(nanos) / NANOS_PER_SEC).is_none() { + return Err(DecodeError::InvalidDuration { secs, nanos }); + } + Ok(Duration::new(secs, nanos)) + } +} +impl_borrow_decode!(Duration); + +impl Decode for Range +where + T: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + let min = T::decode(decoder)?; + let max = T::decode(decoder)?; + Ok(min..max) + } +} +impl<'de, T, Context> BorrowDecode<'de, Context> for Range +where + T: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let min = T::borrow_decode(decoder)?; + let max = T::borrow_decode(decoder)?; + Ok(min..max) + } +} + +impl Decode for RangeInclusive +where + T: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + let min = T::decode(decoder)?; + let max = T::decode(decoder)?; + Ok(RangeInclusive::new(min, max)) + } +} + +impl<'de, T, Context> BorrowDecode<'de, Context> for RangeInclusive +where + T: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let min = T::borrow_decode(decoder)?; + let max = T::borrow_decode(decoder)?; + Ok(RangeInclusive::new(min, max)) + } +} + +impl Decode for Bound +where + T: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + match u32::decode(decoder)? { + 0 => Ok(Bound::Unbounded), + 1 => Ok(Bound::Included(T::decode(decoder)?)), + 2 => Ok(Bound::Excluded(T::decode(decoder)?)), + x => Err(DecodeError::UnexpectedVariant { + allowed: &crate::error::AllowedEnumVariants::Range { max: 2, min: 0 }, + found: x, + type_name: core::any::type_name::>(), + }), + } + } +} + +impl<'de, T, Context> BorrowDecode<'de, Context> for Bound +where + T: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + match u32::decode(decoder)? { + 0 => Ok(Bound::Unbounded), + 1 => Ok(Bound::Included(T::borrow_decode(decoder)?)), + 2 => Ok(Bound::Excluded(T::borrow_decode(decoder)?)), + x => Err(DecodeError::UnexpectedVariant { + allowed: &crate::error::AllowedEnumVariants::Range { max: 2, min: 0 }, + found: x, + type_name: core::any::type_name::>(), + }), + } + } +} + +const UTF8_CHAR_WIDTH: [u8; 256] = [ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, // 0x1F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, // 0x3F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, // 0x5F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, // 0x7F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, // 0x9F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, // 0xBF + 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, // 0xDF + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEF + 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xFF +]; + +// This function is a copy of core::str::utf8_char_width +const fn utf8_char_width(b: u8) -> usize { + UTF8_CHAR_WIDTH[b as usize] as usize +} diff --git a/vendor/bincode-2.0.1/src/de/mod.rs b/vendor/bincode-2.0.1/src/de/mod.rs new file mode 100644 index 0000000..16abcb4 --- /dev/null +++ b/vendor/bincode-2.0.1/src/de/mod.rs @@ -0,0 +1,334 @@ +//! Decoder-based structs and traits. + +mod decoder; +mod impl_core; +mod impl_tuples; +mod impls; + +use self::{ + decoder::WithContext, + read::{BorrowReader, Reader}, +}; +use crate::{ + config::{Config, InternalLimitConfig}, + error::DecodeError, + utils::Sealed, +}; + +pub mod read; + +pub use self::decoder::DecoderImpl; + +/// Trait that makes a type able to be decoded, akin to serde's `DeserializeOwned` trait. +/// +/// Some types may require specific contexts. For example, to decode arena-based collections, an arena allocator must be provided as a context. In these cases, the context type `Context` should be specified or bounded. +/// +/// This trait should be implemented for types which do not have references to data in the reader. For types that contain e.g. `&str` and `&[u8]`, implement [BorrowDecode] instead. +/// +/// Whenever you derive `Decode` for your type, the base trait `BorrowDecode` is automatically implemented. +/// +/// This trait will be automatically implemented with unbounded `Context` if you enable the `derive` feature and add `#[derive(bincode::Decode)]` to your type. Note that if the type contains any lifetimes, `BorrowDecode` will be implemented instead. +/// +/// # Implementing this trait manually +/// +/// If you want to implement this trait for your type, the easiest way is to add a `#[derive(bincode::Decode)]`, build and check your `target/generated/bincode/` folder. This should generate a `_Decode.rs` file. +/// +/// For this struct: +/// +/// ``` +/// struct Entity { +/// pub x: f32, +/// pub y: f32, +/// } +/// ``` +/// +/// It will look something like: +/// +/// ``` +/// # struct Entity { +/// # pub x: f32, +/// # pub y: f32, +/// # } +/// impl bincode::Decode for Entity { +/// fn decode>( +/// decoder: &mut D, +/// ) -> core::result::Result { +/// Ok(Self { +/// x: bincode::Decode::decode(decoder)?, +/// y: bincode::Decode::decode(decoder)?, +/// }) +/// } +/// } +/// impl<'de, Context> bincode::BorrowDecode<'de, Context> for Entity { +/// fn borrow_decode>( +/// decoder: &mut D, +/// ) -> core::result::Result { +/// Ok(Self { +/// x: bincode::BorrowDecode::borrow_decode(decoder)?, +/// y: bincode::BorrowDecode::borrow_decode(decoder)?, +/// }) +/// } +/// } +/// ``` +/// +/// From here you can add/remove fields, or add custom logic. +/// +/// To get specific integer types, you can use: +/// ``` +/// # struct Foo; +/// # impl bincode::Decode for Foo { +/// # fn decode>( +/// # decoder: &mut D, +/// # ) -> core::result::Result { +/// let x: u8 = bincode::Decode::::decode(decoder)?; +/// let x = >::decode(decoder)?; +/// # Ok(Foo) +/// # } +/// # } +/// # bincode::impl_borrow_decode!(Foo); +/// ``` +/// +/// You can use `Context` to require contexts for decoding a type: +/// ``` +/// # /// # use bumpalo::Bump; +/// use bincode::de::Decoder; +/// use bincode::error::DecodeError; +/// struct BytesInArena<'a>(bumpalo::collections::Vec<'a, u8>); +/// impl<'a> bincode::Decode<&'a bumpalo::Bump> for BytesInArena<'a> { +/// fn decode(decoder: &mut D) -> Result { +/// todo!() +/// } +/// # } +/// ``` +pub trait Decode: Sized { + /// Attempt to decode this type with the given [Decode]. + fn decode>(decoder: &mut D) -> Result; +} + +/// Trait that makes a type able to be decoded, akin to serde's `Deserialize` trait. +/// +/// This trait should be implemented for types that contain borrowed data, like `&str` and `&[u8]`. If your type does not have borrowed data, consider implementing [Decode] instead. +/// +/// This trait will be automatically implemented if you enable the `derive` feature and add `#[derive(bincode::Decode)]` to a type with a lifetime. +pub trait BorrowDecode<'de, Context>: Sized { + /// Attempt to decode this type with the given [BorrowDecode]. + fn borrow_decode>( + decoder: &mut D, + ) -> Result; +} + +/// Helper macro to implement `BorrowDecode` for any type that implements `Decode`. +#[macro_export] +macro_rules! impl_borrow_decode { + ($ty:ty $(, $param:tt)*) => { + impl<'de $(, $param)*, __Context> $crate::BorrowDecode<'de, __Context> for $ty { + fn borrow_decode>( + decoder: &mut D, + ) -> core::result::Result { + $crate::Decode::decode(decoder) + } + } + }; +} + +/// Helper macro to implement `BorrowDecode` for any type that implements `Decode`. +#[macro_export] +macro_rules! impl_borrow_decode_with_context { + ($ty:ty, $context:ty $(, $param:tt)*) => { + impl<'de $(, $param)*> $crate::BorrowDecode<'de, $context> for $ty { + fn borrow_decode>( + decoder: &mut D, + ) -> core::result::Result { + $crate::Decode::decode(decoder) + } + } + }; +} + +/// Any source that can decode basic types. This type is most notably implemented for [Decoder]. +pub trait Decoder: Sealed { + /// The concrete [Reader] type + type R: Reader; + + /// The concrete [Config] type + type C: Config; + + /// The decoding context type + type Context; + + /// Returns the decoding context + fn context(&mut self) -> &mut Self::Context; + + /// Wraps decoder with a context + fn with_context(&mut self, context: C) -> WithContext { + WithContext { + decoder: self, + context, + } + } + + /// Returns a mutable reference to the reader + fn reader(&mut self) -> &mut Self::R; + + /// Returns a reference to the config + fn config(&self) -> &Self::C; + + /// Claim that `n` bytes are going to be read from the decoder. + /// This can be used to validate `Configuration::Limit()`. + fn claim_bytes_read(&mut self, n: usize) -> Result<(), DecodeError>; + + /// Claim that we're going to read a container which contains `len` entries of `T`. + /// This will correctly handle overflowing if `len * size_of::() > usize::max_value` + fn claim_container_read(&mut self, len: usize) -> Result<(), DecodeError> { + if ::LIMIT.is_some() { + match len.checked_mul(core::mem::size_of::()) { + Some(val) => self.claim_bytes_read(val), + None => Err(DecodeError::LimitExceeded), + } + } else { + Ok(()) + } + } + + /// Notify the decoder that `n` bytes are being reclaimed. + /// + /// When decoding container types, a typical implementation would claim to read `len * size_of::()` bytes. + /// This is to ensure that bincode won't allocate several GB of memory while constructing the container. + /// + /// Because the implementation claims `len * size_of::()`, but then has to decode each `T`, this would be marked + /// as double. This function allows us to un-claim each `T` that gets decoded. + /// + /// We cannot check if `len * size_of::()` is valid without claiming it, because this would mean that if you have + /// a nested container (e.g. `Vec>`), it does not know how much memory is already claimed, and could easily + /// allocate much more than the user intends. + /// ``` + /// # use bincode::de::{Decode, Decoder}; + /// # use bincode::error::DecodeError; + /// # struct Container(Vec); + /// # impl Container { + /// # fn with_capacity(cap: usize) -> Self { + /// # Self(Vec::with_capacity(cap)) + /// # } + /// # + /// # fn push(&mut self, t: T) { + /// # self.0.push(t); + /// # } + /// # } + /// impl> Decode for Container { + /// fn decode>(decoder: &mut D) -> Result { + /// let len = u64::decode(decoder)?; + /// let len: usize = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?; + /// // Make sure we don't allocate too much memory + /// decoder.claim_bytes_read(len * core::mem::size_of::()); + /// + /// let mut result = Container::with_capacity(len); + /// for _ in 0..len { + /// // un-claim the memory + /// decoder.unclaim_bytes_read(core::mem::size_of::()); + /// result.push(T::decode(decoder)?) + /// } + /// Ok(result) + /// } + /// } + /// impl<'de, Context, T: bincode::BorrowDecode<'de, Context>> bincode::BorrowDecode<'de, Context> for Container { + /// fn borrow_decode>( + /// decoder: &mut D, + /// ) -> core::result::Result { + /// let len = u64::borrow_decode(decoder)?; + /// let len: usize = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?; + /// // Make sure we don't allocate too much memory + /// decoder.claim_bytes_read(len * core::mem::size_of::()); + /// + /// let mut result = Container::with_capacity(len); + /// for _ in 0..len { + /// // un-claim the memory + /// decoder.unclaim_bytes_read(core::mem::size_of::()); + /// result.push(T::borrow_decode(decoder)?) + /// } + /// Ok(result) + /// } + /// } + /// ``` + fn unclaim_bytes_read(&mut self, n: usize); +} + +/// Any source that can decode basic types. This type is most notably implemented for [Decoder]. +/// +/// This is an extension of [Decode] that can also return borrowed data. +pub trait BorrowDecoder<'de>: Decoder { + /// The concrete [BorrowReader] type + type BR: BorrowReader<'de>; + + /// Rerturns a mutable reference to the borrow reader + fn borrow_reader(&mut self) -> &mut Self::BR; +} + +impl Decoder for &mut T +where + T: Decoder, +{ + type R = T::R; + + type C = T::C; + + type Context = T::Context; + + fn reader(&mut self) -> &mut Self::R { + T::reader(self) + } + + fn config(&self) -> &Self::C { + T::config(self) + } + + #[inline] + fn claim_bytes_read(&mut self, n: usize) -> Result<(), DecodeError> { + T::claim_bytes_read(self, n) + } + + #[inline] + fn unclaim_bytes_read(&mut self, n: usize) { + T::unclaim_bytes_read(self, n) + } + + fn context(&mut self) -> &mut Self::Context { + T::context(self) + } +} + +impl<'de, T> BorrowDecoder<'de> for &mut T +where + T: BorrowDecoder<'de>, +{ + type BR = T::BR; + + fn borrow_reader(&mut self) -> &mut Self::BR { + T::borrow_reader(self) + } +} + +/// Decodes only the option variant from the decoder. Will not read any more data than that. +#[inline] +pub(crate) fn decode_option_variant( + decoder: &mut D, + type_name: &'static str, +) -> Result, DecodeError> { + let is_some = u8::decode(decoder)?; + match is_some { + 0 => Ok(None), + 1 => Ok(Some(())), + x => Err(DecodeError::UnexpectedVariant { + found: x as u32, + allowed: &crate::error::AllowedEnumVariants::Range { max: 1, min: 0 }, + type_name, + }), + } +} + +/// Decodes the length of any slice, container, etc from the decoder +#[inline] +pub(crate) fn decode_slice_len(decoder: &mut D) -> Result { + let v = u64::decode(decoder)?; + + v.try_into().map_err(|_| DecodeError::OutsideUsizeRange(v)) +} diff --git a/vendor/bincode-2.0.1/src/de/read.rs b/vendor/bincode-2.0.1/src/de/read.rs new file mode 100644 index 0000000..21c35db --- /dev/null +++ b/vendor/bincode-2.0.1/src/de/read.rs @@ -0,0 +1,112 @@ +//! This module contains reader-based structs and traits. +//! +//! Because `std::io::Read` is only limited to `std` and not `core`, we provide 2 alternative readers. +//! +//! [Reader] is a reader for sources that do not own their data. It is assumed that the reader's data is dropped after the `read` method is called. This reader is incapable of reading borrowed data, like `&str` and `&[u8]`. +//! +//! [BorrowReader] is an extension of `Reader` that also allows returning borrowed data. A `BorrowReader` allows reading `&str` and `&[u8]`. +//! +//! Specifically the `Reader` trait is used by [Decode] and the `BorrowReader` trait is used by `[BorrowDecode]`. +//! +//! [Decode]: ../trait.Decode.html +//! [BorrowDecode]: ../trait.BorrowDecode.html + +use crate::error::DecodeError; + +/// A reader for owned data. See the module documentation for more information. +pub trait Reader { + /// Fill the given `bytes` argument with values. Exactly the length of the given slice must be filled, or else an error must be returned. + fn read(&mut self, bytes: &mut [u8]) -> Result<(), DecodeError>; + + /// If this reader wraps a buffer of any kind, this function lets callers access contents of + /// the buffer without passing data through a buffer first. + #[inline] + fn peek_read(&mut self, _: usize) -> Option<&[u8]> { + None + } + + /// If an implementation of `peek_read` is provided, an implementation of this function + /// must be provided so that subsequent reads or peek-reads do not return the same bytes + #[inline] + fn consume(&mut self, _: usize) {} +} + +impl Reader for &mut T +where + T: Reader, +{ + #[inline] + fn read(&mut self, bytes: &mut [u8]) -> Result<(), DecodeError> { + (**self).read(bytes) + } + + #[inline] + fn peek_read(&mut self, n: usize) -> Option<&[u8]> { + (**self).peek_read(n) + } + + #[inline] + fn consume(&mut self, n: usize) { + (*self).consume(n) + } +} + +/// A reader for borrowed data. Implementors of this must also implement the [Reader] trait. See the module documentation for more information. +pub trait BorrowReader<'storage>: Reader { + /// Read exactly `length` bytes and return a slice to this data. If not enough bytes could be read, an error should be returned. + /// + /// *note*: Exactly `length` bytes must be returned. If less bytes are returned, bincode may panic. If more bytes are returned, the excess bytes may be discarded. + fn take_bytes(&mut self, length: usize) -> Result<&'storage [u8], DecodeError>; +} + +/// A reader type for `&[u8]` slices. Implements both [Reader] and [BorrowReader], and thus can be used for borrowed data. +pub struct SliceReader<'storage> { + pub(crate) slice: &'storage [u8], +} + +impl<'storage> SliceReader<'storage> { + /// Constructs a slice reader + pub const fn new(bytes: &'storage [u8]) -> SliceReader<'storage> { + SliceReader { slice: bytes } + } +} + +impl<'storage> Reader for SliceReader<'storage> { + #[inline(always)] + fn read(&mut self, bytes: &mut [u8]) -> Result<(), DecodeError> { + if bytes.len() > self.slice.len() { + return Err(DecodeError::UnexpectedEnd { + additional: bytes.len() - self.slice.len(), + }); + } + let (read_slice, remaining) = self.slice.split_at(bytes.len()); + bytes.copy_from_slice(read_slice); + self.slice = remaining; + + Ok(()) + } + + #[inline] + fn peek_read(&mut self, n: usize) -> Option<&'storage [u8]> { + self.slice.get(..n) + } + + #[inline] + fn consume(&mut self, n: usize) { + self.slice = self.slice.get(n..).unwrap_or_default(); + } +} + +impl<'storage> BorrowReader<'storage> for SliceReader<'storage> { + #[inline(always)] + fn take_bytes(&mut self, length: usize) -> Result<&'storage [u8], DecodeError> { + if length > self.slice.len() { + return Err(DecodeError::UnexpectedEnd { + additional: length - self.slice.len(), + }); + } + let (read_slice, remaining) = self.slice.split_at(length); + self.slice = remaining; + Ok(read_slice) + } +} diff --git a/vendor/bincode-2.0.1/src/enc/encoder.rs b/vendor/bincode-2.0.1/src/enc/encoder.rs new file mode 100644 index 0000000..7f0bf22 --- /dev/null +++ b/vendor/bincode-2.0.1/src/enc/encoder.rs @@ -0,0 +1,57 @@ +use super::{write::Writer, Encoder}; +use crate::{config::Config, utils::Sealed}; + +/// An Encoder that writes bytes into a given writer `W`. +/// +/// This struct should rarely be used. +/// In most cases, prefer any of the `encode` functions. +/// +/// The ByteOrder that is chosen will impact the endianness that +/// is used to write integers to the writer. +/// +/// ``` +/// # use bincode::enc::{write::SliceWriter, EncoderImpl, Encode}; +/// let slice: &mut [u8] = &mut [0, 0, 0, 0]; +/// let config = bincode::config::legacy().with_big_endian(); +/// +/// let mut encoder = EncoderImpl::new(SliceWriter::new(slice), config); +/// // this u32 can be any Encodable +/// 5u32.encode(&mut encoder).unwrap(); +/// assert_eq!(encoder.into_writer().bytes_written(), 4); +/// assert_eq!(slice, [0, 0, 0, 5]); +/// ``` +pub struct EncoderImpl { + writer: W, + config: C, +} + +impl EncoderImpl { + /// Create a new Encoder + pub const fn new(writer: W, config: C) -> EncoderImpl { + EncoderImpl { writer, config } + } + + /// Return the underlying writer + #[inline] + pub fn into_writer(self) -> W { + self.writer + } +} + +impl Encoder for EncoderImpl { + type W = W; + + type C = C; + + #[inline] + fn writer(&mut self) -> &mut Self::W { + &mut self.writer + } + + #[inline] + fn config(&self) -> &Self::C { + &self.config + } +} + +impl Sealed for EncoderImpl {} diff --git a/vendor/bincode-2.0.1/src/enc/impl_tuples.rs b/vendor/bincode-2.0.1/src/enc/impl_tuples.rs new file mode 100644 index 0000000..adf5f5d --- /dev/null +++ b/vendor/bincode-2.0.1/src/enc/impl_tuples.rs @@ -0,0 +1,404 @@ +use super::{Encode, Encoder}; +use crate::error::EncodeError; + +impl Encode for (A,) +where + A: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + Ok(()) + } +} + +impl Encode for (A, B) +where + A: Encode, + B: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + Ok(()) + } +} + +impl Encode for (A, B, C) +where + A: Encode, + B: Encode, + C: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + self.2.encode(encoder)?; + Ok(()) + } +} + +impl Encode for (A, B, C, D) +where + A: Encode, + B: Encode, + C: Encode, + D: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + self.2.encode(encoder)?; + self.3.encode(encoder)?; + Ok(()) + } +} + +impl Encode for (A, B, C, D, E) +where + A: Encode, + B: Encode, + C: Encode, + D: Encode, + E: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + self.2.encode(encoder)?; + self.3.encode(encoder)?; + self.4.encode(encoder)?; + Ok(()) + } +} + +impl Encode for (A, B, C, D, E, F) +where + A: Encode, + B: Encode, + C: Encode, + D: Encode, + E: Encode, + F: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + self.2.encode(encoder)?; + self.3.encode(encoder)?; + self.4.encode(encoder)?; + self.5.encode(encoder)?; + Ok(()) + } +} + +impl Encode for (A, B, C, D, E, F, G) +where + A: Encode, + B: Encode, + C: Encode, + D: Encode, + E: Encode, + F: Encode, + G: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + self.2.encode(encoder)?; + self.3.encode(encoder)?; + self.4.encode(encoder)?; + self.5.encode(encoder)?; + self.6.encode(encoder)?; + Ok(()) + } +} + +impl Encode for (A, B, C, D, E, F, G, H) +where + A: Encode, + B: Encode, + C: Encode, + D: Encode, + E: Encode, + F: Encode, + G: Encode, + H: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + self.2.encode(encoder)?; + self.3.encode(encoder)?; + self.4.encode(encoder)?; + self.5.encode(encoder)?; + self.6.encode(encoder)?; + self.7.encode(encoder)?; + Ok(()) + } +} + +impl Encode for (A, B, C, D, E, F, G, H, I) +where + A: Encode, + B: Encode, + C: Encode, + D: Encode, + E: Encode, + F: Encode, + G: Encode, + H: Encode, + I: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + self.2.encode(encoder)?; + self.3.encode(encoder)?; + self.4.encode(encoder)?; + self.5.encode(encoder)?; + self.6.encode(encoder)?; + self.7.encode(encoder)?; + self.8.encode(encoder)?; + Ok(()) + } +} + +impl Encode for (A, B, C, D, E, F, G, H, I, J) +where + A: Encode, + B: Encode, + C: Encode, + D: Encode, + E: Encode, + F: Encode, + G: Encode, + H: Encode, + I: Encode, + J: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + self.2.encode(encoder)?; + self.3.encode(encoder)?; + self.4.encode(encoder)?; + self.5.encode(encoder)?; + self.6.encode(encoder)?; + self.7.encode(encoder)?; + self.8.encode(encoder)?; + self.9.encode(encoder)?; + Ok(()) + } +} + +impl Encode for (A, B, C, D, E, F, G, H, I, J, K) +where + A: Encode, + B: Encode, + C: Encode, + D: Encode, + E: Encode, + F: Encode, + G: Encode, + H: Encode, + I: Encode, + J: Encode, + K: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + self.2.encode(encoder)?; + self.3.encode(encoder)?; + self.4.encode(encoder)?; + self.5.encode(encoder)?; + self.6.encode(encoder)?; + self.7.encode(encoder)?; + self.8.encode(encoder)?; + self.9.encode(encoder)?; + self.10.encode(encoder)?; + Ok(()) + } +} + +impl Encode for (A, B, C, D, E, F, G, H, I, J, K, L) +where + A: Encode, + B: Encode, + C: Encode, + D: Encode, + E: Encode, + F: Encode, + G: Encode, + H: Encode, + I: Encode, + J: Encode, + K: Encode, + L: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + self.2.encode(encoder)?; + self.3.encode(encoder)?; + self.4.encode(encoder)?; + self.5.encode(encoder)?; + self.6.encode(encoder)?; + self.7.encode(encoder)?; + self.8.encode(encoder)?; + self.9.encode(encoder)?; + self.10.encode(encoder)?; + self.11.encode(encoder)?; + Ok(()) + } +} + +impl Encode for (A, B, C, D, E, F, G, H, I, J, K, L, M) +where + A: Encode, + B: Encode, + C: Encode, + D: Encode, + E: Encode, + F: Encode, + G: Encode, + H: Encode, + I: Encode, + J: Encode, + K: Encode, + L: Encode, + M: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + self.2.encode(encoder)?; + self.3.encode(encoder)?; + self.4.encode(encoder)?; + self.5.encode(encoder)?; + self.6.encode(encoder)?; + self.7.encode(encoder)?; + self.8.encode(encoder)?; + self.9.encode(encoder)?; + self.10.encode(encoder)?; + self.11.encode(encoder)?; + self.12.encode(encoder)?; + Ok(()) + } +} + +impl Encode for (A, B, C, D, E, F, G, H, I, J, K, L, M, N) +where + A: Encode, + B: Encode, + C: Encode, + D: Encode, + E: Encode, + F: Encode, + G: Encode, + H: Encode, + I: Encode, + J: Encode, + K: Encode, + L: Encode, + M: Encode, + N: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + self.2.encode(encoder)?; + self.3.encode(encoder)?; + self.4.encode(encoder)?; + self.5.encode(encoder)?; + self.6.encode(encoder)?; + self.7.encode(encoder)?; + self.8.encode(encoder)?; + self.9.encode(encoder)?; + self.10.encode(encoder)?; + self.11.encode(encoder)?; + self.12.encode(encoder)?; + self.13.encode(encoder)?; + Ok(()) + } +} + +impl Encode + for (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) +where + A: Encode, + B: Encode, + C: Encode, + D: Encode, + E: Encode, + F: Encode, + G: Encode, + H: Encode, + I: Encode, + J: Encode, + K: Encode, + L: Encode, + M: Encode, + N: Encode, + O: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + self.2.encode(encoder)?; + self.3.encode(encoder)?; + self.4.encode(encoder)?; + self.5.encode(encoder)?; + self.6.encode(encoder)?; + self.7.encode(encoder)?; + self.8.encode(encoder)?; + self.9.encode(encoder)?; + self.10.encode(encoder)?; + self.11.encode(encoder)?; + self.12.encode(encoder)?; + self.13.encode(encoder)?; + self.14.encode(encoder)?; + Ok(()) + } +} + +impl Encode + for (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) +where + A: Encode, + B: Encode, + C: Encode, + D: Encode, + E: Encode, + F: Encode, + G: Encode, + H: Encode, + I: Encode, + J: Encode, + K: Encode, + L: Encode, + M: Encode, + N: Encode, + O: Encode, + P: Encode, +{ + fn encode<_E: Encoder>(&self, encoder: &mut _E) -> Result<(), EncodeError> { + self.0.encode(encoder)?; + self.1.encode(encoder)?; + self.2.encode(encoder)?; + self.3.encode(encoder)?; + self.4.encode(encoder)?; + self.5.encode(encoder)?; + self.6.encode(encoder)?; + self.7.encode(encoder)?; + self.8.encode(encoder)?; + self.9.encode(encoder)?; + self.10.encode(encoder)?; + self.11.encode(encoder)?; + self.12.encode(encoder)?; + self.13.encode(encoder)?; + self.14.encode(encoder)?; + self.15.encode(encoder)?; + Ok(()) + } +} diff --git a/vendor/bincode-2.0.1/src/enc/impls.rs b/vendor/bincode-2.0.1/src/enc/impls.rs new file mode 100644 index 0000000..ebc6c73 --- /dev/null +++ b/vendor/bincode-2.0.1/src/enc/impls.rs @@ -0,0 +1,491 @@ +use super::{write::Writer, Encode, Encoder}; +use crate::{ + config::{Endianness, IntEncoding, InternalEndianConfig, InternalIntEncodingConfig}, + error::EncodeError, +}; +use core::cmp::Reverse; +use core::{ + cell::{Cell, RefCell}, + marker::PhantomData, + num::{ + NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, + NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping, + }, + ops::{Bound, Range, RangeInclusive}, + time::Duration, +}; + +impl Encode for () { + fn encode(&self, _: &mut E) -> Result<(), EncodeError> { + Ok(()) + } +} + +impl Encode for PhantomData { + fn encode(&self, _: &mut E) -> Result<(), EncodeError> { + Ok(()) + } +} + +impl Encode for bool { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + u8::from(*self).encode(encoder) + } +} + +impl Encode for u8 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + encoder.writer().write(&[*self]) + } +} + +impl Encode for NonZeroU8 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.get().encode(encoder) + } +} + +impl Encode for u16 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match E::C::INT_ENCODING { + IntEncoding::Variable => { + crate::varint::varint_encode_u16(encoder.writer(), E::C::ENDIAN, *self) + } + IntEncoding::Fixed => match E::C::ENDIAN { + Endianness::Big => encoder.writer().write(&self.to_be_bytes()), + Endianness::Little => encoder.writer().write(&self.to_le_bytes()), + }, + } + } +} + +impl Encode for NonZeroU16 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.get().encode(encoder) + } +} + +impl Encode for u32 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match E::C::INT_ENCODING { + IntEncoding::Variable => { + crate::varint::varint_encode_u32(encoder.writer(), E::C::ENDIAN, *self) + } + IntEncoding::Fixed => match E::C::ENDIAN { + Endianness::Big => encoder.writer().write(&self.to_be_bytes()), + Endianness::Little => encoder.writer().write(&self.to_le_bytes()), + }, + } + } +} + +impl Encode for NonZeroU32 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.get().encode(encoder) + } +} + +impl Encode for u64 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match E::C::INT_ENCODING { + IntEncoding::Variable => { + crate::varint::varint_encode_u64(encoder.writer(), E::C::ENDIAN, *self) + } + IntEncoding::Fixed => match E::C::ENDIAN { + Endianness::Big => encoder.writer().write(&self.to_be_bytes()), + Endianness::Little => encoder.writer().write(&self.to_le_bytes()), + }, + } + } +} + +impl Encode for NonZeroU64 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.get().encode(encoder) + } +} + +impl Encode for u128 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match E::C::INT_ENCODING { + IntEncoding::Variable => { + crate::varint::varint_encode_u128(encoder.writer(), E::C::ENDIAN, *self) + } + IntEncoding::Fixed => match E::C::ENDIAN { + Endianness::Big => encoder.writer().write(&self.to_be_bytes()), + Endianness::Little => encoder.writer().write(&self.to_le_bytes()), + }, + } + } +} + +impl Encode for NonZeroU128 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.get().encode(encoder) + } +} + +impl Encode for usize { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match E::C::INT_ENCODING { + IntEncoding::Variable => { + crate::varint::varint_encode_usize(encoder.writer(), E::C::ENDIAN, *self) + } + IntEncoding::Fixed => match E::C::ENDIAN { + Endianness::Big => encoder.writer().write(&(*self as u64).to_be_bytes()), + Endianness::Little => encoder.writer().write(&(*self as u64).to_le_bytes()), + }, + } + } +} + +impl Encode for NonZeroUsize { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.get().encode(encoder) + } +} + +impl Encode for i8 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + encoder.writer().write(&[*self as u8]) + } +} + +impl Encode for NonZeroI8 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.get().encode(encoder) + } +} + +impl Encode for i16 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match E::C::INT_ENCODING { + IntEncoding::Variable => { + crate::varint::varint_encode_i16(encoder.writer(), E::C::ENDIAN, *self) + } + IntEncoding::Fixed => match E::C::ENDIAN { + Endianness::Big => encoder.writer().write(&self.to_be_bytes()), + Endianness::Little => encoder.writer().write(&self.to_le_bytes()), + }, + } + } +} + +impl Encode for NonZeroI16 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.get().encode(encoder) + } +} + +impl Encode for i32 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match E::C::INT_ENCODING { + IntEncoding::Variable => { + crate::varint::varint_encode_i32(encoder.writer(), E::C::ENDIAN, *self) + } + IntEncoding::Fixed => match E::C::ENDIAN { + Endianness::Big => encoder.writer().write(&self.to_be_bytes()), + Endianness::Little => encoder.writer().write(&self.to_le_bytes()), + }, + } + } +} + +impl Encode for NonZeroI32 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.get().encode(encoder) + } +} + +impl Encode for i64 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match E::C::INT_ENCODING { + IntEncoding::Variable => { + crate::varint::varint_encode_i64(encoder.writer(), E::C::ENDIAN, *self) + } + IntEncoding::Fixed => match E::C::ENDIAN { + Endianness::Big => encoder.writer().write(&self.to_be_bytes()), + Endianness::Little => encoder.writer().write(&self.to_le_bytes()), + }, + } + } +} + +impl Encode for NonZeroI64 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.get().encode(encoder) + } +} + +impl Encode for i128 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match E::C::INT_ENCODING { + IntEncoding::Variable => { + crate::varint::varint_encode_i128(encoder.writer(), E::C::ENDIAN, *self) + } + IntEncoding::Fixed => match E::C::ENDIAN { + Endianness::Big => encoder.writer().write(&self.to_be_bytes()), + Endianness::Little => encoder.writer().write(&self.to_le_bytes()), + }, + } + } +} + +impl Encode for NonZeroI128 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.get().encode(encoder) + } +} + +impl Encode for isize { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match E::C::INT_ENCODING { + IntEncoding::Variable => { + crate::varint::varint_encode_isize(encoder.writer(), E::C::ENDIAN, *self) + } + IntEncoding::Fixed => match E::C::ENDIAN { + Endianness::Big => encoder.writer().write(&(*self as i64).to_be_bytes()), + Endianness::Little => encoder.writer().write(&(*self as i64).to_le_bytes()), + }, + } + } +} + +impl Encode for NonZeroIsize { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.get().encode(encoder) + } +} + +impl Encode for f32 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match E::C::ENDIAN { + Endianness::Big => encoder.writer().write(&self.to_be_bytes()), + Endianness::Little => encoder.writer().write(&self.to_le_bytes()), + } + } +} + +impl Encode for f64 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match E::C::ENDIAN { + Endianness::Big => encoder.writer().write(&self.to_be_bytes()), + Endianness::Little => encoder.writer().write(&self.to_le_bytes()), + } + } +} + +impl Encode for Wrapping { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.0.encode(encoder) + } +} + +impl Encode for Reverse { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.0.encode(encoder) + } +} + +impl Encode for char { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + encode_utf8(encoder.writer(), *self) + } +} + +impl Encode for [T] +where + T: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + super::encode_slice_len(encoder, self.len())?; + + if unty::type_equal::() { + // Safety: T = u8 + let t: &[u8] = unsafe { core::mem::transmute(self) }; + encoder.writer().write(t)?; + return Ok(()); + } + + for item in self { + item.encode(encoder)?; + } + Ok(()) + } +} + +const TAG_CONT: u8 = 0b1000_0000; +const TAG_TWO_B: u8 = 0b1100_0000; +const TAG_THREE_B: u8 = 0b1110_0000; +const TAG_FOUR_B: u8 = 0b1111_0000; +const MAX_ONE_B: u32 = 0x80; +const MAX_TWO_B: u32 = 0x800; +const MAX_THREE_B: u32 = 0x10000; + +fn encode_utf8(writer: &mut impl Writer, c: char) -> Result<(), EncodeError> { + let code = c as u32; + + if code < MAX_ONE_B { + writer.write(&[c as u8]) + } else if code < MAX_TWO_B { + let mut buf = [0u8; 2]; + buf[0] = ((code >> 6) & 0x1F) as u8 | TAG_TWO_B; + buf[1] = (code & 0x3F) as u8 | TAG_CONT; + writer.write(&buf) + } else if code < MAX_THREE_B { + let mut buf = [0u8; 3]; + buf[0] = ((code >> 12) & 0x0F) as u8 | TAG_THREE_B; + buf[1] = ((code >> 6) & 0x3F) as u8 | TAG_CONT; + buf[2] = (code & 0x3F) as u8 | TAG_CONT; + writer.write(&buf) + } else { + let mut buf = [0u8; 4]; + buf[0] = ((code >> 18) & 0x07) as u8 | TAG_FOUR_B; + buf[1] = ((code >> 12) & 0x3F) as u8 | TAG_CONT; + buf[2] = ((code >> 6) & 0x3F) as u8 | TAG_CONT; + buf[3] = (code & 0x3F) as u8 | TAG_CONT; + writer.write(&buf) + } +} + +impl Encode for str { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.as_bytes().encode(encoder) + } +} + +impl Encode for [T; N] +where + T: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + if unty::type_equal::() { + // Safety: this is &[u8; N] + let array_slice: &[u8] = + unsafe { core::slice::from_raw_parts(self.as_ptr().cast(), N) }; + encoder.writer().write(array_slice) + } else { + for item in self.iter() { + item.encode(encoder)?; + } + Ok(()) + } + } +} + +impl Encode for Option +where + T: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + super::encode_option_variant(encoder, self)?; + if let Some(val) = self { + val.encode(encoder)?; + } + Ok(()) + } +} + +impl Encode for Result +where + T: Encode, + U: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match self { + Ok(val) => { + 0u32.encode(encoder)?; + val.encode(encoder) + } + Err(err) => { + 1u32.encode(encoder)?; + err.encode(encoder) + } + } + } +} + +impl Encode for Cell +where + T: Encode + Copy, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + T::encode(&self.get(), encoder) + } +} + +impl Encode for RefCell +where + T: Encode + ?Sized, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + let borrow_guard = self + .try_borrow() + .map_err(|e| EncodeError::RefCellAlreadyBorrowed { + inner: e, + type_name: core::any::type_name::>(), + })?; + T::encode(&borrow_guard, encoder) + } +} + +impl Encode for Duration { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.as_secs().encode(encoder)?; + self.subsec_nanos().encode(encoder)?; + Ok(()) + } +} + +impl Encode for Range +where + T: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.start.encode(encoder)?; + self.end.encode(encoder)?; + Ok(()) + } +} + +impl Encode for RangeInclusive +where + T: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.start().encode(encoder)?; + self.end().encode(encoder)?; + Ok(()) + } +} + +impl Encode for Bound +where + T: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match self { + Self::Unbounded => { + 0u32.encode(encoder)?; + } + Self::Included(val) => { + 1u32.encode(encoder)?; + val.encode(encoder)?; + } + Self::Excluded(val) => { + 2u32.encode(encoder)?; + val.encode(encoder)?; + } + } + Ok(()) + } +} + +impl Encode for &T +where + T: Encode + ?Sized, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + T::encode(self, encoder) + } +} diff --git a/vendor/bincode-2.0.1/src/enc/mod.rs b/vendor/bincode-2.0.1/src/enc/mod.rs new file mode 100644 index 0000000..c5c37f8 --- /dev/null +++ b/vendor/bincode-2.0.1/src/enc/mod.rs @@ -0,0 +1,103 @@ +//! Encoder-based structs and traits. + +mod encoder; +mod impl_tuples; +mod impls; + +use self::write::Writer; +use crate::{config::Config, error::EncodeError, utils::Sealed}; + +pub mod write; + +pub use self::encoder::EncoderImpl; + +/// Any source that can be encoded. This trait should be implemented for all types that you want to be able to use with any of the `encode_with` methods. +/// +/// This trait will be automatically implemented if you enable the `derive` feature and add `#[derive(bincode::Encode)]` to your trait. +/// +/// # Implementing this trait manually +/// +/// If you want to implement this trait for your type, the easiest way is to add a `#[derive(bincode::Encode)]`, build and check your `target/generated/bincode/` folder. This should generate a `_Encode.rs` file. +/// +/// For this struct: +/// +/// ``` +/// struct Entity { +/// pub x: f32, +/// pub y: f32, +/// } +/// ``` +/// It will look something like: +/// +/// ``` +/// # struct Entity { +/// # pub x: f32, +/// # pub y: f32, +/// # } +/// impl bincode::Encode for Entity { +/// fn encode( +/// &self, +/// encoder: &mut E, +/// ) -> core::result::Result<(), bincode::error::EncodeError> { +/// bincode::Encode::encode(&self.x, encoder)?; +/// bincode::Encode::encode(&self.y, encoder)?; +/// Ok(()) +/// } +/// } +/// ``` +/// +/// From here you can add/remove fields, or add custom logic. +pub trait Encode { + /// Encode a given type. + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError>; +} + +/// Helper trait to encode basic types into. +pub trait Encoder: Sealed { + /// The concrete [Writer] type + type W: Writer; + + /// The concrete [Config] type + type C: Config; + + /// Returns a mutable reference to the writer + fn writer(&mut self) -> &mut Self::W; + + /// Returns a reference to the config + fn config(&self) -> &Self::C; +} + +impl Encoder for &mut T +where + T: Encoder, +{ + type W = T::W; + + type C = T::C; + + fn writer(&mut self) -> &mut Self::W { + T::writer(self) + } + + fn config(&self) -> &Self::C { + T::config(self) + } +} + +/// Encode the variant of the given option. Will not encode the option itself. +#[inline] +pub(crate) fn encode_option_variant( + encoder: &mut E, + value: &Option, +) -> Result<(), EncodeError> { + match value { + None => 0u8.encode(encoder), + Some(_) => 1u8.encode(encoder), + } +} + +/// Encodes the length of any slice, container, etc into the given encoder +#[inline] +pub(crate) fn encode_slice_len(encoder: &mut E, len: usize) -> Result<(), EncodeError> { + (len as u64).encode(encoder) +} diff --git a/vendor/bincode-2.0.1/src/enc/write.rs b/vendor/bincode-2.0.1/src/enc/write.rs new file mode 100644 index 0000000..97a4784 --- /dev/null +++ b/vendor/bincode-2.0.1/src/enc/write.rs @@ -0,0 +1,82 @@ +//! This module contains writer-based structs and traits. +//! +//! Because `std::io::Write` is only limited to `std` and not `core`, we provide our own [Writer]. + +use crate::error::EncodeError; + +/// Trait that indicates that a struct can be used as a destination to encode data too. This is used by [Encode] +/// +/// [Encode]: ../trait.Encode.html +pub trait Writer { + /// Write `bytes` to the underlying writer. Exactly `bytes.len()` bytes must be written, or else an error should be returned. + fn write(&mut self, bytes: &[u8]) -> Result<(), EncodeError>; +} + +impl Writer for &mut T { + #[inline] + fn write(&mut self, bytes: &[u8]) -> Result<(), EncodeError> { + (**self).write(bytes) + } +} + +/// A helper struct that implements `Writer` for a `&[u8]` slice. +/// +/// ``` +/// use bincode::enc::write::{Writer, SliceWriter}; +/// +/// let destination = &mut [0u8; 100]; +/// let mut writer = SliceWriter::new(destination); +/// writer.write(&[1, 2, 3, 4, 5]).unwrap(); +/// +/// assert_eq!(writer.bytes_written(), 5); +/// assert_eq!(destination[0..6], [1, 2, 3, 4, 5, 0]); +/// ``` +pub struct SliceWriter<'storage> { + slice: &'storage mut [u8], + original_length: usize, +} + +impl<'storage> SliceWriter<'storage> { + /// Create a new instance of `SliceWriter` with the given byte array. + pub fn new(bytes: &'storage mut [u8]) -> SliceWriter<'storage> { + let original = bytes.len(); + SliceWriter { + slice: bytes, + original_length: original, + } + } + + /// Return the amount of bytes written so far. + pub fn bytes_written(&self) -> usize { + self.original_length - self.slice.len() + } +} + +impl Writer for SliceWriter<'_> { + #[inline(always)] + fn write(&mut self, bytes: &[u8]) -> Result<(), EncodeError> { + if bytes.len() > self.slice.len() { + return Err(EncodeError::UnexpectedEnd); + } + let (a, b) = core::mem::take(&mut self.slice).split_at_mut(bytes.len()); + a.copy_from_slice(bytes); + self.slice = b; + + Ok(()) + } +} + +/// A writer that counts how many bytes were written. This is useful for e.g. pre-allocating buffers bfeore writing to them. +#[derive(Default)] +pub struct SizeWriter { + /// the amount of bytes that were written so far + pub bytes_written: usize, +} +impl Writer for SizeWriter { + #[inline(always)] + fn write(&mut self, bytes: &[u8]) -> Result<(), EncodeError> { + self.bytes_written += bytes.len(); + + Ok(()) + } +} diff --git a/vendor/bincode-2.0.1/src/error.rs b/vendor/bincode-2.0.1/src/error.rs new file mode 100644 index 0000000..7fb9c5c --- /dev/null +++ b/vendor/bincode-2.0.1/src/error.rs @@ -0,0 +1,265 @@ +//! Errors that can be encounting by Encoding and Decoding. + +/// Errors that can be encountered by encoding a type +#[non_exhaustive] +#[derive(Debug)] +pub enum EncodeError { + /// The writer ran out of storage. + UnexpectedEnd, + + /// The `RefCell` is already borrowed + RefCellAlreadyBorrowed { + /// The inner borrow error + inner: core::cell::BorrowError, + /// the type name of the RefCell being encoded that is currently borrowed. + type_name: &'static str, + }, + + /// An uncommon error occurred, see the inner text for more information + Other(&'static str), + + /// An uncommon error occurred, see the inner text for more information + #[cfg(feature = "alloc")] + OtherString(alloc::string::String), + + /// A `std::path::Path` was being encoded but did not contain a valid `&str` representation + #[cfg(feature = "std")] + InvalidPathCharacters, + + /// The targeted writer encountered an `std::io::Error` + #[cfg(feature = "std")] + Io { + /// The encountered error + inner: std::io::Error, + /// The amount of bytes that were written before the error occurred + index: usize, + }, + + /// The encoder tried to encode a `Mutex` or `RwLock`, but the locking failed + #[cfg(feature = "std")] + LockFailed { + /// The type name of the mutex for debugging purposes + type_name: &'static str, + }, + + /// The encoder tried to encode a `SystemTime`, but it was before `SystemTime::UNIX_EPOCH` + #[cfg(feature = "std")] + InvalidSystemTime { + /// The error that was thrown by the SystemTime + inner: std::time::SystemTimeError, + /// The SystemTime that caused the error + time: std::boxed::Box, + }, + + #[cfg(feature = "serde")] + /// A serde-specific error that occurred while decoding. + Serde(crate::features::serde::EncodeError), +} + +impl core::fmt::Display for EncodeError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + // TODO: Improve this? + write!(f, "{:?}", self) + } +} + +/// Errors that can be encountered by decoding a type +#[non_exhaustive] +#[derive(Debug)] +pub enum DecodeError { + /// The reader reached its end but more bytes were expected. + UnexpectedEnd { + /// Gives an estimate of how many extra bytes are needed. + /// + /// **Note**: this is only an estimate and not indicative of the actual bytes needed. + /// + /// **Note**: Bincode has no look-ahead mechanism. This means that this will only return the amount of bytes to be read for the current action, and not take into account the entire data structure being read. + additional: usize, + }, + + /// The given configuration limit was exceeded + LimitExceeded, + + /// Invalid type was found. The decoder tried to read type `expected`, but found type `found` instead. + InvalidIntegerType { + /// The type that was being read from the reader + expected: IntegerType, + /// The type that was encoded in the data + found: IntegerType, + }, + + /// The decoder tried to decode any of the `NonZero*` types but the value is zero + NonZeroTypeIsZero { + /// The type that was being read from the reader + non_zero_type: IntegerType, + }, + + /// Invalid enum variant was found. The decoder tried to decode variant index `found`, but the variant index should be between `min` and `max`. + UnexpectedVariant { + /// The type name that was being decoded. + type_name: &'static str, + + /// The variants that are allowed + allowed: &'static AllowedEnumVariants, + + /// The index of the enum that the decoder encountered + found: u32, + }, + + /// The decoder tried to decode a `str`, but an utf8 error was encountered. + Utf8 { + /// The inner error + inner: core::str::Utf8Error, + }, + + /// The decoder tried to decode a `char` and failed. The given buffer contains the bytes that are read at the moment of failure. + InvalidCharEncoding([u8; 4]), + + /// The decoder tried to decode a `bool` and failed. The given value is what is actually read. + InvalidBooleanValue(u8), + + /// The decoder tried to decode an array of length `required`, but the binary data contained an array of length `found`. + ArrayLengthMismatch { + /// The length of the array required by the rust type. + required: usize, + /// The length of the array found in the binary format. + found: usize, + }, + + /// The encoded value is outside of the range of the target usize type. + /// + /// This can happen if an usize was encoded on an architecture with a larger + /// usize type and then decoded on an architecture with a smaller one. For + /// example going from a 64 bit architecture to a 32 or 16 bit one may + /// cause this error. + OutsideUsizeRange(u64), + + /// Tried to decode an enum with no variants + EmptyEnum { + /// The type that was being decoded + type_name: &'static str, + }, + + /// The decoder tried to decode a Duration and overflowed the number of seconds. + InvalidDuration { + /// The number of seconds in the duration. + secs: u64, + + /// The number of nanoseconds in the duration, which when converted to seconds and added to + /// `secs`, overflows a `u64`. + nanos: u32, + }, + + /// The decoder tried to decode a SystemTime and overflowed + InvalidSystemTime { + /// The duration which could not have been added to + /// [`UNIX_EPOCH`](std::time::SystemTime::UNIX_EPOCH) + duration: core::time::Duration, + }, + + /// The decoder tried to decode a `CString`, but the incoming data contained a 0 byte + #[cfg(feature = "std")] + CStringNulError { + /// Nul byte position + position: usize, + }, + + /// The reader encountered an IO error but more bytes were expected. + #[cfg(feature = "std")] + Io { + /// The IO error expected + inner: std::io::Error, + + /// Gives an estimate of how many extra bytes are needed. + /// + /// **Note**: this is only an estimate and not indicative of the actual bytes needed. + /// + /// **Note**: Bincode has no look-ahead mechanism. This means that this will only return the amount of bytes to be read for the current action, and not take into account the entire data structure being read. + additional: usize, + }, + + /// An uncommon error occurred, see the inner text for more information + Other(&'static str), + + /// An uncommon error occurred, see the inner text for more information + #[cfg(feature = "alloc")] + OtherString(alloc::string::String), + + #[cfg(feature = "serde")] + /// A serde-specific error that occurred while decoding. + Serde(crate::features::serde::DecodeError), +} + +impl core::fmt::Display for DecodeError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + // TODO: Improve this? + write!(f, "{:?}", self) + } +} + +impl DecodeError { + /// If the current error is `InvalidIntegerType`, change the `expected` and + /// `found` values from `Ux` to `Ix`. This is needed to have correct error + /// reporting in src/varint/decode_signed.rs since this calls + /// src/varint/decode_unsigned.rs and needs to correct the `expected` and + /// `found` types. + pub(crate) fn change_integer_type_to_signed(self) -> DecodeError { + match self { + Self::InvalidIntegerType { expected, found } => Self::InvalidIntegerType { + expected: expected.into_signed(), + found: found.into_signed(), + }, + other => other, + } + } +} + +/// Indicates which enum variants are allowed +#[non_exhaustive] +#[derive(Debug, PartialEq, Eq)] +pub enum AllowedEnumVariants { + /// All values between `min` and `max` (inclusive) are allowed + #[allow(missing_docs)] + Range { min: u32, max: u32 }, + /// Each one of these values is allowed + Allowed(&'static [u32]), +} + +/// Integer types. Used by [DecodeError]. These types have no purpose other than being shown in errors. +#[non_exhaustive] +#[derive(Debug, PartialEq, Eq)] +#[allow(missing_docs)] +pub enum IntegerType { + U8, + U16, + U32, + U64, + U128, + Usize, + + I8, + I16, + I32, + I64, + I128, + Isize, + + Reserved, +} + +impl IntegerType { + /// Change the `Ux` value to the associated `Ix` value. + /// Returns the old value if `self` is already `Ix`. + pub(crate) const fn into_signed(self) -> Self { + match self { + Self::U8 => Self::I8, + Self::U16 => Self::I16, + Self::U32 => Self::I32, + Self::U64 => Self::I64, + Self::U128 => Self::I128, + Self::Usize => Self::Isize, + + other => other, + } + } +} diff --git a/vendor/bincode-2.0.1/src/features/derive.rs b/vendor/bincode-2.0.1/src/features/derive.rs new file mode 100644 index 0000000..1d07ba1 --- /dev/null +++ b/vendor/bincode-2.0.1/src/features/derive.rs @@ -0,0 +1,2 @@ +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +pub use bincode_derive::{BorrowDecode, Decode, Encode}; diff --git a/vendor/bincode-2.0.1/src/features/impl_alloc.rs b/vendor/bincode-2.0.1/src/features/impl_alloc.rs new file mode 100644 index 0000000..61624af --- /dev/null +++ b/vendor/bincode-2.0.1/src/features/impl_alloc.rs @@ -0,0 +1,603 @@ +use crate::{ + de::{read::Reader, BorrowDecoder, Decode, Decoder}, + enc::{ + self, + write::{SizeWriter, Writer}, + Encode, Encoder, + }, + error::{DecodeError, EncodeError}, + impl_borrow_decode, BorrowDecode, Config, +}; +use alloc::{ + borrow::{Cow, ToOwned}, + boxed::Box, + collections::*, + rc::Rc, + string::String, + vec::Vec, +}; + +#[cfg(target_has_atomic = "ptr")] +use alloc::sync::Arc; + +#[derive(Default)] +pub(crate) struct VecWriter { + inner: Vec, +} + +impl VecWriter { + /// Create a new vec writer with the given capacity + pub fn with_capacity(cap: usize) -> Self { + Self { + inner: Vec::with_capacity(cap), + } + } + // May not be used in all feature combinations + #[allow(dead_code)] + pub(crate) fn collect(self) -> Vec { + self.inner + } +} + +impl enc::write::Writer for VecWriter { + #[inline(always)] + fn write(&mut self, bytes: &[u8]) -> Result<(), EncodeError> { + self.inner.extend_from_slice(bytes); + Ok(()) + } +} + +/// Encode the given value into a `Vec` with the given `Config`. See the [config] module for more information. +/// +/// [config]: config/index.html +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] +pub fn encode_to_vec(val: E, config: C) -> Result, EncodeError> { + let size = { + let mut size_writer = enc::EncoderImpl::<_, C>::new(SizeWriter::default(), config); + val.encode(&mut size_writer)?; + size_writer.into_writer().bytes_written + }; + let writer = VecWriter::with_capacity(size); + let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config); + val.encode(&mut encoder)?; + Ok(encoder.into_writer().inner) +} + +impl Decode for BinaryHeap +where + T: Decode + Ord, +{ + fn decode>(decoder: &mut D) -> Result { + Ok(Vec::::decode(decoder)?.into()) + } +} +impl<'de, T, Context> BorrowDecode<'de, Context> for BinaryHeap +where + T: BorrowDecode<'de, Context> + Ord, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + Ok(Vec::::borrow_decode(decoder)?.into()) + } +} + +impl Encode for BinaryHeap +where + T: Encode + Ord, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + // BLOCKEDTODO(https://github.com/rust-lang/rust/issues/83659): we can u8 optimize this with `.as_slice()` + crate::enc::encode_slice_len(encoder, self.len())?; + for val in self.iter() { + val.encode(encoder)?; + } + Ok(()) + } +} + +impl Decode for BTreeMap +where + K: Decode + Ord, + V: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + let len = crate::de::decode_slice_len(decoder)?; + decoder.claim_container_read::<(K, V)>(len)?; + + let mut map = BTreeMap::new(); + for _ in 0..len { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::<(K, V)>()); + + let key = K::decode(decoder)?; + let value = V::decode(decoder)?; + map.insert(key, value); + } + Ok(map) + } +} +impl<'de, K, V, Context> BorrowDecode<'de, Context> for BTreeMap +where + K: BorrowDecode<'de, Context> + Ord, + V: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let len = crate::de::decode_slice_len(decoder)?; + decoder.claim_container_read::<(K, V)>(len)?; + + let mut map = BTreeMap::new(); + for _ in 0..len { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::<(K, V)>()); + + let key = K::borrow_decode(decoder)?; + let value = V::borrow_decode(decoder)?; + map.insert(key, value); + } + Ok(map) + } +} + +impl Encode for BTreeMap +where + K: Encode + Ord, + V: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + crate::enc::encode_slice_len(encoder, self.len())?; + for (key, val) in self.iter() { + key.encode(encoder)?; + val.encode(encoder)?; + } + Ok(()) + } +} + +impl Decode for BTreeSet +where + T: Decode + Ord, +{ + fn decode>(decoder: &mut D) -> Result { + let len = crate::de::decode_slice_len(decoder)?; + decoder.claim_container_read::(len)?; + + let mut map = BTreeSet::new(); + for _ in 0..len { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::()); + + let key = T::decode(decoder)?; + map.insert(key); + } + Ok(map) + } +} +impl<'de, T, Context> BorrowDecode<'de, Context> for BTreeSet +where + T: BorrowDecode<'de, Context> + Ord, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let len = crate::de::decode_slice_len(decoder)?; + decoder.claim_container_read::(len)?; + + let mut map = BTreeSet::new(); + for _ in 0..len { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::()); + + let key = T::borrow_decode(decoder)?; + map.insert(key); + } + Ok(map) + } +} + +impl Encode for BTreeSet +where + T: Encode + Ord, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + crate::enc::encode_slice_len(encoder, self.len())?; + for item in self.iter() { + item.encode(encoder)?; + } + Ok(()) + } +} + +impl Decode for VecDeque +where + T: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + Ok(Vec::::decode(decoder)?.into()) + } +} +impl<'de, T, Context> BorrowDecode<'de, Context> for VecDeque +where + T: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + Ok(Vec::::borrow_decode(decoder)?.into()) + } +} + +impl Encode for VecDeque +where + T: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + crate::enc::encode_slice_len(encoder, self.len())?; + if unty::type_equal::() { + let slices: (&[T], &[T]) = self.as_slices(); + // Safety: T is u8 so turning this into `&[u8]` is okay + let slices: (&[u8], &[u8]) = unsafe { + ( + core::slice::from_raw_parts(slices.0.as_ptr().cast(), slices.0.len()), + core::slice::from_raw_parts(slices.1.as_ptr().cast(), slices.1.len()), + ) + }; + + encoder.writer().write(slices.0)?; + encoder.writer().write(slices.1)?; + } else { + for item in self.iter() { + item.encode(encoder)?; + } + } + Ok(()) + } +} + +impl Decode for Vec +where + T: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + let len = crate::de::decode_slice_len(decoder)?; + + if unty::type_equal::() { + decoder.claim_container_read::(len)?; + // optimize for reading u8 vecs + let mut vec = alloc::vec![0u8; len]; + decoder.reader().read(&mut vec)?; + // Safety: Vec is Vec + Ok(unsafe { core::mem::transmute::, Vec>(vec) }) + } else { + decoder.claim_container_read::(len)?; + + let mut vec = Vec::with_capacity(len); + for _ in 0..len { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::()); + + vec.push(T::decode(decoder)?); + } + Ok(vec) + } + } +} + +impl<'de, T, Context> BorrowDecode<'de, Context> for Vec +where + T: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let len = crate::de::decode_slice_len(decoder)?; + + if unty::type_equal::() { + decoder.claim_container_read::(len)?; + // optimize for reading u8 vecs + let mut vec = alloc::vec![0u8; len]; + decoder.reader().read(&mut vec)?; + // Safety: Vec is Vec + Ok(unsafe { core::mem::transmute::, Vec>(vec) }) + } else { + decoder.claim_container_read::(len)?; + + let mut vec = Vec::with_capacity(len); + for _ in 0..len { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::()); + + vec.push(T::borrow_decode(decoder)?); + } + Ok(vec) + } + } +} + +impl Encode for Vec +where + T: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + crate::enc::encode_slice_len(encoder, self.len())?; + if unty::type_equal::() { + // Safety: T == u8 + let slice: &[u8] = unsafe { core::mem::transmute(self.as_slice()) }; + encoder.writer().write(slice)?; + Ok(()) + } else { + for item in self.iter() { + item.encode(encoder)?; + } + Ok(()) + } + } +} + +impl Decode for String { + fn decode>(decoder: &mut D) -> Result { + let bytes = Vec::::decode(decoder)?; + String::from_utf8(bytes).map_err(|e| DecodeError::Utf8 { + inner: e.utf8_error(), + }) + } +} +impl_borrow_decode!(String); + +impl Decode for Box { + fn decode(decoder: &mut D) -> Result { + String::decode(decoder).map(String::into_boxed_str) + } +} +impl_borrow_decode!(Box); + +impl Encode for String { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.as_bytes().encode(encoder) + } +} + +impl Decode for Box +where + T: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + let t = T::decode(decoder)?; + Ok(Box::new(t)) + } +} +impl<'de, T, Context> BorrowDecode<'de, Context> for Box +where + T: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let t = T::borrow_decode(decoder)?; + Ok(Box::new(t)) + } +} + +impl Encode for Box +where + T: Encode + ?Sized, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + T::encode(self, encoder) + } +} + +impl Decode for Box<[T]> +where + T: Decode + 'static, +{ + fn decode>(decoder: &mut D) -> Result { + let vec = Vec::decode(decoder)?; + Ok(vec.into_boxed_slice()) + } +} + +impl<'de, T, Context> BorrowDecode<'de, Context> for Box<[T]> +where + T: BorrowDecode<'de, Context> + 'de, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let vec = Vec::borrow_decode(decoder)?; + Ok(vec.into_boxed_slice()) + } +} + +impl Decode for Cow<'_, T> +where + T: ToOwned + ?Sized, + ::Owned: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + let t = ::Owned::decode(decoder)?; + Ok(Cow::Owned(t)) + } +} +impl<'cow, T, Context> BorrowDecode<'cow, Context> for Cow<'cow, T> +where + T: ToOwned + ?Sized, + &'cow T: BorrowDecode<'cow, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let t = <&T>::borrow_decode(decoder)?; + Ok(Cow::Borrowed(t)) + } +} + +impl Encode for Cow<'_, T> +where + T: ToOwned + ?Sized, + for<'a> &'a T: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.as_ref().encode(encoder) + } +} + +#[test] +fn test_cow_round_trip() { + let start = Cow::Borrowed("Foo"); + let encoded = crate::encode_to_vec(&start, crate::config::standard()).unwrap(); + let (end, _) = + crate::borrow_decode_from_slice::, _>(&encoded, crate::config::standard()) + .unwrap(); + assert_eq!(start, end); + let (end, _) = + crate::decode_from_slice::, _>(&encoded, crate::config::standard()).unwrap(); + assert_eq!(start, end); +} + +impl Decode for Rc +where + T: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + let t = T::decode(decoder)?; + Ok(Rc::new(t)) + } +} + +impl Decode for Rc { + fn decode>(decoder: &mut D) -> Result { + let decoded = String::decode(decoder)?; + Ok(decoded.into()) + } +} + +impl<'de, T, Context> BorrowDecode<'de, Context> for Rc +where + T: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let t = T::borrow_decode(decoder)?; + Ok(Rc::new(t)) + } +} + +impl<'de, Context> BorrowDecode<'de, Context> for Rc { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let decoded = String::decode(decoder)?; + Ok(decoded.into()) + } +} + +impl Encode for Rc +where + T: Encode + ?Sized, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + T::encode(self, encoder) + } +} + +impl Decode for Rc<[T]> +where + T: Decode + 'static, +{ + fn decode>(decoder: &mut D) -> Result { + let vec = Vec::decode(decoder)?; + Ok(vec.into()) + } +} + +impl<'de, T, Context> BorrowDecode<'de, Context> for Rc<[T]> +where + T: BorrowDecode<'de, Context> + 'de, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let vec = Vec::borrow_decode(decoder)?; + Ok(vec.into()) + } +} + +#[cfg(target_has_atomic = "ptr")] +impl Decode for Arc +where + T: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + let t = T::decode(decoder)?; + Ok(Arc::new(t)) + } +} + +#[cfg(target_has_atomic = "ptr")] +impl Decode for Arc { + fn decode>(decoder: &mut D) -> Result { + let decoded = String::decode(decoder)?; + Ok(decoded.into()) + } +} + +#[cfg(target_has_atomic = "ptr")] +impl<'de, T, Context> BorrowDecode<'de, Context> for Arc +where + T: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let t = T::borrow_decode(decoder)?; + Ok(Arc::new(t)) + } +} + +#[cfg(target_has_atomic = "ptr")] +impl<'de, Context> BorrowDecode<'de, Context> for Arc { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let decoded = String::decode(decoder)?; + Ok(decoded.into()) + } +} + +#[cfg(target_has_atomic = "ptr")] +impl Encode for Arc +where + T: Encode + ?Sized, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + T::encode(self, encoder) + } +} + +#[cfg(target_has_atomic = "ptr")] +impl Decode for Arc<[T]> +where + T: Decode + 'static, +{ + fn decode>(decoder: &mut D) -> Result { + let vec = Vec::decode(decoder)?; + Ok(vec.into()) + } +} + +#[cfg(target_has_atomic = "ptr")] +impl<'de, T, Context> BorrowDecode<'de, Context> for Arc<[T]> +where + T: BorrowDecode<'de, Context> + 'de, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let vec = Vec::borrow_decode(decoder)?; + Ok(vec.into()) + } +} diff --git a/vendor/bincode-2.0.1/src/features/impl_std.rs b/vendor/bincode-2.0.1/src/features/impl_std.rs new file mode 100644 index 0000000..ef1f328 --- /dev/null +++ b/vendor/bincode-2.0.1/src/features/impl_std.rs @@ -0,0 +1,554 @@ +use crate::{ + config::Config, + de::{read::Reader, BorrowDecode, BorrowDecoder, Decode, Decoder, DecoderImpl}, + enc::{write::Writer, Encode, Encoder, EncoderImpl}, + error::{DecodeError, EncodeError}, + impl_borrow_decode, +}; +use core::time::Duration; +use std::{ + collections::{HashMap, HashSet}, + ffi::{CStr, CString}, + hash::Hash, + io::Read, + net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, + path::{Path, PathBuf}, + sync::{Mutex, RwLock}, + time::SystemTime, +}; + +/// Decode type `D` from the given reader with the given `Config`. The reader can be any type that implements `std::io::Read`, e.g. `std::fs::File`. +/// +/// See the [config] module for more information about config options. +/// +/// [config]: config/index.html +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +pub fn decode_from_std_read, C: Config, R: std::io::Read>( + src: &mut R, + config: C, +) -> Result { + decode_from_std_read_with_context(src, config, ()) +} + +/// Decode type `D` from the given reader with the given `Config` and `Context`. The reader can be any type that implements `std::io::Read`, e.g. `std::fs::File`. +/// +/// See the [config] module for more information about config options. +/// +/// [config]: config/index.html +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +pub fn decode_from_std_read_with_context< + Context, + D: Decode, + C: Config, + R: std::io::Read, +>( + src: &mut R, + config: C, + context: Context, +) -> Result { + let reader = IoReader::new(src); + let mut decoder = DecoderImpl::<_, C, Context>::new(reader, config, context); + D::decode(&mut decoder) +} + +pub(crate) struct IoReader { + reader: R, +} + +impl IoReader { + pub const fn new(reader: R) -> Self { + Self { reader } + } +} + +impl Reader for IoReader +where + R: std::io::Read, +{ + #[inline(always)] + fn read(&mut self, bytes: &mut [u8]) -> Result<(), DecodeError> { + self.reader + .read_exact(bytes) + .map_err(|inner| DecodeError::Io { + inner, + additional: bytes.len(), + }) + } +} + +impl Reader for std::io::BufReader +where + R: std::io::Read, +{ + fn read(&mut self, bytes: &mut [u8]) -> Result<(), DecodeError> { + self.read_exact(bytes).map_err(|inner| DecodeError::Io { + inner, + additional: bytes.len(), + }) + } + + #[inline] + fn peek_read(&mut self, n: usize) -> Option<&[u8]> { + self.buffer().get(..n) + } + + #[inline] + fn consume(&mut self, n: usize) { + ::consume(self, n); + } +} + +/// Encode the given value into any type that implements `std::io::Write`, e.g. `std::fs::File`, with the given `Config`. +/// See the [config] module for more information. +/// Returns the amount of bytes written. +/// +/// [config]: config/index.html +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +pub fn encode_into_std_write( + val: E, + dst: &mut W, + config: C, +) -> Result { + let writer = IoWriter::new(dst); + let mut encoder = EncoderImpl::<_, C>::new(writer, config); + val.encode(&mut encoder)?; + Ok(encoder.into_writer().bytes_written()) +} + +pub(crate) struct IoWriter<'a, W: std::io::Write> { + writer: &'a mut W, + bytes_written: usize, +} + +impl<'a, W: std::io::Write> IoWriter<'a, W> { + pub fn new(writer: &'a mut W) -> Self { + Self { + writer, + bytes_written: 0, + } + } + + pub const fn bytes_written(&self) -> usize { + self.bytes_written + } +} + +impl Writer for IoWriter<'_, W> { + #[inline(always)] + fn write(&mut self, bytes: &[u8]) -> Result<(), EncodeError> { + self.writer + .write_all(bytes) + .map_err(|inner| EncodeError::Io { + inner, + index: self.bytes_written, + })?; + self.bytes_written += bytes.len(); + Ok(()) + } +} + +impl Encode for &CStr { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.to_bytes().encode(encoder) + } +} + +impl Encode for CString { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.as_bytes().encode(encoder) + } +} + +impl Decode for CString { + fn decode>(decoder: &mut D) -> Result { + let vec = std::vec::Vec::decode(decoder)?; + CString::new(vec).map_err(|inner| DecodeError::CStringNulError { + position: inner.nul_position(), + }) + } +} +impl_borrow_decode!(CString); + +impl Encode for Mutex +where + T: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + let t = self.lock().map_err(|_| EncodeError::LockFailed { + type_name: core::any::type_name::>(), + })?; + t.encode(encoder) + } +} + +impl Decode for Mutex +where + T: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + let t = T::decode(decoder)?; + Ok(Mutex::new(t)) + } +} +impl<'de, T, Context> BorrowDecode<'de, Context> for Mutex +where + T: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let t = T::borrow_decode(decoder)?; + Ok(Mutex::new(t)) + } +} + +impl Encode for RwLock +where + T: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + let t = self.read().map_err(|_| EncodeError::LockFailed { + type_name: core::any::type_name::>(), + })?; + t.encode(encoder) + } +} + +impl Decode for RwLock +where + T: Decode, +{ + fn decode>(decoder: &mut D) -> Result { + let t = T::decode(decoder)?; + Ok(RwLock::new(t)) + } +} +impl<'de, T, Context> BorrowDecode<'de, Context> for RwLock +where + T: BorrowDecode<'de, Context>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let t = T::borrow_decode(decoder)?; + Ok(RwLock::new(t)) + } +} + +impl Encode for SystemTime { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + let duration = self.duration_since(SystemTime::UNIX_EPOCH).map_err(|e| { + EncodeError::InvalidSystemTime { + inner: e, + time: std::boxed::Box::new(*self), + } + })?; + duration.encode(encoder) + } +} + +impl Decode for SystemTime { + fn decode>(decoder: &mut D) -> Result { + let duration = Duration::decode(decoder)?; + match SystemTime::UNIX_EPOCH.checked_add(duration) { + Some(t) => Ok(t), + None => Err(DecodeError::InvalidSystemTime { duration }), + } + } +} +impl_borrow_decode!(SystemTime); + +impl Encode for &'_ Path { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match self.to_str() { + Some(str) => str.encode(encoder), + None => Err(EncodeError::InvalidPathCharacters), + } + } +} + +impl<'de, Context> BorrowDecode<'de, Context> for &'de Path { + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let str = <&'de str>::borrow_decode(decoder)?; + Ok(Path::new(str)) + } +} + +impl Encode for PathBuf { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.as_path().encode(encoder) + } +} + +impl Decode for PathBuf { + fn decode>(decoder: &mut D) -> Result { + let string = std::string::String::decode(decoder)?; + Ok(string.into()) + } +} +impl_borrow_decode!(PathBuf); + +impl Encode for IpAddr { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match self { + IpAddr::V4(v4) => { + 0u32.encode(encoder)?; + v4.encode(encoder) + } + IpAddr::V6(v6) => { + 1u32.encode(encoder)?; + v6.encode(encoder) + } + } + } +} + +impl Decode for IpAddr { + fn decode>(decoder: &mut D) -> Result { + match u32::decode(decoder)? { + 0 => Ok(IpAddr::V4(Ipv4Addr::decode(decoder)?)), + 1 => Ok(IpAddr::V6(Ipv6Addr::decode(decoder)?)), + found => Err(DecodeError::UnexpectedVariant { + allowed: &crate::error::AllowedEnumVariants::Range { min: 0, max: 1 }, + found, + type_name: core::any::type_name::(), + }), + } + } +} +impl_borrow_decode!(IpAddr); + +impl Encode for Ipv4Addr { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + encoder.writer().write(&self.octets()) + } +} + +impl Decode for Ipv4Addr { + fn decode>(decoder: &mut D) -> Result { + let mut buff = [0u8; 4]; + decoder.reader().read(&mut buff)?; + Ok(Self::from(buff)) + } +} +impl_borrow_decode!(Ipv4Addr); + +impl Encode for Ipv6Addr { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + encoder.writer().write(&self.octets()) + } +} + +impl Decode for Ipv6Addr { + fn decode>(decoder: &mut D) -> Result { + let mut buff = [0u8; 16]; + decoder.reader().read(&mut buff)?; + Ok(Self::from(buff)) + } +} +impl_borrow_decode!(Ipv6Addr); + +impl Encode for SocketAddr { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + match self { + SocketAddr::V4(v4) => { + 0u32.encode(encoder)?; + v4.encode(encoder) + } + SocketAddr::V6(v6) => { + 1u32.encode(encoder)?; + v6.encode(encoder) + } + } + } +} + +impl Decode for SocketAddr { + fn decode>(decoder: &mut D) -> Result { + match u32::decode(decoder)? { + 0 => Ok(SocketAddr::V4(SocketAddrV4::decode(decoder)?)), + 1 => Ok(SocketAddr::V6(SocketAddrV6::decode(decoder)?)), + found => Err(DecodeError::UnexpectedVariant { + allowed: &crate::error::AllowedEnumVariants::Range { min: 0, max: 1 }, + found, + type_name: core::any::type_name::(), + }), + } + } +} +impl_borrow_decode!(SocketAddr); + +impl Encode for SocketAddrV4 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.ip().encode(encoder)?; + self.port().encode(encoder) + } +} + +impl Decode for SocketAddrV4 { + fn decode>(decoder: &mut D) -> Result { + let ip = Ipv4Addr::decode(decoder)?; + let port = u16::decode(decoder)?; + Ok(Self::new(ip, port)) + } +} +impl_borrow_decode!(SocketAddrV4); + +impl Encode for SocketAddrV6 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + self.ip().encode(encoder)?; + self.port().encode(encoder) + } +} + +impl Decode for SocketAddrV6 { + fn decode>(decoder: &mut D) -> Result { + let ip = Ipv6Addr::decode(decoder)?; + let port = u16::decode(decoder)?; + Ok(Self::new(ip, port, 0, 0)) + } +} +impl_borrow_decode!(SocketAddrV6); + +impl std::error::Error for EncodeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::RefCellAlreadyBorrowed { inner, .. } => Some(inner), + Self::Io { inner, .. } => Some(inner), + Self::InvalidSystemTime { inner, .. } => Some(inner), + _ => None, + } + } +} +impl std::error::Error for DecodeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Utf8 { inner } => Some(inner), + _ => None, + } + } +} + +impl Encode for HashMap +where + K: Encode, + V: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + crate::enc::encode_slice_len(encoder, self.len())?; + for (k, v) in self.iter() { + Encode::encode(k, encoder)?; + Encode::encode(v, encoder)?; + } + Ok(()) + } +} + +impl Decode for HashMap +where + K: Decode + Eq + std::hash::Hash, + V: Decode, + S: std::hash::BuildHasher + Default, +{ + fn decode>(decoder: &mut D) -> Result { + let len = crate::de::decode_slice_len(decoder)?; + decoder.claim_container_read::<(K, V)>(len)?; + + let hash_builder: S = Default::default(); + let mut map = HashMap::with_capacity_and_hasher(len, hash_builder); + for _ in 0..len { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::<(K, V)>()); + + let k = K::decode(decoder)?; + let v = V::decode(decoder)?; + map.insert(k, v); + } + Ok(map) + } +} +impl<'de, K, V, S, Context> BorrowDecode<'de, Context> for HashMap +where + K: BorrowDecode<'de, Context> + Eq + std::hash::Hash, + V: BorrowDecode<'de, Context>, + S: std::hash::BuildHasher + Default, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let len = crate::de::decode_slice_len(decoder)?; + decoder.claim_container_read::<(K, V)>(len)?; + + let hash_builder: S = Default::default(); + let mut map = HashMap::with_capacity_and_hasher(len, hash_builder); + for _ in 0..len { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::<(K, V)>()); + + let k = K::borrow_decode(decoder)?; + let v = V::borrow_decode(decoder)?; + map.insert(k, v); + } + Ok(map) + } +} + +impl Decode for HashSet +where + T: Decode + Eq + Hash, + S: std::hash::BuildHasher + Default, +{ + fn decode>(decoder: &mut D) -> Result { + let len = crate::de::decode_slice_len(decoder)?; + decoder.claim_container_read::(len)?; + + let hash_builder: S = Default::default(); + let mut map: HashSet = HashSet::with_capacity_and_hasher(len, hash_builder); + for _ in 0..len { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::()); + + let key = T::decode(decoder)?; + map.insert(key); + } + Ok(map) + } +} + +impl<'de, T, S, Context> BorrowDecode<'de, Context> for HashSet +where + T: BorrowDecode<'de, Context> + Eq + Hash, + S: std::hash::BuildHasher + Default, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let len = crate::de::decode_slice_len(decoder)?; + decoder.claim_container_read::(len)?; + + let mut map = HashSet::with_capacity_and_hasher(len, S::default()); + for _ in 0..len { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::()); + + let key = T::borrow_decode(decoder)?; + map.insert(key); + } + Ok(map) + } +} + +impl Encode for HashSet +where + T: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + crate::enc::encode_slice_len(encoder, self.len())?; + for item in self.iter() { + item.encode(encoder)?; + } + Ok(()) + } +} diff --git a/vendor/bincode-2.0.1/src/features/mod.rs b/vendor/bincode-2.0.1/src/features/mod.rs new file mode 100644 index 0000000..16a67e1 --- /dev/null +++ b/vendor/bincode-2.0.1/src/features/mod.rs @@ -0,0 +1,18 @@ +#[cfg(feature = "alloc")] +mod impl_alloc; +#[cfg(feature = "alloc")] +pub use self::impl_alloc::*; + +#[cfg(feature = "std")] +mod impl_std; +#[cfg(feature = "std")] +pub use self::impl_std::*; + +#[cfg(feature = "derive")] +mod derive; +#[cfg(feature = "derive")] +pub use self::derive::*; + +#[cfg(feature = "serde")] +#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] +pub mod serde; diff --git a/vendor/bincode-2.0.1/src/features/serde/de_borrowed.rs b/vendor/bincode-2.0.1/src/features/serde/de_borrowed.rs new file mode 100644 index 0000000..d0cbefc --- /dev/null +++ b/vendor/bincode-2.0.1/src/features/serde/de_borrowed.rs @@ -0,0 +1,496 @@ +use super::DecodeError as SerdeDecodeError; +use crate::{ + config::Config, + de::{read::SliceReader, BorrowDecode, BorrowDecoder, Decode, DecoderImpl}, + error::DecodeError, +}; +use core::marker::PhantomData; +use serde::de::*; + +/// Serde decoder encapsulating a borrowed reader. +pub struct BorrowedSerdeDecoder<'de, DE: BorrowDecoder<'de>> { + pub(super) de: DE, + pub(super) pd: PhantomData<&'de ()>, +} + +impl<'de, DE: BorrowDecoder<'de>> BorrowedSerdeDecoder<'de, DE> { + /// Return a type implementing `serde::Deserializer`. + pub fn as_deserializer<'a>( + &'a mut self, + ) -> impl serde::Deserializer<'de, Error = DecodeError> + 'a { + SerdeDecoder { + de: &mut self.de, + pd: PhantomData, + } + } +} + +impl<'de, C: Config, Context> BorrowedSerdeDecoder<'de, DecoderImpl, C, Context>> { + /// Creates the decoder from a borrowed slice. + pub fn from_slice( + slice: &'de [u8], + config: C, + context: Context, + ) -> BorrowedSerdeDecoder<'de, DecoderImpl, C, Context>> + where + C: Config, + { + let reader = SliceReader::new(slice); + let decoder = DecoderImpl::new(reader, config, context); + Self { + de: decoder, + pd: PhantomData, + } + } +} + +/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read. +/// +/// See the [config](../config/index.html) module for more information on configurations. +pub fn borrow_decode_from_slice<'de, D, C>( + slice: &'de [u8], + config: C, +) -> Result<(D, usize), DecodeError> +where + D: Deserialize<'de>, + C: Config, +{ + let mut serde_decoder = + BorrowedSerdeDecoder::, C, ()>>::from_slice(slice, config, ()); + let result = D::deserialize(serde_decoder.as_deserializer())?; + let bytes_read = slice.len() - serde_decoder.de.borrow_reader().slice.len(); + Ok((result, bytes_read)) +} + +/// Decode a borrowed type from the given slice using a seed. Some parts of the decoded type are expected to be referring to the given slice +pub fn seed_decode_from_slice<'de, D, C>( + seed: D, + slice: &'de [u8], + config: C, +) -> Result<(D::Value, usize), DecodeError> +where + D: DeserializeSeed<'de>, + C: Config, +{ + let mut serde_decoder = + BorrowedSerdeDecoder::, C, ()>>::from_slice(slice, config, ()); + let result = seed.deserialize(serde_decoder.as_deserializer())?; + let bytes_read = slice.len() - serde_decoder.de.borrow_reader().slice.len(); + Ok((result, bytes_read)) +} + +pub(super) struct SerdeDecoder<'a, 'de, DE: BorrowDecoder<'de>> { + pub(super) de: &'a mut DE, + pub(super) pd: PhantomData<&'de ()>, +} + +impl<'de, DE: BorrowDecoder<'de>> Deserializer<'de> for SerdeDecoder<'_, 'de, DE> { + type Error = DecodeError; + + fn deserialize_any(self, _: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(SerdeDecodeError::AnyNotSupported.into()) + } + + fn deserialize_bool(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_bool(Decode::decode(&mut self.de)?) + } + + fn deserialize_i8(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i8(Decode::decode(&mut self.de)?) + } + + fn deserialize_i16(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i16(Decode::decode(&mut self.de)?) + } + + fn deserialize_i32(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i32(Decode::decode(&mut self.de)?) + } + + fn deserialize_i64(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i64(Decode::decode(&mut self.de)?) + } + + serde::serde_if_integer128! { + fn deserialize_i128(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i128(Decode::decode(&mut self.de)?) + } + } + + fn deserialize_u8(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u8(Decode::decode(&mut self.de)?) + } + + fn deserialize_u16(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u16(Decode::decode(&mut self.de)?) + } + + fn deserialize_u32(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u32(Decode::decode(&mut self.de)?) + } + + fn deserialize_u64(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u64(Decode::decode(&mut self.de)?) + } + + serde::serde_if_integer128! { + fn deserialize_u128(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u128(Decode::decode(&mut self.de)?) + } + } + + fn deserialize_f32(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_f32(Decode::decode(&mut self.de)?) + } + + fn deserialize_f64(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_f64(Decode::decode(&mut self.de)?) + } + + fn deserialize_char(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_char(Decode::decode(&mut self.de)?) + } + + fn deserialize_str(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + let str = <&'de str>::borrow_decode(&mut self.de)?; + visitor.visit_borrowed_str(str) + } + + #[cfg(not(feature = "alloc"))] + fn deserialize_string(self, _: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(SerdeDecodeError::CannotBorrowOwnedData.into()) + } + + #[cfg(feature = "alloc")] + fn deserialize_string(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_string(Decode::decode(&mut self.de)?) + } + + fn deserialize_bytes(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + let bytes = <&'de [u8]>::borrow_decode(&mut self.de)?; + visitor.visit_borrowed_bytes(bytes) + } + + #[cfg(not(feature = "alloc"))] + fn deserialize_byte_buf(self, _: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(SerdeDecodeError::CannotBorrowOwnedData.into()) + } + + #[cfg(feature = "alloc")] + fn deserialize_byte_buf(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_byte_buf(Decode::decode(&mut self.de)?) + } + + fn deserialize_option(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + let variant = crate::de::decode_option_variant(&mut self.de, "Option")?; + if variant.is_some() { + visitor.visit_some(self) + } else { + visitor.visit_none() + } + } + + fn deserialize_unit(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_unit() + } + + fn deserialize_unit_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_unit() + } + + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_seq(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + let len = usize::decode(&mut self.de)?; + self.deserialize_tuple(len, visitor) + } + + fn deserialize_tuple(mut self, len: usize, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + struct Access<'a, 'b, 'de, DE: BorrowDecoder<'de>> { + deserializer: &'a mut SerdeDecoder<'b, 'de, DE>, + len: usize, + } + + impl<'de, 'a, 'b: 'a, DE: BorrowDecoder<'de> + 'b> SeqAccess<'de> for Access<'a, 'b, 'de, DE> { + type Error = DecodeError; + + fn next_element_seed(&mut self, seed: T) -> Result, DecodeError> + where + T: DeserializeSeed<'de>, + { + if self.len > 0 { + self.len -= 1; + let value = DeserializeSeed::deserialize( + seed, + SerdeDecoder { + de: self.deserializer.de, + pd: PhantomData, + }, + )?; + Ok(Some(value)) + } else { + Ok(None) + } + } + + fn size_hint(&self) -> Option { + Some(self.len) + } + } + + visitor.visit_seq(Access { + deserializer: &mut self, + len, + }) + } + + fn deserialize_tuple_struct( + self, + _name: &'static str, + len: usize, + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + self.deserialize_tuple(len, visitor) + } + + fn deserialize_map(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + struct Access<'a, 'b, 'de, DE: BorrowDecoder<'de>> { + deserializer: &'a mut SerdeDecoder<'b, 'de, DE>, + len: usize, + } + + impl<'de, 'a, 'b: 'a, DE: BorrowDecoder<'de> + 'b> MapAccess<'de> for Access<'a, 'b, 'de, DE> { + type Error = DecodeError; + + fn next_key_seed(&mut self, seed: K) -> Result, DecodeError> + where + K: DeserializeSeed<'de>, + { + if self.len > 0 { + self.len -= 1; + let key = DeserializeSeed::deserialize( + seed, + SerdeDecoder { + de: self.deserializer.de, + pd: PhantomData, + }, + )?; + Ok(Some(key)) + } else { + Ok(None) + } + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: DeserializeSeed<'de>, + { + let value = DeserializeSeed::deserialize( + seed, + SerdeDecoder { + de: self.deserializer.de, + pd: PhantomData, + }, + )?; + Ok(value) + } + + fn size_hint(&self) -> Option { + Some(self.len) + } + } + + let len = usize::decode(&mut self.de)?; + + visitor.visit_map(Access { + deserializer: &mut self, + len, + }) + } + + fn deserialize_struct( + self, + _name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + self.deserialize_tuple(fields.len(), visitor) + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_enum(self) + } + + fn deserialize_identifier(self, _visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(SerdeDecodeError::IdentifierNotSupported.into()) + } + + fn deserialize_ignored_any(self, _: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(SerdeDecodeError::IgnoredAnyNotSupported.into()) + } + + fn is_human_readable(&self) -> bool { + false + } +} + +impl<'de, DE: BorrowDecoder<'de>> EnumAccess<'de> for SerdeDecoder<'_, 'de, DE> { + type Error = DecodeError; + type Variant = Self; + + fn variant_seed(mut self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where + V: DeserializeSeed<'de>, + { + let idx = u32::decode(&mut self.de)?; + let val = seed.deserialize(idx.into_deserializer())?; + Ok((val, self)) + } +} + +impl<'de, DE: BorrowDecoder<'de>> VariantAccess<'de> for SerdeDecoder<'_, 'de, DE> { + type Error = DecodeError; + + fn unit_variant(self) -> Result<(), Self::Error> { + Ok(()) + } + + fn newtype_variant_seed(self, seed: T) -> Result + where + T: DeserializeSeed<'de>, + { + DeserializeSeed::deserialize(seed, self) + } + + fn tuple_variant(self, len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + Deserializer::deserialize_tuple(self, len, visitor) + } + + fn struct_variant( + self, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + Deserializer::deserialize_tuple(self, fields.len(), visitor) + } +} diff --git a/vendor/bincode-2.0.1/src/features/serde/de_owned.rs b/vendor/bincode-2.0.1/src/features/serde/de_owned.rs new file mode 100644 index 0000000..9c6e7ba --- /dev/null +++ b/vendor/bincode-2.0.1/src/features/serde/de_owned.rs @@ -0,0 +1,523 @@ +use super::{de_borrowed::borrow_decode_from_slice, DecodeError as SerdeDecodeError}; +use crate::{ + config::Config, + de::{read::Reader, Decode, Decoder, DecoderImpl}, + error::DecodeError, +}; +use serde::de::*; + +#[cfg(feature = "std")] +use crate::features::IoReader; + +/// Serde decoder encapsulating an owned reader. +pub struct OwnedSerdeDecoder { + pub(super) de: DE, +} + +impl OwnedSerdeDecoder { + /// Return a type implementing `serde::Deserializer`. + pub fn as_deserializer<'a>( + &'a mut self, + ) -> impl for<'de> serde::Deserializer<'de, Error = DecodeError> + 'a { + SerdeDecoder { de: &mut self.de } + } +} + +#[cfg(feature = "std")] +impl<'r, C: Config, R: std::io::Read> OwnedSerdeDecoder, C, ()>> { + /// Creates the decoder from an `std::io::Read` implementor. + pub fn from_std_read( + src: &'r mut R, + config: C, + ) -> OwnedSerdeDecoder, C, ()>> + where + C: Config, + { + let reader = IoReader::new(src); + let decoder = DecoderImpl::new(reader, config, ()); + Self { de: decoder } + } +} + +impl OwnedSerdeDecoder> { + /// Creates the decoder from a [`Reader`] implementor. + pub fn from_reader(reader: R, config: C) -> OwnedSerdeDecoder> + where + C: Config, + { + let decoder = DecoderImpl::new(reader, config, ()); + Self { de: decoder } + } +} + +/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read. +/// +/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [borrow_decode_from_slice]. +/// +/// See the [config] module for more information on configurations. +/// +/// [borrow_decode_from_slice]: fn.borrow_decode_from_slice.html +/// [config]: ../config/index.html +pub fn decode_from_slice(slice: &[u8], config: C) -> Result<(D, usize), DecodeError> +where + D: DeserializeOwned, + C: Config, +{ + borrow_decode_from_slice(slice, config) +} + +/// Decode type `D` from the given reader with the given `Config`. The reader can be any type that implements `std::io::Read`, e.g. `std::fs::File`. +/// +/// See the [config] module for more information about config options. +/// +/// [config]: ../config/index.html +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +pub fn decode_from_std_read<'r, D: DeserializeOwned, C: Config, R: std::io::Read>( + src: &'r mut R, + config: C, +) -> Result { + let mut serde_decoder = + OwnedSerdeDecoder::, C, ()>>::from_std_read(src, config); + D::deserialize(serde_decoder.as_deserializer()) +} + +/// Attempt to decode a given type `D` from the given [Reader]. +/// +/// See the [config] module for more information on configurations. +/// +/// [config]: ../config/index.html +pub fn decode_from_reader( + reader: R, + config: C, +) -> Result { + let mut serde_decoder = OwnedSerdeDecoder::>::from_reader(reader, config); + D::deserialize(serde_decoder.as_deserializer()) +} + +pub(super) struct SerdeDecoder<'a, DE: Decoder> { + pub(super) de: &'a mut DE, +} + +impl<'de, DE: Decoder> Deserializer<'de> for SerdeDecoder<'_, DE> { + type Error = DecodeError; + + fn deserialize_any(self, _: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(SerdeDecodeError::AnyNotSupported.into()) + } + + fn deserialize_bool(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_bool(Decode::decode(&mut self.de)?) + } + + fn deserialize_i8(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i8(Decode::decode(&mut self.de)?) + } + + fn deserialize_i16(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i16(Decode::decode(&mut self.de)?) + } + + fn deserialize_i32(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i32(Decode::decode(&mut self.de)?) + } + + fn deserialize_i64(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i64(Decode::decode(&mut self.de)?) + } + + serde::serde_if_integer128! { + fn deserialize_i128(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i128(Decode::decode(&mut self.de)?) + } + } + + fn deserialize_u8(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u8(Decode::decode(&mut self.de)?) + } + + fn deserialize_u16(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u16(Decode::decode(&mut self.de)?) + } + + fn deserialize_u32(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u32(Decode::decode(&mut self.de)?) + } + + fn deserialize_u64(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u64(Decode::decode(&mut self.de)?) + } + + serde::serde_if_integer128! { + fn deserialize_u128(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u128(Decode::decode(&mut self.de)?) + } + } + + fn deserialize_f32(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_f32(Decode::decode(&mut self.de)?) + } + + fn deserialize_f64(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_f64(Decode::decode(&mut self.de)?) + } + + fn deserialize_char(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_char(Decode::decode(&mut self.de)?) + } + + #[cfg(feature = "alloc")] + fn deserialize_str(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_string(Decode::decode(&mut self.de)?) + } + + #[cfg(not(feature = "alloc"))] + fn deserialize_str(self, _: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(SerdeDecodeError::CannotBorrowOwnedData.into()) + } + + #[cfg(feature = "alloc")] + fn deserialize_string(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_string(Decode::decode(&mut self.de)?) + } + + #[cfg(not(feature = "alloc"))] + fn deserialize_string(self, _: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(SerdeDecodeError::CannotAllocate.into()) + } + + #[cfg(feature = "alloc")] + fn deserialize_bytes(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_byte_buf(Decode::decode(&mut self.de)?) + } + + #[cfg(not(feature = "alloc"))] + fn deserialize_bytes(self, _visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(SerdeDecodeError::CannotBorrowOwnedData.into()) + } + + #[cfg(feature = "alloc")] + fn deserialize_byte_buf(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_byte_buf(Decode::decode(&mut self.de)?) + } + #[cfg(not(feature = "alloc"))] + fn deserialize_byte_buf(self, _: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(SerdeDecodeError::CannotAllocate.into()) + } + + fn deserialize_option(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + let variant = crate::de::decode_option_variant(&mut self.de, "Option")?; + if variant.is_some() { + visitor.visit_some(self) + } else { + visitor.visit_none() + } + } + + fn deserialize_unit(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_unit() + } + + fn deserialize_unit_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_unit() + } + + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_seq(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + let len = usize::decode(&mut self.de)?; + self.deserialize_tuple(len, visitor) + } + + fn deserialize_tuple(mut self, len: usize, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + struct Access<'a, 'b, DE: Decoder> { + deserializer: &'a mut SerdeDecoder<'b, DE>, + len: usize, + } + + impl<'de, 'a, 'b: 'a, DE: Decoder + 'b> SeqAccess<'de> for Access<'a, 'b, DE> { + type Error = DecodeError; + + fn next_element_seed(&mut self, seed: T) -> Result, DecodeError> + where + T: DeserializeSeed<'de>, + { + if self.len > 0 { + self.len -= 1; + let value = DeserializeSeed::deserialize( + seed, + SerdeDecoder { + de: self.deserializer.de, + }, + )?; + Ok(Some(value)) + } else { + Ok(None) + } + } + + fn size_hint(&self) -> Option { + Some(self.len) + } + } + + visitor.visit_seq(Access { + deserializer: &mut self, + len, + }) + } + + fn deserialize_tuple_struct( + self, + _name: &'static str, + len: usize, + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + self.deserialize_tuple(len, visitor) + } + + fn deserialize_map(mut self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + struct Access<'a, 'b, DE: Decoder> { + deserializer: &'a mut SerdeDecoder<'b, DE>, + len: usize, + } + + impl<'de, 'a, 'b: 'a, DE: Decoder + 'b> MapAccess<'de> for Access<'a, 'b, DE> { + type Error = DecodeError; + + fn next_key_seed(&mut self, seed: K) -> Result, DecodeError> + where + K: DeserializeSeed<'de>, + { + if self.len > 0 { + self.len -= 1; + let key = DeserializeSeed::deserialize( + seed, + SerdeDecoder { + de: self.deserializer.de, + }, + )?; + Ok(Some(key)) + } else { + Ok(None) + } + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: DeserializeSeed<'de>, + { + let value = DeserializeSeed::deserialize( + seed, + SerdeDecoder { + de: self.deserializer.de, + }, + )?; + Ok(value) + } + + fn size_hint(&self) -> Option { + Some(self.len) + } + } + + let len = usize::decode(&mut self.de)?; + + visitor.visit_map(Access { + deserializer: &mut self, + len, + }) + } + + fn deserialize_struct( + self, + _name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + self.deserialize_tuple(fields.len(), visitor) + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_enum(self) + } + + fn deserialize_identifier(self, _visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(SerdeDecodeError::IdentifierNotSupported.into()) + } + + fn deserialize_ignored_any(self, _: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(SerdeDecodeError::IgnoredAnyNotSupported.into()) + } + + fn is_human_readable(&self) -> bool { + false + } +} + +impl<'de, DE: Decoder> EnumAccess<'de> for SerdeDecoder<'_, DE> { + type Error = DecodeError; + type Variant = Self; + + fn variant_seed(mut self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where + V: DeserializeSeed<'de>, + { + let idx = u32::decode(&mut self.de)?; + let val = seed.deserialize(idx.into_deserializer())?; + Ok((val, self)) + } +} + +impl<'de, DE: Decoder> VariantAccess<'de> for SerdeDecoder<'_, DE> { + type Error = DecodeError; + + fn unit_variant(self) -> Result<(), Self::Error> { + Ok(()) + } + + fn newtype_variant_seed(self, seed: T) -> Result + where + T: DeserializeSeed<'de>, + { + DeserializeSeed::deserialize(seed, self) + } + + fn tuple_variant(self, len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + Deserializer::deserialize_tuple(self, len, visitor) + } + + fn struct_variant( + self, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + Deserializer::deserialize_tuple(self, fields.len(), visitor) + } +} diff --git a/vendor/bincode-2.0.1/src/features/serde/mod.rs b/vendor/bincode-2.0.1/src/features/serde/mod.rs new file mode 100644 index 0000000..5874cca --- /dev/null +++ b/vendor/bincode-2.0.1/src/features/serde/mod.rs @@ -0,0 +1,303 @@ +//! Support for serde integration. Enable this with the `serde` feature. +//! +//! To encode/decode type that implement serde's trait, you can use: +//! - [borrow_decode_from_slice] +//! - [decode_from_slice] +//! - [encode_into_slice] +//! - [encode_to_vec] +//! +//! For interop with bincode's [Decode]/[Encode], you can use: +//! - [Compat] +//! - [BorrowCompat] +//! +//! For interop with bincode's `derive` feature, you can use the `#[bincode(with_serde)]` attribute on each field that implements serde's traits. +//! +//! ``` +//! # #[cfg(feature = "derive")] +//! # mod foo { +//! # use bincode::{Decode, Encode}; +//! # use serde_derive::{Deserialize, Serialize}; +//! #[derive(Serialize, Deserialize)] +//! pub struct SerdeType { +//! // ... +//! } +//! +//! #[derive(Decode, Encode)] +//! pub struct StructWithSerde { +//! #[bincode(with_serde)] +//! pub serde: SerdeType, +//! } +//! +//! #[derive(Decode, Encode)] +//! pub enum EnumWithSerde { +//! Unit(#[bincode(with_serde)] SerdeType), +//! Struct { +//! #[bincode(with_serde)] +//! serde: SerdeType, +//! }, +//! } +//! # } +//! ``` +//! +//! # Known issues +//! +//! Because bincode is a format without meta data, there are several known issues with serde's attributes. Please do not use any of the following attributes if you plan on using bincode, or use bincode's own `derive` macros. +//! - `#[serde(flatten)]` +//! - `#[serde(skip)]` +//! - `#[serde(skip_deserializing)]` +//! - `#[serde(skip_serializing)]` +//! - `#[serde(skip_serializing_if = "path")]` +//! - `#[serde(tag = "...")]` +//! - `#[serde(untagged)]` +//! +//! **Using any of the above attributes can and will cause issues with bincode and will result in lost data**. Consider using bincode's own derive macro instead. +//! +//! # Why move away from serde? +//! +//! Serde is a great library, but it has some issues that makes us want to be decoupled from serde: +//! - The issues documented above with attributes. +//! - Serde has chosen to not have a MSRV ([source](https://github.com/serde-rs/serde/pull/2257)). We think MSRV is important, bincode 1 still compiles with rust 1.18. +//! - Before serde we had rustc-serializer. Serde has more than replaced rustc-serializer, but we can imagine a future where serde is replaced by something else. +//! - We believe that less dependencies is better, and that you should be able to choose your own dependencies. If you disable all features, bincode 2 only has 1 dependency. ([`unty`], a micro crate we manage ourselves) +//! +//! **note:** just because we're making serde an optional dependency, it does not mean we're dropping support for serde. Serde will still be fully supported, we're just giving you the option to not use it. +//! +//! [Decode]: ../de/trait.Decode.html +//! [Encode]: ../enc/trait.Encode.html +//! [`unty`]: https://crates.io/crates/unty + +mod de_borrowed; +mod de_owned; +mod ser; + +pub use self::de_borrowed::*; +pub use self::de_owned::*; +pub use self::ser::*; + +/// A serde-specific error that occurred while decoding. +#[derive(Debug)] +#[non_exhaustive] +pub enum DecodeError { + /// Bincode does not support serde's `any` decoding feature. + /// + /// See the "known issues" list in the serde module for more information on this. + AnyNotSupported, + + /// Bincode does not support serde identifiers + IdentifierNotSupported, + + /// Bincode does not support serde's `ignored_any`. + /// + /// See the "known issues" list in the serde module for more information on this. + IgnoredAnyNotSupported, + + /// Serde tried decoding a borrowed value from an owned reader. Use `serde_decode_borrowed_from_*` instead + CannotBorrowOwnedData, + + /// Could not allocate data like `String` and `Vec` + #[cfg(not(feature = "alloc"))] + CannotAllocate, + + /// Custom serde error but bincode is unable to allocate a string. Set a breakpoint where this is thrown for more information. + #[cfg(not(feature = "alloc"))] + CustomError, +} + +#[cfg(feature = "alloc")] +impl serde::de::Error for crate::error::DecodeError { + fn custom(msg: T) -> Self + where + T: core::fmt::Display, + { + use alloc::string::ToString; + Self::OtherString(msg.to_string()) + } +} + +#[cfg(not(feature = "std"))] +impl serde::de::StdError for crate::error::DecodeError {} + +#[cfg(not(feature = "alloc"))] +impl serde::de::Error for crate::error::DecodeError { + fn custom(_: T) -> Self + where + T: core::fmt::Display, + { + DecodeError::CustomError.into() + } +} + +#[allow(clippy::from_over_into)] +impl Into for DecodeError { + fn into(self) -> crate::error::DecodeError { + crate::error::DecodeError::Serde(self) + } +} + +/// A serde-specific error that occurred while encoding. +#[derive(Debug)] +#[non_exhaustive] +pub enum EncodeError { + /// Serde provided bincode with a sequence without a length, which is not supported in bincode + SequenceMustHaveLength, + + /// [Serializer::collect_str] got called but bincode was unable to allocate memory. + #[cfg(not(feature = "alloc"))] + CannotCollectStr, + + /// Custom serde error but bincode is unable to allocate a string. Set a breakpoint where this is thrown for more information. + #[cfg(not(feature = "alloc"))] + CustomError, +} + +#[allow(clippy::from_over_into)] +impl Into for EncodeError { + fn into(self) -> crate::error::EncodeError { + crate::error::EncodeError::Serde(self) + } +} + +#[cfg(feature = "alloc")] +impl serde::ser::Error for crate::error::EncodeError { + fn custom(msg: T) -> Self + where + T: core::fmt::Display, + { + use alloc::string::ToString; + + Self::OtherString(msg.to_string()) + } +} + +#[cfg(not(feature = "std"))] +impl serde::de::StdError for crate::error::EncodeError {} + +#[cfg(not(feature = "alloc"))] +impl serde::ser::Error for crate::error::EncodeError { + fn custom(_: T) -> Self + where + T: core::fmt::Display, + { + EncodeError::CustomError.into() + } +} + +/// Wrapper struct that implements [Decode] and [Encode] on any type that implements serde's [DeserializeOwned] and [Serialize] respectively. +/// +/// This works for most types, but if you're dealing with borrowed data consider using [BorrowCompat] instead. +/// +/// [Decode]: ../de/trait.Decode.html +/// [Encode]: ../enc/trait.Encode.html +/// [DeserializeOwned]: https://docs.rs/serde/1/serde/de/trait.DeserializeOwned.html +/// [Serialize]: https://docs.rs/serde/1/serde/trait.Serialize.html +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +pub struct Compat(pub T); + +impl crate::Decode for Compat +where + T: serde::de::DeserializeOwned, +{ + fn decode(decoder: &mut D) -> Result { + let serde_decoder = de_owned::SerdeDecoder { de: decoder }; + T::deserialize(serde_decoder).map(Compat) + } +} +impl<'de, T, Context> crate::BorrowDecode<'de, Context> for Compat +where + T: serde::de::DeserializeOwned, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let serde_decoder = de_owned::SerdeDecoder { de: decoder }; + T::deserialize(serde_decoder).map(Compat) + } +} + +impl crate::Encode for Compat +where + T: serde::Serialize, +{ + fn encode( + &self, + encoder: &mut E, + ) -> Result<(), crate::error::EncodeError> { + let serializer = ser::SerdeEncoder { enc: encoder }; + self.0.serialize(serializer)?; + Ok(()) + } +} + +impl core::fmt::Debug for Compat +where + T: core::fmt::Debug, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_tuple("Compat").field(&self.0).finish() + } +} + +impl core::fmt::Display for Compat +where + T: core::fmt::Display, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.0.fmt(f) + } +} + +/// Wrapper struct that implements [BorrowDecode] and [Encode] on any type that implements serde's [Deserialize] and [Serialize] respectively. This is mostly used on `&[u8]` and `&str`, for other types consider using [Compat] instead. +/// +/// [BorrowDecode]: ../de/trait.BorrowDecode.html +/// [Encode]: ../enc/trait.Encode.html +/// [Deserialize]: https://docs.rs/serde/1/serde/de/trait.Deserialize.html +/// [Serialize]: https://docs.rs/serde/1/serde/trait.Serialize.html +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +pub struct BorrowCompat(pub T); + +impl<'de, T, Context> crate::de::BorrowDecode<'de, Context> for BorrowCompat +where + T: serde::de::Deserialize<'de>, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let serde_decoder = de_borrowed::SerdeDecoder { + de: decoder, + pd: core::marker::PhantomData, + }; + T::deserialize(serde_decoder).map(BorrowCompat) + } +} + +impl crate::Encode for BorrowCompat +where + T: serde::Serialize, +{ + fn encode( + &self, + encoder: &mut E, + ) -> Result<(), crate::error::EncodeError> { + let serializer = ser::SerdeEncoder { enc: encoder }; + self.0.serialize(serializer)?; + Ok(()) + } +} + +impl core::fmt::Debug for BorrowCompat +where + T: core::fmt::Debug, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_tuple("BorrowCompat").field(&self.0).finish() + } +} + +impl core::fmt::Display for BorrowCompat +where + T: core::fmt::Display, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.0.fmt(f) + } +} diff --git a/vendor/bincode-2.0.1/src/features/serde/ser.rs b/vendor/bincode-2.0.1/src/features/serde/ser.rs new file mode 100644 index 0000000..5dbdde3 --- /dev/null +++ b/vendor/bincode-2.0.1/src/features/serde/ser.rs @@ -0,0 +1,406 @@ +use super::EncodeError as SerdeEncodeError; +use crate::{ + config::Config, + enc::{write::Writer, Encode, Encoder}, + error::EncodeError, +}; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +use serde::ser::*; + +/// Encode the given value into a `Vec` with the given `Config`. See the [config] module for more information. +/// +/// [config]: ../config/index.html +#[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] +pub fn encode_to_vec(val: E, config: C) -> Result, EncodeError> +where + E: Serialize, + C: Config, +{ + let mut encoder = crate::enc::EncoderImpl::new(crate::VecWriter::default(), config); + let serializer = SerdeEncoder { enc: &mut encoder }; + val.serialize(serializer)?; + Ok(encoder.into_writer().collect()) +} + +/// Encode the given value into the given slice. Returns the amount of bytes that have been written. +/// +/// See the [config] module for more information on configurations. +/// +/// [config]: ../config/index.html +pub fn encode_into_slice(val: E, dst: &mut [u8], config: C) -> Result +where + E: Serialize, + C: Config, +{ + let mut encoder = + crate::enc::EncoderImpl::new(crate::enc::write::SliceWriter::new(dst), config); + let serializer = SerdeEncoder { enc: &mut encoder }; + val.serialize(serializer)?; + Ok(encoder.into_writer().bytes_written()) +} + +/// Encode the given value into a custom [Writer]. +/// +/// See the [config] module for more information on configurations. +/// +/// [config]: ../config/index.html +pub fn encode_into_writer( + val: E, + writer: W, + config: C, +) -> Result<(), EncodeError> { + let mut encoder = crate::enc::EncoderImpl::<_, C>::new(writer, config); + let serializer = SerdeEncoder { enc: &mut encoder }; + val.serialize(serializer)?; + Ok(()) +} + +/// Encode the given value into any type that implements `std::io::Write`, e.g. `std::fs::File`, with the given `Config`. +/// See the [config] module for more information. +/// +/// [config]: ../config/index.html +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(feature = "std")] +pub fn encode_into_std_write( + val: E, + dst: &mut W, + config: C, +) -> Result { + let writer = crate::IoWriter::new(dst); + let mut encoder = crate::enc::EncoderImpl::<_, C>::new(writer, config); + let serializer = SerdeEncoder { enc: &mut encoder }; + val.serialize(serializer)?; + Ok(encoder.into_writer().bytes_written()) +} + +pub(super) struct SerdeEncoder<'a, ENC: Encoder> { + pub(super) enc: &'a mut ENC, +} + +impl Serializer for SerdeEncoder<'_, ENC> +where + ENC: Encoder, +{ + type Ok = (); + + type Error = EncodeError; + + type SerializeSeq = Self; + type SerializeTuple = Self; + type SerializeTupleStruct = Self; + type SerializeTupleVariant = Self; + type SerializeMap = Self; + type SerializeStruct = Self; + type SerializeStructVariant = Self; + + fn serialize_bool(self, v: bool) -> Result { + v.encode(self.enc) + } + + fn serialize_i8(self, v: i8) -> Result { + v.encode(self.enc) + } + + fn serialize_i16(self, v: i16) -> Result { + v.encode(self.enc) + } + + fn serialize_i32(self, v: i32) -> Result { + v.encode(self.enc) + } + + fn serialize_i64(self, v: i64) -> Result { + v.encode(self.enc) + } + + serde::serde_if_integer128! { + fn serialize_i128(self, v: i128) -> Result { + v.encode(self.enc) + } + } + + fn serialize_u8(self, v: u8) -> Result { + v.encode(self.enc) + } + + fn serialize_u16(self, v: u16) -> Result { + v.encode(self.enc) + } + + fn serialize_u32(self, v: u32) -> Result { + v.encode(self.enc) + } + + fn serialize_u64(self, v: u64) -> Result { + v.encode(self.enc) + } + + serde::serde_if_integer128! { + fn serialize_u128(self, v: u128) -> Result { + v.encode(self.enc) + } + } + + fn serialize_f32(self, v: f32) -> Result { + v.encode(self.enc) + } + + fn serialize_f64(self, v: f64) -> Result { + v.encode(self.enc) + } + + fn serialize_char(self, v: char) -> Result { + v.encode(self.enc) + } + + fn serialize_str(self, v: &str) -> Result { + v.encode(self.enc) + } + + fn serialize_bytes(self, v: &[u8]) -> Result { + v.encode(self.enc) + } + + fn serialize_none(self) -> Result { + 0u8.encode(self.enc) + } + + fn serialize_some(mut self, value: &T) -> Result + where + T: Serialize + ?Sized, + { + 1u8.encode(&mut self.enc)?; + value.serialize(self) + } + + fn serialize_unit(self) -> Result { + Ok(()) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + Ok(()) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + variant_index: u32, + _variant: &'static str, + ) -> Result { + variant_index.encode(self.enc) + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result + where + T: Serialize + ?Sized, + { + value.serialize(self) + } + + fn serialize_newtype_variant( + mut self, + _name: &'static str, + variant_index: u32, + _variant: &'static str, + value: &T, + ) -> Result + where + T: Serialize + ?Sized, + { + variant_index.encode(&mut self.enc)?; + value.serialize(self) + } + + fn serialize_seq(mut self, len: Option) -> Result { + let len = len.ok_or_else(|| SerdeEncodeError::SequenceMustHaveLength.into())?; + len.encode(&mut self.enc)?; + Ok(Compound { enc: self.enc }) + } + + fn serialize_tuple(self, _: usize) -> Result { + Ok(self) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Ok(Compound { enc: self.enc }) + } + + fn serialize_tuple_variant( + mut self, + _name: &'static str, + variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + variant_index.encode(&mut self.enc)?; + Ok(Compound { enc: self.enc }) + } + + fn serialize_map(mut self, len: Option) -> Result { + let len = len.ok_or_else(|| SerdeEncodeError::SequenceMustHaveLength.into())?; + len.encode(&mut self.enc)?; + Ok(Compound { enc: self.enc }) + } + + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Ok(Compound { enc: self.enc }) + } + + fn serialize_struct_variant( + mut self, + _name: &'static str, + variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + variant_index.encode(&mut self.enc)?; + Ok(Compound { enc: self.enc }) + } + + #[cfg(not(feature = "alloc"))] + fn collect_str(self, _: &T) -> Result + where + T: core::fmt::Display + ?Sized, + { + Err(SerdeEncodeError::CannotCollectStr.into()) + } + + fn is_human_readable(&self) -> bool { + false + } +} + +type Compound<'a, ENC> = SerdeEncoder<'a, ENC>; + +impl SerializeSeq for Compound<'_, ENC> { + type Ok = (); + type Error = EncodeError; + + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize + ?Sized, + { + value.serialize(SerdeEncoder { enc: self.enc }) + } + + fn end(self) -> Result { + Ok(()) + } +} + +impl SerializeTuple for Compound<'_, ENC> { + type Ok = (); + type Error = EncodeError; + + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize + ?Sized, + { + value.serialize(SerdeEncoder { enc: self.enc }) + } + + fn end(self) -> Result { + Ok(()) + } +} + +impl SerializeTupleStruct for Compound<'_, ENC> { + type Ok = (); + type Error = EncodeError; + + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize + ?Sized, + { + value.serialize(SerdeEncoder { enc: self.enc }) + } + + fn end(self) -> Result { + Ok(()) + } +} + +impl SerializeTupleVariant for Compound<'_, ENC> { + type Ok = (); + type Error = EncodeError; + + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize + ?Sized, + { + value.serialize(SerdeEncoder { enc: self.enc }) + } + + fn end(self) -> Result { + Ok(()) + } +} + +impl SerializeMap for Compound<'_, ENC> { + type Ok = (); + type Error = EncodeError; + + fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> + where + T: Serialize + ?Sized, + { + key.serialize(SerdeEncoder { enc: self.enc }) + } + + fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize + ?Sized, + { + value.serialize(SerdeEncoder { enc: self.enc }) + } + + fn end(self) -> Result { + Ok(()) + } +} + +impl SerializeStruct for Compound<'_, ENC> { + type Ok = (); + type Error = EncodeError; + + fn serialize_field(&mut self, _key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: Serialize + ?Sized, + { + value.serialize(SerdeEncoder { enc: self.enc }) + } + + fn end(self) -> Result { + Ok(()) + } +} + +impl SerializeStructVariant for Compound<'_, ENC> { + type Ok = (); + type Error = EncodeError; + + fn serialize_field(&mut self, _key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: Serialize + ?Sized, + { + value.serialize(SerdeEncoder { enc: self.enc }) + } + + fn end(self) -> Result { + Ok(()) + } +} diff --git a/vendor/bincode-2.0.1/src/lib.rs b/vendor/bincode-2.0.1/src/lib.rs new file mode 100644 index 0000000..1555c5e --- /dev/null +++ b/vendor/bincode-2.0.1/src/lib.rs @@ -0,0 +1,237 @@ +#![no_std] +#![warn(missing_docs, unused_lifetimes)] +#![cfg_attr(docsrs, feature(doc_cfg))] + +//! Bincode is a crate for encoding and decoding using a tiny binary +//! serialization strategy. Using it, you can easily go from having +//! an object in memory, quickly serialize it to bytes, and then +//! deserialize it back just as fast! +//! +//! If you're coming from bincode 1, check out our [migration guide](migration_guide/index.html) +//! +//! # Serde +//! +//! Starting from bincode 2, serde is now an optional dependency. If you want to use serde, please enable the `serde` feature. See [Features](#features) for more information. +//! +//! # Features +//! +//! |Name |Default?|Affects MSRV?|Supported types for Encode/Decode|Enabled methods |Other| +//! |------|--------|-------------|-----------------------------------------|-----------------------------------------------------------------|-----| +//! |std | Yes | No |`HashMap` and `HashSet`|`decode_from_std_read` and `encode_into_std_write`| +//! |alloc | Yes | No |All common containers in alloc, like `Vec`, `String`, `Box`|`encode_to_vec`| +//! |atomic| Yes | No |All `Atomic*` integer types, e.g. `AtomicUsize`, and `AtomicBool`|| +//! |derive| Yes | No |||Enables the `BorrowDecode`, `Decode` and `Encode` derive macros| +//! |serde | No | Yes (MSRV reliant on serde)|`Compat` and `BorrowCompat`, which will work for all types that implement serde's traits|serde-specific encode/decode functions in the [serde] module|Note: There are several [known issues](serde/index.html#known-issues) when using serde and bincode| +//! +//! # Which functions to use +//! +//! Bincode has a couple of pairs of functions that are used in different situations. +//! +//! |Situation|Encode|Decode| +//! |---|---|--- +//! |You're working with [`fs::File`] or [`net::TcpStream`]|[`encode_into_std_write`]|[`decode_from_std_read`]| +//! |you're working with in-memory buffers|[`encode_to_vec`]|[`decode_from_slice`]| +//! |You want to use a custom [Reader] and [Writer]|[`encode_into_writer`]|[`decode_from_reader`]| +//! |You're working with pre-allocated buffers or on embedded targets|[`encode_into_slice`]|[`decode_from_slice`]| +//! +//! **Note:** If you're using `serde`, use `bincode::serde::...` instead of `bincode::...` +//! +//! # Example +//! +//! ```rust +//! let mut slice = [0u8; 100]; +//! +//! // You can encode any type that implements `Encode`. +//! // You can automatically implement this trait on custom types with the `derive` feature. +//! let input = ( +//! 0u8, +//! 10u32, +//! 10000i128, +//! 'a', +//! [0u8, 1u8, 2u8, 3u8] +//! ); +//! +//! let length = bincode::encode_into_slice( +//! input, +//! &mut slice, +//! bincode::config::standard() +//! ).unwrap(); +//! +//! let slice = &slice[..length]; +//! println!("Bytes written: {:?}", slice); +//! +//! // Decoding works the same as encoding. +//! // The trait used is `Decode`, and can also be automatically implemented with the `derive` feature. +//! let decoded: (u8, u32, i128, char, [u8; 4]) = bincode::decode_from_slice(slice, bincode::config::standard()).unwrap().0; +//! +//! assert_eq!(decoded, input); +//! ``` +//! +//! [`fs::File`]: std::fs::File +//! [`net::TcpStream`]: std::net::TcpStream +//! + +#![doc(html_root_url = "https://docs.rs/bincode/2.0.1")] +#![crate_name = "bincode"] +#![crate_type = "rlib"] + +#[cfg(feature = "alloc")] +extern crate alloc; +#[cfg(any(feature = "std", test))] +extern crate std; + +mod atomic; +mod features; +pub(crate) mod utils; +pub(crate) mod varint; + +use de::{read::Reader, Decoder}; +use enc::write::Writer; + +#[cfg(any( + feature = "alloc", + feature = "std", + feature = "derive", + feature = "serde" +))] +pub use features::*; + +pub mod config; +#[macro_use] +pub mod de; +pub mod enc; +pub mod error; + +pub use de::{BorrowDecode, Decode}; +pub use enc::Encode; + +use config::Config; + +/// Encode the given value into the given slice. Returns the amount of bytes that have been written. +/// +/// See the [config] module for more information on configurations. +/// +/// [config]: config/index.html +pub fn encode_into_slice( + val: E, + dst: &mut [u8], + config: C, +) -> Result { + let writer = enc::write::SliceWriter::new(dst); + let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config); + val.encode(&mut encoder)?; + Ok(encoder.into_writer().bytes_written()) +} + +/// Encode the given value into a custom [Writer]. +/// +/// See the [config] module for more information on configurations. +/// +/// [config]: config/index.html +pub fn encode_into_writer( + val: E, + writer: W, + config: C, +) -> Result<(), error::EncodeError> { + let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config); + val.encode(&mut encoder)?; + Ok(()) +} + +/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read. +/// +/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [borrow_decode_from_slice]. +/// +/// See the [config] module for more information on configurations. +/// +/// [config]: config/index.html +pub fn decode_from_slice, C: Config>( + src: &[u8], + config: C, +) -> Result<(D, usize), error::DecodeError> { + decode_from_slice_with_context(src, config, ()) +} + +/// Attempt to decode a given type `D` from the given slice with `Context`. Returns the decoded output and the amount of bytes read. +/// +/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [borrow_decode_from_slice]. +/// +/// See the [config] module for more information on configurations. +/// +/// [config]: config/index.html +pub fn decode_from_slice_with_context, C: Config>( + src: &[u8], + config: C, + context: Context, +) -> Result<(D, usize), error::DecodeError> { + let reader = de::read::SliceReader::new(src); + let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context); + let result = D::decode(&mut decoder)?; + let bytes_read = src.len() - decoder.reader().slice.len(); + Ok((result, bytes_read)) +} + +/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read. +/// +/// See the [config] module for more information on configurations. +/// +/// [config]: config/index.html +pub fn borrow_decode_from_slice<'a, D: de::BorrowDecode<'a, ()>, C: Config>( + src: &'a [u8], + config: C, +) -> Result<(D, usize), error::DecodeError> { + borrow_decode_from_slice_with_context(src, config, ()) +} + +/// Attempt to decode a given type `D` from the given slice with `Context`. Returns the decoded output and the amount of bytes read. +/// +/// See the [config] module for more information on configurations. +/// +/// [config]: config/index.html +pub fn borrow_decode_from_slice_with_context< + 'a, + Context, + D: de::BorrowDecode<'a, Context>, + C: Config, +>( + src: &'a [u8], + config: C, + context: Context, +) -> Result<(D, usize), error::DecodeError> { + let reader = de::read::SliceReader::new(src); + let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context); + let result = D::borrow_decode(&mut decoder)?; + let bytes_read = src.len() - decoder.reader().slice.len(); + Ok((result, bytes_read)) +} + +/// Attempt to decode a given type `D` from the given [Reader]. +/// +/// See the [config] module for more information on configurations. +/// +/// [config]: config/index.html +pub fn decode_from_reader, R: Reader, C: Config>( + reader: R, + config: C, +) -> Result { + let mut decoder = de::DecoderImpl::<_, C, ()>::new(reader, config, ()); + D::decode(&mut decoder) +} + +// TODO: Currently our doctests fail when trying to include the specs because the specs depend on `derive` and `alloc`. +// But we want to have the specs in the docs always +#[cfg(all(feature = "alloc", feature = "derive", doc))] +pub mod spec { + #![doc = include_str!("../docs/spec.md")] +} + +#[cfg(doc)] +pub mod migration_guide { + #![doc = include_str!("../docs/migration_guide.md")] +} + +// Test the examples in readme.md +#[cfg(all(feature = "alloc", feature = "derive", doctest))] +mod readme { + #![doc = include_str!("../readme.md")] +} diff --git a/vendor/bincode-2.0.1/src/utils.rs b/vendor/bincode-2.0.1/src/utils.rs new file mode 100644 index 0000000..418f659 --- /dev/null +++ b/vendor/bincode-2.0.1/src/utils.rs @@ -0,0 +1,3 @@ +pub trait Sealed {} + +impl Sealed for &mut T where T: Sealed {} diff --git a/vendor/bincode-2.0.1/src/varint/decode_signed.rs b/vendor/bincode-2.0.1/src/varint/decode_signed.rs new file mode 100644 index 0000000..cae4e4f --- /dev/null +++ b/vendor/bincode-2.0.1/src/varint/decode_signed.rs @@ -0,0 +1,92 @@ +use crate::{ + config::Endianness, + de::read::Reader, + error::{DecodeError, IntegerType}, +}; + +pub fn varint_decode_i16(read: &mut R, endian: Endianness) -> Result { + let n = super::varint_decode_u16(read, endian) + .map_err(DecodeError::change_integer_type_to_signed)?; + Ok(if n % 2 == 0 { + // positive number + (n / 2) as _ + } else { + // negative number + // !m * 2 + 1 = n + // !m * 2 = n - 1 + // !m = (n - 1) / 2 + // m = !((n - 1) / 2) + // since we have n is odd, we have floor(n / 2) = floor((n - 1) / 2) + !(n / 2) as _ + }) +} + +pub fn varint_decode_i32(read: &mut R, endian: Endianness) -> Result { + let n = super::varint_decode_u32(read, endian) + .map_err(DecodeError::change_integer_type_to_signed)?; + Ok(if n % 2 == 0 { + // positive number + (n / 2) as _ + } else { + // negative number + // !m * 2 + 1 = n + // !m * 2 = n - 1 + // !m = (n - 1) / 2 + // m = !((n - 1) / 2) + // since we have n is odd, we have floor(n / 2) = floor((n - 1) / 2) + !(n / 2) as _ + }) +} + +pub fn varint_decode_i64(read: &mut R, endian: Endianness) -> Result { + let n = super::varint_decode_u64(read, endian) + .map_err(DecodeError::change_integer_type_to_signed)?; + Ok(if n % 2 == 0 { + // positive number + (n / 2) as _ + } else { + // negative number + // !m * 2 + 1 = n + // !m * 2 = n - 1 + // !m = (n - 1) / 2 + // m = !((n - 1) / 2) + // since we have n is odd, we have floor(n / 2) = floor((n - 1) / 2) + !(n / 2) as _ + }) +} + +pub fn varint_decode_i128( + read: &mut R, + endian: Endianness, +) -> Result { + let n = super::varint_decode_u128(read, endian) + .map_err(DecodeError::change_integer_type_to_signed)?; + Ok(if n % 2 == 0 { + // positive number + (n / 2) as _ + } else { + // negative number + // !m * 2 + 1 = n + // !m * 2 = n - 1 + // !m = (n - 1) / 2 + // m = !((n - 1) / 2) + // since we have n is odd, we have floor(n / 2) = floor((n - 1) / 2) + !(n / 2) as _ + }) +} + +pub fn varint_decode_isize( + read: &mut R, + endian: Endianness, +) -> Result { + match varint_decode_i64(read, endian) { + Ok(val) => Ok(val as isize), + Err(DecodeError::InvalidIntegerType { found, .. }) => { + Err(DecodeError::InvalidIntegerType { + expected: IntegerType::Isize, + found: found.into_signed(), + }) + } + Err(e) => Err(e), + } +} diff --git a/vendor/bincode-2.0.1/src/varint/decode_unsigned.rs b/vendor/bincode-2.0.1/src/varint/decode_unsigned.rs new file mode 100644 index 0000000..d6ab1e0 --- /dev/null +++ b/vendor/bincode-2.0.1/src/varint/decode_unsigned.rs @@ -0,0 +1,710 @@ +use core::convert::TryInto; + +use super::{SINGLE_BYTE_MAX, U128_BYTE, U16_BYTE, U32_BYTE, U64_BYTE}; +use crate::{ + config::Endianness, + de::read::Reader, + error::{DecodeError, IntegerType}, +}; + +#[inline(never)] +#[cold] +fn deserialize_varint_cold_u16(read: &mut R, endian: Endianness) -> Result +where + R: Reader, +{ + let mut bytes = [0u8; 1]; + read.read(&mut bytes)?; + match bytes[0] { + byte @ 0..=SINGLE_BYTE_MAX => Ok(byte as u16), + U16_BYTE => { + let mut bytes = [0u8; 2]; + read.read(&mut bytes)?; + Ok(match endian { + Endianness::Big => u16::from_be_bytes(bytes), + Endianness::Little => u16::from_le_bytes(bytes), + }) + } + U32_BYTE => invalid_varint_discriminant(IntegerType::U16, IntegerType::U32), + U64_BYTE => invalid_varint_discriminant(IntegerType::U16, IntegerType::U64), + U128_BYTE => invalid_varint_discriminant(IntegerType::U16, IntegerType::U128), + _ => invalid_varint_discriminant(IntegerType::U16, IntegerType::Reserved), + } +} + +#[inline(never)] +#[cold] +fn deserialize_varint_cold_u32(read: &mut R, endian: Endianness) -> Result +where + R: Reader, +{ + let mut bytes = [0u8; 1]; + read.read(&mut bytes)?; + match bytes[0] { + byte @ 0..=SINGLE_BYTE_MAX => Ok(byte as u32), + U16_BYTE => { + let mut bytes = [0u8; 2]; + read.read(&mut bytes)?; + Ok(match endian { + Endianness::Big => u16::from_be_bytes(bytes) as u32, + Endianness::Little => u16::from_le_bytes(bytes) as u32, + }) + } + U32_BYTE => { + let mut bytes = [0u8; 4]; + read.read(&mut bytes)?; + Ok(match endian { + Endianness::Big => u32::from_be_bytes(bytes), + Endianness::Little => u32::from_le_bytes(bytes), + }) + } + U64_BYTE => invalid_varint_discriminant(IntegerType::U32, IntegerType::U64), + U128_BYTE => invalid_varint_discriminant(IntegerType::U32, IntegerType::U128), + _ => invalid_varint_discriminant(IntegerType::U32, IntegerType::Reserved), + } +} + +#[inline(never)] +#[cold] +fn deserialize_varint_cold_u64(read: &mut R, endian: Endianness) -> Result +where + R: Reader, +{ + let mut bytes = [0u8; 1]; + read.read(&mut bytes)?; + match bytes[0] { + byte @ 0..=SINGLE_BYTE_MAX => Ok(byte as u64), + U16_BYTE => { + let mut bytes = [0u8; 2]; + read.read(&mut bytes)?; + Ok(match endian { + Endianness::Big => u16::from_be_bytes(bytes) as u64, + Endianness::Little => u16::from_le_bytes(bytes) as u64, + }) + } + U32_BYTE => { + let mut bytes = [0u8; 4]; + read.read(&mut bytes)?; + Ok(match endian { + Endianness::Big => u32::from_be_bytes(bytes) as u64, + Endianness::Little => u32::from_le_bytes(bytes) as u64, + }) + } + U64_BYTE => { + let mut bytes = [0u8; 8]; + read.read(&mut bytes)?; + Ok(match endian { + Endianness::Big => u64::from_be_bytes(bytes), + Endianness::Little => u64::from_le_bytes(bytes), + }) + } + U128_BYTE => invalid_varint_discriminant(IntegerType::U64, IntegerType::U128), + _ => invalid_varint_discriminant(IntegerType::U64, IntegerType::Reserved), + } +} + +#[inline(never)] +#[cold] +fn deserialize_varint_cold_usize(read: &mut R, endian: Endianness) -> Result +where + R: Reader, +{ + let mut bytes = [0u8; 1]; + read.read(&mut bytes)?; + match bytes[0] { + byte @ 0..=SINGLE_BYTE_MAX => Ok(byte as usize), + U16_BYTE => { + let mut bytes = [0u8; 2]; + read.read(&mut bytes)?; + Ok(match endian { + Endianness::Big => u16::from_be_bytes(bytes) as usize, + Endianness::Little => u16::from_le_bytes(bytes) as usize, + }) + } + U32_BYTE => { + let mut bytes = [0u8; 4]; + read.read(&mut bytes)?; + Ok(match endian { + Endianness::Big => u32::from_be_bytes(bytes) as usize, + Endianness::Little => u32::from_le_bytes(bytes) as usize, + }) + } + U64_BYTE => { + let mut bytes = [0u8; 8]; + read.read(&mut bytes)?; + Ok(match endian { + Endianness::Big => u64::from_be_bytes(bytes) as usize, + Endianness::Little => u64::from_le_bytes(bytes) as usize, + }) + } + U128_BYTE => invalid_varint_discriminant(IntegerType::Usize, IntegerType::U128), + _ => invalid_varint_discriminant(IntegerType::Usize, IntegerType::Reserved), + } +} + +#[inline(never)] +#[cold] +fn deserialize_varint_cold_u128(read: &mut R, endian: Endianness) -> Result +where + R: Reader, +{ + let mut bytes = [0u8; 1]; + read.read(&mut bytes)?; + match bytes[0] { + byte @ 0..=SINGLE_BYTE_MAX => Ok(byte as u128), + U16_BYTE => { + let mut bytes = [0u8; 2]; + read.read(&mut bytes)?; + Ok(match endian { + Endianness::Big => u16::from_be_bytes(bytes) as u128, + Endianness::Little => u16::from_le_bytes(bytes) as u128, + }) + } + U32_BYTE => { + let mut bytes = [0u8; 4]; + read.read(&mut bytes)?; + Ok(match endian { + Endianness::Big => u32::from_be_bytes(bytes) as u128, + Endianness::Little => u32::from_le_bytes(bytes) as u128, + }) + } + U64_BYTE => { + let mut bytes = [0u8; 8]; + read.read(&mut bytes)?; + Ok(match endian { + Endianness::Big => u64::from_be_bytes(bytes) as u128, + Endianness::Little => u64::from_le_bytes(bytes) as u128, + }) + } + U128_BYTE => { + let mut bytes = [0u8; 16]; + read.read(&mut bytes)?; + Ok(match endian { + Endianness::Big => u128::from_be_bytes(bytes), + Endianness::Little => u128::from_le_bytes(bytes), + }) + } + _ => invalid_varint_discriminant(IntegerType::U128, IntegerType::Reserved), + } +} + +#[inline(never)] +#[cold] +const fn invalid_varint_discriminant( + expected: IntegerType, + found: IntegerType, +) -> Result { + Err(DecodeError::InvalidIntegerType { expected, found }) +} + +pub fn varint_decode_u16(read: &mut R, endian: Endianness) -> Result { + if let Some(bytes) = read.peek_read(3) { + let (discriminant, bytes) = bytes.split_at(1); + let (out, used) = match discriminant[0] { + byte @ 0..=SINGLE_BYTE_MAX => (byte as u16, 1), + U16_BYTE => { + let val = match endian { + Endianness::Big => u16::from_be_bytes(bytes[..2].try_into().unwrap()), + Endianness::Little => u16::from_le_bytes(bytes[..2].try_into().unwrap()), + }; + + (val, 3) + } + U32_BYTE => return invalid_varint_discriminant(IntegerType::U16, IntegerType::U32), + U64_BYTE => return invalid_varint_discriminant(IntegerType::U16, IntegerType::U64), + U128_BYTE => return invalid_varint_discriminant(IntegerType::U16, IntegerType::U128), + _ => return invalid_varint_discriminant(IntegerType::U16, IntegerType::Reserved), + }; + + read.consume(used); + Ok(out) + } else { + deserialize_varint_cold_u16(read, endian) + } +} + +pub fn varint_decode_u32(read: &mut R, endian: Endianness) -> Result { + if let Some(bytes) = read.peek_read(5) { + let (discriminant, bytes) = bytes.split_at(1); + let (out, used) = match discriminant[0] { + byte @ 0..=SINGLE_BYTE_MAX => (byte as u32, 1), + U16_BYTE => { + let val = match endian { + Endianness::Big => u16::from_be_bytes(bytes[..2].try_into().unwrap()), + Endianness::Little => u16::from_le_bytes(bytes[..2].try_into().unwrap()), + }; + + (val as u32, 3) + } + U32_BYTE => { + let val = match endian { + Endianness::Big => u32::from_be_bytes(bytes[..4].try_into().unwrap()), + Endianness::Little => u32::from_le_bytes(bytes[..4].try_into().unwrap()), + }; + + (val, 5) + } + U64_BYTE => return invalid_varint_discriminant(IntegerType::U32, IntegerType::U64), + U128_BYTE => return invalid_varint_discriminant(IntegerType::U32, IntegerType::U128), + _ => return invalid_varint_discriminant(IntegerType::U32, IntegerType::Reserved), + }; + + read.consume(used); + Ok(out) + } else { + deserialize_varint_cold_u32(read, endian) + } +} + +pub fn varint_decode_u64(read: &mut R, endian: Endianness) -> Result { + if let Some(bytes) = read.peek_read(9) { + let (discriminant, bytes) = bytes.split_at(1); + let (out, used) = match discriminant[0] { + byte @ 0..=SINGLE_BYTE_MAX => (byte as u64, 1), + U16_BYTE => { + let val = match endian { + Endianness::Big => u16::from_be_bytes(bytes[..2].try_into().unwrap()), + Endianness::Little => u16::from_le_bytes(bytes[..2].try_into().unwrap()), + }; + + (val as u64, 3) + } + U32_BYTE => { + let val = match endian { + Endianness::Big => u32::from_be_bytes(bytes[..4].try_into().unwrap()), + Endianness::Little => u32::from_le_bytes(bytes[..4].try_into().unwrap()), + }; + + (val as u64, 5) + } + U64_BYTE => { + let val = match endian { + Endianness::Big => u64::from_be_bytes(bytes[..8].try_into().unwrap()), + Endianness::Little => u64::from_le_bytes(bytes[..8].try_into().unwrap()), + }; + + (val, 9) + } + U128_BYTE => return invalid_varint_discriminant(IntegerType::U32, IntegerType::U128), + _ => return invalid_varint_discriminant(IntegerType::U32, IntegerType::Reserved), + }; + + read.consume(used); + Ok(out) + } else { + deserialize_varint_cold_u64(read, endian) + } +} + +pub fn varint_decode_usize( + read: &mut R, + endian: Endianness, +) -> Result { + if let Some(bytes) = read.peek_read(9) { + let (discriminant, bytes) = bytes.split_at(1); + let (out, used) = match discriminant[0] { + byte @ 0..=SINGLE_BYTE_MAX => (byte as usize, 1), + U16_BYTE => { + let val = match endian { + Endianness::Big => u16::from_be_bytes(bytes[..2].try_into().unwrap()), + Endianness::Little => u16::from_le_bytes(bytes[..2].try_into().unwrap()), + }; + + (val as usize, 3) + } + U32_BYTE => { + let val = match endian { + Endianness::Big => u32::from_be_bytes(bytes[..4].try_into().unwrap()), + Endianness::Little => u32::from_le_bytes(bytes[..4].try_into().unwrap()), + }; + + (val as usize, 5) + } + U64_BYTE => { + let val = match endian { + Endianness::Big => u64::from_be_bytes(bytes[..8].try_into().unwrap()), + Endianness::Little => u64::from_le_bytes(bytes[..8].try_into().unwrap()), + }; + + (val as usize, 9) + } + U128_BYTE => return invalid_varint_discriminant(IntegerType::Usize, IntegerType::U128), + _ => return invalid_varint_discriminant(IntegerType::Usize, IntegerType::Reserved), + }; + + read.consume(used); + Ok(out) + } else { + deserialize_varint_cold_usize(read, endian) + } +} + +pub fn varint_decode_u128( + read: &mut R, + endian: Endianness, +) -> Result { + if let Some(bytes) = read.peek_read(17) { + let (discriminant, bytes) = bytes.split_at(1); + let (out, used) = match discriminant[0] { + byte @ 0..=SINGLE_BYTE_MAX => (byte as u128, 1), + U16_BYTE => { + let val = match endian { + Endianness::Big => u16::from_be_bytes(bytes[..2].try_into().unwrap()), + Endianness::Little => u16::from_le_bytes(bytes[..2].try_into().unwrap()), + }; + + (val as u128, 3) + } + U32_BYTE => { + let val = match endian { + Endianness::Big => u32::from_be_bytes(bytes[..4].try_into().unwrap()), + Endianness::Little => u32::from_le_bytes(bytes[..4].try_into().unwrap()), + }; + + (val as u128, 5) + } + U64_BYTE => { + let val = match endian { + Endianness::Big => u64::from_be_bytes(bytes[..8].try_into().unwrap()), + Endianness::Little => u64::from_le_bytes(bytes[..8].try_into().unwrap()), + }; + + (val as u128, 9) + } + U128_BYTE => { + let val = match endian { + Endianness::Big => u128::from_be_bytes(bytes[..16].try_into().unwrap()), + Endianness::Little => u128::from_le_bytes(bytes[..16].try_into().unwrap()), + }; + + (val, 17) + } + _ => return invalid_varint_discriminant(IntegerType::Usize, IntegerType::Reserved), + }; + + read.consume(used); + Ok(out) + } else { + deserialize_varint_cold_u128(read, endian) + } +} + +#[test] +fn test_decode_u16() { + let cases: &[(&[u8], u16, u16)] = &[ + (&[0], 0, 0), + (&[10], 10, 10), + (&[U16_BYTE, 0, 10], 2560, 10), + ]; + for &(slice, expected_le, expected_be) in cases { + let mut reader = crate::de::read::SliceReader::new(slice); + let found = varint_decode_u16(&mut reader, Endianness::Little).unwrap(); + assert_eq!(expected_le, found); + + let mut reader = crate::de::read::SliceReader::new(slice); + let found = varint_decode_u16(&mut reader, Endianness::Big).unwrap(); + assert_eq!(expected_be, found); + } + + let errors: &[(&[u8], DecodeError)] = &[ + ( + &[U32_BYTE], + DecodeError::InvalidIntegerType { + expected: IntegerType::U16, + found: IntegerType::U32, + }, + ), + ( + &[U64_BYTE], + DecodeError::InvalidIntegerType { + expected: IntegerType::U16, + found: IntegerType::U64, + }, + ), + ( + &[U128_BYTE], + DecodeError::InvalidIntegerType { + expected: IntegerType::U16, + found: IntegerType::U128, + }, + ), + (&[U16_BYTE], DecodeError::UnexpectedEnd { additional: 2 }), + (&[U16_BYTE, 0], DecodeError::UnexpectedEnd { additional: 1 }), + ]; + + for (slice, expected) in errors { + let mut reader = crate::de::read::SliceReader::new(slice); + let found = varint_decode_u16(&mut reader, Endianness::Little).unwrap_err(); + assert_eq!(std::format!("{:?}", expected), std::format!("{:?}", found)); + } +} + +#[test] +fn test_decode_u32() { + let cases: &[(&[u8], u32, u32)] = &[ + (&[0], 0, 0), + (&[10], 10, 10), + (&[U16_BYTE, 0, 10], 2560, 10), + (&[U32_BYTE, 0, 0, 0, 10], 167_772_160, 10), + ]; + for &(slice, expected_le, expected_be) in cases { + let mut reader = crate::de::read::SliceReader::new(slice); + let found = varint_decode_u32(&mut reader, Endianness::Little).unwrap(); + assert_eq!(expected_le, found); + + let mut reader = crate::de::read::SliceReader::new(slice); + let found = varint_decode_u32(&mut reader, Endianness::Big).unwrap(); + assert_eq!(expected_be, found); + } + + let errors: &[(&[u8], DecodeError)] = &[ + ( + &[U64_BYTE], + DecodeError::InvalidIntegerType { + expected: IntegerType::U32, + found: IntegerType::U64, + }, + ), + ( + &[U128_BYTE], + DecodeError::InvalidIntegerType { + expected: IntegerType::U32, + found: IntegerType::U128, + }, + ), + (&[U16_BYTE], DecodeError::UnexpectedEnd { additional: 2 }), + (&[U16_BYTE, 0], DecodeError::UnexpectedEnd { additional: 1 }), + (&[U32_BYTE], DecodeError::UnexpectedEnd { additional: 4 }), + (&[U32_BYTE, 0], DecodeError::UnexpectedEnd { additional: 3 }), + ( + &[U32_BYTE, 0, 0], + DecodeError::UnexpectedEnd { additional: 2 }, + ), + ( + &[U32_BYTE, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 1 }, + ), + ]; + + for (slice, expected) in errors { + let mut reader = crate::de::read::SliceReader::new(slice); + let found = varint_decode_u32(&mut reader, Endianness::Little).unwrap_err(); + assert_eq!(std::format!("{:?}", expected), std::format!("{:?}", found)); + } +} + +#[test] +fn test_decode_u64() { + let cases: &[(&[u8], u64, u64)] = &[ + (&[0], 0, 0), + (&[10], 10, 10), + (&[U16_BYTE, 0, 10], 2560, 10), + (&[U32_BYTE, 0, 0, 0, 10], 167_772_160, 10), + ( + &[U64_BYTE, 0, 0, 0, 0, 0, 0, 0, 10], + 720_575_940_379_279_360, + 10, + ), + ]; + for &(slice, expected_le, expected_be) in cases { + let mut reader = crate::de::read::SliceReader::new(slice); + let found = varint_decode_u64(&mut reader, Endianness::Little).unwrap(); + assert_eq!(expected_le, found); + + let mut reader = crate::de::read::SliceReader::new(slice); + let found = varint_decode_u64(&mut reader, Endianness::Big).unwrap(); + assert_eq!(expected_be, found); + } + + let errors: &[(&[u8], DecodeError)] = &[ + ( + &[U128_BYTE], + DecodeError::InvalidIntegerType { + expected: IntegerType::U64, + found: IntegerType::U128, + }, + ), + (&[U16_BYTE], DecodeError::UnexpectedEnd { additional: 2 }), + (&[U16_BYTE, 0], DecodeError::UnexpectedEnd { additional: 1 }), + (&[U32_BYTE], DecodeError::UnexpectedEnd { additional: 4 }), + (&[U32_BYTE, 0], DecodeError::UnexpectedEnd { additional: 3 }), + ( + &[U32_BYTE, 0, 0], + DecodeError::UnexpectedEnd { additional: 2 }, + ), + ( + &[U32_BYTE, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 1 }, + ), + (&[U64_BYTE], DecodeError::UnexpectedEnd { additional: 8 }), + (&[U64_BYTE, 0], DecodeError::UnexpectedEnd { additional: 7 }), + ( + &[U64_BYTE, 0, 0], + DecodeError::UnexpectedEnd { additional: 6 }, + ), + ( + &[U64_BYTE, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 5 }, + ), + ( + &[U64_BYTE, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 4 }, + ), + ( + &[U64_BYTE, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 3 }, + ), + ( + &[U64_BYTE, 0, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 2 }, + ), + ( + &[U64_BYTE, 0, 0, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 1 }, + ), + ]; + + for (slice, expected) in errors { + let mut reader = crate::de::read::SliceReader::new(slice); + let found = varint_decode_u64(&mut reader, Endianness::Little).unwrap_err(); + assert_eq!(std::format!("{:?}", expected), std::format!("{:?}", found)); + } +} + +#[test] +fn test_decode_u128() { + let cases: &[(&[u8], u128, u128)] = &[ + (&[0], 0, 0), + (&[10], 10, 10), + (&[U16_BYTE, 0, 10], 2560, 10), + (&[U32_BYTE, 0, 0, 0, 10], 167_772_160, 10), + ( + &[U64_BYTE, 0, 0, 0, 0, 0, 0, 0, 10], + 720_575_940_379_279_360, + 10, + ), + ( + &[U128_BYTE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10], + 13_292_279_957_849_158_729_038_070_602_803_445_760, + 10, + ), + ]; + for &(slice, expected_le, expected_be) in cases { + let mut reader = crate::de::read::SliceReader::new(slice); + let found = varint_decode_u128(&mut reader, Endianness::Little).unwrap(); + assert_eq!(expected_le, found); + + let mut reader = crate::de::read::SliceReader::new(slice); + let found = varint_decode_u128(&mut reader, Endianness::Big).unwrap(); + assert_eq!(expected_be, found); + } + + let errors: &[(&[u8], DecodeError)] = &[ + (&[U16_BYTE], DecodeError::UnexpectedEnd { additional: 2 }), + (&[U16_BYTE, 0], DecodeError::UnexpectedEnd { additional: 1 }), + (&[U32_BYTE], DecodeError::UnexpectedEnd { additional: 4 }), + (&[U32_BYTE, 0], DecodeError::UnexpectedEnd { additional: 3 }), + ( + &[U32_BYTE, 0, 0], + DecodeError::UnexpectedEnd { additional: 2 }, + ), + ( + &[U32_BYTE, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 1 }, + ), + (&[U64_BYTE], DecodeError::UnexpectedEnd { additional: 8 }), + (&[U64_BYTE, 0], DecodeError::UnexpectedEnd { additional: 7 }), + ( + &[U64_BYTE, 0, 0], + DecodeError::UnexpectedEnd { additional: 6 }, + ), + ( + &[U64_BYTE, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 5 }, + ), + ( + &[U64_BYTE, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 4 }, + ), + ( + &[U64_BYTE, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 3 }, + ), + ( + &[U64_BYTE, 0, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 2 }, + ), + ( + &[U64_BYTE, 0, 0, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 1 }, + ), + (&[U128_BYTE], DecodeError::UnexpectedEnd { additional: 16 }), + ( + &[U128_BYTE, 0], + DecodeError::UnexpectedEnd { additional: 15 }, + ), + ( + &[U128_BYTE, 0, 0], + DecodeError::UnexpectedEnd { additional: 14 }, + ), + ( + &[U128_BYTE, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 13 }, + ), + ( + &[U128_BYTE, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 12 }, + ), + ( + &[U128_BYTE, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 11 }, + ), + ( + &[U128_BYTE, 0, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 10 }, + ), + ( + &[U128_BYTE, 0, 0, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 9 }, + ), + ( + &[U128_BYTE, 0, 0, 0, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 8 }, + ), + ( + &[U128_BYTE, 0, 0, 0, 0, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 7 }, + ), + ( + &[U128_BYTE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 6 }, + ), + ( + &[U128_BYTE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 5 }, + ), + ( + &[U128_BYTE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 4 }, + ), + ( + &[U128_BYTE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 3 }, + ), + ( + &[U128_BYTE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 2 }, + ), + ( + &[U128_BYTE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + DecodeError::UnexpectedEnd { additional: 1 }, + ), + ]; + + for (slice, expected) in errors { + let mut reader = crate::de::read::SliceReader::new(slice); + let found = varint_decode_u128(&mut reader, Endianness::Little).unwrap_err(); + std::dbg!(slice); + assert_eq!(std::format!("{:?}", expected), std::format!("{:?}", found)); + } +} diff --git a/vendor/bincode-2.0.1/src/varint/encode_signed.rs b/vendor/bincode-2.0.1/src/varint/encode_signed.rs new file mode 100644 index 0000000..01c54e4 --- /dev/null +++ b/vendor/bincode-2.0.1/src/varint/encode_signed.rs @@ -0,0 +1,318 @@ +use super::{varint_encode_u128, varint_encode_u16, varint_encode_u32, varint_encode_u64}; +use crate::{config::Endianness, enc::write::Writer, error::EncodeError}; + +pub fn varint_encode_i16( + writer: &mut W, + endian: Endianness, + val: i16, +) -> Result<(), EncodeError> { + varint_encode_u16( + writer, + endian, + if val < 0 { + // let's avoid the edge case of i16::min_value() + // !n is equal to `-n - 1`, so this is: + // !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1 + !(val as u16) * 2 + 1 + } else { + (val as u16) * 2 + }, + ) +} + +pub fn varint_encode_i32( + writer: &mut W, + endian: Endianness, + val: i32, +) -> Result<(), EncodeError> { + varint_encode_u32( + writer, + endian, + if val < 0 { + // let's avoid the edge case of i32::min_value() + // !n is equal to `-n - 1`, so this is: + // !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1 + !(val as u32) * 2 + 1 + } else { + (val as u32) * 2 + }, + ) +} + +pub fn varint_encode_i64( + writer: &mut W, + endian: Endianness, + val: i64, +) -> Result<(), EncodeError> { + varint_encode_u64( + writer, + endian, + if val < 0 { + // let's avoid the edge case of i64::min_value() + // !n is equal to `-n - 1`, so this is: + // !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1 + !(val as u64) * 2 + 1 + } else { + (val as u64) * 2 + }, + ) +} + +pub fn varint_encode_i128( + writer: &mut W, + endian: Endianness, + val: i128, +) -> Result<(), EncodeError> { + varint_encode_u128( + writer, + endian, + if val < 0 { + // let's avoid the edge case of i128::min_value() + // !n is equal to `-n - 1`, so this is: + // !n * 2 + 1 = 2(-n - 1) + 1 = -2n - 2 + 1 = -2n - 1 + !(val as u128) * 2 + 1 + } else { + (val as u128) * 2 + }, + ) +} + +pub fn varint_encode_isize( + writer: &mut W, + endian: Endianness, + val: isize, +) -> Result<(), EncodeError> { + // isize is being encoded as a i64 + varint_encode_i64(writer, endian, val as i64) +} + +#[test] +fn test_encode_i16() { + let cases: &[(i16, &[u8], &[u8])] = &[ + (0, &[0], &[0]), + (2, &[4], &[4]), + (256, &[super::U16_BYTE, 0, 2], &[super::U16_BYTE, 2, 0]), + ( + 16_000, + &[super::U16_BYTE, 0, 125], + &[super::U16_BYTE, 125, 0], + ), + ( + i16::MAX - 1, + &[super::U16_BYTE, 252, 255], + &[super::U16_BYTE, 255, 252], + ), + ( + i16::MAX, + &[super::U16_BYTE, 254, 255], + &[super::U16_BYTE, 255, 254], + ), + ]; + + use crate::enc::write::SliceWriter; + let mut buffer = [0u8; 20]; + for &(value, expected_le, expected_be) in cases { + std::dbg!(value); + + // Little endian + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_i16(&mut writer, Endianness::Little, value).unwrap(); + + assert_eq!(writer.bytes_written(), expected_le.len()); + assert_eq!(&buffer[..expected_le.len()], expected_le); + + // Big endian + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_i16(&mut writer, Endianness::Big, value).unwrap(); + + assert_eq!(writer.bytes_written(), expected_be.len()); + assert_eq!(&buffer[..expected_be.len()], expected_be); + } +} + +#[test] +fn test_encode_i32() { + let cases: &[(i32, &[u8], &[u8])] = &[ + (0, &[0], &[0]), + (2, &[4], &[4]), + (256, &[super::U16_BYTE, 0, 2], &[super::U16_BYTE, 2, 0]), + ( + 16_000, + &[super::U16_BYTE, 0, 125], + &[super::U16_BYTE, 125, 0], + ), + ( + 40_000, + &[super::U32_BYTE, 128, 56, 1, 0], + &[super::U32_BYTE, 0, 1, 56, 128], + ), + ( + i32::MAX - 1, + &[super::U32_BYTE, 252, 255, 255, 255], + &[super::U32_BYTE, 255, 255, 255, 252], + ), + ( + i32::MAX, + &[super::U32_BYTE, 254, 255, 255, 255], + &[super::U32_BYTE, 255, 255, 255, 254], + ), + ]; + + use crate::enc::write::SliceWriter; + let mut buffer = [0u8; 20]; + for &(value, expected_le, expected_be) in cases { + std::dbg!(value); + + // Little endian + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_i32(&mut writer, Endianness::Little, value).unwrap(); + + assert_eq!(writer.bytes_written(), expected_le.len()); + assert_eq!(&buffer[..expected_le.len()], expected_le); + + // Big endian + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_i32(&mut writer, Endianness::Big, value).unwrap(); + + assert_eq!(writer.bytes_written(), expected_be.len()); + assert_eq!(&buffer[..expected_be.len()], expected_be); + } +} + +#[test] +fn test_encode_i64() { + let cases: &[(i64, &[u8], &[u8])] = &[ + (0, &[0], &[0]), + (2, &[4], &[4]), + (256, &[super::U16_BYTE, 0, 2], &[super::U16_BYTE, 2, 0]), + ( + 16_000, + &[super::U16_BYTE, 0, 125], + &[super::U16_BYTE, 125, 0], + ), + ( + 40_000, + &[super::U32_BYTE, 128, 56, 1, 0], + &[super::U32_BYTE, 0, 1, 56, 128], + ), + ( + 3_000_000_000, + &[super::U64_BYTE, 0, 188, 160, 101, 1, 0, 0, 0], + &[super::U64_BYTE, 0, 0, 0, 1, 101, 160, 188, 0], + ), + ( + i64::MAX - 1, + &[super::U64_BYTE, 252, 255, 255, 255, 255, 255, 255, 255], + &[super::U64_BYTE, 255, 255, 255, 255, 255, 255, 255, 252], + ), + ( + i64::MAX, + &[super::U64_BYTE, 254, 255, 255, 255, 255, 255, 255, 255], + &[super::U64_BYTE, 255, 255, 255, 255, 255, 255, 255, 254], + ), + ]; + + use crate::enc::write::SliceWriter; + let mut buffer = [0u8; 20]; + for &(value, expected_le, expected_be) in cases { + std::dbg!(value); + + // Little endian + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_i64(&mut writer, Endianness::Little, value).unwrap(); + + assert_eq!(writer.bytes_written(), expected_le.len()); + assert_eq!(&buffer[..expected_le.len()], expected_le); + + // Big endian + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_i64(&mut writer, Endianness::Big, value).unwrap(); + + assert_eq!(writer.bytes_written(), expected_be.len()); + assert_eq!(&buffer[..expected_be.len()], expected_be); + } +} + +#[test] +fn test_encode_i128() { + #[rustfmt::skip] + let cases: &[(i128, &[u8], &[u8])] = &[ + (0, &[0], &[0]), + (2, &[4], &[4]), + (256, &[super::U16_BYTE, 0, 2], &[super::U16_BYTE, 2, 0]), + ( + 16_000, + &[super::U16_BYTE, 0, 125], + &[super::U16_BYTE, 125, 0], + ), + ( + 40_000, + &[super::U32_BYTE, 128, 56, 1, 0], + &[super::U32_BYTE, 0, 1, 56, 128], + ), + ( + 3_000_000_000, + &[super::U64_BYTE, 0, 188, 160, 101, 1, 0, 0, 0], + &[super::U64_BYTE, 0, 0, 0, 1, 101, 160, 188, 0], + ), + ( + 11_000_000_000_000_000_000, + &[ + super::U128_BYTE, + 0, 0, 152, 98, 112, 179, 79, 49, + 1, 0, 0, 0, 0, 0, 0, 0, + ], + &[ + super::U128_BYTE, + 0, 0, 0, 0, 0, 0, 0, 1, + 49, 79, 179, 112, 98, 152, 0, 0, + ], + ), + ( + i128::MAX - 1, + &[ + super::U128_BYTE, + 252, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + ], + &[ + super::U128_BYTE, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 252, + ], + ), + ( + i128::MAX, + &[ + super::U128_BYTE, + 254, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + ], + &[ + super::U128_BYTE, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 254, + ], + ), + ]; + + use crate::enc::write::SliceWriter; + let mut buffer = [0u8; 20]; + for &(value, expected_le, expected_be) in cases { + std::dbg!(value); + + // Little endian + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_i128(&mut writer, Endianness::Little, value).unwrap(); + + assert_eq!(writer.bytes_written(), expected_le.len()); + assert_eq!(&buffer[..expected_le.len()], expected_le); + + // Big endian + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_i128(&mut writer, Endianness::Big, value).unwrap(); + + assert_eq!(writer.bytes_written(), expected_be.len()); + assert_eq!(&buffer[..expected_be.len()], expected_be); + } +} diff --git a/vendor/bincode-2.0.1/src/varint/encode_unsigned.rs b/vendor/bincode-2.0.1/src/varint/encode_unsigned.rs new file mode 100644 index 0000000..8024472 --- /dev/null +++ b/vendor/bincode-2.0.1/src/varint/encode_unsigned.rs @@ -0,0 +1,383 @@ +use super::{SINGLE_BYTE_MAX, U128_BYTE, U16_BYTE, U32_BYTE, U64_BYTE}; +use crate::{config::Endianness, enc::write::Writer, error::EncodeError}; + +pub fn varint_encode_u16( + writer: &mut W, + endian: Endianness, + val: u16, +) -> Result<(), EncodeError> { + if val <= SINGLE_BYTE_MAX as _ { + writer.write(&[val as u8]) + } else { + writer.write(&[U16_BYTE])?; + match endian { + Endianness::Big => writer.write(&val.to_be_bytes()), + Endianness::Little => writer.write(&val.to_le_bytes()), + } + } +} + +pub fn varint_encode_u32( + writer: &mut W, + endian: Endianness, + val: u32, +) -> Result<(), EncodeError> { + if val <= SINGLE_BYTE_MAX as _ { + writer.write(&[val as u8]) + } else if val <= u16::MAX as _ { + writer.write(&[U16_BYTE])?; + match endian { + Endianness::Big => writer.write(&(val as u16).to_be_bytes()), + Endianness::Little => writer.write(&(val as u16).to_le_bytes()), + } + } else { + writer.write(&[U32_BYTE])?; + match endian { + Endianness::Big => writer.write(&val.to_be_bytes()), + Endianness::Little => writer.write(&val.to_le_bytes()), + } + } +} + +pub fn varint_encode_u64( + writer: &mut W, + endian: Endianness, + val: u64, +) -> Result<(), EncodeError> { + if val <= SINGLE_BYTE_MAX as _ { + writer.write(&[val as u8]) + } else if val <= u16::MAX as _ { + writer.write(&[U16_BYTE])?; + match endian { + Endianness::Big => writer.write(&(val as u16).to_be_bytes()), + Endianness::Little => writer.write(&(val as u16).to_le_bytes()), + } + } else if val <= u32::MAX as _ { + writer.write(&[U32_BYTE])?; + match endian { + Endianness::Big => writer.write(&(val as u32).to_be_bytes()), + Endianness::Little => writer.write(&(val as u32).to_le_bytes()), + } + } else { + writer.write(&[U64_BYTE])?; + match endian { + Endianness::Big => writer.write(&val.to_be_bytes()), + Endianness::Little => writer.write(&val.to_le_bytes()), + } + } +} + +pub fn varint_encode_u128( + writer: &mut W, + endian: Endianness, + val: u128, +) -> Result<(), EncodeError> { + if val <= SINGLE_BYTE_MAX as _ { + writer.write(&[val as u8]) + } else if val <= u16::MAX as _ { + writer.write(&[U16_BYTE])?; + match endian { + Endianness::Big => writer.write(&(val as u16).to_be_bytes()), + Endianness::Little => writer.write(&(val as u16).to_le_bytes()), + } + } else if val <= u32::MAX as _ { + writer.write(&[U32_BYTE])?; + match endian { + Endianness::Big => writer.write(&(val as u32).to_be_bytes()), + Endianness::Little => writer.write(&(val as u32).to_le_bytes()), + } + } else if val <= u64::MAX as _ { + writer.write(&[U64_BYTE])?; + match endian { + Endianness::Big => writer.write(&(val as u64).to_be_bytes()), + Endianness::Little => writer.write(&(val as u64).to_le_bytes()), + } + } else { + writer.write(&[U128_BYTE])?; + match endian { + Endianness::Big => writer.write(&val.to_be_bytes()), + Endianness::Little => writer.write(&val.to_le_bytes()), + } + } +} + +pub fn varint_encode_usize( + writer: &mut W, + endian: Endianness, + val: usize, +) -> Result<(), EncodeError> { + // usize is being encoded as a u64 + varint_encode_u64(writer, endian, val as u64) +} + +#[test] +fn test_encode_u16() { + use crate::enc::write::SliceWriter; + let mut buffer = [0u8; 20]; + + // these should all encode to a single byte + for i in 0u16..=SINGLE_BYTE_MAX as u16 { + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u16(&mut writer, Endianness::Big, i).unwrap(); + assert_eq!(writer.bytes_written(), 1); + assert_eq!(buffer[0] as u16, i); + + // Assert endianness doesn't matter + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u16(&mut writer, Endianness::Little, i).unwrap(); + assert_eq!(writer.bytes_written(), 1); + assert_eq!(buffer[0] as u16, i); + } + + // these values should encode in 3 bytes (leading byte + 2 bytes) + // Values chosen at random, add new cases as needed + for i in [ + SINGLE_BYTE_MAX as u16 + 1, + 300, + 500, + 700, + 888, + 1234, + u16::MAX, + ] { + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u16(&mut writer, Endianness::Big, i).unwrap(); + assert_eq!(writer.bytes_written(), 3); + assert_eq!(buffer[0], U16_BYTE); + assert_eq!(&buffer[1..3], &i.to_be_bytes()); + + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u16(&mut writer, Endianness::Little, i).unwrap(); + assert_eq!(writer.bytes_written(), 3); + assert_eq!(buffer[0], U16_BYTE); + assert_eq!(&buffer[1..3], &i.to_le_bytes()); + } +} + +#[test] +fn test_encode_u32() { + use crate::enc::write::SliceWriter; + let mut buffer = [0u8; 20]; + + // these should all encode to a single byte + for i in 0u32..=SINGLE_BYTE_MAX as u32 { + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u32(&mut writer, Endianness::Big, i).unwrap(); + assert_eq!(writer.bytes_written(), 1); + assert_eq!(buffer[0] as u32, i); + + // Assert endianness doesn't matter + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u32(&mut writer, Endianness::Little, i).unwrap(); + assert_eq!(writer.bytes_written(), 1); + assert_eq!(buffer[0] as u32, i); + } + + // these values should encode in 3 bytes (leading byte + 2 bytes) + // Values chosen at random, add new cases as needed + for i in [ + SINGLE_BYTE_MAX as u32 + 1, + 300, + 500, + 700, + 888, + 1234, + u16::MAX as u32, + ] { + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u32(&mut writer, Endianness::Big, i).unwrap(); + assert_eq!(writer.bytes_written(), 3); + assert_eq!(buffer[0], U16_BYTE); + assert_eq!(&buffer[1..3], &(i as u16).to_be_bytes()); + + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u32(&mut writer, Endianness::Little, i).unwrap(); + assert_eq!(writer.bytes_written(), 3); + assert_eq!(buffer[0], U16_BYTE); + assert_eq!(&buffer[1..3], &(i as u16).to_le_bytes()); + } + + // these values should encode in 5 bytes (leading byte + 4 bytes) + // Values chosen at random, add new cases as needed + for i in [u16::MAX as u32 + 1, 100_000, 1_000_000, u32::MAX] { + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u32(&mut writer, Endianness::Big, i).unwrap(); + assert_eq!(writer.bytes_written(), 5); + assert_eq!(buffer[0], U32_BYTE); + assert_eq!(&buffer[1..5], &i.to_be_bytes()); + + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u32(&mut writer, Endianness::Little, i).unwrap(); + assert_eq!(writer.bytes_written(), 5); + assert_eq!(buffer[0], U32_BYTE); + assert_eq!(&buffer[1..5], &i.to_le_bytes()); + } +} + +#[test] +fn test_encode_u64() { + use crate::enc::write::SliceWriter; + let mut buffer = [0u8; 20]; + + // these should all encode to a single byte + for i in 0u64..=SINGLE_BYTE_MAX as u64 { + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u64(&mut writer, Endianness::Big, i).unwrap(); + assert_eq!(writer.bytes_written(), 1); + assert_eq!(buffer[0] as u64, i); + + // Assert endianness doesn't matter + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u64(&mut writer, Endianness::Little, i).unwrap(); + assert_eq!(writer.bytes_written(), 1); + assert_eq!(buffer[0] as u64, i); + } + + // these values should encode in 3 bytes (leading byte + 2 bytes) + // Values chosen at random, add new cases as needed + for i in [ + SINGLE_BYTE_MAX as u64 + 1, + 300, + 500, + 700, + 888, + 1234, + u16::MAX as u64, + ] { + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u64(&mut writer, Endianness::Big, i).unwrap(); + assert_eq!(writer.bytes_written(), 3); + assert_eq!(buffer[0], U16_BYTE); + assert_eq!(&buffer[1..3], &(i as u16).to_be_bytes()); + + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u64(&mut writer, Endianness::Little, i).unwrap(); + assert_eq!(writer.bytes_written(), 3); + assert_eq!(buffer[0], U16_BYTE); + assert_eq!(&buffer[1..3], &(i as u16).to_le_bytes()); + } + + // these values should encode in 5 bytes (leading byte + 4 bytes) + // Values chosen at random, add new cases as needed + for i in [u16::MAX as u64 + 1, 100_000, 1_000_000, u32::MAX as u64] { + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u64(&mut writer, Endianness::Big, i).unwrap(); + assert_eq!(writer.bytes_written(), 5); + assert_eq!(buffer[0], U32_BYTE); + assert_eq!(&buffer[1..5], &(i as u32).to_be_bytes()); + + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u64(&mut writer, Endianness::Little, i).unwrap(); + assert_eq!(writer.bytes_written(), 5); + assert_eq!(buffer[0], U32_BYTE); + assert_eq!(&buffer[1..5], &(i as u32).to_le_bytes()); + } + + // these values should encode in 9 bytes (leading byte + 8 bytes) + // Values chosen at random, add new cases as needed + for i in [u32::MAX as u64 + 1, 5_000_000_000, u64::MAX] { + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u64(&mut writer, Endianness::Big, i).unwrap(); + assert_eq!(writer.bytes_written(), 9); + assert_eq!(buffer[0], U64_BYTE); + assert_eq!(&buffer[1..9], &i.to_be_bytes()); + + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u64(&mut writer, Endianness::Little, i).unwrap(); + assert_eq!(writer.bytes_written(), 9); + assert_eq!(buffer[0], U64_BYTE); + assert_eq!(&buffer[1..9], &i.to_le_bytes()); + } +} + +#[test] +fn test_encode_u128() { + use crate::enc::write::SliceWriter; + let mut buffer = [0u8; 20]; + + // these should all encode to a single byte + for i in 0u128..=SINGLE_BYTE_MAX as u128 { + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u128(&mut writer, Endianness::Big, i).unwrap(); + assert_eq!(writer.bytes_written(), 1); + assert_eq!(buffer[0] as u128, i); + + // Assert endianness doesn't matter + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u128(&mut writer, Endianness::Little, i).unwrap(); + assert_eq!(writer.bytes_written(), 1); + assert_eq!(buffer[0] as u128, i); + } + + // these values should encode in 3 bytes (leading byte + 2 bytes) + // Values chosen at random, add new cases as needed + for i in [ + SINGLE_BYTE_MAX as u128 + 1, + 300, + 500, + 700, + 888, + 1234, + u16::MAX as u128, + ] { + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u128(&mut writer, Endianness::Big, i).unwrap(); + assert_eq!(writer.bytes_written(), 3); + assert_eq!(buffer[0], U16_BYTE); + assert_eq!(&buffer[1..3], &(i as u16).to_be_bytes()); + + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u128(&mut writer, Endianness::Little, i).unwrap(); + assert_eq!(writer.bytes_written(), 3); + assert_eq!(buffer[0], U16_BYTE); + assert_eq!(&buffer[1..3], &(i as u16).to_le_bytes()); + } + + // these values should encode in 5 bytes (leading byte + 4 bytes) + // Values chosen at random, add new cases as needed + for i in [u16::MAX as u128 + 1, 100_000, 1_000_000, u32::MAX as u128] { + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u128(&mut writer, Endianness::Big, i).unwrap(); + assert_eq!(writer.bytes_written(), 5); + assert_eq!(buffer[0], U32_BYTE); + assert_eq!(&buffer[1..5], &(i as u32).to_be_bytes()); + + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u128(&mut writer, Endianness::Little, i).unwrap(); + assert_eq!(writer.bytes_written(), 5); + assert_eq!(buffer[0], U32_BYTE); + assert_eq!(&buffer[1..5], &(i as u32).to_le_bytes()); + } + + // these values should encode in 9 bytes (leading byte + 8 bytes) + // Values chosen at random, add new cases as needed + for i in [u32::MAX as u128 + 1, 5_000_000_000, u64::MAX as u128] { + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u128(&mut writer, Endianness::Big, i).unwrap(); + assert_eq!(writer.bytes_written(), 9); + assert_eq!(buffer[0], U64_BYTE); + assert_eq!(&buffer[1..9], &(i as u64).to_be_bytes()); + + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u128(&mut writer, Endianness::Little, i).unwrap(); + assert_eq!(writer.bytes_written(), 9); + assert_eq!(buffer[0], U64_BYTE); + assert_eq!(&buffer[1..9], &(i as u64).to_le_bytes()); + } + + // these values should encode in 17 bytes (leading byte + 16 bytes) + // Values chosen at random, add new cases as needed + for i in [u64::MAX as u128 + 1, u128::MAX] { + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u128(&mut writer, Endianness::Big, i).unwrap(); + assert_eq!(writer.bytes_written(), 17); + assert_eq!(buffer[0], U128_BYTE); + assert_eq!(&buffer[1..17], &i.to_be_bytes()); + + let mut writer = SliceWriter::new(&mut buffer); + varint_encode_u128(&mut writer, Endianness::Little, i).unwrap(); + assert_eq!(writer.bytes_written(), 17); + assert_eq!(buffer[0], U128_BYTE); + assert_eq!(&buffer[1..17], &i.to_le_bytes()); + } +} diff --git a/vendor/bincode-2.0.1/src/varint/mod.rs b/vendor/bincode-2.0.1/src/varint/mod.rs new file mode 100644 index 0000000..63cc578 --- /dev/null +++ b/vendor/bincode-2.0.1/src/varint/mod.rs @@ -0,0 +1,29 @@ +mod decode_signed; +mod decode_unsigned; +mod encode_signed; +mod encode_unsigned; + +pub use self::{ + decode_signed::{ + varint_decode_i128, varint_decode_i16, varint_decode_i32, varint_decode_i64, + varint_decode_isize, + }, + decode_unsigned::{ + varint_decode_u128, varint_decode_u16, varint_decode_u32, varint_decode_u64, + varint_decode_usize, + }, + encode_signed::{ + varint_encode_i128, varint_encode_i16, varint_encode_i32, varint_encode_i64, + varint_encode_isize, + }, + encode_unsigned::{ + varint_encode_u128, varint_encode_u16, varint_encode_u32, varint_encode_u64, + varint_encode_usize, + }, +}; + +const SINGLE_BYTE_MAX: u8 = 250; +const U16_BYTE: u8 = 251; +const U32_BYTE: u8 = 252; +const U64_BYTE: u8 = 253; +const U128_BYTE: u8 = 254; diff --git a/vendor/bincode-2.0.1/tests/alloc.rs b/vendor/bincode-2.0.1/tests/alloc.rs new file mode 100644 index 0000000..f5bc75e --- /dev/null +++ b/vendor/bincode-2.0.1/tests/alloc.rs @@ -0,0 +1,197 @@ +#![allow(clippy::disallowed_names)] +#![cfg(feature = "alloc")] + +extern crate alloc; + +mod utils; + +use alloc::borrow::Cow; +use alloc::collections::*; +#[cfg(not(feature = "serde"))] +use alloc::rc::Rc; +#[cfg(all(target_has_atomic = "ptr", not(feature = "serde")))] +use alloc::sync::Arc; +use utils::{the_same, the_same_with_comparer}; + +struct Foo { + pub a: u32, + pub b: u32, +} + +impl bincode::Encode for Foo { + fn encode( + &self, + encoder: &mut E, + ) -> Result<(), bincode::error::EncodeError> { + self.a.encode(encoder)?; + self.b.encode(encoder)?; + Ok(()) + } +} + +impl bincode::Decode for Foo { + fn decode( + decoder: &mut D, + ) -> Result { + Ok(Self { + a: bincode::Decode::decode(decoder)?, + b: bincode::Decode::decode(decoder)?, + }) + } +} +bincode::impl_borrow_decode!(Foo); + +#[test] +fn test_vec() { + let vec = bincode::encode_to_vec(Foo { a: 5, b: 10 }, bincode::config::standard()).unwrap(); + assert_eq!(vec, &[5, 10]); + + let (foo, len): (Foo, usize) = + bincode::decode_from_slice(&vec, bincode::config::standard()).unwrap(); + assert_eq!(foo.a, 5); + assert_eq!(foo.b, 10); + assert_eq!(len, 2); + + let vec: Vec = bincode::decode_from_slice( + &[4, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4], + bincode::config::legacy(), + ) + .unwrap() + .0; + assert_eq!(vec, &[1, 2, 3, 4]); + + let vec: Vec> = bincode::decode_from_slice( + &[4, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4], + bincode::config::legacy(), + ) + .unwrap() + .0; + assert_eq!( + vec, + &[ + Cow::Borrowed(&1), + Cow::Borrowed(&2), + Cow::Borrowed(&3), + Cow::Borrowed(&4) + ] + ); +} + +#[test] +fn test_alloc_commons() { + the_same::>(vec![1, 2, 3, 4, 5]); + the_same(String::from("Hello world")); + the_same(Box::::new(5)); + the_same(Box::<[u32]>::from(vec![1, 2, 3, 4, 5])); + the_same(Cow::::Owned(5)); + the_same(Cow::::Borrowed(&5)); + #[cfg(not(feature = "serde"))] + { + // Serde doesn't support Rc or Arc + the_same(Rc::::new(5)); + the_same(Rc::<[u32]>::from(vec![1, 2, 3, 4, 5])); + + #[cfg(target_has_atomic = "ptr")] + { + the_same(Arc::::new(5)); + the_same(Arc::<[u32]>::from(vec![1, 2, 3, 4, 5])); + } + } + + the_same_with_comparer( + { + let mut map = BinaryHeap::::new(); + map.push(1); + map.push(2); + map.push(3); + map.push(4); + map.push(5); + map + }, + |a, b| a.iter().collect::>() == b.iter().collect::>(), + ); + the_same({ + let mut map = BTreeMap::::new(); + map.insert(5, -5); + map + }); + the_same({ + let mut set = BTreeSet::::new(); + set.insert(5); + set + }); + the_same({ + let mut set = VecDeque::::new(); + set.push_back(15); + set.push_front(5); + set + }); +} + +#[test] +fn test_container_limits() { + use bincode::{error::DecodeError, BorrowDecode, Decode}; + + const DECODE_LIMIT: usize = 100_000; + + // for this test we'll create a malformed package of a lot of bytes + let test_cases = &[ + // u64::max_value(), should overflow + #[cfg(target_pointer_width = "64")] + bincode::encode_to_vec(u64::MAX, bincode::config::standard()).unwrap(), + #[cfg(target_pointer_width = "32")] + bincode::encode_to_vec(u32::MAX, bincode::config::standard()).unwrap(), + // A high value which doesn't overflow, but exceeds the decode limit + bincode::encode_to_vec(DECODE_LIMIT as u64, bincode::config::standard()).unwrap(), + ]; + + fn validate_fail + for<'de> BorrowDecode<'de, ()> + core::fmt::Debug>( + slice: &[u8], + ) { + let result = bincode::decode_from_slice::( + slice, + bincode::config::standard().with_limit::(), + ); + + let name = core::any::type_name::(); + match result { + Ok(_) => panic!("Decoding {} should fail, it instead succeeded", name), + Err(DecodeError::OutsideUsizeRange(_)) if cfg!(target_pointer_width = "32") => {}, + Err(DecodeError::LimitExceeded) => {}, + Err(e) => panic!("Expected OutsideUsizeRange (on 32 bit platforms) or LimitExceeded whilst decoding {}, got {:?}", name, e), + } + } + + for slice in test_cases { + validate_fail::>(slice); + validate_fail::>(slice); + validate_fail::>(slice); + validate_fail::>(slice); + validate_fail::>(slice); + validate_fail::(slice); + #[cfg(feature = "std")] + { + validate_fail::>(slice); + validate_fail::>(slice); + } + } +} + +#[cfg(target_has_atomic = "ptr")] +#[test] +fn test_arc_str() { + use alloc::sync::Arc; + + let start: Arc = Arc::from("Example String"); + let mut target = [0u8; 100]; + let config = bincode::config::standard(); + + let len = { + let start: Arc = Arc::clone(&start); + bincode::encode_into_slice(start, &mut target, config).unwrap() + }; + let slice = &target[..len]; + + let decoded: Arc = bincode::borrow_decode_from_slice(slice, config).unwrap().0; + assert_eq!(decoded, start); +} diff --git a/vendor/bincode-2.0.1/tests/atomic.rs b/vendor/bincode-2.0.1/tests/atomic.rs new file mode 100644 index 0000000..136d3fd --- /dev/null +++ b/vendor/bincode-2.0.1/tests/atomic.rs @@ -0,0 +1,66 @@ +mod utils; + +use core::sync::atomic::Ordering; +#[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 = "ptr")] +use core::sync::atomic::{AtomicIsize, AtomicUsize}; +use utils::the_same_with_comparer; + +#[test] +fn test_atomic_commons() { + #[cfg(target_has_atomic = "8")] + the_same_with_comparer(AtomicBool::new(true), |a, b| { + a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst) + }); + #[cfg(target_has_atomic = "8")] + the_same_with_comparer(AtomicBool::new(false), |a, b| { + a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst) + }); + #[cfg(target_has_atomic = "8")] + the_same_with_comparer(AtomicU8::new(0), |a, b| { + a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst) + }); + #[cfg(target_has_atomic = "16")] + the_same_with_comparer(AtomicU16::new(0), |a, b| { + a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst) + }); + #[cfg(target_has_atomic = "32")] + the_same_with_comparer(AtomicU32::new(0), |a, b| { + a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst) + }); + #[cfg(target_has_atomic = "64")] + the_same_with_comparer(AtomicU64::new(0), |a, b| { + a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst) + }); + #[cfg(target_has_atomic = "ptr")] + the_same_with_comparer(AtomicUsize::new(0), |a, b| { + a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst) + }); + #[cfg(target_has_atomic = "8")] + the_same_with_comparer(AtomicI8::new(0), |a, b| { + a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst) + }); + #[cfg(target_has_atomic = "16")] + the_same_with_comparer(AtomicI16::new(0), |a, b| { + a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst) + }); + #[cfg(target_has_atomic = "32")] + the_same_with_comparer(AtomicI32::new(0), |a, b| { + a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst) + }); + #[cfg(target_has_atomic = "64")] + the_same_with_comparer(AtomicI64::new(0), |a, b| { + a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst) + }); + #[cfg(target_has_atomic = "ptr")] + the_same_with_comparer(AtomicIsize::new(0), |a, b| { + a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst) + }); +} diff --git a/vendor/bincode-2.0.1/tests/basic_types.rs b/vendor/bincode-2.0.1/tests/basic_types.rs new file mode 100644 index 0000000..0aae093 --- /dev/null +++ b/vendor/bincode-2.0.1/tests/basic_types.rs @@ -0,0 +1,310 @@ +mod utils; + +use bincode::error::DecodeError; +use core::cell::{Cell, RefCell}; +use core::cmp::Reverse; +use core::ops::Bound; +use core::time::Duration; +use std::num::*; +use utils::{the_same, the_same_with_comparer}; + +#[test] +fn test_numbers() { + // integer types + the_same(5u8); + the_same(5u16); + the_same(5u32); + the_same(5u64); + the_same(5u128); + the_same(5usize); + + the_same(5i8); + the_same(5i16); + the_same(5i32); + the_same(5i64); + the_same(5i128); + the_same(5isize); + + println!("Test {:?}", 5.0f32); + the_same_with_comparer(5.0f32, |a, b| (a - b).abs() <= f32::EPSILON); + the_same_with_comparer(5.0f64, |a, b| (a - b).abs() <= f64::EPSILON); + + // bool + the_same(true); + the_same(false); + + // utf8 characters + for char in "aÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö文😀😁😂😃".chars() + { + the_same(char); + } + + // tuples, up to 8 + the_same((1u8,)); + the_same((1u8, 2u8)); + the_same((1u8, 2u8, 3u8)); + the_same((1u8, 2u8, 3u8, 4u8)); + the_same((1u8, 2u8, 3u8, 4u8, 5u8)); + the_same((1u8, 2u8, 3u8, 4u8, 5u8, 6u8)); + the_same((1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8)); + the_same((1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8)); + + // arrays + #[rustfmt::skip] + #[cfg(not(feature = "serde"))] // serde doesn't support arrays this big + the_same([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, + 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, + 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 + ]); + + // Common types + the_same(Option::::None); + the_same(Option::::Some(1234)); + + the_same(Result::::Ok(1555)); + the_same(Result::::Err(15)); + + the_same(Cell::::new(15)); + the_same(RefCell::::new(15)); + + the_same(Duration::new(5, 730023852)); + the_same(5u8..10u8); + the_same(5u8..=10u8); + the_same(Bound::::Unbounded); + the_same(Bound::::Included(105)); + the_same(Bound::::Excluded(5)); + + // NonZero* types + the_same(NonZeroU8::new(0)); + the_same(NonZeroU8::new(123)); + the_same(NonZeroU16::new(0)); + the_same(NonZeroU16::new(12345)); + the_same(NonZeroU32::new(0)); + the_same(NonZeroU32::new(12345)); + the_same(NonZeroU64::new(0)); + the_same(NonZeroU64::new(12345)); + the_same(NonZeroU128::new(0)); + the_same(NonZeroU128::new(12345)); + the_same(NonZeroUsize::new(0)); + the_same(NonZeroUsize::new(12345)); + + the_same(NonZeroI8::new(0)); + the_same(NonZeroI8::new(123)); + the_same(NonZeroI16::new(0)); + the_same(NonZeroI16::new(12345)); + the_same(NonZeroI32::new(0)); + the_same(NonZeroI32::new(12345)); + the_same(NonZeroI64::new(0)); + the_same(NonZeroI64::new(12345)); + the_same(NonZeroI128::new(0)); + the_same(NonZeroI128::new(12345)); + the_same(NonZeroIsize::new(0)); + the_same(NonZeroIsize::new(12345)); + + // Wrapping types + the_same(Wrapping(5u8)); + the_same(Wrapping(5u16)); + the_same(Wrapping(5u32)); + the_same(Wrapping(5u64)); + the_same(Wrapping(5u128)); + the_same(Wrapping(5usize)); + + the_same(Wrapping(5i8)); + the_same(Wrapping(5i16)); + the_same(Wrapping(5i32)); + the_same(Wrapping(5i64)); + the_same(Wrapping(5i128)); + the_same(Wrapping(5isize)); + + // Reverse types + the_same(Reverse(5u8)); + the_same(Reverse(5u16)); + the_same(Reverse(5u32)); + the_same(Reverse(5u64)); + the_same(Reverse(5u128)); + the_same(Reverse(5usize)); + + the_same(Reverse(5i8)); + the_same(Reverse(5i16)); + the_same(Reverse(5i32)); + the_same(Reverse(5i64)); + the_same(Reverse(5i128)); + the_same(Reverse(5isize)); +} + +#[test] +fn test_refcell_already_borrowed() { + let cell = RefCell::new(5u32); + // first get a mutable reference to the cell + let _mutable_guard = cell.borrow_mut(); + // now try to encode it + let mut slice = [0u8; 10]; + let result = bincode::encode_into_slice(&cell, &mut slice, bincode::config::standard()) + .expect_err("Encoding a borrowed refcell should fail"); + + match result { + bincode::error::EncodeError::RefCellAlreadyBorrowed { .. } => {} // ok + x => panic!("Expected a RefCellAlreadyBorrowed error, found {:?}", x), + } +} + +#[test] +fn test_slice() { + let mut buffer = [0u8; 32]; + let input: &[u8] = &[1, 2, 3, 4, 5, 6, 7]; + bincode::encode_into_slice(input, &mut buffer, bincode::config::standard()).unwrap(); + assert_eq!(&buffer[..8], &[7, 1, 2, 3, 4, 5, 6, 7]); + + let (output, len): (&[u8], usize) = + bincode::borrow_decode_from_slice(&buffer[..8], bincode::config::standard()).unwrap(); + assert_eq!(input, output); + assert_eq!(len, 8); +} + +#[test] +fn test_option_slice() { + let mut buffer = [0u8; 32]; + let input: Option<&[u8]> = Some(&[1, 2, 3, 4, 5, 6, 7]); + let n = bincode::encode_into_slice(input, &mut buffer, bincode::config::standard()).unwrap(); + assert_eq!(&buffer[..n], &[1, 7, 1, 2, 3, 4, 5, 6, 7]); + + let (output, len): (Option<&[u8]>, usize) = + bincode::borrow_decode_from_slice(&buffer[..n], bincode::config::standard()).unwrap(); + assert_eq!(input, output); + assert_eq!(len, n); + + let mut buffer = [0u8; 32]; + let input: Option<&[u8]> = None; + let n = bincode::encode_into_slice(input, &mut buffer, bincode::config::standard()).unwrap(); + assert_eq!(&buffer[..n], &[0]); + + let (output, len): (Option<&[u8]>, usize) = + bincode::borrow_decode_from_slice(&buffer[..n], bincode::config::standard()).unwrap(); + assert_eq!(input, output); + assert_eq!(len, n); +} + +#[test] +fn test_str() { + let mut buffer = [0u8; 32]; + let input: &str = "Hello world"; + bincode::encode_into_slice(input, &mut buffer, bincode::config::standard()).unwrap(); + assert_eq!( + &buffer[..12], + &[11, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100] + ); + + let (output, len): (&str, usize) = + bincode::borrow_decode_from_slice(&buffer[..12], bincode::config::standard()).unwrap(); + assert_eq!(input, output); + assert_eq!(len, 12); +} + +#[test] +fn test_option_str() { + let mut buffer = [0u8; 32]; + let input: Option<&str> = Some("Hello world"); + let n = bincode::encode_into_slice(input, &mut buffer, bincode::config::standard()).unwrap(); + assert_eq!( + &buffer[..n], + &[1, 11, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100] + ); + + let (output, len): (Option<&str>, usize) = + bincode::borrow_decode_from_slice(&buffer[..n], bincode::config::standard()).unwrap(); + assert_eq!(input, output); + assert_eq!(len, n); + + let mut buffer = [0u8; 32]; + let input: Option<&str> = None; + let n = bincode::encode_into_slice(input, &mut buffer, bincode::config::standard()).unwrap(); + assert_eq!(&buffer[..n], &[0]); + + let (output, len): (Option<&str>, usize) = + bincode::borrow_decode_from_slice(&buffer[..n], bincode::config::standard()).unwrap(); + assert_eq!(input, output); + assert_eq!(len, n); +} + +#[test] +fn test_array() { + let mut buffer = [0u8; 32]; + let input: [u8; 10] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]; + bincode::encode_into_slice(input, &mut buffer, bincode::config::standard()).unwrap(); + assert_eq!(&buffer[..10], &[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]); + + let (output, len): ([u8; 10], usize) = + bincode::decode_from_slice(&buffer[..11], bincode::config::standard()).unwrap(); + assert_eq!(input, output); + assert_eq!(len, 10); + + let mut buffer = [0u8; 32]; + let input: [u8; 1] = [1]; + let config = bincode::config::standard() + .with_fixed_int_encoding() + .with_little_endian(); + let len = bincode::encode_into_slice(input, &mut buffer, config).unwrap(); + assert_eq!(len, 1); + assert_eq!(&buffer[..1], &[1]); + + let (output, len): ([u8; 1], usize) = bincode::decode_from_slice(&buffer[..9], config).unwrap(); + assert_eq!(len, 1); + assert_eq!(input, output); +} + +#[test] +fn test_duration_out_of_range() { + let mut input = [0u8; 14]; + + bincode::encode_into_slice( + (u64::MAX, u32::MAX), + &mut input, + bincode::config::standard(), + ) + .unwrap(); + + let result: Result<(std::time::Duration, usize), _> = + bincode::decode_from_slice(&input, bincode::config::standard()); + + match result { + Err(DecodeError::InvalidDuration { + secs: u64::MAX, + nanos: u32::MAX, + }) => {} + Err(e) => panic!("Expected InvalidDuration, got {:?}", e), + Ok(_) => panic!("Expected the decode to fail"), + } +} + +#[test] +fn test_duration_wrapping() { + let mut input = [0u8; 14]; + + bincode::encode_into_slice( + (u64::MAX - 4, u32::MAX), + &mut input, + bincode::config::standard(), + ) + .unwrap(); + + let (result, _): (std::time::Duration, _) = + bincode::decode_from_slice(&input, bincode::config::standard()).unwrap(); + + assert_eq!(result.as_secs(), u64::MAX); + + assert_eq!(result.subsec_nanos(), 294967295); +} diff --git a/vendor/bincode-2.0.1/tests/context.rs b/vendor/bincode-2.0.1/tests/context.rs new file mode 100644 index 0000000..5c85147 --- /dev/null +++ b/vendor/bincode-2.0.1/tests/context.rs @@ -0,0 +1,105 @@ +#![cfg(all(feature = "alloc", feature = "derive"))] + +use bincode::{ + config, de::BorrowDecoder, decode_from_slice, decode_from_slice_with_context, encode_to_vec, + error::DecodeError, BorrowDecode, Decode, Encode, +}; +use bumpalo::{collections::Vec, vec, Bump}; + +#[derive(PartialEq, Eq, Debug)] +struct CodableVec<'bump, T: 'bump>(Vec<'bump, T>); + +impl<'bump, T: Encode> Encode for CodableVec<'bump, T> { + fn encode( + &self, + encoder: &mut E, + ) -> Result<(), bincode::error::EncodeError> { + self.0.as_slice().encode(encoder) + } +} + +impl<'bump, T: Decode<&'bump Bump>> Decode<&'bump Bump> for CodableVec<'bump, T> { + fn decode>( + decoder: &mut D, + ) -> Result { + let len = u64::decode(decoder)?; + let len = usize::try_from(len).map_err(|_| DecodeError::OutsideUsizeRange(len))?; + decoder.claim_container_read::(len)?; + let mut vec = Vec::with_capacity_in(len, decoder.context()); + for _ in 0..len { + decoder.unclaim_bytes_read(core::mem::size_of::()); + vec.push(T::decode(decoder)?); + } + Ok(Self(vec)) + } +} + +impl<'de, 'bump, T: BorrowDecode<'de, &'bump Bump>> BorrowDecode<'de, &'bump Bump> + for CodableVec<'bump, T> +{ + fn borrow_decode>( + decoder: &mut D, + ) -> Result { + let len = u64::decode(decoder)?; + let len = usize::try_from(len).map_err(|_| DecodeError::OutsideUsizeRange(len))?; + + decoder.claim_container_read::(len)?; + + let mut vec = Vec::with_capacity_in(len, decoder.context()); + for _ in 0..len { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::()); + + vec.push(T::borrow_decode(decoder)?); + } + Ok(Self(vec)) + } +} + +#[derive(Encode, Decode, PartialEq, Eq, Debug)] +#[bincode(decode_context = "&'bump Bump")] +struct Container<'bump> { + vec: CodableVec<'bump, u32>, +} + +#[derive(Encode, Decode, PartialEq, Eq, Debug)] +#[bincode(decode_context = "&'bump Bump")] +enum _EnumContainer<'bump> { + Vec(CodableVec<'bump, u32>), +} + +#[ouroboros::self_referencing] +struct SelfReferencing { + bump: Bump, + #[borrows(bump)] + #[not_covariant] + container: Container<'this>, +} + +impl Decode for SelfReferencing { + fn decode>( + decoder: &mut D, + ) -> Result { + SelfReferencing::try_new(Bump::new(), |bump| { + Container::decode(&mut decoder.with_context(bump)) + }) + } +} + +#[test] +fn decode_with_context() { + let config = config::standard(); + let bump = Bump::new(); + let container = Container { + vec: CodableVec(vec![in ≎ 1, 2, 3]), + }; + + let bytes = encode_to_vec(&container, config).unwrap(); + let (decoded_container, _) = + decode_from_slice_with_context::<_, Container, _>(&bytes, config, &bump).unwrap(); + + assert_eq!(container, decoded_container); + + let self_referencing: SelfReferencing = decode_from_slice(&bytes, config).unwrap().0; + self_referencing.with_container(|c| assert_eq!(&container, c)) +} diff --git a/vendor/bincode-2.0.1/tests/derive.rs b/vendor/bincode-2.0.1/tests/derive.rs new file mode 100644 index 0000000..c059c96 --- /dev/null +++ b/vendor/bincode-2.0.1/tests/derive.rs @@ -0,0 +1,467 @@ +#![cfg(feature = "derive")] + +use bincode::error::DecodeError; + +#[derive(bincode::Encode, PartialEq, Debug)] +pub(crate) struct Test { + a: T, + b: u32, + c: u8, +} + +#[test] +fn test_encode() { + let start = Test { + a: 5i32, + b: 10u32, + c: 20u8, + }; + let mut slice = [0u8; 1024]; + let bytes_written = + bincode::encode_into_slice(start, &mut slice, bincode::config::standard()).unwrap(); + assert_eq!(bytes_written, 3); + assert_eq!(&slice[..bytes_written], &[10, 10, 20]); +} +#[derive(PartialEq, Debug, Eq)] +pub struct Test2 { + a: T, + b: u32, + c: u32, +} +impl ::bincode::Decode for Test2 +where + T: ::bincode::Decode, +{ + fn decode>( + decoder: &mut D, + ) -> core::result::Result { + Ok(Self { + a: ::bincode::Decode::decode(decoder)?, + b: ::bincode::Decode::decode(decoder)?, + c: ::bincode::Decode::decode(decoder)?, + }) + } +} +impl<'__de, T, Context> ::bincode::BorrowDecode<'__de, Context> for Test2 +where + T: ::bincode::BorrowDecode<'__de, Context> + '__de, +{ + fn borrow_decode>( + decoder: &mut D, + ) -> core::result::Result { + Ok(Self { + a: ::bincode::BorrowDecode::borrow_decode(decoder)?, + b: ::bincode::BorrowDecode::borrow_decode(decoder)?, + c: ::bincode::BorrowDecode::borrow_decode(decoder)?, + }) + } +} + +#[test] +fn test_decode() { + let start = Test2 { + a: 5u32, + b: 10u32, + c: 1024u32, + }; + let slice = [5, 10, 251, 0, 4]; + let (result, len): (Test2, usize) = + bincode::decode_from_slice(&slice, bincode::config::standard()).unwrap(); + assert_eq!(result, start); + assert_eq!(len, 5); +} + +#[derive(bincode::BorrowDecode, bincode::Encode, PartialEq, Debug, Eq)] +pub struct Test3<'a> { + a: &'a str, + b: u32, + c: u32, + d: Option<&'a [u8]>, +} + +#[test] +fn test_encode_decode_str() { + let start = Test3 { + a: "Foo bar", + b: 10u32, + c: 1024u32, + d: Some(b"Foo bar"), + }; + let mut slice = [0u8; 100]; + + let len = bincode::encode_into_slice(&start, &mut slice, bincode::config::standard()).unwrap(); + assert_eq!(len, 21); + let (end, len): (Test3, usize) = + bincode::borrow_decode_from_slice(&slice[..len], bincode::config::standard()).unwrap(); + assert_eq!(end, start); + assert_eq!(len, 21); +} + +#[derive(bincode::Encode, bincode::Decode, PartialEq, Debug, Eq)] +pub struct TestTupleStruct(u32, u32, u32); + +#[test] +fn test_encode_tuple() { + let start = TestTupleStruct(5, 10, 1024); + let mut slice = [0u8; 1024]; + let bytes_written = + bincode::encode_into_slice(start, &mut slice, bincode::config::standard()).unwrap(); + assert_eq!(bytes_written, 5); + assert_eq!(&slice[..bytes_written], &[5, 10, 251, 0, 4]); +} + +#[test] +fn test_decode_tuple() { + let start = TestTupleStruct(5, 10, 1024); + let slice = [5, 10, 251, 0, 4]; + let (result, len): (TestTupleStruct, usize) = + bincode::decode_from_slice(&slice, bincode::config::standard()).unwrap(); + assert_eq!(result, start); + assert_eq!(len, 5); +} + +#[derive(bincode::Encode, bincode::Decode, PartialEq, Debug, Eq)] +pub enum TestEnum { + Foo, + Bar { name: u32 }, + Baz(u32, u32, u32), +} +#[test] +fn test_encode_enum_struct_variant() { + let start = TestEnum::Bar { name: 5u32 }; + let mut slice = [0u8; 1024]; + let bytes_written = + bincode::encode_into_slice(start, &mut slice, bincode::config::standard()).unwrap(); + assert_eq!(bytes_written, 2); + assert_eq!(&slice[..bytes_written], &[1, 5]); +} + +#[test] +fn test_decode_enum_struct_variant() { + let start = TestEnum::Bar { name: 5u32 }; + let slice = [1, 5]; + let (result, len): (TestEnum, usize) = + bincode::decode_from_slice(&slice, bincode::config::standard()).unwrap(); + assert_eq!(result, start); + assert_eq!(len, 2); +} + +#[test] +fn test_decode_enum_unit_variant() { + let start = TestEnum::Foo; + let slice = [0]; + let (result, len): (TestEnum, usize) = + bincode::decode_from_slice(&slice, bincode::config::standard()).unwrap(); + assert_eq!(result, start); + assert_eq!(len, 1); +} + +#[test] +fn test_encode_enum_unit_variant() { + let start = TestEnum::Foo; + let mut slice = [0u8; 1024]; + let bytes_written = + bincode::encode_into_slice(start, &mut slice, bincode::config::standard()).unwrap(); + assert_eq!(bytes_written, 1); + assert_eq!(&slice[..bytes_written], &[0]); +} + +#[test] +fn test_encode_enum_tuple_variant() { + let start = TestEnum::Baz(5, 10, 1024); + let mut slice = [0u8; 1024]; + let bytes_written = + bincode::encode_into_slice(start, &mut slice, bincode::config::standard()).unwrap(); + assert_eq!(bytes_written, 6); + assert_eq!(&slice[..bytes_written], &[2, 5, 10, 251, 0, 4]); +} + +#[test] +fn test_decode_enum_tuple_variant() { + let start = TestEnum::Baz(5, 10, 1024); + let slice = [2, 5, 10, 251, 0, 4]; + let (result, len): (TestEnum, usize) = + bincode::decode_from_slice(&slice, bincode::config::standard()).unwrap(); + assert_eq!(result, start); + assert_eq!(len, 6); +} + +#[derive(bincode::Encode, bincode::BorrowDecode, PartialEq, Debug, Eq)] +pub enum TestEnum2<'a> { + Foo, + Bar { name: &'a str }, + Baz(u32, u32, u32), +} + +#[test] +fn test_encode_borrowed_enum_struct_variant() { + let start = TestEnum2::Bar { name: "foo" }; + let mut slice = [0u8; 1024]; + let bytes_written = + bincode::encode_into_slice(start, &mut slice, bincode::config::standard()).unwrap(); + assert_eq!(bytes_written, 5); + assert_eq!(&slice[..bytes_written], &[1, 3, 102, 111, 111]); +} + +#[test] +fn test_decode_borrowed_enum_struct_variant() { + let start = TestEnum2::Bar { name: "foo" }; + let slice = [1, 3, 102, 111, 111]; + let (result, len): (TestEnum2, usize) = + bincode::borrow_decode_from_slice(&slice, bincode::config::standard()).unwrap(); + assert_eq!(result, start); + assert_eq!(len, 5); +} + +#[test] +fn test_decode_borrowed_enum_unit_variant() { + let start = TestEnum2::Foo; + let slice = [0]; + let (result, len): (TestEnum2, usize) = + bincode::borrow_decode_from_slice(&slice, bincode::config::standard()).unwrap(); + assert_eq!(result, start); + assert_eq!(len, 1); +} + +#[test] +fn test_encode_borrowed_enum_unit_variant() { + let start = TestEnum2::Foo; + let mut slice = [0u8; 1024]; + let bytes_written = + bincode::encode_into_slice(start, &mut slice, bincode::config::standard()).unwrap(); + assert_eq!(bytes_written, 1); + assert_eq!(&slice[..bytes_written], &[0]); +} + +#[test] +fn test_encode_borrowed_enum_tuple_variant() { + let start = TestEnum2::Baz(5, 10, 1024); + let mut slice = [0u8; 1024]; + let bytes_written = + bincode::encode_into_slice(start, &mut slice, bincode::config::standard()).unwrap(); + assert_eq!(bytes_written, 6); + assert_eq!(&slice[..bytes_written], &[2, 5, 10, 251, 0, 4]); +} + +#[test] +fn test_decode_borrowed_enum_tuple_variant() { + let start = TestEnum2::Baz(5, 10, 1024); + let slice = [2, 5, 10, 251, 0, 4]; + let (result, len): (TestEnum2, usize) = + bincode::borrow_decode_from_slice(&slice, bincode::config::standard()).unwrap(); + assert_eq!(result, start); + assert_eq!(len, 6); +} + +#[derive(bincode::Decode, bincode::Encode, PartialEq, Eq, Debug)] +enum CStyleEnum { + A = -1, + B = 2, + C, + D = 5, + E, +} + +#[test] +fn test_c_style_enum() { + fn ser(e: CStyleEnum) -> u8 { + let mut slice = [0u8; 10]; + let bytes_written = + bincode::encode_into_slice(e, &mut slice, bincode::config::standard()).unwrap(); + assert_eq!(bytes_written, 1); + slice[0] + } + + assert_eq!(ser(CStyleEnum::A), 0); + assert_eq!(ser(CStyleEnum::B), 1); + assert_eq!(ser(CStyleEnum::C), 2); + assert_eq!(ser(CStyleEnum::D), 3); + assert_eq!(ser(CStyleEnum::E), 4); + + fn assert_de_successfully(num: u8, expected: CStyleEnum) { + match bincode::decode_from_slice::(&[num], bincode::config::standard()) { + Ok((result, len)) => { + assert_eq!(len, 1); + assert_eq!(result, expected) + } + Err(e) => panic!("Could not deserialize CStyleEnum idx {num}: {e:?}"), + } + } + + fn assert_de_fails(num: u8) { + match bincode::decode_from_slice::(&[num], bincode::config::standard()) { + Ok(_) => { + panic!("Expected to not be able to decode CStyleEnum index {num}, but it succeeded") + } + Err(DecodeError::UnexpectedVariant { + type_name: "CStyleEnum", + allowed: &bincode::error::AllowedEnumVariants::Allowed(&[0, 1, 2, 3, 4]), + found, + }) if found == num as u32 => {} + Err(e) => panic!("Expected DecodeError::UnexpectedVariant, got {e:?}"), + } + } + + assert_de_successfully(0, CStyleEnum::A); + assert_de_successfully(1, CStyleEnum::B); + assert_de_successfully(2, CStyleEnum::C); + assert_de_successfully(3, CStyleEnum::D); + assert_de_successfully(4, CStyleEnum::E); + assert_de_fails(5); +} + +macro_rules! macro_newtype { + ($name:ident) => { + #[derive(bincode::Encode, bincode::Decode, PartialEq, Eq, Debug)] + pub struct $name(pub usize); + }; +} +macro_newtype!(MacroNewType); + +#[test] +fn test_macro_newtype() { + for val in [0, 100, usize::MAX] { + let mut usize_slice = [0u8; 10]; + let usize_len = + bincode::encode_into_slice(val, &mut usize_slice, bincode::config::standard()).unwrap(); + + let mut newtype_slice = [0u8; 10]; + let newtype_len = bincode::encode_into_slice( + MacroNewType(val), + &mut newtype_slice, + bincode::config::standard(), + ) + .unwrap(); + + assert_eq!(usize_len, newtype_len); + assert_eq!(usize_slice, newtype_slice); + + let (newtype, len) = bincode::decode_from_slice::( + &newtype_slice, + bincode::config::standard(), + ) + .unwrap(); + assert_eq!(newtype, MacroNewType(val)); + assert_eq!(len, newtype_len); + } +} + +#[derive(bincode::Encode, bincode::Decode, Debug)] +pub enum EmptyEnum {} + +#[derive(bincode::Encode, bincode::BorrowDecode, Debug)] +pub enum BorrowedEmptyEnum {} + +#[test] +fn test_empty_enum_decode() { + match bincode::decode_from_slice::(&[], bincode::config::standard()) { + Ok(_) => panic!("We successfully decoded an empty slice, this should never happen"), + Err(DecodeError::EmptyEnum { + type_name: "derive::EmptyEnum", + }) => {} + Err(e) => panic!("Expected DecodeError::EmptyEnum, got {e:?}"), + } +} + +#[derive(bincode::Encode, bincode::Decode, PartialEq, Debug, Eq)] +pub enum TestWithGeneric { + Foo, + Bar(T), +} + +#[test] +fn test_enum_with_generics_roundtrip() { + let start = TestWithGeneric::Bar(1234); + let mut slice = [0u8; 10]; + let bytes_written = + bincode::encode_into_slice(&start, &mut slice, bincode::config::standard()).unwrap(); + assert_eq!( + &slice[..bytes_written], + &[ + 1, // variant 1 + 251, // u16 + 210, 4 // 1234 + ] + ); + + let decoded: TestWithGeneric = + bincode::decode_from_slice(&slice[..bytes_written], bincode::config::standard()) + .unwrap() + .0; + assert_eq!(start, decoded); + + let start = TestWithGeneric::<()>::Foo; + let mut slice = [0u8; 10]; + let bytes_written = + bincode::encode_into_slice(&start, &mut slice, bincode::config::standard()).unwrap(); + assert_eq!(&slice[..bytes_written], &[0]); + + let decoded: TestWithGeneric<()> = + bincode::decode_from_slice(&slice[..bytes_written], bincode::config::standard()) + .unwrap() + .0; + assert_eq!(start, decoded); +} + +mod derive_with_polluted_scope { + #[allow(dead_code)] + #[allow(non_snake_case)] + fn Ok() {} + + #[allow(dead_code)] + #[allow(non_snake_case)] + fn Err() {} + + #[derive(bincode::Encode, bincode::Decode)] + struct A { + a: u32, + } + + #[derive(bincode::Encode, bincode::Decode)] + enum B { + A, + B, + } +} + +#[cfg(feature = "alloc")] +mod zoxide { + extern crate alloc; + + use alloc::borrow::Cow; + use bincode::{Decode, Encode}; + + pub type Rank = f64; + pub type Epoch = u64; + + #[derive(Encode, Decode)] + pub struct Dir<'a> { + pub path: Cow<'a, str>, + pub rank: Rank, + pub last_accessed: Epoch, + } + + #[test] + fn test() { + let dirs = vec![ + Dir { + path: Cow::Borrowed("Foo"), + rank: 1.23, + last_accessed: 5, + }, + Dir { + path: Cow::Owned(String::from("Bar")), + rank: 2.34, + last_accessed: 10, + }, + ]; + let config = bincode::config::standard(); + + let slice = bincode::encode_to_vec(dirs, config).unwrap(); + let decoded: Vec = bincode::borrow_decode_from_slice(&slice, config).unwrap().0; + + assert_eq!(decoded.len(), 2); + assert!(matches!(decoded[0].path, Cow::Borrowed("Foo"))); + assert!(matches!(decoded[1].path, Cow::Borrowed("Bar"))); + } +} diff --git a/vendor/bincode-2.0.1/tests/derive_rename.rs b/vendor/bincode-2.0.1/tests/derive_rename.rs new file mode 100644 index 0000000..fe2d0cf --- /dev/null +++ b/vendor/bincode-2.0.1/tests/derive_rename.rs @@ -0,0 +1,14 @@ +#![cfg(feature = "derive")] + +extern crate bincode as bincode_new; + +// Make sure that the `bincode` crate exists, just symlink it to `core. +extern crate core as bincode; + +#[derive(bincode_new::Encode)] +#[bincode(crate = "bincode_new")] +#[allow(dead_code)] +struct DeriveRenameTest { + a: u32, + b: u32, +} diff --git a/vendor/bincode-2.0.1/tests/error_size.rs b/vendor/bincode-2.0.1/tests/error_size.rs new file mode 100644 index 0000000..dfc03ea --- /dev/null +++ b/vendor/bincode-2.0.1/tests/error_size.rs @@ -0,0 +1,15 @@ +#![cfg(target_pointer_width = "64")] + +#[test] +fn decode_error_size() { + assert_eq!(std::mem::size_of::(), 32); +} + +#[test] +fn encode_error_size() { + #[cfg(feature = "std")] + assert_eq!(std::mem::size_of::(), 32); + + #[cfg(not(feature = "std"))] + assert_eq!(std::mem::size_of::(), 24); +} diff --git a/vendor/bincode-2.0.1/tests/issues.rs b/vendor/bincode-2.0.1/tests/issues.rs new file mode 100644 index 0000000..cd027b1 --- /dev/null +++ b/vendor/bincode-2.0.1/tests/issues.rs @@ -0,0 +1,40 @@ +#![no_std] + +#[path = "issues/issue_431.rs"] +mod issue_431; + +#[path = "issues/issue_427.rs"] +mod issue_427; + +#[path = "issues/issue_467.rs"] +mod issue_467; + +#[path = "issues/issue_459.rs"] +mod issue_459; + +#[path = "issues/issue_474.rs"] +mod issue_474; + +#[path = "issues/issue_498.rs"] +mod issue_498; + +#[path = "issues/issue_500.rs"] +mod issue_500; + +#[path = "issues/issue_523.rs"] +mod issue_523; + +#[path = "issues/issue_537.rs"] +mod issue_537; + +#[path = "issues/issue_547.rs"] +mod issue_547; + +#[path = "issues/issue_570.rs"] +mod issue_570; + +#[path = "issues/issue_592.rs"] +mod issue_592; + +#[path = "issues/issue_614.rs"] +mod issue_614; diff --git a/vendor/bincode-2.0.1/tests/issues/issue_427.rs b/vendor/bincode-2.0.1/tests/issues/issue_427.rs new file mode 100644 index 0000000..09ea981 --- /dev/null +++ b/vendor/bincode-2.0.1/tests/issues/issue_427.rs @@ -0,0 +1,69 @@ +#![cfg(feature = "derive")] + +/// HID-IO Packet Buffer Struct +/// +/// # Remarks +/// Used to store HID-IO data chunks. Will be chunked into individual packets on transmission. +#[repr(C)] +#[derive(PartialEq, Eq, Clone, Debug, bincode::Encode)] +pub struct HidIoPacketBuffer { + /// Type of packet (Continued is automatically set if needed) + pub ptype: u32, + /// Packet Id + pub id: u32, + /// Packet length for serialization (in bytes) + pub max_len: u32, + /// Payload data, chunking is done automatically by serializer + pub data: [u8; H], + /// Set False if buffer is not complete, True if it is + pub done: bool, +} + +#[repr(u32)] +#[derive(PartialEq, Eq, Clone, Copy, Debug, bincode::Encode)] +#[allow(dead_code)] +/// Requests for to perform a specific action +pub enum HidIoCommandId { + SupportedIds = 0x00, + GetInfo = 0x01, + TestPacket = 0x02, + ResetHidIo = 0x03, + Reserved = 0x04, // ... 0x0F + + GetProperties = 0x10, + KeyState = 0x11, + KeyboardLayout = 0x12, + KeyLayout = 0x13, + KeyShapes = 0x14, + LedLayout = 0x15, + FlashMode = 0x16, + UnicodeText = 0x17, + UnicodeState = 0x18, + HostMacro = 0x19, + SleepMode = 0x1A, + + KllState = 0x20, + PixelSetting = 0x21, + PixelSet1c8b = 0x22, + PixelSet3c8b = 0x23, + PixelSet1c16b = 0x24, + PixelSet3c16b = 0x25, + + OpenUrl = 0x30, + TerminalCmd = 0x31, + GetInputLayout = 0x32, + SetInputLayout = 0x33, + TerminalOut = 0x34, + + HidKeyboard = 0x40, + HidKeyboardLed = 0x41, + HidMouse = 0x42, + HidJoystick = 0x43, + HidSystemCtrl = 0x44, + HidConsumerCtrl = 0x45, + + ManufacturingTest = 0x50, + ManufacturingResult = 0x51, + + Unused = 0xFFFF, +} diff --git a/vendor/bincode-2.0.1/tests/issues/issue_431.rs b/vendor/bincode-2.0.1/tests/issues/issue_431.rs new file mode 100644 index 0000000..03b35d2 --- /dev/null +++ b/vendor/bincode-2.0.1/tests/issues/issue_431.rs @@ -0,0 +1,42 @@ +#![cfg(all(feature = "std", feature = "derive"))] + +extern crate std; + +use bincode::{Decode, Encode}; +use std::borrow::Cow; +use std::string::String; + +#[derive(Decode, Encode, PartialEq, Debug)] +#[bincode( + decode_context = "()", + borrow_decode_bounds = "&'__de U<'a, A>: ::bincode::de::BorrowDecode<'__de, ()> + '__de, '__de: 'a" +)] +struct T<'a, A: Clone + Encode + Decode<()>> { + t: Cow<'a, U<'a, A>>, +} + +#[derive(Clone, Decode, Encode, PartialEq, Debug)] +#[bincode( + decode_context = "()", + borrow_decode_bounds = "&'__de A: ::bincode::de::BorrowDecode<'__de, ()> + '__de, '__de: 'a" +)] +struct U<'a, A: Clone + Encode + Decode<()>> { + u: Cow<'a, A>, +} + +#[test] +fn test() { + let u = U { + u: Cow::Owned(String::from("Hello world")), + }; + let t = T { + t: Cow::Borrowed(&u), + }; + let vec = bincode::encode_to_vec(&t, bincode::config::standard()).unwrap(); + + let (decoded, len): (T, usize) = + bincode::decode_from_slice(&vec, bincode::config::standard()).unwrap(); + + assert_eq!(t, decoded); + assert_eq!(len, 12); +} diff --git a/vendor/bincode-2.0.1/tests/issues/issue_459.rs b/vendor/bincode-2.0.1/tests/issues/issue_459.rs new file mode 100644 index 0000000..831041f --- /dev/null +++ b/vendor/bincode-2.0.1/tests/issues/issue_459.rs @@ -0,0 +1,13 @@ +#![cfg(all(feature = "std", feature = "derive"))] + +extern crate std; + +use std::collections::BTreeMap; + +#[derive(bincode::Encode)] +struct AllTypes(BTreeMap); + +#[test] +fn test_issue_459() { + let _result = bincode::encode_to_vec(AllTypes(BTreeMap::new()), bincode::config::standard()); +} diff --git a/vendor/bincode-2.0.1/tests/issues/issue_467.rs b/vendor/bincode-2.0.1/tests/issues/issue_467.rs new file mode 100644 index 0000000..0ca0c1f --- /dev/null +++ b/vendor/bincode-2.0.1/tests/issues/issue_467.rs @@ -0,0 +1,14 @@ +#![cfg(all(feature = "std", feature = "derive"))] + +extern crate std; + +use std::collections::BTreeMap; + +#[derive(bincode::Decode, bincode::Encode)] +struct AllTypes(BTreeMap); + +#[test] +fn test_issue_467() { + let _result: Result<(AllTypes, _), _> = + bincode::decode_from_slice(&[], bincode::config::standard().with_limit::<1024>()); +} diff --git a/vendor/bincode-2.0.1/tests/issues/issue_474.rs b/vendor/bincode-2.0.1/tests/issues/issue_474.rs new file mode 100644 index 0000000..0526ebb --- /dev/null +++ b/vendor/bincode-2.0.1/tests/issues/issue_474.rs @@ -0,0 +1,94 @@ +#![cfg(all(feature = "serde", feature = "std"))] + +extern crate std; + +use chrono::{DateTime, Utc}; +use serde::de::DeserializeOwned; +use std::collections::HashMap; +use std::prelude::rust_2021::*; +use uuid::Uuid; + +#[derive(serde_derive::Serialize, serde_derive::Deserialize, PartialEq, Eq, Debug)] +pub struct MyStruct { + name: String, +} + +#[derive(serde_derive::Serialize, serde_derive::Deserialize, PartialEq, Eq, Debug)] +pub struct CustomerTest { + pub id: Option, + pub email_address: Option, + pub is_active: Option, + pub date_stamp: Option>, +} + +#[test] +fn test() { + let test = MyStruct { + name: "Test Value".into(), + }; + let cache_id = Uuid::nil(); + let cache = MemCache::default(); + + cache.set_data::(&cache_id, &test, 5).unwrap(); + let model = cache.get_data::(&cache_id).unwrap(); + assert_eq!(test, model); + + let test = CustomerTest { + id: Some(Uuid::nil()), + email_address: Some("foo@bar".into()), + is_active: None, + date_stamp: Some(Utc::now()), + }; + + cache.set_data::(&cache_id, &test, 5).unwrap(); + let model = cache.get_data::(&cache_id).unwrap(); + assert_eq!(test, model); +} + +#[derive(Default)] +struct MemCache { + cache: std::sync::RwLock>, +} + +impl MemCache { + fn set_data( + &self, + key: &Uuid, + cache_data: &T, + expire_seconds: i64, + ) -> Result<(), bincode::error::EncodeError> + where + T: Send + Sync + serde::Serialize, + { + let config = bincode::config::standard(); + let mut guard = self.cache.write().unwrap(); + + let encoded = bincode::serde::encode_to_vec(cache_data, config)?; + let cache_item = CacheItem::new(encoded, expire_seconds); + + guard.insert(*key, cache_item); + Ok(()) + } + + fn get_data(&self, key: &Uuid) -> Result + where + T: Send + Sync + DeserializeOwned, + { + let config = bincode::config::standard(); + let guard = self.cache.read().unwrap(); + let cache_item = guard.get(key).unwrap(); + let (decoded, _len): (T, usize) = + bincode::serde::decode_from_slice(&cache_item.payload[..], config)?; + Ok(decoded) + } +} + +struct CacheItem { + payload: Vec, +} + +impl CacheItem { + fn new(payload: Vec, _expire_seconds: i64) -> Self { + Self { payload } + } +} diff --git a/vendor/bincode-2.0.1/tests/issues/issue_498.rs b/vendor/bincode-2.0.1/tests/issues/issue_498.rs new file mode 100644 index 0000000..f301c4b --- /dev/null +++ b/vendor/bincode-2.0.1/tests/issues/issue_498.rs @@ -0,0 +1,17 @@ +#![cfg(feature = "std")] + +extern crate std; + +use std::ffi::CString; + +#[test] +fn test_issue_498() { + let bytes = [1, 0, 0, 0, 0, 0, 0, 0, 0]; + let out: Result<(CString, _), _> = + bincode::decode_from_slice(&bytes, bincode::config::legacy().with_limit::<1024>()); + + match out.unwrap_err() { + bincode::error::DecodeError::CStringNulError { position: _ } => {} + err => panic!("Expected CStringNullErr, found {:?}", err), + } +} diff --git a/vendor/bincode-2.0.1/tests/issues/issue_500.rs b/vendor/bincode-2.0.1/tests/issues/issue_500.rs new file mode 100644 index 0000000..6c013ba --- /dev/null +++ b/vendor/bincode-2.0.1/tests/issues/issue_500.rs @@ -0,0 +1,37 @@ +#![cfg(all(feature = "serde", feature = "derive", feature = "std"))] + +extern crate std; + +type NodeId = u64; + +use std::collections::BTreeSet; + +#[derive( + bincode::Encode, + bincode::Decode, + serde_derive::Serialize, + serde_derive::Deserialize, + Debug, + PartialEq, + Eq, +)] +pub struct Membership { + /// learners set + learners: BTreeSet, +} + +#[test] +fn test() { + let mut start = Membership { + learners: BTreeSet::new(), + }; + start.learners.insert(1); + + let config = bincode::config::legacy(); + let encoded = bincode::encode_to_vec(&start, config).unwrap(); + std::dbg!(&encoded); + let decoded: Membership = bincode::serde::decode_from_slice(&encoded, config) + .unwrap() + .0; + assert_eq!(start, decoded); +} diff --git a/vendor/bincode-2.0.1/tests/issues/issue_523.rs b/vendor/bincode-2.0.1/tests/issues/issue_523.rs new file mode 100644 index 0000000..2cda3f9 --- /dev/null +++ b/vendor/bincode-2.0.1/tests/issues/issue_523.rs @@ -0,0 +1,9 @@ +#![cfg(all(feature = "derive", feature = "std"))] + +extern crate std; + +use bincode::{Decode, Encode}; +use std::borrow::Cow; + +#[derive(Clone, Encode, Decode)] +pub struct Foo<'a>(Cow<'a, str>); diff --git a/vendor/bincode-2.0.1/tests/issues/issue_537.rs b/vendor/bincode-2.0.1/tests/issues/issue_537.rs new file mode 100644 index 0000000..4dd8bbf --- /dev/null +++ b/vendor/bincode-2.0.1/tests/issues/issue_537.rs @@ -0,0 +1,8 @@ +#![cfg(all(feature = "derive", feature = "std"))] + +use bincode::{Decode, Encode}; + +#[derive(Encode, Decode)] +struct Foo { + x: Bar, +} diff --git a/vendor/bincode-2.0.1/tests/issues/issue_547.rs b/vendor/bincode-2.0.1/tests/issues/issue_547.rs new file mode 100644 index 0000000..7c75021 --- /dev/null +++ b/vendor/bincode-2.0.1/tests/issues/issue_547.rs @@ -0,0 +1,24 @@ +#![cfg(all(feature = "serde", feature = "std"))] + +use glam::vec3; + +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, PartialEq)] +struct Instance { + position: glam::Vec3, +} + +#[test] +fn test() { + let instance = Instance { + position: vec3(2.0, 2.0, 2.0), + }; + + let m = bincode::serde::encode_to_vec(&instance, bincode::config::standard()).unwrap(); + let instance2: Instance = bincode::serde::decode_from_slice(&m, bincode::config::standard()) + .unwrap() + .0; + + assert_eq!(instance, instance2); +} diff --git a/vendor/bincode-2.0.1/tests/issues/issue_570.rs b/vendor/bincode-2.0.1/tests/issues/issue_570.rs new file mode 100644 index 0000000..def9043 --- /dev/null +++ b/vendor/bincode-2.0.1/tests/issues/issue_570.rs @@ -0,0 +1,6 @@ +#![cfg(feature = "derive")] + +#[derive(bincode::Encode, bincode::Decode)] +pub struct Eg { + data: (D, E), +} diff --git a/vendor/bincode-2.0.1/tests/issues/issue_592.rs b/vendor/bincode-2.0.1/tests/issues/issue_592.rs new file mode 100644 index 0000000..995e28e --- /dev/null +++ b/vendor/bincode-2.0.1/tests/issues/issue_592.rs @@ -0,0 +1,8 @@ +#![cfg(all(feature = "derive", feature = "std"))] + +use bincode::{Decode, Encode}; + +#[derive(Encode, Decode)] +pub enum TypeOfFile { + Unknown = -1, +} diff --git a/vendor/bincode-2.0.1/tests/issues/issue_614.rs b/vendor/bincode-2.0.1/tests/issues/issue_614.rs new file mode 100644 index 0000000..c36b17e --- /dev/null +++ b/vendor/bincode-2.0.1/tests/issues/issue_614.rs @@ -0,0 +1,22 @@ +#![cfg(feature = "derive")] + +use bincode::{Decode, Encode}; + +#[derive(Encode, Decode, Clone)] +pub struct A; +#[derive(Encode, Decode, Clone)] +pub struct B +where + T: Clone + Encode + Decode<()>, +{ + pub t: T, +} + +#[derive(Encode, Decode)] +pub struct MyStruct +where + T: Clone + Encode + Decode<()>, +{ + pub a: A, + pub b: B, +} diff --git a/vendor/bincode-2.0.1/tests/serde.rs b/vendor/bincode-2.0.1/tests/serde.rs new file mode 100644 index 0000000..7a5ed83 --- /dev/null +++ b/vendor/bincode-2.0.1/tests/serde.rs @@ -0,0 +1,253 @@ +#![cfg(all(feature = "serde", feature = "alloc", feature = "derive"))] + +extern crate alloc; + +use serde_derive::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, bincode::Encode, bincode::Decode)] +pub struct SerdeRoundtrip { + pub a: u32, + #[serde(skip)] + pub b: u32, + pub c: TupleS, +} + +#[derive(Serialize, Deserialize, bincode::Encode, bincode::Decode, PartialEq, Debug)] +pub struct TupleS(f32, f32, f32); + +#[test] +fn test_serde_round_trip() { + // validate serde attribute working + let json = serde_json::to_string(&SerdeRoundtrip { + a: 5, + b: 5, + c: TupleS(2.0, 3.0, 4.0), + }) + .unwrap(); + assert_eq!("{\"a\":5,\"c\":[2.0,3.0,4.0]}", json); + + let result: SerdeRoundtrip = serde_json::from_str(&json).unwrap(); + assert_eq!(result.a, 5); + assert_eq!(result.b, 0); + + // validate bincode working + let bytes = bincode::serde::encode_to_vec( + SerdeRoundtrip { + a: 15, + b: 15, + c: TupleS(2.0, 3.0, 4.0), + }, + bincode::config::standard(), + ) + .unwrap(); + assert_eq!(bytes, &[15, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 128, 64]); + let (result, len): (SerdeRoundtrip, usize) = + bincode::serde::decode_from_slice(&bytes, bincode::config::standard()).unwrap(); + assert_eq!(result.a, 15); + assert_eq!(result.b, 0); // remember: b is skipped + assert_eq!(result.c, TupleS(2.0, 3.0, 4.0)); + assert_eq!(len, 13); +} + +#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)] +pub struct SerdeWithBorrowedData<'a> { + pub a: u32, + #[serde(skip)] + pub b: u32, + pub str: &'a str, +} + +#[test] +fn test_serialize_deserialize_borrowed_data() { + let input = SerdeWithBorrowedData { + a: 5, + b: 5, + str: "Hello world", + }; + + #[rustfmt::skip] + let expected = &[ + 5, // a + // b is skipped + 11, // str length + b'H', b'e', b'l', b'l', b'o', b' ', b'w', b'o', b'r', b'l', b'd' // str + ]; + + let mut result = [0u8; 20]; + let len = bincode::serde::encode_into_slice(&input, &mut result, bincode::config::standard()) + .unwrap(); + let result = &result[..len]; + assert_eq!(result, expected); + + let result = bincode::serde::encode_to_vec(&input, bincode::config::standard()).unwrap(); + + assert_eq!(result, expected); + + let (output, len): (SerdeWithBorrowedData, usize) = + bincode::serde::borrow_decode_from_slice(&result, bincode::config::standard()).unwrap(); + assert_eq!( + SerdeWithBorrowedData { + b: 0, // remember: b is skipped + ..input + }, + output + ); + assert_eq!(len, 13); +} + +#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)] +pub struct SerdeWithOwnedData { + pub a: u32, + #[serde(skip)] + pub b: u32, + pub str: String, +} + +#[test] +fn test_serialize_deserialize_owned_data() { + let input = SerdeWithOwnedData { + a: 5, + b: 5, + str: String::from("Hello world"), + }; + + #[rustfmt::skip] + let expected = &[ + 5, // a + // b is skipped + 11, // str length + b'H', b'e', b'l', b'l', b'o', b' ', b'w', b'o', b'r', b'l', b'd' // str + ]; + + let mut result = [0u8; 20]; + let len = bincode::serde::encode_into_slice(&input, &mut result, bincode::config::standard()) + .unwrap(); + let result = &result[..len]; + assert_eq!(result, expected); + + let result = bincode::serde::encode_to_vec(&input, bincode::config::standard()).unwrap(); + + assert_eq!(result, expected); + + let (output, len): (SerdeWithOwnedData, usize) = + bincode::serde::decode_from_slice(&result, bincode::config::standard()).unwrap(); + assert_eq!( + SerdeWithOwnedData { + b: 0, // remember: b is skipped + ..input + }, + output + ); + assert_eq!(len, 13); +} + +#[cfg(feature = "derive")] +mod derive { + use bincode::{ + serde::{BorrowCompat, Compat}, + Decode, Encode, + }; + use serde_derive::{Deserialize, Serialize}; + + #[derive(Serialize, Deserialize, PartialEq, Eq, Debug)] + pub struct SerdeType { + pub a: u32, + } + + #[derive(Decode, Encode, PartialEq, Eq, Debug)] + pub struct StructWithSerde { + #[bincode(with_serde)] + pub serde: SerdeType, + } + + #[derive(Decode, Encode, PartialEq, Eq, Debug)] + pub enum EnumWithSerde { + Unit(#[bincode(with_serde)] SerdeType), + Struct { + #[bincode(with_serde)] + serde: SerdeType, + }, + } + + #[test] + fn test_serde_derive() { + fn test_encode_decode(start: T, expected_len: usize) + where + T: bincode::Encode + bincode::Decode<()> + PartialEq + core::fmt::Debug, + { + let mut slice = [0u8; 100]; + let len = bincode::encode_into_slice(&start, &mut slice, bincode::config::standard()) + .unwrap(); + assert_eq!(len, expected_len); + let slice = &slice[..len]; + let (result, len): (T, usize) = + bincode::decode_from_slice(slice, bincode::config::standard()).unwrap(); + + assert_eq!(start, result); + assert_eq!(len, expected_len); + } + test_encode_decode( + StructWithSerde { + serde: SerdeType { a: 5 }, + }, + 1, + ); + test_encode_decode(EnumWithSerde::Unit(SerdeType { a: 5 }), 2); + test_encode_decode( + EnumWithSerde::Struct { + serde: SerdeType { a: 5 }, + }, + 2, + ); + } + + #[test] + fn test_vec_compat_debug() { + let compat = Compat(vec![0, 1, 2, 3]); + let debug_view = format!("{:?}", compat); + assert_eq!(debug_view, "Compat([0, 1, 2, 3])") + } + + #[test] + fn test_i32_compat_debug() { + let compat = Compat(1337_i32); + let debug_view = format!("{:?}", compat); + assert_eq!(debug_view, "Compat(1337)") + } + + #[test] + fn test_i32_compat_display() { + let compat = Compat(1337_i32); + let debug_view = format!("{}", compat); + assert_eq!(debug_view, "1337") + } + + #[test] + fn test_f32_compat_display() { + let compat = Compat(1.5_f32); + let debug_view = format!("{}", compat); + assert_eq!(debug_view, "1.5") + } + + #[test] + fn test_vec_borrow_compat_debug() { + let vector = vec![0, 1, 2, 3]; + let borrow_compat = BorrowCompat(&vector); + let debug_view = format!("{:?}", borrow_compat); + assert_eq!(debug_view, "BorrowCompat([0, 1, 2, 3])") + } + + #[test] + fn test_str_borrow_compat_debug() { + let borrow_compat = BorrowCompat("Hello World!"); + let debug_view = format!("{:?}", borrow_compat); + assert_eq!(debug_view, "BorrowCompat(\"Hello World!\")") + } + + #[test] + fn test_str_borrow_compat_display() { + let borrow_compat = BorrowCompat("Hello World!"); + let debug_view = format!("{}", borrow_compat); + assert_eq!(debug_view, "Hello World!") + } +} diff --git a/vendor/bincode-2.0.1/tests/std.rs b/vendor/bincode-2.0.1/tests/std.rs new file mode 100644 index 0000000..0c33c6f --- /dev/null +++ b/vendor/bincode-2.0.1/tests/std.rs @@ -0,0 +1,203 @@ +#![allow(clippy::disallowed_names)] +#![cfg(feature = "std")] + +mod utils; + +use bincode::error::DecodeError; +use std::{ + ffi::CString, + io::{Cursor, Seek, SeekFrom}, + net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, + path::{Path, PathBuf}, + sync::{Mutex, RwLock}, +}; +use utils::the_same; + +use crate::utils::the_same_with_comparer; + +struct Foo { + pub a: u32, + pub b: u32, +} + +impl bincode::Encode for Foo { + fn encode( + &self, + encoder: &mut E, + ) -> Result<(), bincode::error::EncodeError> { + self.a.encode(encoder)?; + self.b.encode(encoder)?; + Ok(()) + } +} + +impl bincode::Decode for Foo { + fn decode( + decoder: &mut D, + ) -> Result { + Ok(Self { + a: bincode::Decode::decode(decoder)?, + b: bincode::Decode::decode(decoder)?, + }) + } +} + +#[test] +fn test_std_cursor() { + let mut cursor = Cursor::<&[u8]>::new(&[5, 10]); + let foo: Foo = bincode::decode_from_std_read(&mut cursor, bincode::config::standard()).unwrap(); + + assert_eq!(foo.a, 5); + assert_eq!(foo.b, 10); +} + +#[test] +#[cfg_attr(miri, ignore)] // miri does not like `tempfile` +fn test_std_file() { + let mut file = tempfile::tempfile().expect("Could not create temp file"); + + let bytes_written = bincode::encode_into_std_write( + Foo { a: 30, b: 50 }, + &mut file, + bincode::config::standard(), + ) + .unwrap(); + assert_eq!(bytes_written, 2); + file.seek(SeekFrom::Start(0)).unwrap(); + + let foo: Foo = bincode::decode_from_std_read(&mut file, bincode::config::standard()).unwrap(); + + assert_eq!(foo.a, 30); + assert_eq!(foo.b, 50); +} + +#[test] +fn test_std_commons() { + the_same(CString::new("Hello world").unwrap()); + the_same(PathBuf::from("C:/Program Files/Foo")); + the_same(Ipv4Addr::LOCALHOST); + the_same(Ipv6Addr::LOCALHOST); + the_same(IpAddr::V4(Ipv4Addr::LOCALHOST)); + the_same(IpAddr::V6(Ipv6Addr::LOCALHOST)); + the_same(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 12345)); + the_same(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 12345, 0, 0)); + the_same(SocketAddr::V4(SocketAddrV4::new( + Ipv4Addr::LOCALHOST, + 12345, + ))); + the_same(SocketAddr::V6(SocketAddrV6::new( + Ipv6Addr::LOCALHOST, + 12345, + 0, + 0, + ))); + the_same_with_comparer(Mutex::new("Hello world".to_string()), |a, b| { + *a.lock().unwrap() == *b.lock().unwrap() + }); + the_same_with_comparer(RwLock::new("Hello world".to_string()), |a, b| { + *a.read().unwrap() == *b.read().unwrap() + }); + + let mut map = std::collections::HashMap::new(); + map.insert("Hello".to_owned(), "world".to_owned()); + map.insert("How".to_owned(), "are".to_owned()); + map.insert("you".to_owned(), "doing?".to_owned()); + the_same(map); + + let mut set = std::collections::HashSet::new(); + set.insert("Hello".to_string()); + set.insert("World".to_string()); + the_same(set); + + // HashMap and HashSet with custom hash algorithm + type MyBuildHasher = std::hash::BuildHasherDefault; + let mut custom_map: std::collections::HashMap = + Default::default(); + custom_map.insert("Hello".to_owned(), "world".to_owned()); + custom_map.insert("How".to_owned(), "are".to_owned()); + custom_map.insert("you".to_owned(), "doing?".to_owned()); + the_same(custom_map); + + let mut custom_set: std::collections::HashSet = Default::default(); + custom_set.insert("Hello".to_string()); + custom_set.insert("World".to_string()); + the_same(custom_set); + + // Borrowed values + let config = bincode::config::standard(); + let mut buffer = [0u8; 1024]; + + // &CStr + let cstr = c"Hello world"; + let len = bincode::encode_into_slice(cstr, &mut buffer, config).unwrap(); + let (decoded, len): (CString, usize) = + bincode::decode_from_slice(&buffer[..len], config).unwrap(); + assert_eq!(cstr, decoded.as_c_str()); + assert_eq!(len, 12); + + // Path + let path = Path::new("C:/Program Files/Foo"); + let len = bincode::encode_into_slice(path, &mut buffer, config).unwrap(); + let (decoded, len): (&Path, usize) = + bincode::borrow_decode_from_slice(&buffer[..len], config).unwrap(); + assert_eq!(path, decoded); + assert_eq!(len, 21); +} + +#[test] +fn test_system_time_out_of_range() { + let input = [0xfd, 0x90, 0x0c, 0xfd, 0xfd, 0x90, 0x0c, 0xfd, 0x90, 0x90]; + + let result: Result<(std::time::SystemTime, usize), _> = + bincode::decode_from_slice(&input, bincode::config::standard()); + + match result { + Ok(_) => panic!("Expected the decode to fail, but it succeeded"), + Err(DecodeError::InvalidSystemTime { duration }) => { + assert_eq!( + duration, + std::time::Duration::new(10447520527445462160, 144) + ) + } + Err(e) => panic!("Expected DecodeError::InvalidSystemTime, got {e:?}"), + } +} + +/// Simple example of user-defined hasher to test encoding/decoding HashMap and HashSet with custom hash algorithms. +#[derive(Copy, Clone, Default)] +pub struct ExampleCustomHasher { + pub hash: u64, +} + +impl std::hash::Hasher for ExampleCustomHasher { + fn write(&mut self, value: &[u8]) { + for (index, &item) in value.iter().enumerate() { + self.hash ^= u64::from(item) << ((index % 8) * 8); + } + } + + fn finish(&self) -> u64 { + self.hash + } +} + +#[test] +fn test_decode_borrow_str_in_array() { + let (strs, _): (Vec<&str>, usize) = bincode::borrow_decode_from_slice( + &[ + 3, 3, b'a', b'b', b'c', 3, b'd', b'e', b'f', 3, b'g', b'h', b'i', + ], + bincode::config::standard(), + ) + .unwrap(); + assert_eq!(strs, vec!["abc", "def", "ghi"]); + + let (strs, _): ([&str; 3], usize) = bincode::borrow_decode_from_slice( + &[ + 3, b'a', b'b', b'c', 3, b'd', b'e', b'f', 3, b'g', b'h', b'i', + ], + bincode::config::standard(), + ) + .unwrap(); + assert_eq!(strs, ["abc", "def", "ghi"]); +} diff --git a/vendor/bincode-2.0.1/tests/utils.rs b/vendor/bincode-2.0.1/tests/utils.rs new file mode 100644 index 0000000..22e3533 --- /dev/null +++ b/vendor/bincode-2.0.1/tests/utils.rs @@ -0,0 +1,158 @@ +use core::fmt::Debug; + +fn the_same_with_config(element: &V, config: C, cmp: CMP) +where + V: TheSameTrait, + C: bincode::config::Config, + CMP: Fn(&V, &V) -> bool, +{ + let mut buffer = [0u8; 2048]; + let len = bincode::encode_into_slice(element, &mut buffer, config).unwrap(); + println!( + "{:?} ({}): {:?} ({:?})", + element, + core::any::type_name::(), + &buffer[..len], + core::any::type_name::() + ); + let (decoded, decoded_len): (V, usize) = bincode::decode_from_slice(&buffer, config).unwrap(); + + assert!( + cmp(element, &decoded), + "Comparison failed\nDecoded: {:?}\nExpected: {:?}\nBytes: {:?}", + decoded, + element, + &buffer[..len], + ); + assert_eq!(len, decoded_len); + + #[cfg(feature = "serde")] + the_same_with_config_serde(element, config, cmp) +} + +#[cfg(feature = "serde")] +fn the_same_with_config_serde(element: &V, config: C, cmp: CMP) +where + V: TheSameTrait, + C: bincode::config::Config, + CMP: Fn(&V, &V) -> bool, +{ + let mut buffer = [0u8; 2048]; + let len = bincode::serde::encode_into_slice(element, &mut buffer, config); + + let decoded = bincode::serde::decode_from_slice(&buffer, config); + + let len = len.unwrap(); + let (decoded, decoded_len): (V, usize) = decoded.unwrap(); + println!( + "{:?} ({}): {:?} ({:?})", + element, + core::any::type_name::(), + &buffer[..len], + core::any::type_name::() + ); + + assert!( + cmp(element, &decoded), + "Comparison failed\nDecoded: {:?}\nExpected: {:?}\nBytes: {:?}", + decoded, + element, + &buffer[..len], + ); + assert_eq!(len, decoded_len); +} + +pub fn the_same_with_comparer(element: V, cmp: CMP) +where + V: TheSameTrait, + CMP: Fn(&V, &V) -> bool, +{ + // A matrix of each different config option possible + the_same_with_config( + &element, + bincode::config::standard() + .with_little_endian() + .with_fixed_int_encoding(), + &cmp, + ); + the_same_with_config( + &element, + bincode::config::standard() + .with_big_endian() + .with_fixed_int_encoding(), + &cmp, + ); + the_same_with_config( + &element, + bincode::config::standard() + .with_little_endian() + .with_variable_int_encoding(), + &cmp, + ); + the_same_with_config( + &element, + bincode::config::standard() + .with_big_endian() + .with_variable_int_encoding(), + &cmp, + ); + the_same_with_config( + &element, + bincode::config::standard() + .with_little_endian() + .with_fixed_int_encoding(), + &cmp, + ); + the_same_with_config( + &element, + bincode::config::standard() + .with_big_endian() + .with_fixed_int_encoding(), + &cmp, + ); + the_same_with_config( + &element, + bincode::config::standard() + .with_little_endian() + .with_variable_int_encoding(), + &cmp, + ); + the_same_with_config( + &element, + bincode::config::standard() + .with_big_endian() + .with_variable_int_encoding(), + &cmp, + ); +} + +#[cfg(feature = "serde")] +pub trait TheSameTrait: + bincode::Encode + + bincode::Decode<()> + + serde::de::DeserializeOwned + + serde::Serialize + + Debug + + 'static +{ +} +#[cfg(feature = "serde")] +impl TheSameTrait for T where + T: bincode::Encode + + bincode::Decode<()> + + serde::de::DeserializeOwned + + serde::Serialize + + Debug + + 'static +{ +} + +#[cfg(not(feature = "serde"))] +pub trait TheSameTrait: bincode::Encode + bincode::Decode<()> + Debug + 'static {} +#[cfg(not(feature = "serde"))] +impl TheSameTrait for T where T: bincode::Encode + bincode::Decode<()> + Debug + 'static {} + +#[allow(dead_code)] // This is not used in every test +pub fn the_same(element: V) { + the_same_with_comparer(element, |a, b| a == b); +} diff --git a/vendor/bincode_derive-2.0.1/.cargo_vcs_info.json b/vendor/bincode_derive-2.0.1/.cargo_vcs_info.json new file mode 100644 index 0000000..9546ae0 --- /dev/null +++ b/vendor/bincode_derive-2.0.1/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "4673360aa638b2b907dff24538de54f258d157da" + }, + "path_in_vcs": "derive" +} \ No newline at end of file diff --git a/vendor/bincode_derive-2.0.1/.gitignore b/vendor/bincode_derive-2.0.1/.gitignore new file mode 100644 index 0000000..4fffb2f --- /dev/null +++ b/vendor/bincode_derive-2.0.1/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/vendor/bincode_derive-2.0.1/Cargo.lock b/vendor/bincode_derive-2.0.1/Cargo.lock new file mode 100644 index 0000000..5607d03 --- /dev/null +++ b/vendor/bincode_derive-2.0.1/Cargo.lock @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bincode_derive" +version = "2.0.1" +dependencies = [ + "virtue", +] + +[[package]] +name = "virtue" +version = "0.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" diff --git a/vendor/bincode_derive-2.0.1/Cargo.toml b/vendor/bincode_derive-2.0.1/Cargo.toml new file mode 100644 index 0000000..ea96e2a --- /dev/null +++ b/vendor/bincode_derive-2.0.1/Cargo.toml @@ -0,0 +1,50 @@ +# 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_derive" +version = "2.0.1" +authors = [ + "Zoey Riordan ", + "Victor Koenders ", +] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Implementation of #[derive(Encode, Decode)] for bincode" +documentation = "https://docs.rs/bincode_derive" +readme = "readme.md" +keywords = [ + "binary", + "encode", + "decode", + "serialize", + "deserialize", +] +categories = [ + "encoding", + "network-programming", +] +license = "MIT" +repository = "https://github.com/bincode-org/bincode" + +[lib] +name = "bincode_derive" +path = "src/lib.rs" +proc-macro = true + +[dependencies.virtue] +version = "0.0.18" diff --git a/vendor/bincode_derive-2.0.1/Cargo.toml.orig b/vendor/bincode_derive-2.0.1/Cargo.toml.orig new file mode 100644 index 0000000..5ae4d59 --- /dev/null +++ b/vendor/bincode_derive-2.0.1/Cargo.toml.orig @@ -0,0 +1,23 @@ +[package] +name = "bincode_derive" +version = "2.0.1" # remember to update bincode +authors = [ + "Zoey Riordan ", + "Victor Koenders ", +] +edition = "2021" +rust-version = "1.85.0" + +repository = "https://github.com/bincode-org/bincode" +documentation = "https://docs.rs/bincode_derive" +readme = "./readme.md" +categories = ["encoding", "network-programming"] +keywords = ["binary", "encode", "decode", "serialize", "deserialize"] +license = "MIT" +description = "Implementation of #[derive(Encode, Decode)] for bincode" + +[lib] +proc-macro = true + +[dependencies] +virtue = "0.0.18" diff --git a/vendor/bincode_derive-2.0.1/LICENSE.md b/vendor/bincode_derive-2.0.1/LICENSE.md new file mode 100644 index 0000000..26b1f00 --- /dev/null +++ b/vendor/bincode_derive-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_derive-2.0.1/readme.md b/vendor/bincode_derive-2.0.1/readme.md new file mode 100644 index 0000000..0e652ce --- /dev/null +++ b/vendor/bincode_derive-2.0.1/readme.md @@ -0,0 +1,28 @@ +# Bincode-derive + +The derive crate for bincode. Implements `bincode::Encode` and `bincode::Decode`. + +This crate is roughly split into 2 parts: + +# Parsing + +Most of parsing is done in the `src/parse/` folder. This will generate the following types: +- `Attributes`, not being used currently +- `Visibility`, not being used currently +- `DataType` either `Struct` or `Enum`, with the name of the data type being parsed +- `Generics` the generics part of the type, e.g. `struct Foo<'a>` +- `GenericConstraints` the "where" part of the type + +# Generate + +Generating the code implementation is done in either `src/derive_enum.rs` and `src/derive_struct.rs`. + +This is supported by the structs in `src/generate`. The most notable points of this module are: +- `StreamBuilder` is a thin but friendly wrapper around `TokenStream` +- `Generator` is the base type of the code generator. This has helper methods to generate implementations: + - `ImplFor` is a helper struct for a single `impl A for B` construction. In this functions can be defined: + - `GenerateFnBody` is a helper struct for a single function in the above `impl`. This is created with a callback to `FnBuilder` which helps set some properties. `GenerateFnBody` has a `stream()` function which returns ` StreamBuilder` for the function. + +For additional derive testing, see the test cases in `../tests` + +For testing purposes, all generated code is outputted to the current `target/generated/bincode` folder, under file name `_Encode.rs` and `_Decode.rs`. This can help with debugging. diff --git a/vendor/bincode_derive-2.0.1/src/attribute.rs b/vendor/bincode_derive-2.0.1/src/attribute.rs new file mode 100644 index 0000000..d6e8042 --- /dev/null +++ b/vendor/bincode_derive-2.0.1/src/attribute.rs @@ -0,0 +1,131 @@ +use virtue::prelude::*; +use virtue::utils::{parse_tagged_attribute, ParsedAttribute}; + +pub struct ContainerAttributes { + pub crate_name: String, + pub bounds: Option<(String, Literal)>, + pub decode_bounds: Option<(String, Literal)>, + pub decode_context: Option<(String, Literal)>, + pub borrow_decode_bounds: Option<(String, Literal)>, + pub encode_bounds: Option<(String, Literal)>, +} + +impl Default for ContainerAttributes { + fn default() -> Self { + Self { + crate_name: "::bincode".to_string(), + bounds: None, + decode_bounds: None, + decode_context: None, + encode_bounds: None, + borrow_decode_bounds: None, + } + } +} + +impl FromAttribute for ContainerAttributes { + fn parse(group: &Group) -> Result> { + let attributes = match parse_tagged_attribute(group, "bincode")? { + Some(body) => body, + None => return Ok(None), + }; + let mut result = Self::default(); + for attribute in attributes { + match attribute { + ParsedAttribute::Property(key, val) if key.to_string() == "crate" => { + let val_string = val.to_string(); + if val_string.starts_with('"') && val_string.ends_with('"') { + result.crate_name = val_string[1..val_string.len() - 1].to_string(); + } else { + return Err(Error::custom_at("Should be a literal str", val.span())); + } + } + ParsedAttribute::Property(key, val) if key.to_string() == "bounds" => { + let val_string = val.to_string(); + if val_string.starts_with('"') && val_string.ends_with('"') { + result.bounds = + Some((val_string[1..val_string.len() - 1].to_string(), val)); + } else { + return Err(Error::custom_at("Should be a literal str", val.span())); + } + } + ParsedAttribute::Property(key, val) if key.to_string() == "decode_bounds" => { + let val_string = val.to_string(); + if val_string.starts_with('"') && val_string.ends_with('"') { + result.decode_bounds = + Some((val_string[1..val_string.len() - 1].to_string(), val)); + } else { + return Err(Error::custom_at("Should be a literal str", val.span())); + } + } + ParsedAttribute::Property(key, val) if key.to_string() == "decode_context" => { + let val_string = val.to_string(); + if val_string.starts_with('"') && val_string.ends_with('"') { + result.decode_context = + Some((val_string[1..val_string.len() - 1].to_string(), val)); + } else { + return Err(Error::custom_at("Should be a literal str", val.span())); + } + } + ParsedAttribute::Property(key, val) if key.to_string() == "encode_bounds" => { + let val_string = val.to_string(); + if val_string.starts_with('"') && val_string.ends_with('"') { + result.encode_bounds = + Some((val_string[1..val_string.len() - 1].to_string(), val)); + } else { + return Err(Error::custom_at("Should be a literal str", val.span())); + } + } + ParsedAttribute::Property(key, val) + if key.to_string() == "borrow_decode_bounds" => + { + let val_string = val.to_string(); + if val_string.starts_with('"') && val_string.ends_with('"') { + result.borrow_decode_bounds = + Some((val_string[1..val_string.len() - 1].to_string(), val)); + } else { + return Err(Error::custom_at("Should be a literal str", val.span())); + } + } + ParsedAttribute::Tag(i) => { + return Err(Error::custom_at("Unknown field attribute", i.span())) + } + ParsedAttribute::Property(key, _) => { + return Err(Error::custom_at("Unknown field attribute", key.span())) + } + _ => {} + } + } + Ok(Some(result)) + } +} + +#[derive(Default)] +pub struct FieldAttributes { + pub with_serde: bool, +} + +impl FromAttribute for FieldAttributes { + fn parse(group: &Group) -> Result> { + let attributes = match parse_tagged_attribute(group, "bincode")? { + Some(body) => body, + None => return Ok(None), + }; + let mut result = Self::default(); + for attribute in attributes { + match attribute { + ParsedAttribute::Tag(i) if i.to_string() == "with_serde" => { + result.with_serde = true; + } + ParsedAttribute::Tag(i) => { + return Err(Error::custom_at("Unknown field attribute", i.span())) + } + ParsedAttribute::Property(key, _) => { + return Err(Error::custom_at("Unknown field attribute", key.span())) + } + _ => {} + } + } + Ok(Some(result)) + } +} diff --git a/vendor/bincode_derive-2.0.1/src/derive_enum.rs b/vendor/bincode_derive-2.0.1/src/derive_enum.rs new file mode 100644 index 0000000..2ba17c5 --- /dev/null +++ b/vendor/bincode_derive-2.0.1/src/derive_enum.rs @@ -0,0 +1,449 @@ +use crate::attribute::{ContainerAttributes, FieldAttributes}; +use virtue::prelude::*; + +const TUPLE_FIELD_PREFIX: &str = "field_"; + +pub(crate) struct DeriveEnum { + pub variants: Vec, + pub attributes: ContainerAttributes, +} + +impl DeriveEnum { + fn iter_fields(&self) -> EnumVariantIterator { + EnumVariantIterator { + idx: 0, + variants: &self.variants, + } + } + + pub fn generate_encode(self, generator: &mut Generator) -> Result<()> { + let crate_name = self.attributes.crate_name.as_str(); + generator + .impl_for(format!("{}::Encode", crate_name)) + .modify_generic_constraints(|generics, where_constraints| { + if let Some((bounds, lit)) = + (self.attributes.encode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) + { + where_constraints.clear(); + where_constraints + .push_parsed_constraint(bounds) + .map_err(|e| e.with_span(lit.span()))?; + } else { + for g in generics.iter_generics() { + where_constraints + .push_constraint(g, format!("{}::Encode", crate_name)) + .unwrap(); + } + } + Ok(()) + })? + .generate_fn("encode") + .with_generic_deps("__E", [format!("{}::enc::Encoder", crate_name)]) + .with_self_arg(FnSelfArg::RefSelf) + .with_arg("encoder", "&mut __E") + .with_return_type(format!( + "core::result::Result<(), {}::error::EncodeError>", + crate_name + )) + .body(|fn_body| { + fn_body.ident_str("match"); + fn_body.ident_str("self"); + fn_body.group(Delimiter::Brace, |match_body| { + if self.variants.is_empty() { + self.encode_empty_enum_case(match_body)?; + } + for (variant_index, variant) in self.iter_fields() { + // Self::Variant + match_body.ident_str("Self"); + match_body.puncts("::"); + match_body.ident(variant.name.clone()); + + // if we have any fields, declare them here + // Self::Variant { a, b, c } + if let Some(fields) = variant.fields.as_ref() { + let delimiter = fields.delimiter(); + match_body.group(delimiter, |field_body| { + for (idx, field_name) in fields.names().into_iter().enumerate() { + if idx != 0 { + field_body.punct(','); + } + field_body.push( + field_name.to_token_tree_with_prefix(TUPLE_FIELD_PREFIX), + ); + } + Ok(()) + })?; + } + + // Arrow + // Self::Variant { a, b, c } => + match_body.puncts("=>"); + + // Body of this variant + // Note that the fields are available as locals because of the match destructuring above + // { + // encoder.encode_u32(n)?; + // bincode::Encode::encode(a, encoder)?; + // bincode::Encode::encode(b, encoder)?; + // bincode::Encode::encode(c, encoder)?; + // } + match_body.group(Delimiter::Brace, |body| { + // variant index + body.push_parsed(format!("::encode", crate_name))?; + body.group(Delimiter::Parenthesis, |args| { + args.punct('&'); + args.group(Delimiter::Parenthesis, |num| { + num.extend(variant_index); + Ok(()) + })?; + args.punct(','); + args.push_parsed("encoder")?; + Ok(()) + })?; + body.punct('?'); + body.punct(';'); + // If we have any fields, encode them all one by one + if let Some(fields) = variant.fields.as_ref() { + for field_name in fields.names() { + let attributes = field_name + .attributes() + .get_attribute::()? + .unwrap_or_default(); + if attributes.with_serde { + body.push_parsed(format!( + "{0}::Encode::encode(&{0}::serde::Compat({1}), encoder)?;", + crate_name, + field_name.to_string_with_prefix(TUPLE_FIELD_PREFIX), + ))?; + } else { + body.push_parsed(format!( + "{0}::Encode::encode({1}, encoder)?;", + crate_name, + field_name.to_string_with_prefix(TUPLE_FIELD_PREFIX), + ))?; + } + } + } + body.push_parsed("core::result::Result::Ok(())")?; + Ok(()) + })?; + match_body.punct(','); + } + Ok(()) + })?; + Ok(()) + })?; + Ok(()) + } + + /// If we're encoding an empty enum, we need to add an empty case in the form of: + /// `_ => core::unreachable!(),` + fn encode_empty_enum_case(&self, builder: &mut StreamBuilder) -> Result { + builder.push_parsed("_ => core::unreachable!()").map(|_| ()) + } + + /// Build the catch-all case for an int-to-enum decode implementation + fn invalid_variant_case(&self, enum_name: &str, result: &mut StreamBuilder) -> Result { + let crate_name = self.attributes.crate_name.as_str(); + + // we'll be generating: + // variant => Err( + // bincode::error::DecodeError::UnexpectedVariant { + // found: variant, + // type_name: + // allowed: ..., + // } + // ) + // + // Where allowed is either: + // - bincode::error::AllowedEnumVariants::Range { min: 0, max: } + // if we have no fixed value variants + // - bincode::error::AllowedEnumVariants::Allowed(&[, , ...]) + // if we have fixed value variants + result.ident_str("variant"); + result.puncts("=>"); + result.push_parsed("core::result::Result::Err")?; + result.group(Delimiter::Parenthesis, |err_inner| { + err_inner.push_parsed(format!( + "{}::error::DecodeError::UnexpectedVariant", + crate_name + ))?; + err_inner.group(Delimiter::Brace, |variant_inner| { + variant_inner.ident_str("found"); + variant_inner.punct(':'); + variant_inner.ident_str("variant"); + variant_inner.punct(','); + + variant_inner.ident_str("type_name"); + variant_inner.punct(':'); + variant_inner.lit_str(enum_name); + variant_inner.punct(','); + + variant_inner.ident_str("allowed"); + variant_inner.punct(':'); + + if self.variants.iter().any(|i| i.value.is_some()) { + // we have fixed values, implement AllowedEnumVariants::Allowed + variant_inner.push_parsed(format!( + "&{}::error::AllowedEnumVariants::Allowed", + crate_name + ))?; + variant_inner.group(Delimiter::Parenthesis, |allowed_inner| { + allowed_inner.punct('&'); + allowed_inner.group(Delimiter::Bracket, |allowed_slice| { + for (idx, (ident, _)) in self.iter_fields().enumerate() { + if idx != 0 { + allowed_slice.punct(','); + } + allowed_slice.extend(ident); + } + Ok(()) + })?; + Ok(()) + })?; + } else { + // no fixed values, implement a range + variant_inner.push_parsed(format!( + "&{0}::error::AllowedEnumVariants::Range {{ min: 0, max: {1} }}", + crate_name, + self.variants.len() - 1 + ))?; + } + Ok(()) + })?; + Ok(()) + })?; + Ok(()) + } + + pub fn generate_decode(self, generator: &mut Generator) -> Result<()> { + let crate_name = self.attributes.crate_name.as_str(); + + let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context { + decode_context.as_str() + } else { + "__Context" + }; + // Remember to keep this mostly in sync with generate_borrow_decode + + let enum_name = generator.target_name().to_string(); + + let mut impl_for = generator.impl_for(format!("{}::Decode", crate_name)); + + if self.attributes.decode_context.is_none() { + impl_for = impl_for.with_impl_generics(["__Context"]); + } + + impl_for + .with_trait_generics([decode_context]) + .modify_generic_constraints(|generics, where_constraints| { + if let Some((bounds, lit)) = (self.attributes.decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) { + where_constraints.clear(); + where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?; + } else { + for g in generics.iter_generics() { + where_constraints.push_constraint(g, format!("{}::Decode<__Context>", crate_name))?; + } + } + Ok(()) + })? + .generate_fn("decode") + .with_generic_deps("__D", [format!("{}::de::Decoder", crate_name, decode_context)]) + .with_arg("decoder", "&mut __D") + .with_return_type(format!("core::result::Result", crate_name)) + .body(|fn_builder| { + if self.variants.is_empty() { + fn_builder.push_parsed(format!( + "core::result::Result::Err({}::error::DecodeError::EmptyEnum {{ type_name: core::any::type_name::() }})", + crate_name + ))?; + } else { + fn_builder + .push_parsed(format!( + "let variant_index = >::decode(decoder)?;", + crate_name + ))?; + fn_builder.push_parsed("match variant_index")?; + fn_builder.group(Delimiter::Brace, |variant_case| { + for (mut variant_index, variant) in self.iter_fields() { + // idx => Ok(..) + if variant_index.len() > 1 { + variant_case.push_parsed("x if x == ")?; + variant_case.extend(variant_index); + } else { + variant_case.push(variant_index.remove(0)); + } + variant_case.puncts("=>"); + variant_case.push_parsed("core::result::Result::Ok")?; + variant_case.group(Delimiter::Parenthesis, |variant_case_body| { + // Self::Variant { } + // Self::Variant { 0: ..., 1: ... 2: ... }, + // Self::Variant { a: ..., b: ... c: ... }, + variant_case_body.ident_str("Self"); + variant_case_body.puncts("::"); + variant_case_body.ident(variant.name.clone()); + + variant_case_body.group(Delimiter::Brace, |variant_body| { + if let Some(fields) = variant.fields.as_ref() { + let is_tuple = matches!(fields, Fields::Tuple(_)); + for (idx, field) in fields.names().into_iter().enumerate() { + if is_tuple { + variant_body.lit_usize(idx); + } else { + variant_body.ident(field.unwrap_ident().clone()); + } + variant_body.punct(':'); + let attributes = field.attributes().get_attribute::()?.unwrap_or_default(); + if attributes.with_serde { + variant_body + .push_parsed(format!( + "<{0}::serde::Compat<_> as {0}::Decode::<__D::Context>>::decode(decoder)?.0,", + crate_name + ))?; + } else { + variant_body + .push_parsed(format!( + "{}::Decode::<__D::Context>::decode(decoder)?,", + crate_name + ))?; + } + } + } + Ok(()) + })?; + Ok(()) + })?; + variant_case.punct(','); + } + + // invalid idx + self.invalid_variant_case(&enum_name, variant_case) + })?; + } + Ok(()) + })?; + self.generate_borrow_decode(generator)?; + Ok(()) + } + + pub fn generate_borrow_decode(self, generator: &mut Generator) -> Result<()> { + let crate_name = &self.attributes.crate_name; + + let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context { + decode_context.as_str() + } else { + "__Context" + }; + + // Remember to keep this mostly in sync with generate_decode + let enum_name = generator.target_name().to_string(); + + let mut impl_for = generator + .impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"]) + .with_trait_generics([decode_context]); + if self.attributes.decode_context.is_none() { + impl_for = impl_for.with_impl_generics(["__Context"]); + } + + impl_for + .modify_generic_constraints(|generics, where_constraints| { + if let Some((bounds, lit)) = (self.attributes.borrow_decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) { + where_constraints.clear(); + where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?; + } else { + for g in generics.iter_generics() { + where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de, {}>", crate_name, decode_context)).unwrap(); + } + for lt in generics.iter_lifetimes() { + where_constraints.push_parsed_constraint(format!("'__de: '{}", lt.ident))?; + } + } + Ok(()) + })? + .generate_fn("borrow_decode") + .with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de, Context = {}>", crate_name, decode_context)]) + .with_arg("decoder", "&mut __D") + .with_return_type(format!("core::result::Result", crate_name)) + .body(|fn_builder| { + if self.variants.is_empty() { + fn_builder.push_parsed(format!( + "core::result::Result::Err({}::error::DecodeError::EmptyEnum {{ type_name: core::any::type_name::() }})", + crate_name + ))?; + } else { + fn_builder + .push_parsed(format!("let variant_index = >::decode(decoder)?;", crate_name))?; + fn_builder.push_parsed("match variant_index")?; + fn_builder.group(Delimiter::Brace, |variant_case| { + for (mut variant_index, variant) in self.iter_fields() { + // idx => Ok(..) + if variant_index.len() > 1 { + variant_case.push_parsed("x if x == ")?; + variant_case.extend(variant_index); + } else { + variant_case.push(variant_index.remove(0)); + } + variant_case.puncts("=>"); + variant_case.push_parsed("core::result::Result::Ok")?; + variant_case.group(Delimiter::Parenthesis, |variant_case_body| { + // Self::Variant { } + // Self::Variant { 0: ..., 1: ... 2: ... }, + // Self::Variant { a: ..., b: ... c: ... }, + variant_case_body.ident_str("Self"); + variant_case_body.puncts("::"); + variant_case_body.ident(variant.name.clone()); + + variant_case_body.group(Delimiter::Brace, |variant_body| { + if let Some(fields) = variant.fields.as_ref() { + let is_tuple = matches!(fields, Fields::Tuple(_)); + for (idx, field) in fields.names().into_iter().enumerate() { + if is_tuple { + variant_body.lit_usize(idx); + } else { + variant_body.ident(field.unwrap_ident().clone()); + } + variant_body.punct(':'); + let attributes = field.attributes().get_attribute::()?.unwrap_or_default(); + if attributes.with_serde { + variant_body + .push_parsed(format!("<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode::<__D::Context>>::borrow_decode(decoder)?.0,", crate_name))?; + } else { + variant_body.push_parsed(format!("{}::BorrowDecode::<__D::Context>::borrow_decode(decoder)?,", crate_name))?; + } + } + } + Ok(()) + })?; + Ok(()) + })?; + variant_case.punct(','); + } + + // invalid idx + self.invalid_variant_case(&enum_name, variant_case) + })?; + } + Ok(()) + })?; + Ok(()) + } +} + +struct EnumVariantIterator<'a> { + variants: &'a [EnumVariant], + idx: usize, +} + +impl<'a> Iterator for EnumVariantIterator<'a> { + type Item = (Vec, &'a EnumVariant); + + fn next(&mut self) -> Option { + let idx = self.idx; + let variant = self.variants.get(self.idx)?; + self.idx += 1; + + let tokens = vec![TokenTree::Literal(Literal::u32_suffixed(idx as u32))]; + + Some((tokens, variant)) + } +} diff --git a/vendor/bincode_derive-2.0.1/src/derive_struct.rs b/vendor/bincode_derive-2.0.1/src/derive_struct.rs new file mode 100644 index 0000000..93a63a0 --- /dev/null +++ b/vendor/bincode_derive-2.0.1/src/derive_struct.rs @@ -0,0 +1,211 @@ +use crate::attribute::{ContainerAttributes, FieldAttributes}; +use virtue::prelude::*; + +pub(crate) struct DeriveStruct { + pub fields: Option, + pub attributes: ContainerAttributes, +} + +impl DeriveStruct { + pub fn generate_encode(self, generator: &mut Generator) -> Result<()> { + let crate_name = &self.attributes.crate_name; + generator + .impl_for(format!("{}::Encode", crate_name)) + .modify_generic_constraints(|generics, where_constraints| { + if let Some((bounds, lit)) = + (self.attributes.encode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) + { + where_constraints.clear(); + where_constraints + .push_parsed_constraint(bounds) + .map_err(|e| e.with_span(lit.span()))?; + } else { + for g in generics.iter_generics() { + where_constraints + .push_constraint(g, format!("{}::Encode", crate_name)) + .unwrap(); + } + } + Ok(()) + })? + .generate_fn("encode") + .with_generic_deps("__E", [format!("{}::enc::Encoder", crate_name)]) + .with_self_arg(virtue::generate::FnSelfArg::RefSelf) + .with_arg("encoder", "&mut __E") + .with_return_type(format!( + "core::result::Result<(), {}::error::EncodeError>", + crate_name + )) + .body(|fn_body| { + if let Some(fields) = self.fields.as_ref() { + for field in fields.names() { + let attributes = field + .attributes() + .get_attribute::()? + .unwrap_or_default(); + if attributes.with_serde { + fn_body.push_parsed(format!( + "{0}::Encode::encode(&{0}::serde::Compat(&self.{1}), encoder)?;", + crate_name, field + ))?; + } else { + fn_body.push_parsed(format!( + "{}::Encode::encode(&self.{}, encoder)?;", + crate_name, field + ))?; + } + } + } + fn_body.push_parsed("core::result::Result::Ok(())")?; + Ok(()) + })?; + Ok(()) + } + + pub fn generate_decode(self, generator: &mut Generator) -> Result<()> { + // Remember to keep this mostly in sync with generate_borrow_decode + let crate_name = &self.attributes.crate_name; + let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context { + decode_context.as_str() + } else { + "__Context" + }; + + let mut impl_for = generator.impl_for(format!("{}::Decode", crate_name)); + if self.attributes.decode_context.is_none() { + impl_for = impl_for.with_impl_generics(["__Context"]); + } + + impl_for + .with_trait_generics([decode_context]) + .modify_generic_constraints(|generics, where_constraints| { + if let Some((bounds, lit)) = (self.attributes.decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) { + where_constraints.clear(); + where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?; + } else { + for g in generics.iter_generics() { + where_constraints.push_constraint(g, format!("{}::Decode<{}>", crate_name, decode_context)).unwrap(); + } + } + Ok(()) + })? + .generate_fn("decode") + .with_generic_deps("__D", [format!("{}::de::Decoder", crate_name, decode_context)]) + .with_arg("decoder", "&mut __D") + .with_return_type(format!("core::result::Result", crate_name)) + .body(|fn_body| { + // Ok(Self { + fn_body.push_parsed("core::result::Result::Ok")?; + fn_body.group(Delimiter::Parenthesis, |ok_group| { + ok_group.ident_str("Self"); + ok_group.group(Delimiter::Brace, |struct_body| { + // Fields + // { + // a: bincode::Decode::decode(decoder)?, + // b: bincode::Decode::decode(decoder)?, + // ... + // } + if let Some(fields) = self.fields.as_ref() { + for field in fields.names() { + let attributes = field.attributes().get_attribute::()?.unwrap_or_default(); + if attributes.with_serde { + struct_body + .push_parsed(format!( + "{1}: (<{0}::serde::Compat<_> as {0}::Decode::<{2}>>::decode(decoder)?).0,", + crate_name, + field, + decode_context, + ))?; + } else { + struct_body + .push_parsed(format!( + "{1}: {0}::Decode::decode(decoder)?,", + crate_name, + field + ))?; + } + } + } + Ok(()) + })?; + Ok(()) + })?; + Ok(()) + })?; + self.generate_borrow_decode(generator)?; + Ok(()) + } + + pub fn generate_borrow_decode(self, generator: &mut Generator) -> Result<()> { + // Remember to keep this mostly in sync with generate_decode + let crate_name = self.attributes.crate_name; + + let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context { + decode_context.as_str() + } else { + "__Context" + }; + + let mut impl_for = generator + .impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"]) + .with_trait_generics([decode_context]); + if self.attributes.decode_context.is_none() { + impl_for = impl_for.with_impl_generics(["__Context"]); + } + + impl_for + .modify_generic_constraints(|generics, where_constraints| { + if let Some((bounds, lit)) = (self.attributes.borrow_decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) { + where_constraints.clear(); + where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?; + } else { + for g in generics.iter_generics() { + where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de, {}>", crate_name, decode_context)).unwrap(); + } + for lt in generics.iter_lifetimes() { + where_constraints.push_parsed_constraint(format!("'__de: '{}", lt.ident))?; + } + } + Ok(()) + })? + .generate_fn("borrow_decode") + .with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de, Context = {}>", crate_name, decode_context)]) + .with_arg("decoder", "&mut __D") + .with_return_type(format!("core::result::Result", crate_name)) + .body(|fn_body| { + // Ok(Self { + fn_body.push_parsed("core::result::Result::Ok")?; + fn_body.group(Delimiter::Parenthesis, |ok_group| { + ok_group.ident_str("Self"); + ok_group.group(Delimiter::Brace, |struct_body| { + if let Some(fields) = self.fields.as_ref() { + for field in fields.names() { + let attributes = field.attributes().get_attribute::()?.unwrap_or_default(); + if attributes.with_serde { + struct_body + .push_parsed(format!( + "{1}: (<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode::<'_, {2}>>::borrow_decode(decoder)?).0,", + crate_name, + field, + decode_context, + ))?; + } else { + struct_body + .push_parsed(format!( + "{1}: {0}::BorrowDecode::<'_, {2}>::borrow_decode(decoder)?,", + crate_name, + field, + decode_context, + ))?; + } + } + } + Ok(()) + })?; + Ok(()) + })?; + Ok(()) + })?; + Ok(()) + } +} diff --git a/vendor/bincode_derive-2.0.1/src/lib.rs b/vendor/bincode_derive-2.0.1/src/lib.rs new file mode 100644 index 0000000..166bb2f --- /dev/null +++ b/vendor/bincode_derive-2.0.1/src/lib.rs @@ -0,0 +1,105 @@ +mod attribute; +mod derive_enum; +mod derive_struct; + +use attribute::ContainerAttributes; +use virtue::prelude::*; + +#[proc_macro_derive(Encode, attributes(bincode))] +pub fn derive_encode(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + derive_encode_inner(input).unwrap_or_else(|e| e.into_token_stream()) +} + +fn derive_encode_inner(input: TokenStream) -> Result { + let parse = Parse::new(input)?; + let (mut generator, attributes, body) = parse.into_generator(); + let attributes = attributes + .get_attribute::()? + .unwrap_or_default(); + + match body { + Body::Struct(body) => { + derive_struct::DeriveStruct { + fields: body.fields, + attributes, + } + .generate_encode(&mut generator)?; + } + Body::Enum(body) => { + derive_enum::DeriveEnum { + variants: body.variants, + attributes, + } + .generate_encode(&mut generator)?; + } + } + + generator.export_to_file("bincode", "Encode"); + generator.finish() +} + +#[proc_macro_derive(Decode, attributes(bincode))] +pub fn derive_decode(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + derive_decode_inner(input).unwrap_or_else(|e| e.into_token_stream()) +} + +fn derive_decode_inner(input: TokenStream) -> Result { + let parse = Parse::new(input)?; + let (mut generator, attributes, body) = parse.into_generator(); + let attributes = attributes + .get_attribute::()? + .unwrap_or_default(); + + match body { + Body::Struct(body) => { + derive_struct::DeriveStruct { + fields: body.fields, + attributes, + } + .generate_decode(&mut generator)?; + } + Body::Enum(body) => { + derive_enum::DeriveEnum { + variants: body.variants, + attributes, + } + .generate_decode(&mut generator)?; + } + } + + generator.export_to_file("bincode", "Decode"); + generator.finish() +} + +#[proc_macro_derive(BorrowDecode, attributes(bincode))] +pub fn derive_borrow_decode(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + derive_borrow_decode_inner(input).unwrap_or_else(|e| e.into_token_stream()) +} + +fn derive_borrow_decode_inner(input: TokenStream) -> Result { + let parse = Parse::new(input)?; + let (mut generator, attributes, body) = parse.into_generator(); + let attributes = attributes + .get_attribute::()? + .unwrap_or_default(); + + match body { + Body::Struct(body) => { + derive_struct::DeriveStruct { + fields: body.fields, + attributes, + } + .generate_borrow_decode(&mut generator)?; + } + Body::Enum(body) => { + derive_enum::DeriveEnum { + variants: body.variants, + attributes, + } + .generate_borrow_decode(&mut generator)?; + } + } + + generator.export_to_file("bincode", "BorrowDecode"); + generator.finish() +} diff --git a/vendor/provenance.json b/vendor/provenance.json new file mode 100644 index 0000000..9d567df --- /dev/null +++ b/vendor/provenance.json @@ -0,0 +1,134 @@ +{ + "baseline": "e4cfd4c", + "packages": [ + { + "allowed_manifest_deltas": [ + { + "after": "1.75", + "before": "1.85.0", + "path": [ + "package", + "rust-version" + ] + }, + { + "after": "=2.0.1", + "before": "2.0.1", + "path": [ + "dependencies", + "bincode_derive", + "version" + ] + } + ], + "archive": "upstream/bincode-2.0.1.crate", + "files": { + ".cargo_vcs_info.json": "fb3753ea9fb359976d4446c1b6b79dab1f00752275bd2906d6e85fc9b38243c7", + ".mailmap": "dd72318107ef4d669ca6afc82ec65fd16e3765144794627ec195bb597458c137", + ".rustfmt.toml": "8f201bf4d9ff69411e98031ad1b168f58ce02d91fd33bc80406115c2506355d4", + "CODE_OF_CONDUCT.md": "1aaf7ba84cd5ba4bf57351ac4ab5ebef47af4119f7a4a565d1bfd90a1347f197", + "Cargo.lock": "2a627f6bad4b87786e3783347eb29ac05b34d35cab997640f7e5f19d739341d4", + "Cargo.toml": "13ec1ceb0b2e62982668e358079b09466dba3757c246503c3b56e5b094ae484d", + "Cargo.toml.orig": "bc3493695855b1a7b89fe4e5c345a637751de471106ca58dd04d2a1ca5121c83", + "LICENSE.md": "90d7e062634054e6866d3c81e6a2b3058a840e6af733e98e80bdfe1a7dec6912", + "benches/inline.rs": "957aa40a798268af08ea07e2ef6eed7a3ea271e65e22f338a04defd209f8595f", + "benches/string.rs": "346dd7c0b2b934158a158b94c47c4bbe06f089adeb3f24a8bf65ee439ae11ec0", + "benches/varint.rs": "b57e86e626ac7c68c4a866dd431e1aa633cb66fc45db0d70c68cce936bff9f27", + "docs/migration_guide.md": "627982890a984c0742e7faf7d3484a3179070a16a2553c180d8237e79056329d", + "docs/spec.md": "cc8f4125c5b4250dd4ae4edca9e6a93e323f2a5f9121760041ef5e4d8dd19f7c", + "readme.md": "d38641c831939b2e00c5d0dc22ae333d807632e03b93204c7d1dd62d3532b411", + "src/atomic.rs": "7058988f0eee71a8070701605d819623e0da2ee82bf49ed7d512683b1b428203", + "src/config.rs": "e1b1122010e9aa313ba1b342d0f17320bc4652aa82d78ac14e6dcec2fc2ac349", + "src/de/decoder.rs": "1d075ebcff6c35edfc262da683ff973c9047ccf1b53998122d68c06ef365d3c1", + "src/de/impl_core.rs": "d58f0ef2f7d386c17519bc010add4e4133e249c44cc66ae488814f6eabf831b5", + "src/de/impl_tuples.rs": "0a6501fa9ec5c82856e6aaf2fdabbdd4da87a7489441eadc974f23920849c28b", + "src/de/impls.rs": "edba5b823ec87741f6436c834ede4a5c17fb1eb6c0cbb6d704c424ebd6fc535e", + "src/de/mod.rs": "c75b71b3ac44c010d62ee6d4cff5e053b96c50d107399536e18e21bc52d25fed", + "src/de/read.rs": "c153b52f8819f0999d3c4af850109d812143359d02237d6b074ee830a9277d20", + "src/enc/encoder.rs": "508bd324315315409f6e24195104c5320a5cfcc54a72905e69e35272649c56ea", + "src/enc/impl_tuples.rs": "e375a3afb8aea0fda9ab263adcae072679cdf038998295ab62b979b5647c82df", + "src/enc/impls.rs": "0bf22625f0ecd4f3c5bfc0d9d398b250dde741aa6956ec992472832352a98465", + "src/enc/mod.rs": "5513fb0a10e913202892c7b0c6def9a20a1a9ea4dc2069a0d688babea71440d7", + "src/enc/write.rs": "60def760d964bc13832fb8ec31fdbfa5c851447d11d0a7a8364ba4c73e475d9c", + "src/error.rs": "2ab3459a5771fd93ea0588e86ddceaa8c9fb076627ecfb5c3f3726c1e1dc3902", + "src/features/derive.rs": "ac6460101a4b9cc59278e07d4a1154c3c909349fe5be2f94ce6e508df6f6e06b", + "src/features/impl_alloc.rs": "b238e3ffd914b84600906a69dc424bcd541c0e45391f9f844d1735527bc7ade0", + "src/features/impl_std.rs": "d3ae7d9a17b127887665af46db1c09c62eb7ffa5f604ed288d799bf0d4aab45b", + "src/features/mod.rs": "196e870a2da26c86e34f8468436ea04dee740aa821e986dddbefca34fa9a50cd", + "src/features/serde/de_borrowed.rs": "0bb2874cb55081ad388cbd9595efe90f81c7911c33ec8680f989471049afc54c", + "src/features/serde/de_owned.rs": "37d59be8d4434fcb798e14bcbcaeac602c6b38d8bb4550c32ec185a245ad074c", + "src/features/serde/mod.rs": "554abad4103a2bab7ba70facc33fe76b37ebdf5dae8bdf1cc58f412762c9bfd7", + "src/features/serde/ser.rs": "a0d848095e452778db02212a065ca4f5f183cc5780faf10c9d8a811c8a167468", + "src/lib.rs": "5120016e355d73176bc596cfb393af4a5492ac2f2a5d4bca0b942d60ee468138", + "src/utils.rs": "6ffc2504084c5ff26433a50905fdcaf4a984d678bd8eae1fa40ffaace3535ef4", + "src/varint/decode_signed.rs": "756203c67a9bee4079a0de78341309c09579761a62b06e033a53cacdb73642a3", + "src/varint/decode_unsigned.rs": "6e18183fb44cdb874ae2206b158d4ea629512090be2fd2322709fe1e2b108f65", + "src/varint/encode_signed.rs": "8ad5896cbe1f9b39b2acb80e74588362a18060a86b0e24d3df17f6d153c77bb0", + "src/varint/encode_unsigned.rs": "37f3ac960ee0d0b3ef1dfd110518ae4aa70c514c9f67b61dd45c858f0aaaa73b", + "src/varint/mod.rs": "029aac1f7faba793c36f6cecb35f1192c64c91b09cd17883fa26cc3326028de9", + "tests/alloc.rs": "2e9b6cfa7e36f0688d1785f529f5c28c7d7fa06d4e434519c45cde2abe0d9f89", + "tests/atomic.rs": "45f7eb2137ea3aed5f17c2ed0729722c0caedd9f43ecd609bb06606d53ec23f7", + "tests/basic_types.rs": "de90572e704a2bc178558620906417ad016088057bcf41a32f1780382c05100b", + "tests/context.rs": "1c3984c49249cee37911cf4a2a9908b4a26ce16a95f391950d43aef2e26ecf31", + "tests/derive.rs": "88dc709944ca7e991667dba83df71347adf75d2734651e2a296893d5c65fc3d0", + "tests/derive_rename.rs": "0d7e7898ed9ae85814a452923326926bbbc4b01282bbac2a4f79aedb9b4a82d6", + "tests/error_size.rs": "567a10c6c1f5f4e26ce2374e285a6097f42f325c58ce2a3fc90621ad1740c7f5", + "tests/issues.rs": "f068da1a3b99759a402507f643310e1bceed36a56b3324f721e3ca2f7320b9fc", + "tests/issues/issue_427.rs": "63cb61c4ff60a3eab6041b68277a8874d77ecb71d0a998b83d5eb1ad75d6825a", + "tests/issues/issue_431.rs": "36fcdf67cdf9d3f63db30f5bfbf3a7d906b65ee04bcc03ae1d80da4249dac2a3", + "tests/issues/issue_459.rs": "476a975dd548741936e2f849c3a4a9023c222a44ccb66fe7282fcdacf336074a", + "tests/issues/issue_467.rs": "9f5bd6d268e1a4d6f550e90b5efd22b45581e6c1f1e9fbfc1fe1196794703ec0", + "tests/issues/issue_474.rs": "96b339c743cdc0a8b2fdd2b2f8e7d0f7d5e1d974cc951ce70c71933ce34667e2", + "tests/issues/issue_498.rs": "2d1e38f1c01ab0df97a59e569fd24277003ee9b6b311920484c9c19975f314d2", + "tests/issues/issue_500.rs": "97c24d7286ff0e936aa0d3b5a8cce629f3e5bc74ce9b844f9e83365107a9279c", + "tests/issues/issue_523.rs": "f894057122aa37f3d6b4be4d5cc379015041967bbab6f0d06db6b3666eb97fc4", + "tests/issues/issue_537.rs": "15b2905866049b1c965a41dbf1e5a7fa80f2b8aecdfe9d599374563c6397502f", + "tests/issues/issue_547.rs": "098cd699de4eb72e0f486b2f59bde47c96dc9eed06d4141a83e7c7482f73c8fa", + "tests/issues/issue_570.rs": "5ae99e10a1f36490cf71793501342b3216299e16987f28ef524a1e5fd1ca936f", + "tests/issues/issue_592.rs": "14b6debe6f0f93199be5937f50c664f4ffa07d11e8280bf07ec3edb138837324", + "tests/issues/issue_614.rs": "49d9278001601e9cbd2ba0744cb91398105c29b082388518ba7544324ff39170", + "tests/serde.rs": "f2099f9730fc833f18f712a5969de8e8ad0153770f04288b9fcecf6618cdb782", + "tests/std.rs": "d4a378c6d4e3bb0aa9b1f3211072e98b9f81c917443ca7ea36d752764e8ba7a5", + "tests/utils.rs": "3e9caaa06495b93098aa27dca4e5b9af94ca6abce90a6c3d254933fab1b98263" + }, + "license": "MIT", + "name": "bincode", + "sha256": "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "upstream": "https://github.com/bincode-org/bincode", + "version": "2.0.1" + }, + { + "allowed_manifest_deltas": [ + { + "after": "1.75", + "before": "1.85.0", + "path": [ + "package", + "rust-version" + ] + } + ], + "archive": "upstream/bincode_derive-2.0.1.crate", + "files": { + ".cargo_vcs_info.json": "a1f5050f6b5cb96b62bce096cb3835bed9de25858401a0c8e06e234cffd56db8", + ".gitignore": "c1e953ee360e77de57f7b02f1b7880bd6a3dc22d1a69e953c2ac2c52cc52d247", + "Cargo.lock": "d2d582c65756ee42230796dc351612a8ac3955abaac778788b1d74cac02914f3", + "Cargo.toml": "b775ad96d707d8d001f9c7d9d4449ee520754b52fbae4bf41210920f2d2c3319", + "Cargo.toml.orig": "8144ae64b100254066a17216f4b4d638167168ad89e9ddfb8646880654b0e045", + "LICENSE.md": "90d7e062634054e6866d3c81e6a2b3058a840e6af733e98e80bdfe1a7dec6912", + "readme.md": "57be4be36acb40331160fe2cbe15139e3826002aac695a722e3b2ddb9c178b83", + "src/attribute.rs": "c08ac0eb96eb5660625cfdbad25ceaa80dfcd76734313b04d37bddcb5e832193", + "src/derive_enum.rs": "97c14e7d168bd2a724e6eb5b18abd1e358fad31bc85da6b74a83b6847d4598ad", + "src/derive_struct.rs": "e9053afca954888f1c6ed00d84ba32b5606685f7514a8c08852b3d88be74c178", + "src/lib.rs": "5aa0056f6bfbc0628c18ac6d1adf7a2a01b2426e38e95dfaf9172cca258810fd" + }, + "license": "MIT", + "name": "bincode_derive", + "sha256": "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "upstream": "https://github.com/bincode-org/bincode", + "version": "2.0.1" + } + ] +} diff --git a/vendor/upstream/bincode-2.0.1.crate b/vendor/upstream/bincode-2.0.1.crate new file mode 100644 index 0000000000000000000000000000000000000000..b36b48b2726a53a156a42b71d54e9fd777539437 GIT binary patch literal 70469 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

UdF`qgSU*2>6-7pMF(I15;!0gojSLu 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 y5 zxC>TVOlXY=ahtPC_wX&FHKvAZCYVg0y!6`HWg*&6nLn<$^15HcP`=+!Gq&Aj^^BYQ z0`KpM;Ui&uuxzTgvhS3jZ52~(->E4wu7q9E9T6}rimCoCX#j|hmz4m^U zzI>Ls*zU|J(%tuR%0903?PL6{!MWRZzVDgWrq1zPWjR*z&pxXrtlQ51d^Y3Gd*|9E zR?eNf$(WP%)z5XuH(%xo(KxJY%DUC{W?#$oHn&q3rd^3^H1z&EHAY9FNYu&onZ!-U zFV;34c6WAeU0A38_4nU%MTdPAZ*JwUnECM3-I@PG66xsaVC|dXGg8%xM zGn+*J|5>J5`+CDOk6rKo{m%Cc%J}ow#3J3*e`DA5`+w`!6gc?Rx7b&REpYtMS#aca z^-DvJm)#YO&FagZKTYP!TBMay6leZ=i>FxFdEvur!HZmj{@9rPXjY!J_lZH_GahcC z7YWPnrPum;B|6;~-sq_P>7l(h-+$50>(fQ2`8zN)$ag?; zkwoi0kB9?zSNvRhbr%8cm&NX6LkWg@?N;K&}gge?qxT{`(7_R^{iXpq-IfX zZ1*zNIXCik-?HDIb?)5T&acfaIyI9VMD1DvKbt3%ZuXy=HCL`xyFiCSEqT^gfe8L(N*xoP3C6WvryuFfsMvD0=OVv7>EBY@8^tbPpIaPZ9Rk6q7VuNo% z^O=*^6};H z?{Q1GcL{9z{X%1b*zXr2FPZD5I{Q24rDiU4dcx0o^QyA6?wROM!WaI0P*1%6^U4~3 zhBQUH)!%+>{Pxn|-;~Id)I$!f^Pe_!uy&?89GTbV;Gt8VB_zCV%YhF%Z*JOkU$c1Z zcuu2*#jGf|`_gGY7X9jFRp>$b?~Z@k3!Z6TlRZwc-$@_Owr(4*0_=KU^9`JRrsIi}iw<&TST zSt|ZH^ZRjh(JHmwtx+#D8~00E&eHGRA6vD_|9IT4*sw^IAcxJu>QYr*FFb>^`D>)N z#hHI#fA{l%@my~2%$$;273F-&IeTt9KYS6J+_L}W7*ybTPZRW|Ik|w#3sShVK+8eMW-}_d4d7guPgRr#Og#?pLItTvr z6=?Fef9?{Q`tycj+pUW~9@v=j*$7K2osd`2D!#Qe{SjOL{s`}TZ(Uc^9Mih^bb)!) z+PvEtTYB?WU(GA!+1otpZ1U}{+EII`aY+p zT}vZNw6EPMHgWlA$6l6y*w5Ll>cQlO>`9Yabo?H;#ZRz2AoKdEN^4~-$B!51*3G<~ z@7sN;sKd}@(x=7+y2?qcY@&T4DNQ>Lu3GG;u~#yp=1YSwFKfr7_8i^X-V8^TZmx`# zN!H0BtnVhZ@NbaGd}~$nHGuO$0$0i9>Ar?eQ^g&R&Q~p*aI9bP*r0tA4dml{rBWIh$f4phuL(BRK$9-{=?tfdH zv2*U)z{`&9-s@P(&nWJ)e0xCafW7$iZ|7#FB&siXCh~F9deigQT4(LHm+f=cWG$JLJc|L-w7xVXi>Ygl6*%*@yRw-vnsfu;&+=^vygP#>&@i$tb{Av2s{Xe#?uYDP^ z;qP7Zl>LXNl-T@nJ5_itV@p-Ks-HxTL@S@9u|@AsVfP7aofn(KD(jhVGydk-zuNlH zSE+3KPkkyk%;shb2(3>S+nM_IJO4eIFqWI9W&ci8|9mka^Wv1{ir*TahgL1VwKk~V zK`Vyic1r{Ij0(ote>6l6`n_FdBQ5I}ShfAwee3fTU+SCozL(Xz`t9cTXqi5Z>QS5aFvNMf3#0z=9Yui`|kzS znj1}@tB|+xrluH^>0U`Lu|MZRq*HW6*2(Q`=Xt0cw|2v(4;CvToWHzlS|gwNagXNa zgiYcsa~8~BAa;23{f9Si8o5uub>mp0gMWfB@!y~_|?O-m<9bP%mNz&qxWj0F*?S7xkBQ3?Hb3BNyna_a;&b3{RsoE{eC04=u6UkdB&ug zY8L6UzHB#+n7w-vz%=WHmcNPSw1rt5HxFx=P3d`fq!P~W^X@x{(t@_+cM-CPOvcm E0D3Gd7XSbN literal 0 HcmV?d00001 diff --git a/vendor/upstream/bincode_derive-2.0.1.crate b/vendor/upstream/bincode_derive-2.0.1.crate new file mode 100644 index 0000000000000000000000000000000000000000..4f33eb8bddb84b873659b682de1dde740ef23373 GIT binary patch literal 7404 zcmb2|=HOspU|?YSpOl%GoS%{!pORXXS(d76q-UUKsFz%nSdz-{);2fzw#TKPYqb6y zUK2d^#Cgp_&rDYfeB+pLq?AQNVfS|bE~8C0+e&Xt@}A_pqy;FJI2TY@Bzy?`c`aYG>Qu+_hVmUH|fHRo=|F^SQMf|4e&Z68qPF-)o!Q zzn8PkU)$Sz=J}76hj&MPS$TN>>({q$e|U3Kx#n11LRE{+@7ZqXg0b$<*pT1_kzANlh=tuMT{~L95O8-8;`Ty+O zuUr1E&(F`B_U*r*-T9NQ_rG~wmkVI3KU?^K@9cqXXAVA?_Gh!Z?5mlKZzp`yeHgUR zM*S?qY%9G#g-owX9+Y1Hdg4OKv1bhz_$2t3FV~J=@%;8W=X;ZQU4QE=3V*_i- z-$bsN=w7`|zGD0T7wiX5n1_WQeDL*n?%ksH)p8z3RyV%<5~izi_j>O4sk|OFYc;~= zM_vC{aiSsbTITM&ZEN%PhTXmw^}BTPzIFLcoWDzx&u%h{FRy=_bLs21W6#2R^Kvep zEzMr*7hk?R`flmw-FMj@)qVNOKgpn?=j;A$`?gu`{kQ$}*Z&@`|2u!4BV*Pt#q#f6 z?JkR-JIXKKxo>UtYx16a8S``B^rYCI+?}6N|NhP2&QCJe{>#_Cn(#5>!7SN`7cKh2 zLOWDm1PkfuuG2fwYb&9$m5X6TL$;*}`?vbc)+3vaO_`t{axz?6N+6=>MPq=<%>q^)udkc zTuYmNXIFAkm51bV^A3@;*+QS$;#q5r6Rzx@cXzYw0UNdMg}fU4Z?d_pN+0aH-tkZO z<&C>~UsnhVh)$I6TWcq|t44ui$JuWUVS#t&1#2~4F6212Z=YWawA zw?;)XPd!{Rdx_-hU$1@lhDACk9}f8z>#vc_BmV#X((O;ql&V_vo~WhC_l)mN*(2+c zufqHmTFiO}7$uWIbtk zbpMrV^1cNOK2x%LAJ;KxnrMDFbltYz^lY%m;)NTWe(2ZUSgCRS%QvS)0TP0{LhY{k2~K-uD&3!gYCS{ z^(s>n-Se&HjpoZ3R5se|T)6*?(U+ys`*nVw-*T4u`2U1AuV4PCFHSCA-1A@lp|E84 z)IC>s8s)N{DBck0Y?Twt&-<$43L~%Zsw1K|-PVX03Tbmkc8anV_(pG=YIAwpqBVDX z)7R>(xf!lp0YRgNwr|sw8*cqytZJ_w%(X=@Yb-DMoPHBE^+jibWx5cTJBk9(5 zmMh{d3bMT=wj2=-QzL49bh9%QeV$M2aWG%pm&v~DZGudy(*>hlp$k;ISJZ5m-jLAc zTD0$dl-X$;)vE^mf}uUNTF)1`FFnQfGN5?D4ZiN~L*Y6}CC3?WXmk8LaDaiQx8V%` zF`a4L@%(QV>bfO3>P&j4opHNn0mH{D3TDk6y#IsTu4UYjyHOY4Y{BQa{Wzn|mye2% zm$a3vX*&1iWx@gmmMi~yu1Q#5V+)j5bY?!NB<6Mh%iY9DLbtxpurW2~ z$o~Lsj>GTQSxf9N*U>4L%~Pp$4lI~;cH8e(qo^Netn^%-%(7>wg!P&eA3yxCpYnDw4SlfewMhrpIxj#M&Y*dnvd$1mMYc9>nGKl_Vb%u`tki`mQ>hBla|H#QvD7-|xA#RR~Ce)vE1JEz3_c)^H(cIjdU)v$2TV0+nIb2?Ay-%|Mvcjc{0k9ztxY6r+)}#);h1Z zXkER@d1+j)MyoR(mG7E#R#CUvjU5VN&z4dx8h7 zj-T^Lx)Gu8`~7_0f93mMZzkXP|Mk|lXH)*h>wmA8*Zlw6kHtQQ=|Z)8^1=Nd@2q(9 ztC@)>nQeYdXM5Yh#jVhH9)%*^Zx_vb(IEQiCe&;nC+a+%u)Xo06`)zm3mp#+i(-Pti2!yvZ zwKFDux@vjEEv%r`?DMLJJ?#vQshb6L#VWZMb1vL+a)a;z$y8akFSe7CqW_6z-w?hp zar@A{8-dC*uCwjiAb4`&>vwxh%Gaj|{7zV^xQcBbcfwTZFORf>H~dK1BW`mf|IvLL z!M=Ac>}g7pZeGG7LH)%?Tvxd^R&>m3UE`r|vG0eLn8X+EF|U+A z{Rh|bxlOa58Q*97{QSWrgz*_|Z4;Kl_-1-=Kz zZwVZ3nsBe;8OI#u7ti_xpL2hoWwmGZkx=6TOO7KObAQcgR5X^HUzKRBxS&>e?{mgO zazOdw!+1kQyproOYi ze@StN=@qlJ*(nD^dqn(B`rhC6E5~F4i&VpDZtv75I}IutA|GUanXpoAa@`F1tyQ9r z4<}ZdFqlhC5%)Y>w_~}`w)CKijwz)(lzH{m1$6J&%W$OWyYJ4VgX|8?{yQUH{nEPK zxP!~FgHOPuLRma2Ge=zeUflE394w_WJ;xjm*w(0-$E=;89k*PVvs(R(U8|M9a3_EGceYctvCfuI?oXPMFY*7o+r;_(%+(L1kC{K~ z+QPK?`r^4^D)LgFuV$zhEmq4HNj1r9-^N(Od*(-g{!{4uXWNW#J`9fp!tGqi?mLHDp{+{srS$wlo?5%arcbcy~di+u5ZzWr` zu0uWF7~jr%%xJ#mC(j$JjI|pVMyakZJ83Cfa#Z`zl6{Zd)5?z;9IDwTx8p?}qghs{ zcL_(K9b3EJPqm|Mci05mmq#!8VRTnv_T!Uf!maN&&Zq2mHeEqDYb*P@yC)R% z?>&w`cG~zAbA0)c7)9;!a@91x1LB6s1^Fj0@Eq8AB2GzWk67;7&{g}FK6@&2M`|nY zKkun~?yCOiS5cmjQge8&cu~>XN5Yxw5-y%x!CQGs*!6|(Wah&iDyn%W?`-P`opIaS zSmRH@t4G^TZvWw_$#~e}so$-&RlfPApID#Fz7fk5pOUDYe}58}@F}iI=DcPq9KX8# z90Y16Htsq3hPC$Gw8t*%ayVXWkMyl$^omhYH;`I2m$BpvmLTuyQWn>wj7sp;# zUBUe7!6B8er+>ci=!*&aaVq3gNJE;O6tGK)o1kLxB6#SS)O~6o3}gT>?&?QyXRN$`?3jf{mJZfV)`1S zG)+hFkY&XrCB*{$)TBtGi3RNQr+KIZ=&L3LcAl8MA*VjcO3fj0X4A)(J-wM-UXrtP zoyF7qx32zam87<9{+#UNdk-cFae250@+M@v@3Ps=(NF^h+q3tm-uYmvS^-4Ip>qR%&l)tCwKcVckjKHxVf<8f|YHyjM;zQDw!?3 zVojSxFRuEqmuc$40N%H!7$@7VnKZ%Yl=$V%zUm)%KUr@r`|$MrpUx>6{Zp4roceX@ z=hrI*58PRB`%+TI&sW^?BF4sMmmJPEyuat&mGCY4nPu5NsU_1)Bn>rlWNiP~&Arm6 z!TjgY+WTVsW+87@9W`ZT;PLei=~kHSwRM)+giaPUXQgLzr`)~bD}S~*XXYYCVU?FB zu8BqHZtYIDZjQflYP)BIc*w;iAA?@`Jx|@L8+h*0rbm}VzE(#(UL+VcUuplJc?O(9WBIIZOWV7Qt+O8ctD!h>ACkOs z^A*?rm75nWdZcnZ#rw-QlT8aa{2FDfBR(y@ryR#04am&SjlC#N9FP1|u_9%HGdD z-C0kprB%eW7oHWm=D7W@m~7tx^|@QCBE%OSi^zU z^2CgVysIB6r6-?yRxH-EdbQFk!7}6Ri9Ku2eE2NWmi|R5QBhn+^03B@MqXi|RmQ*5 zc@<^^87}-FqxcNu76m=kMU%%&m`+Po9n(A zbXF~Aoi^2G-a@~7@4}v~VAgTz&Fb5KCb0OzzZ<+utX+1@*sSe-Mt_-YLhG4j{%q?~ z`D!jLo7P!4T|?*D%lUjy7hayBx;66X+ck{oS?McHj&tjttf=)ZO*`v*L%&q1;isC! z8iviRCw@C*>a%u*ikx!MT=ULIr$(@ry_w^u!kKmFa%3`DA3i<4@EYG4{w|L<@87ju zStfJ;{=GBuNnMMAg|jF8zOwz`idy#i3;K(WZ;V}`8ZUBj(wf6_4mzH%*I%*Tu-J9~ zBi2;U`%4$>(_66iS=Jhzu#DD7MgP(#4dRmT_H~5`nYDe&{~Rz)djHJp5-Iy;zSS?3 z+PS;s>&F?9`S%~mr}k;a&yp9hQrKuY_nQsZsry&#TzEEb2%Rp(m$kKGy&P{;kX63= z)Sb6OgEwY0X6$%cwYI0W%ks0*Q|~2bn;!iOTX#yEXW^%{W-~W2=-+VOXP^3Jv-hzp z`CmOl&3HuDevsJMboJef^&fR-sQ%1y4RKkhd;jTqw|6}Z-`}73v)k{$VZTF3!iE0N zt2WKJJz-{@Ay1y^GpQMt$5NLidRAXHUXy6%YuTL6H*0Ql_2QI0;uDW%Wz33edM|tL z60=y>1{bb_3c=2Yp9a)9oPJaCX#0#r&i*|QcQLTv?N|`E@vrr{?;9TnUVgPW`hR!S z)pdvdw$E8|mV4gw{Ljf*N~h;r>{3hpwe+Ztl}fsuc(0e}=L4_4Un`$rOt%Wywhak>6kf> zcE8Qmm=w=sd|rRg3)kf_ysC%8+0`D^t)J9mv8cj1#o(u>)ke)fCl|)MU*XD7?{b)0 za-eD5@f$BC9$G}Xai3YkrT5lF=Jwf)j7Nd#Tn9>G{h4Q-xWD?6_|Kp6Gd6M^eDKhv zZie~63E{ym?>~OKbZiE{*0GYRgp3mx$_k8m-hXHL@^Jrd&ybEep2aa2&c`Qa2+TC> zH9PyxU{A%0eLwanFSt@}D)g_K_aCp#t~Jk+jD&duxfPdcxC&do)R0mQ<_Ok*zA9tF z(v~_g+vi7o4oG#>I4rn4G5E`(8G-9PZvMQvX|KmVyQMpm=M*u&wwQH#f#EEH<_rEDKHDG_{+2xfO5F?Bow+aY@MJuP z;??)x%9CE_bUw1|HIK6;MHxm_A#cummPY^OJd|EtFXk+tAp^ZPR z%<|LiFZJG6^K9BOrRelJ`DE6_Jqu$5$^v#M=N`B={#DKXbKYe)w@&bZtYU?*#E4*-h$Ts;@*W$Ru338M#GIeS zpTF*wmeo)Gz^#hM^%HJ4f6Q<=e0ctq|E|20^6 zt4-&tIZCeP(_aqs<-r6 z^2+Qt?lbn)#Mf4J&AY;)c{8FXm?zR%>F;7cBu$kL!(VJz{ z9C9YUZEM~9m}l;rE32hcJ;c4It2gTCXa7^O&;7S#^V9D>)4Oec9$tQOv%lNtLx&pg zE^X{Rm!xF>y|2?LOet1*#@)8%Gk5N&-1*wvUxD-g^wcYx_2RUIU-wUnaMyR7_H*uZ zjmNkC^puo7ynIu!usLDYt_st8jeB1H?DR;vBJt$ucFq9duy)&bWsXie-fzrSI6q0; zFL-BbK%Sz_GqFQK<(yq_9!%x@Z}c!;?a%3!`k5c}h5w}<+VAsYI_LkG>pBy+KfidW zylF^Pid9HNsHa5;%a%BF0 z5pRcGm7kV++Ijct@4S3?-RhKQ%DZ$Xm-gpvcbRNa>*Z^ba*1n&x{}PyQSCtkwPH zx?^oqceUqvURUJPk(&CHanWw`rPA|wnH869zNb?qD17s#P~jy)sz$1-zbqUeLBpv2K^QXgx2p)1_(l?=~&w%4i5=JhVCMYY@}P z%adg?WDcF(yZU=z{eS(xi`Vd%{eOS!*RNw&-v7_dy}Ir6@A~=g{_d|V|Me-}aa!Kj zr}s*}%&xc-zW;aczRMrvKi#`C^LI|-`cM1reA;*C_}v=K_or(Y{4R116;Dc%c*?u0 zvQl>2pKjICMZdR+?aI=&cABrdqBZ~WuJ622-K_u0c|INXZhIecBJ@X+PTtdZ1-8@n zXj;@4rLi4qee|PxlXA24oKGj?J-*L1%@Q*f+y5i;qxF<&wJH^o>dEh)AFzFBwesoQ zr++`L?l`r0PwLUY#>IR10}?{!y{(;cXpYQxVIG!$FRp&czpJ0aYOI^^j^9#c`;oh^ z#j+=Emz3J4zsp}{>-oD)Pb;VHwBB$)ZeGaF`?U|23C3>~dspt0n{#IW#A?lelGy#X z*WUf!7xGSg;~#$h8KXPjy!7K_$M3r$$~Nk0 zsu%6tenxK#|F7_Kg-J^9t8-q&ZQlNbb4T*T8!4IMIcHxKFMnNJf9JD-x3z502d!1} zAN%-LE?8=FA*gM7IiLP%W?g<+<>~BEr*{1O_~@BY*q_d%qfMbJ^`kdjt9Uabcz0ym z1b>y5Gc#{Sy6&t$ANlv?qe~&NZ#I7_UjFNRg zs#!{}ns7SnYmi{%A`abUJ95)a_;`d48}WoqJ6o^T@wBbz9w+xShU4qopF6Ccw7x~m z|HzUzbHx8g#?C+JsA?QI#U#y0qj^c8P~P4z7Ctcx7az}&|5360$8`glD&+v7SG>13 zI3Ea1a(g!OSlvtRy&-Jv$ue7c{_fRmH~P2eNtk`APvIgat=oH3*8gnGJmOO%`+>cP zw^{u4DyG+WSE@``DV6x)bM?F5&CvS~?90^r{`s0ts#y9&+SoSM;E&S5qMO%zfzGZCnxWkw2qP-|8gd_aU z(roK(_rq@ros9Z)$5?yYlh*ay)~M?LS(&QyGc(}nr21RlaVKv1Z+^mkY4eFm;+B6~ zr|*%OBpUtWWJGS{Yx|ih@oiEkS|hTWm#^iW#Ps8`M(fcNQ7+~xWq;E$JB&W***{(W UXUhEj-#*)aY(JsFaEpNf0Gh3ZMF0Q* literal 0 HcmV?d00001 diff --git a/vendor/verify.py b/vendor/verify.py new file mode 100644 index 0000000..d659ad9 --- /dev/null +++ b/vendor/verify.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python3 +"""Verify the complete metadata-only codec backport; Python 3.11+, stdlib only. + +Usage: python3 vendor/verify.py --root vendor [--self-test] +Trust anchors are the published archive SHA256 entries in baseline e4cfd4c. +Verification never extracts archives or repairs files. +""" +import argparse +import copy +import hashlib +import json +from pathlib import Path, PurePosixPath +import shutil +import tarfile +import tempfile +import tomllib + +BASELINE = "e4cfd4c" +ARCHIVES = { + "bincode": "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740", + "bincode_derive": "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09", +} +SOURCE = "registry+https://github.com/rust-lang/crates.io-index" +UPSTREAM = "https://github.com/bincode-org/bincode" + + +def require(condition, message): + if not condition: + raise ValueError(message) + + +def digest(data): + return hashlib.sha256(data).hexdigest() + + +def deltas(name): + changes = [{"path": ["package", "rust-version"], "before": "1.85.0", "after": "1.75"}] + if name == "bincode": + changes.append({"path": ["dependencies", "bincode_derive", "version"], "before": "2.0.1", "after": "=2.0.1"}) + return changes + + +def verify_archive_checksums(root): + require(not root.is_symlink(), "vendor root is a symlink") + require(not (root / "provenance.json").is_symlink(), "provenance symlink") + require(not (root / "upstream").is_symlink(), "archive directory symlink") + provenance = json.loads((root / "provenance.json").read_text()) + require(set(provenance) == {"baseline", "packages"}, "unexpected provenance fields") + require(provenance["baseline"] == BASELINE, "baseline mismatch") + records = provenance["packages"] + require(len(records) == 2 and {p["name"] for p in records} == set(ARCHIVES), "package inventory mismatch") + expected_archives = {name + "-2.0.1.crate" for name in ARCHIVES} + require({p.name for p in (root / "upstream").iterdir()} == expected_archives, "archive file set mismatch") + originals = {} + for record in records: + name = record["name"] + stem = name + "-2.0.1" + require(set(record) == {"name", "version", "archive", "sha256", "source", "license", "upstream", "files", "allowed_manifest_deltas"}, "unexpected package provenance fields") + require(record["version"] == "2.0.1" and record["archive"] == "upstream/" + stem + ".crate", "package identity mismatch") + require(record["sha256"] == ARCHIVES[name], "inventory archive checksum mismatch") + require(record["source"] == SOURCE and record["license"] == "MIT" and record["upstream"] == UPSTREAM, "source/license provenance mismatch") + require(record["allowed_manifest_deltas"] == deltas(name), "manifest delta inventory mismatch") + archive = root / record["archive"] + require(archive.is_file() and not archive.is_symlink(), "unsafe archive file") + require(digest(archive.read_bytes()) == ARCHIVES[name], "archive checksum mismatch: " + name) + files = {} + with tarfile.open(archive, "r:gz") as tar: + for member in tar.getmembers(): + path = PurePosixPath(member.name) + require(member.isfile() and not path.is_absolute() and ".." not in path.parts and "\\" not in member.name and len(path.parts) > 1 and path.parts[0] == stem and str(path) == member.name, "unsafe archive member: " + member.name) + relative = str(path.relative_to(stem)) + require(relative not in files, "duplicate archive member") + files[relative] = tar.extractfile(member).read() + require(record["files"] == {path: digest(data) for path, data in files.items()}, "archive member inventory/checksum mismatch: " + name) + require({"LICENSE.md", "Cargo.toml", "Cargo.toml.orig", ".cargo_vcs_info.json"} <= set(files), "missing upstream release/license metadata") + originals[name] = files + return originals + + +def verify_complete_package_trees(root, originals): + for name, files in originals.items(): + directory = root / (name + "-2.0.1") + require(directory.is_dir() and not directory.is_symlink(), "unsafe package directory") + actual = set() + actual_dirs = set() + expected_dirs = set() + for relative in files: + expected_dirs.update(str(p) for p in PurePosixPath(relative).parents if str(p) != ".") + for path in directory.rglob("*"): + require(not path.is_symlink(), "symlink in package tree") + relative = path.relative_to(directory).as_posix() + if path.is_dir(): + actual_dirs.add(relative) + else: + require(path.is_file(), "special file in package tree") + actual.add(relative) + require(actual == set(files) and actual_dirs == expected_dirs, "complete package file/directory set mismatch: " + name) + for relative, original in files.items(): + if relative != "Cargo.toml": + require((directory / relative).read_bytes() == original, "upstream byte mismatch: " + name + "/" + relative) + + +def verify_manifest_allowlist(root, originals): + for name, files in originals.items(): + original = files["Cargo.toml"] + before = b'rust-version = "1.85.0"' + require(original.count(before) == 1, "unexpected original rust-version text") + expected = original.replace(before, b'rust-version = "1.75"') + if name == "bincode": + before = b'[dependencies.bincode_derive]\nversion = "2.0.1"' + require(expected.count(before) == 1, "unexpected original derive text") + expected = expected.replace(before, b'[dependencies.bincode_derive]\nversion = "=2.0.1"') + actual = (root / (name + "-2.0.1") / "Cargo.toml").read_bytes() + require(actual == expected, "textual manifest allowlist mismatch: " + name) + parsed = tomllib.loads(original.decode()) + require(parsed["package"]["name"] == name and parsed["package"]["version"] == "2.0.1" and parsed["package"]["license"] == "MIT", "upstream manifest identity mismatch") + modified = copy.deepcopy(parsed) + for change in deltas(name): + table = modified + for key in change["path"][:-1]: + table = table[key] + key = change["path"][-1] + require(table[key] == change["before"], "original parsed manifest mismatch") + table[key] = change["after"] + require(tomllib.loads(actual.decode()) == modified, "parsed manifest allowlist mismatch: " + name) + # The original author manifest is retained byte-for-byte, not rewritten. + tomllib.loads(files["Cargo.toml.orig"].decode()) + + +def verify(root): + originals = verify_archive_checksums(root) + verify_complete_package_trees(root, originals) + verify_manifest_allowlist(root, originals) + return originals + + +def self_test(root): + def source_edit(tree): + path = tree / "bincode-2.0.1/src/lib.rs" + path.write_bytes(path.read_bytes() + b"\n// altered\n") + + def license_remove(tree): + (tree / "bincode-2.0.1/LICENSE.md").unlink() + + def source_extra(tree): + (tree / "bincode_derive-2.0.1/src/extra.rs").write_text("// extra\n") + + def manifest_edit(tree): + path = tree / "bincode-2.0.1/Cargo.toml" + path.write_bytes(path.read_bytes().replace(b'edition = "2021"', b'edition = "2018"')) + + def archive_edit(tree): + path = tree / "upstream/bincode-2.0.1.crate" + path.write_bytes(path.read_bytes() + b"altered") + + def checksum_edit(tree): + path = tree / "provenance.json" + data = json.loads(path.read_text()) + data["packages"][0]["sha256"] = "0" * 64 + path.write_text(json.dumps(data)) + + def inventory_edit(tree): + path = tree / "provenance.json" + data = json.loads(path.read_text()) + data["packages"][0]["files"]["src/lib.rs"] = "0" * 64 + path.write_text(json.dumps(data)) + + with tempfile.TemporaryDirectory(prefix="hexwork-vendor-verifier-") as temp: + for mutate in (None, source_edit, license_remove, source_extra, manifest_edit, archive_edit, checksum_edit, inventory_edit): + tree = Path(temp) / "vendor" + shutil.copytree(root, tree) + if mutate: + mutate(tree) + try: + verify(tree) + except ValueError: + print("self-test rejected:", mutate.__name__) + else: + raise ValueError("negative control accepted: " + mutate.__name__) + else: + verify(tree) + print("self-test accepted: pristine copy") + shutil.rmtree(tree) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--root", type=Path, required=True) + parser.add_argument("--self-test", action="store_true") + args = parser.parse_args() + try: + originals = verify(args.root) + print("PASS verify_archive_checksums, verify_complete_package_trees, verify_manifest_allowlist:", sum(map(len, originals.values())), "authenticated files") + if args.self_test: + self_test(args.root) + except (ValueError, OSError, KeyError, TypeError, tarfile.TarError) as error: + parser.exit(1, "FAIL vendor verification: " + str(error) + "\n") + + +if __name__ == "__main__": + main()