From cd2854fcb50cccf04841f45c38b8c69ee479c29b Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Fri, 5 Dec 2025 18:23:47 +0000 Subject: [PATCH 1/3] deps: add vendor depenency crate Add cargo config to support building a unified cargo static lib to include multiple crate dependencies to be used by Node.js. This also allows additional crate dependencies to be added, like amaro. --- .github/workflows/test-shared.yml | 4 +- Makefile | 2 +- deps/crates/.cargo/config.toml | 5 + deps/crates/.gitignore | 3 + deps/crates/Cargo.lock | 481 ++++++++++++++++++++++++++++++ deps/crates/Cargo.toml | 32 ++ deps/crates/crates.gyp | 54 ++++ deps/crates/src/lib.rs | 7 + tools/v8_gypfiles/v8.gyp | 6 +- 9 files changed, 588 insertions(+), 6 deletions(-) create mode 100644 deps/crates/.cargo/config.toml create mode 100644 deps/crates/.gitignore create mode 100644 deps/crates/Cargo.lock create mode 100644 deps/crates/Cargo.toml create mode 100644 deps/crates/crates.gyp create mode 100644 deps/crates/src/lib.rs diff --git a/.github/workflows/test-shared.yml b/.github/workflows/test-shared.yml index afe94d8452854a..f1509989a1f78e 100644 --- a/.github/workflows/test-shared.yml +++ b/.github/workflows/test-shared.yml @@ -16,6 +16,7 @@ on: - deps/ada/** - deps/brotli/** - deps/cares/** + - deps/crates/** - deps/corepack/** - deps/icu-small/** - deps/icu-tmp/** @@ -25,7 +26,6 @@ on: - deps/openssl/*/** - deps/simdjson/** - deps/sqlite/** - - deps/temporal/** - deps/uv/** - deps/uvwasi/** - deps/zlib/** @@ -62,6 +62,7 @@ on: - deps/ada/** - deps/brotli/** - deps/cares/** + - deps/crates/** - deps/corepack/** - deps/icu-small/** - deps/icu-tmp/** @@ -71,7 +72,6 @@ on: - deps/openssl/*/** - deps/simdjson/** - deps/sqlite/** - - deps/temporal/** - deps/uv/** - deps/uvwasi/** - deps/zlib/** diff --git a/Makefile b/Makefile index 0fcf860ee56e82..cae210bffeb6e0 100644 --- a/Makefile +++ b/Makefile @@ -1232,6 +1232,7 @@ ifeq ($(SKIP_SHARED_DEPS), 1) $(RM) -r $(TARNAME)/deps/ada $(RM) -r $(TARNAME)/deps/brotli $(RM) -r $(TARNAME)/deps/cares + $(RM) -r $(TARNAME)/deps/crates $(RM) -r $(TARNAME)/deps/icu-small $(RM) -r $(TARNAME)/deps/icu-tmp $(RM) -r $(TARNAME)/deps/llhttp @@ -1241,7 +1242,6 @@ ifeq ($(SKIP_SHARED_DEPS), 1) find $(TARNAME)/deps/openssl -mindepth 1 -maxdepth 1 -type d -exec $(RM) -r {} + $(RM) -r $(TARNAME)/deps/simdjson $(RM) -r $(TARNAME)/deps/sqlite - $(RM) -r $(TARNAME)/deps/temporal $(RM) -r $(TARNAME)/deps/uv $(RM) -r $(TARNAME)/deps/uvwasi $(RM) -r $(TARNAME)/deps/zlib diff --git a/deps/crates/.cargo/config.toml b/deps/crates/.cargo/config.toml new file mode 100644 index 00000000000000..02369289646870 --- /dev/null +++ b/deps/crates/.cargo/config.toml @@ -0,0 +1,5 @@ +[source.crates-io] +replace-with = "vendored-sources" + +[source.vendored-sources] +directory = "vendor" diff --git a/deps/crates/.gitignore b/deps/crates/.gitignore new file mode 100644 index 00000000000000..f8f4159ca0c75a --- /dev/null +++ b/deps/crates/.gitignore @@ -0,0 +1,3 @@ +# Include everything in `vendor/` except for hidden files +!vendor/**/* +.DS_Store diff --git a/deps/crates/Cargo.lock b/deps/crates/Cargo.lock new file mode 100644 index 00000000000000..7ae5240fdbed26 --- /dev/null +++ b/deps/crates/Cargo.lock @@ -0,0 +1,481 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "calendrical_calculations" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a0b39595c6ee54a8d0900204ba4c401d0ab4eb45adaf07178e8d017541529e7" +dependencies = [ + "core_maths", + "displaydoc", +] + +[[package]] +name = "core_maths" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30" +dependencies = [ + "libm", +] + +[[package]] +name = "diplomat" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ece782ffeb426ef0d3074c5623e8f6552cc912e4bbeecfda9583cb01b02b8ba1" +dependencies = [ + "diplomat_core", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "diplomat-runtime" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c270cf75c6ba9d974a7a670d96c7bf8007cd0d03e1fbe128d62bd47d9fe25aef" + +[[package]] +name = "diplomat_core" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb0f9322e2c506400ac3f374abfcaf9fd841fcdb729bbf008a135b600f99ede7" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "smallvec", + "strck", + "syn", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "icu_calendar" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "362941891d17750e05cd8fdfca4a89a86552825d625a937020ee1a65580da1f9" +dependencies = [ + "calendrical_calculations", + "displaydoc", + "icu_calendar_data", + "icu_locale", + "icu_locale_core", + "icu_provider", + "ixdtf 0.5.0", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_calendar_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219c8639ab936713a87b571eed2bc2615aa9137e8af6eb221446ee5644acc18" + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ae5921528335e91da1b6c695dbf1ec37df5ac13faa3f91e5640be93aa2fbefd" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_locale_data", + "icu_provider", + "potential_utf", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93cca704c2d63cf8a91f5c2c5f88e027940dede132319b85a52939db9758f7e5" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locale_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fdef0c124749d06a743c69e938350816554eb63ac979166590e2b4ee4252765" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "ixdtf" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8289f7f711a1a51f80e2e368355d023042ca55d8d554fd5e953f01464c15842d" +dependencies = [ + "displaydoc", +] + +[[package]] +name = "ixdtf" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84de9d95a6d2547d9b77ee3f25fa0ee32e3c3a6484d47a55adebc0439c077992" + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "node_crates" +version = "0.1.0" +dependencies = [ + "icu_calendar", + "icu_calendar_data", + "icu_collections", + "icu_locale", + "icu_locale_core", + "icu_locale_data", + "icu_provider", + "temporal_capi", + "temporal_rs", + "timezone_provider", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "serde_core", + "writeable", + "zerovec", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "resb" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a067ab3b5ca3b4dc307d0de9cf75f9f5e6ca9717b192b2f28a36c83e5de9e76" +dependencies = [ + "potential_utf", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "strck" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42316e70da376f3d113a68d138a60d8a9883c604fe97942721ec2068dab13a9f" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "temporal_capi" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf286aa4f5e07b9e46eeab2e1a55f8a752635f2fa92c88bf8287404e190c6cb" +dependencies = [ + "diplomat", + "diplomat-runtime", + "icu_calendar", + "icu_locale", + "num-traits", + "temporal_rs", + "timezone_provider", + "writeable", + "zoneinfo64", +] + +[[package]] +name = "temporal_rs" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7305090e19b67670330fde1365b7c2c8a3b5a5ef6c92efc238b3b964a8c395fd" +dependencies = [ + "core_maths", + "icu_calendar", + "icu_locale", + "ixdtf 0.6.4", + "num-traits", + "timezone_provider", + "tinystr", + "writeable", +] + +[[package]] +name = "timezone_provider" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071d5533454ed925a1f4841f7128d1d248f3465d6a18e9afe298212916cc3269" +dependencies = [ + "tinystr", + "zerotrie", + "zerovec", + "zoneinfo64", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "serde_core", + "zerovec", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "serde", + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zoneinfo64" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6916519e4a1cff59d49e0b902caed549d85dbbbf623a95af5c8320d5c08c6e13" +dependencies = [ + "calendrical_calculations", + "icu_locale_core", + "potential_utf", + "resb", + "serde", +] diff --git a/deps/crates/Cargo.toml b/deps/crates/Cargo.toml new file mode 100644 index 00000000000000..ee208c16db1f2b --- /dev/null +++ b/deps/crates/Cargo.toml @@ -0,0 +1,32 @@ +# This file defines all third-party Rust dependencies approved for use +# in Node.js. + +[package] +edition = "2021" +name = "node_crates" +version = "0.1.0" +rust-version = "1.82" + +[lib] +crate-type = ["staticlib"] + +[dependencies] +# Pin all temporal dependencies to the last version support rustc 1.82 +icu_calendar = "~2.0.0" +icu_calendar_data = "~2.0.0" +icu_collections = "~2.0.0" +icu_locale = "~2.0.0" +icu_locale_core = "~2.0.0" +icu_locale_data = "~2.0.0" +icu_provider = "~2.0.0" +timezone_provider = "=0.1.0" + +[dependencies.temporal_capi] +version = "=0.1.0" +features = ["zoneinfo64"] + +[dependencies.temporal_rs] +version = "=0.1.0" +default-features = false +# This is necessary to enable a spec-compliance quirk when upgrading to v0.1.2 +# features = ["float64_representable_durations"] diff --git a/deps/crates/crates.gyp b/deps/crates/crates.gyp new file mode 100644 index 00000000000000..25384f2d0dfef8 --- /dev/null +++ b/deps/crates/crates.gyp @@ -0,0 +1,54 @@ +{ + 'variables': { + 'cargo_vendor_dir': './vendor', + }, + 'targets': [ + { + 'target_name': 'node_crates', + 'type': 'none', + 'hard_dependency': 1, + 'sources': [ + 'Cargo.toml', + 'Cargo.lock', + 'src/lib.rs', + ], + 'link_settings': { + 'libraries': [ + '<(SHARED_INTERMEDIATE_DIR)/>(cargo_build_mode)/libnode_crates.a', + ], + }, + 'actions': [ + { + 'action_name': 'cargo_build', + 'inputs': [ + '<@(_sources)' + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/>(cargo_build_mode)/libnode_crates.a' + ], + 'action': [ + 'cargo', + 'rustc', + '>@(cargo_build_flags)', + '--frozen', + '--target-dir', + '<(SHARED_INTERMEDIATE_DIR)' + ], + } + ], + }, + { + 'target_name': 'temporal_capi', + 'type': 'none', + 'sources': [], + 'dependencies': [ + 'node_crates', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '<(cargo_vendor_dir)/temporal_capi/bindings/cpp', + ], + }, + }, + ] +} diff --git a/deps/crates/src/lib.rs b/deps/crates/src/lib.rs new file mode 100644 index 00000000000000..d2705806664fc9 --- /dev/null +++ b/deps/crates/src/lib.rs @@ -0,0 +1,7 @@ +// The root of an empty crate that is used for running Cargo against the +// dependencies used by Node.js. + +// Suppress warnings about re-exported dependencies. + +#[allow(unused_imports)] +use temporal_capi; diff --git a/tools/v8_gypfiles/v8.gyp b/tools/v8_gypfiles/v8.gyp index 153ed31d6db08f..f22e914e1fc4a6 100644 --- a/tools/v8_gypfiles/v8.gyp +++ b/tools/v8_gypfiles/v8.gyp @@ -321,7 +321,7 @@ }], ['v8_enable_temporal_support==1 and node_shared_temporal_capi=="false"', { 'dependencies': [ - '../../deps/temporal/temporal_capi/temporal_capi.gyp:temporal_capi', + '../../deps/crates/crates.gyp:temporal_capi', ], }], ], @@ -363,7 +363,7 @@ }], ['v8_enable_temporal_support==1 and node_shared_temporal_capi=="false"', { 'dependencies': [ - '../../deps/temporal/temporal_capi/temporal_capi.gyp:temporal_capi', + '../../deps/crates/crates.gyp:temporal_capi', ], }], ['v8_target_arch=="ia32"', { @@ -1141,7 +1141,7 @@ 'conditions': [ ['node_shared_temporal_capi=="false"', { 'dependencies': [ - '../../deps/temporal/temporal_capi/temporal_capi.gyp:temporal_capi', + '../../deps/crates/crates.gyp:temporal_capi', ], }], ], From c9113ad7f75d61a0a65914fa4cc50aff0b2c4914 Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Fri, 5 Dec 2025 18:23:57 +0000 Subject: [PATCH 2/3] deps: apply cargo vendor --- .../vendor/autocfg/.cargo-checksum.json | 1 + deps/crates/vendor/autocfg/Cargo.lock | 6 + deps/crates/vendor/autocfg/Cargo.toml | 76 + deps/crates/vendor/autocfg/LICENSE-APACHE | 201 + deps/crates/vendor/autocfg/LICENSE-MIT | 25 + deps/crates/vendor/autocfg/README.md | 117 + .../vendor/autocfg/examples/integers.rs | 9 + .../crates/vendor/autocfg/examples/nightly.rs | 18 + deps/crates/vendor/autocfg/examples/paths.rs | 22 + deps/crates/vendor/autocfg/examples/traits.rs | 26 + .../vendor/autocfg/examples/versions.rs | 9 + deps/crates/vendor/autocfg/src/error.rs | 81 + deps/crates/vendor/autocfg/src/lib.rs | 636 ++ deps/crates/vendor/autocfg/src/rustc.rs | 89 + deps/crates/vendor/autocfg/src/tests.rs | 54 + deps/crates/vendor/autocfg/src/version.rs | 65 + deps/crates/vendor/autocfg/tests/no_std.rs | 28 + deps/crates/vendor/autocfg/tests/rustflags.rs | 34 + .../vendor/autocfg/tests/support/mod.rs | 21 + deps/crates/vendor/autocfg/tests/tests.rs | 189 + deps/crates/vendor/autocfg/tests/wrap_ignored | 12 + deps/crates/vendor/autocfg/tests/wrappers.rs | 56 + .../.cargo-checksum.json | 1 + .../calendrical_calculations/Cargo.toml | 77 + .../vendor/calendrical_calculations/LICENSE | 201 + .../vendor/calendrical_calculations/README.md | 21 + .../calendrical_calculations/src/astronomy.rs | 2631 +++++++++ .../src/chinese_based.rs | 815 +++ .../calendrical_calculations/src/coptic.rs | 32 + .../calendrical_calculations/src/error.rs | 29 + .../calendrical_calculations/src/ethiopian.rs | 24 + .../calendrical_calculations/src/gregorian.rs | 151 + .../calendrical_calculations/src/hebrew.rs | 707 +++ .../src/hebrew_keviyah.rs | 1067 ++++ .../calendrical_calculations/src/helpers.rs | 347 ++ .../calendrical_calculations/src/islamic.rs | 262 + .../calendrical_calculations/src/julian.rs | 141 + .../calendrical_calculations/src/lib.rs | 77 + .../calendrical_calculations/src/persian.rs | 216 + .../calendrical_calculations/src/rata_die.rs | 231 + .../vendor/core_maths/.cargo-checksum.json | 1 + deps/crates/vendor/core_maths/Cargo.toml | 37 + deps/crates/vendor/core_maths/LICENSE | 21 + deps/crates/vendor/core_maths/README.md | 16 + deps/crates/vendor/core_maths/src/lib.rs | 1221 ++++ .../diplomat-runtime/.cargo-checksum.json | 1 + .../crates/vendor/diplomat-runtime/Cargo.toml | 55 + .../vendor/diplomat-runtime/LICENSE-APACHE | 201 + .../vendor/diplomat-runtime/LICENSE-MIT | 27 + deps/crates/vendor/diplomat-runtime/README.md | 42 + .../vendor/diplomat-runtime/src/callback.rs | 62 + .../crates/vendor/diplomat-runtime/src/lib.rs | 104 + .../vendor/diplomat-runtime/src/result.rs | 124 + .../diplomat-runtime/src/rust_interop.rs | 79 + .../vendor/diplomat-runtime/src/slices.rs | 291 + .../vendor/diplomat-runtime/src/wasm_glue.rs | 98 + .../vendor/diplomat-runtime/src/write.rs | 270 + .../vendor/diplomat/.cargo-checksum.json | 1 + deps/crates/vendor/diplomat/Cargo.toml | 70 + deps/crates/vendor/diplomat/LICENSE-APACHE | 201 + deps/crates/vendor/diplomat/LICENSE-MIT | 27 + deps/crates/vendor/diplomat/README.md | 42 + .../vendor/diplomat/src/enum_convert.rs | 87 + deps/crates/vendor/diplomat/src/lib.rs | 1248 ++++ ...diplomat__tests__both_kinds_of_option.snap | 100 + .../diplomat__tests__callback_arguments.snap | 140 + .../diplomat__tests__cfgd_struct.snap | 26 + .../diplomat__tests__cfged_method-2.snap | 24 + .../diplomat__tests__cfged_method.snap | 22 + ...t__tests__method_taking_mutable_slice.snap | 21 + ...mat__tests__method_taking_mutable_str.snap | 26 + ...mat__tests__method_taking_owned_slice.snap | 21 + ...lomat__tests__method_taking_owned_str.snap | 23 + .../diplomat__tests__method_taking_slice.snap | 21 + .../diplomat__tests__method_taking_str.snap | 21 + .../diplomat__tests__mod_with_enum.snap | 24 + ...diplomat__tests__mod_with_rust_result.snap | 20 + ...iplomat__tests__mod_with_write_result.snap | 25 + .../diplomat__tests__multilevel_borrows.snap | 49 + .../diplomat__tests__self_params.snap | 28 + .../snapshots/diplomat__tests__slices.snap | 180 + .../snapshots/diplomat__tests__traits.snap | 99 + .../diplomat/src/transparent_convert.rs | 32 + .../vendor/diplomat_core/.cargo-checksum.json | 1 + deps/crates/vendor/diplomat_core/Cargo.toml | 90 + .../vendor/diplomat_core/LICENSE-APACHE | 201 + deps/crates/vendor/diplomat_core/LICENSE-MIT | 27 + deps/crates/vendor/diplomat_core/README.md | 42 + .../vendor/diplomat_core/src/ast/attrs.rs | 519 ++ .../vendor/diplomat_core/src/ast/docs.rs | 440 ++ .../vendor/diplomat_core/src/ast/enums.rs | 127 + .../vendor/diplomat_core/src/ast/functions.rs | 116 + .../vendor/diplomat_core/src/ast/idents.rs | 86 + .../vendor/diplomat_core/src/ast/lifetimes.rs | 637 ++ .../vendor/diplomat_core/src/ast/macros.rs | 637 ++ .../vendor/diplomat_core/src/ast/methods.rs | 615 ++ .../vendor/diplomat_core/src/ast/mod.rs | 52 + .../vendor/diplomat_core/src/ast/modules.rs | 590 ++ .../vendor/diplomat_core/src/ast/opaque.rs | 64 + .../vendor/diplomat_core/src/ast/paths.rs | 77 + ...iplomat_core__ast__attrs__tests__attr.snap | 12 + ...mat_core__ast__attrs__tests__cfg_attr.snap | 11 + ...lomat_core__ast__attrs__tests__cfgs-2.snap | 6 + ...lomat_core__ast__attrs__tests__cfgs-3.snap | 8 + ...lomat_core__ast__attrs__tests__cfgs-4.snap | 8 + ...lomat_core__ast__attrs__tests__cfgs-5.snap | 14 + ...iplomat_core__ast__attrs__tests__cfgs.snap | 6 + ...mat_core__ast__attrs__tests__rename-2.snap | 8 + ...lomat_core__ast__attrs__tests__rename.snap | 8 + ...e__ast__enums__tests__enum_with_discr.snap | 37 + ..._core__ast__enums__tests__simple_enum.snap | 27 + ..._ast__functions__tests__free_function.snap | 21 + ...tions__tests__free_function_lifetimes.snap | 35 + ...unctions__tests__free_function_output.snap | 24 + ...re__ast__methods__tests__cfged_method.snap | 34 + ...__methods__tests__nonstatic_methods-2.snap | 42 + ...st__methods__tests__nonstatic_methods.snap | 35 + ...ast__methods__tests__static_methods-2.snap | 33 + ...__ast__methods__tests__static_methods.snap | 32 + ...__import_in_non_diplomat_not_analyzed.snap | 32 + ...st__modules__tests__method_visibility.snap | 32 + ...core__ast__modules__tests__simple_mod.snap | 159 + ...e__ast__structs__tests__simple_struct.snap | 33 + ...core__ast__types__tests__lifetimes-10.snap | 10 + ...core__ast__types__tests__lifetimes-11.snap | 9 + ...core__ast__types__tests__lifetimes-12.snap | 9 + ..._core__ast__types__tests__lifetimes-2.snap | 12 + ..._core__ast__types__tests__lifetimes-3.snap | 13 + ..._core__ast__types__tests__lifetimes-4.snap | 12 + ..._core__ast__types__tests__lifetimes-5.snap | 14 + ..._core__ast__types__tests__lifetimes-6.snap | 18 + ..._core__ast__types__tests__lifetimes-7.snap | 19 + ..._core__ast__types__tests__lifetimes-8.snap | 9 + ..._core__ast__types__tests__lifetimes-9.snap | 8 + ...at_core__ast__types__tests__lifetimes.snap | 12 + ...__ast__types__tests__typename_boxes-2.snap | 11 + ...re__ast__types__tests__typename_boxes.snap | 7 + ...re__ast__types__tests__typename_named.snap | 10 + ..._ast__types__tests__typename_option-2.snap | 11 + ...e__ast__types__tests__typename_option.snap | 7 + ...__types__tests__typename_primitives-2.snap | 6 + ...__types__tests__typename_primitives-3.snap | 6 + ...st__types__tests__typename_primitives.snap | 6 + ...__types__tests__typename_references-2.snap | 13 + ...st__types__tests__typename_references.snap | 9 + ..._ast__types__tests__typename_result-2.snap | 12 + ..._ast__types__tests__typename_result-3.snap | 12 + ..._ast__types__tests__typename_result-4.snap | 12 + ...e__ast__types__tests__typename_result.snap | 12 + ...__validity__tests__lifetime_in_return.snap | 7 + .../vendor/diplomat_core/src/ast/structs.rs | 85 + .../vendor/diplomat_core/src/ast/traits.rs | 148 + .../vendor/diplomat_core/src/ast/types.rs | 1794 ++++++ .../vendor/diplomat_core/src/environment.rs | 96 + .../vendor/diplomat_core/src/hir/attrs.rs | 1650 ++++++ .../vendor/diplomat_core/src/hir/defs.rs | 253 + .../vendor/diplomat_core/src/hir/elision.rs | 612 ++ .../vendor/diplomat_core/src/hir/lifetimes.rs | 453 ++ .../vendor/diplomat_core/src/hir/lowering.rs | 1958 ++++++ .../vendor/diplomat_core/src/hir/methods.rs | 312 + .../src/hir/methods/borrowing_field.rs | 357 ++ .../src/hir/methods/borrowing_param.rs | 418 ++ .../vendor/diplomat_core/src/hir/mod.rs | 31 + .../vendor/diplomat_core/src/hir/paths.rs | 249 + .../diplomat_core/src/hir/primitives.rs | 141 + ...iplomat_core__hir__attrs__tests__auto.snap | 6 + ...t_core__hir__attrs__tests__comparator.snap | 22 + ...mat_core__hir__attrs__tests__iterator.snap | 12 + ...mocking_interface_for_non_opaque_type.snap | 5 + ...ts__mocking_interface_for_opaque_type.snap | 5 + ...ing_interface_for_unsupported_backend.snap | 5 + ...attrs__tests__primitive_struct_slices.snap | 5 + ...struct_slices_for_unsupported_backend.snap | 5 + ...s__struct_ref_for_unsupported_backend.snap | 5 + ...r__attrs__tests__unsupported_features.snap | 8 + ...hir__elision__tests__borrowing_fields.snap | 25 + ...ir__elision__tests__elision_in_struct.snap | 152 + ...core__hir__elision__tests__simple_mod.snap | 528 ++ ...__type_context__tests__basic_lowering.snap | 17 + ...text__tests__callback_borrowing_fails.snap | 5 + ...k_borrowing_fails_with_unsafe_borrows.snap | 6 + ...pe_context__tests__lifetime_in_return.snap | 6 + ..._hir__type_context__tests__mut_struct.snap | 5 + ...type_context__tests__mut_struct_fails.snap | 5 + ..._type_context__tests__non_opaque_move.snap | 8 + ...ts__non_primitive_struct_slices_fails.snap | 6 + ...text__tests__opaque_checks_with_error.snap | 7 + ...t__tests__opaque_checks_with_safe_use.snap | 5 + ..._hir__type_context__tests__opaque_ffi.snap | 9 + ...ore__hir__type_context__tests__option.snap | 11 + ...__type_context__tests__option_invalid.snap | 8 + ...ir__type_context__tests__option_valid.snap | 8 + ...ntext__tests__required_implied_bounds.snap | 11 + ...e_context__tests__return_struct_slice.snap | 5 + ...type_context__tests__struct_forbidden.snap | 10 + ...type_context__tests__struct_ref_fails.snap | 6 + ...__type_context__tests__zst_non_opaque.snap | 5 + .../diplomat_core/src/hir/ty_position.rs | 335 ++ .../diplomat_core/src/hir/type_context.rs | 1396 +++++ .../vendor/diplomat_core/src/hir/types.rs | 244 + deps/crates/vendor/diplomat_core/src/lib.rs | 15 + .../vendor/displaydoc/.cargo-checksum.json | 1 + deps/crates/vendor/displaydoc/CHANGELOG.md | 58 + deps/crates/vendor/displaydoc/Cargo.lock | 404 ++ deps/crates/vendor/displaydoc/Cargo.toml | 115 + deps/crates/vendor/displaydoc/LICENSE-APACHE | 201 + deps/crates/vendor/displaydoc/LICENSE-MIT | 23 + deps/crates/vendor/displaydoc/README.md | 115 + deps/crates/vendor/displaydoc/README.tpl | 23 + .../vendor/displaydoc/examples/simple.rs | 36 + deps/crates/vendor/displaydoc/src/attr.rs | 137 + deps/crates/vendor/displaydoc/src/expand.rs | 409 ++ deps/crates/vendor/displaydoc/src/fmt.rs | 159 + deps/crates/vendor/displaydoc/src/lib.rs | 186 + .../vendor/displaydoc/tests/compile_tests.rs | 29 + deps/crates/vendor/displaydoc/tests/happy.rs | 152 + .../displaydoc/tests/no_std/enum_prefix.rs | 36 + .../tests/no_std/enum_prefix_missing.rs | 35 + .../tests/no_std/enum_prefix_missing.stderr | 22 + .../displaydoc/tests/no_std/multi_line.rs | 37 + .../displaydoc/tests/no_std/multi_line.stderr | 22 + .../tests/no_std/multi_line_allow.rs | 38 + .../vendor/displaydoc/tests/no_std/with.rs | 32 + .../vendor/displaydoc/tests/no_std/without.rs | 28 + .../displaydoc/tests/no_std/without.stderr | 22 + .../vendor/displaydoc/tests/num_in_field.rs | 22 + .../displaydoc/tests/std/enum_prefix.rs | 36 + .../tests/std/enum_prefix_missing.rs | 35 + .../tests/std/enum_prefix_missing.stderr | 22 + .../vendor/displaydoc/tests/std/multi_line.rs | 37 + .../displaydoc/tests/std/multi_line.stderr | 22 + .../displaydoc/tests/std/multi_line_allow.rs | 38 + .../vendor/displaydoc/tests/std/multiple.rs | 38 + .../vendor/displaydoc/tests/std/without.rs | 28 + .../displaydoc/tests/std/without.stderr | 22 + .../vendor/displaydoc/tests/variantless.rs | 6 + .../crates/vendor/displaydoc/update-readme.sh | 5 + .../vendor/icu_calendar/.cargo-checksum.json | 1 + deps/crates/vendor/icu_calendar/Cargo.toml | 168 + deps/crates/vendor/icu_calendar/LICENSE | 46 + deps/crates/vendor/icu_calendar/README.md | 79 + .../vendor/icu_calendar/benches/convert.rs | 106 + .../vendor/icu_calendar/benches/date.rs | 268 + .../benches/fixtures/datetimes.json | 82 + .../icu_calendar/benches/fixtures/mod.rs | 18 + .../vendor/icu_calendar/src/any_calendar.rs | 1992 +++++++ .../vendor/icu_calendar/src/cal/buddhist.rs | 435 ++ .../vendor/icu_calendar/src/cal/chinese.rs | 1039 ++++ .../icu_calendar/src/cal/chinese_based.rs | 446 ++ .../vendor/icu_calendar/src/cal/coptic.rs | 234 + .../vendor/icu_calendar/src/cal/dangi.rs | 932 +++ .../vendor/icu_calendar/src/cal/ethiopian.rs | 394 ++ .../vendor/icu_calendar/src/cal/gregorian.rs | 389 ++ .../vendor/icu_calendar/src/cal/hebrew.rs | 516 ++ .../vendor/icu_calendar/src/cal/hijri.rs | 2050 +++++++ .../src/cal/hijri/ummalqura_data.rs | 317 + .../vendor/icu_calendar/src/cal/indian.rs | 507 ++ .../crates/vendor/icu_calendar/src/cal/iso.rs | 576 ++ .../vendor/icu_calendar/src/cal/japanese.rs | 955 +++ .../vendor/icu_calendar/src/cal/julian.rs | 493 ++ .../crates/vendor/icu_calendar/src/cal/mod.rs | 51 + .../vendor/icu_calendar/src/cal/persian.rs | 726 +++ .../crates/vendor/icu_calendar/src/cal/roc.rs | 443 ++ .../vendor/icu_calendar/src/calendar.rs | 105 + .../icu_calendar/src/calendar_arithmetic.rs | 427 ++ deps/crates/vendor/icu_calendar/src/date.rs | 524 ++ .../vendor/icu_calendar/src/duration.rs | 158 + deps/crates/vendor/icu_calendar/src/error.rs | 92 + deps/crates/vendor/icu_calendar/src/ixdtf.rs | 120 + deps/crates/vendor/icu_calendar/src/lib.rs | 140 + .../vendor/icu_calendar/src/provider.rs | 342 ++ .../src/provider/chinese_based.rs | 298 + .../vendor/icu_calendar/src/provider/hijri.rs | 165 + .../icu_calendar/src/tests/continuity_test.rs | 242 + .../vendor/icu_calendar/src/tests/mod.rs | 5 + deps/crates/vendor/icu_calendar/src/types.rs | 375 ++ deps/crates/vendor/icu_calendar/src/week.rs | 676 +++ .../icu_calendar_data/.cargo-checksum.json | 1 + .../vendor/icu_calendar_data/Cargo.toml | 60 + deps/crates/vendor/icu_calendar_data/LICENSE | 46 + .../crates/vendor/icu_calendar_data/README.md | 14 + deps/crates/vendor/icu_calendar_data/build.rs | 11 + .../data/calendar_chinese_v1.rs.data | 75 + .../data/calendar_dangi_v1.rs.data | 75 + .../calendar_hijri_simulated_mecca_v1.rs.data | 75 + .../calendar_japanese_extended_v1.rs.data | 75 + .../data/calendar_japanese_modern_v1.rs.data | 75 + .../data/calendar_week_v1.rs.data | 64 + .../vendor/icu_calendar_data/data/mod.rs | 44 + .../vendor/icu_calendar_data/src/lib.rs | 17 + .../icu_collections/.cargo-checksum.json | 1 + deps/crates/vendor/icu_collections/Cargo.lock | 856 +++ deps/crates/vendor/icu_collections/Cargo.toml | 154 + deps/crates/vendor/icu_collections/LICENSE | 46 + deps/crates/vendor/icu_collections/README.md | 27 + .../icu_collections/benches/codepointtrie.rs | 104 + .../vendor/icu_collections/benches/iai_cpt.rs | 77 + .../icu_collections/benches/inv_list.rs | 66 + .../icu_collections/benches/tries/gc_fast.rs | 1128 ++++ .../icu_collections/benches/tries/gc_small.rs | 865 +++ .../icu_collections/benches/tries/mod.rs | 6 + .../examples/unicode_bmp_blocks_selector.rs | 71 + .../icu_collections/src/char16trie/mod.rs | 44 + .../icu_collections/src/char16trie/trie.rs | 490 ++ .../src/codepointinvlist/builder.rs | 986 ++++ .../src/codepointinvlist/conversions.rs | 180 + .../src/codepointinvlist/cpinvlist.rs | 1064 ++++ .../src/codepointinvlist/mod.rs | 82 + .../src/codepointinvlist/utils.rs | 118 + .../src/codepointinvliststringlist/mod.rs | 384 ++ .../src/codepointtrie/cptrie.rs | 1345 +++++ .../src/codepointtrie/error.rs | 24 + .../src/codepointtrie/impl_const.rs | 76 + .../icu_collections/src/codepointtrie/mod.rs | 51 + .../src/codepointtrie/planes.rs | 296 + .../src/codepointtrie/serde.rs | 52 + .../icu_collections/src/codepointtrie/toml.rs | 124 + .../icu_collections/src/iterator_utils.rs | 188 + deps/crates/vendor/icu_collections/src/lib.rs | 44 + .../icu_collections/tests/char16trie.rs | 304 + .../vendor/icu_collections/tests/cpt.rs | 489 ++ .../tests/data/char16trie/empty.toml | 11 + .../tests/data/char16trie/months.toml | 19 + .../tests/data/char16trie/test_a.toml | 11 + .../tests/data/char16trie/test_a_ab.toml | 11 + .../tests/data/char16trie/test_branches.toml | 15 + .../tests/data/char16trie/test_compact.toml | 16 + .../data/char16trie/test_long_branch.toml | 28 + .../data/char16trie/test_long_sequence.toml | 32 + .../data/char16trie/test_shortest_branch.toml | 11 + .../tests/data/cpt/free-blocks.16.toml | 113 + .../tests/data/cpt/free-blocks.32.toml | 113 + .../tests/data/cpt/free-blocks.8.toml | 113 + .../tests/data/cpt/free-blocks.small16.toml | 53 + .../tests/data/cpt/grow-data.16.toml | 117 + .../tests/data/cpt/grow-data.32.toml | 113 + .../tests/data/cpt/grow-data.8.toml | 113 + .../tests/data/cpt/grow-data.small16.toml | 53 + .../tests/data/cpt/planes.toml | 140 + .../tests/data/cpt/set-empty.16.toml | 101 + .../tests/data/cpt/set-empty.32.toml | 101 + .../tests/data/cpt/set-empty.8.toml | 101 + .../tests/data/cpt/set-empty.small16.toml | 41 + .../tests/data/cpt/set-single-value.16.toml | 101 + .../tests/data/cpt/set-single-value.32.toml | 101 + .../tests/data/cpt/set-single-value.8.toml | 101 + .../data/cpt/set-single-value.small16.toml | 41 + .../tests/data/cpt/set1.16.toml | 138 + .../tests/data/cpt/set1.32.toml | 138 + .../tests/data/cpt/set1.8.toml | 138 + .../tests/data/cpt/set1.small16.toml | 81 + .../tests/data/cpt/set2-overlap.16.toml | 128 + .../tests/data/cpt/set2-overlap.32.toml | 128 + .../tests/data/cpt/set2-overlap.small16.toml | 73 + .../tests/data/cpt/set3-initial-9.16.toml | 128 + .../tests/data/cpt/set3-initial-9.32.toml | 128 + .../tests/data/cpt/set3-initial-9.8.toml | 128 + .../data/cpt/set3-initial-9.small16.toml | 72 + .../tests/data/cpt/short-all-same.16.toml | 321 + .../tests/data/cpt/short-all-same.8.toml | 385 ++ .../data/cpt/short-all-same.small16.toml | 321 + .../tests/data/cpt/small0-in-fast.16.toml | 116 + .../tests/data/cpt/small0-in-fast.32.toml | 116 + .../tests/data/cpt/small0-in-fast.8.toml | 116 + .../data/cpt/small0-in-fast.small16.toml | 63 + .../vendor/icu_locale/.cargo-checksum.json | 1 + deps/crates/vendor/icu_locale/Cargo.toml | 161 + deps/crates/vendor/icu_locale/LICENSE | 46 + deps/crates/vendor/icu_locale/README.md | 75 + .../icu_locale/benches/fixtures/locales.json | 41 + .../fixtures/uncanonicalized-locales.json | 88 + .../benches/locale_canonicalizer.rs | 107 + .../vendor/icu_locale/src/canonicalizer.rs | 625 ++ .../vendor/icu_locale/src/directionality.rs | 255 + .../vendor/icu_locale/src/exemplar_chars.rs | 305 + deps/crates/vendor/icu_locale/src/expander.rs | 606 ++ .../icu_locale/src/fallback/algorithms.rs | 515 ++ .../vendor/icu_locale/src/fallback/mod.rs | 255 + deps/crates/vendor/icu_locale/src/lib.rs | 113 + deps/crates/vendor/icu_locale/src/provider.rs | 486 ++ .../tests/fixtures/canonicalize.json | 444 ++ .../icu_locale/tests/fixtures/maximize.json | 214 + .../icu_locale/tests/fixtures/minimize.json | 26 + .../vendor/icu_locale/tests/fixtures/mod.rs | 12 + .../icu_locale/tests/locale_canonicalizer.rs | 81 + .../icu_locale_core/.cargo-checksum.json | 1 + deps/crates/vendor/icu_locale_core/Cargo.toml | 159 + deps/crates/vendor/icu_locale_core/LICENSE | 46 + deps/crates/vendor/icu_locale_core/README.md | 55 + .../benches/fixtures/langid.json | 48 + .../benches/fixtures/locale.json | 26 + .../icu_locale_core/benches/fixtures/mod.rs | 28 + .../benches/fixtures/subtags.json | 18 + .../icu_locale_core/benches/helpers/macros.rs | 110 + .../icu_locale_core/benches/helpers/mod.rs | 5 + .../icu_locale_core/benches/iai_langid.rs | 125 + .../vendor/icu_locale_core/benches/langid.rs | 92 + .../vendor/icu_locale_core/benches/locale.rs | 86 + .../vendor/icu_locale_core/benches/subtags.rs | 39 + .../crates/vendor/icu_locale_core/src/data.rs | 440 ++ .../vendor/icu_locale_core/src/databake.rs | 22 + .../icu_locale_core/src/extensions/mod.rs | 397 ++ .../src/extensions/other/mod.rs | 264 + .../src/extensions/private/mod.rs | 250 + .../src/extensions/private/other.rs | 47 + .../src/extensions/transform/fields.rs | 220 + .../src/extensions/transform/key.rs | 32 + .../src/extensions/transform/mod.rs | 331 ++ .../src/extensions/transform/value.rs | 160 + .../src/extensions/unicode/attribute.rs | 34 + .../src/extensions/unicode/attributes.rs | 177 + .../src/extensions/unicode/key.rs | 32 + .../src/extensions/unicode/keywords.rs | 418 ++ .../src/extensions/unicode/mod.rs | 269 + .../src/extensions/unicode/subdivision.rs | 181 + .../src/extensions/unicode/value.rs | 354 ++ .../vendor/icu_locale_core/src/helpers.rs | 425 ++ .../vendor/icu_locale_core/src/langid.rs | 662 +++ deps/crates/vendor/icu_locale_core/src/lib.rs | 96 + .../vendor/icu_locale_core/src/locale.rs | 607 ++ .../vendor/icu_locale_core/src/macros.rs | 187 + .../icu_locale_core/src/parser/errors.rs | 69 + .../icu_locale_core/src/parser/langid.rs | 273 + .../icu_locale_core/src/parser/locale.rs | 42 + .../vendor/icu_locale_core/src/parser/mod.rs | 185 + .../src/preferences/extensions/mod.rs | 23 + .../preferences/extensions/unicode/errors.rs | 15 + .../extensions/unicode/keywords/calendar.rs | 69 + .../extensions/unicode/keywords/collation.rs | 79 + .../extensions/unicode/keywords/currency.rs | 31 + .../unicode/keywords/currency_format.rs | 20 + .../unicode/keywords/dictionary_break.rs | 39 + .../extensions/unicode/keywords/emoji.rs | 25 + .../extensions/unicode/keywords/first_day.rs | 31 + .../extensions/unicode/keywords/hour_cycle.rs | 20 + .../extensions/unicode/keywords/line_break.rs | 23 + .../unicode/keywords/line_break_word.rs | 25 + .../unicode/keywords/measurement_system.rs | 22 + .../keywords/measurement_unit_override.rs | 20 + .../extensions/unicode/keywords/mod.rs | 44 + .../unicode/keywords/numbering_system.rs | 26 + .../unicode/keywords/region_override.rs | 63 + .../unicode/keywords/regional_subdivision.rs | 52 + .../unicode/keywords/sentence_supression.rs | 21 + .../extensions/unicode/keywords/timezone.rs | 26 + .../extensions/unicode/keywords/variant.rs | 16 + .../extensions/unicode/macros/enum_keyword.rs | 320 + .../extensions/unicode/macros/mod.rs | 13 + .../unicode/macros/struct_keyword.rs | 124 + .../src/preferences/extensions/unicode/mod.rs | 17 + .../icu_locale_core/src/preferences/locale.rs | 180 + .../icu_locale_core/src/preferences/mod.rs | 612 ++ .../vendor/icu_locale_core/src/serde.rs | 134 + .../icu_locale_core/src/shortvec/litemap.rs | 198 + .../icu_locale_core/src/shortvec/mod.rs | 370 ++ .../icu_locale_core/src/subtags/language.rs | 59 + .../vendor/icu_locale_core/src/subtags/mod.rs | 163 + .../icu_locale_core/src/subtags/region.rs | 60 + .../icu_locale_core/src/subtags/script.rs | 41 + .../icu_locale_core/src/subtags/variant.rs | 35 + .../icu_locale_core/src/subtags/variants.rs | 136 + .../vendor/icu_locale_core/src/zerovec.rs | 131 + .../tests/fixtures/canonicalize.json | 68 + .../tests/fixtures/invalid-extensions.json | 162 + .../tests/fixtures/invalid.json | 142 + .../tests/fixtures/langid.json | 167 + .../tests/fixtures/locale.json | 298 + .../icu_locale_core/tests/fixtures/mod.rs | 254 + .../vendor/icu_locale_core/tests/langid.rs | 156 + .../vendor/icu_locale_core/tests/locale.rs | 119 + .../icu_locale_data/.cargo-checksum.json | 1 + deps/crates/vendor/icu_locale_data/Cargo.toml | 60 + deps/crates/vendor/icu_locale_data/LICENSE | 46 + deps/crates/vendor/icu_locale_data/README.md | 14 + deps/crates/vendor/icu_locale_data/build.rs | 11 + .../data/locale_aliases_v1.rs.data | 114 + ...e_exemplar_characters_auxiliary_v1.rs.data | 1080 ++++ ...ocale_exemplar_characters_index_v1.rs.data | 835 +++ ...locale_exemplar_characters_main_v1.rs.data | 1178 ++++ ...ale_exemplar_characters_numbers_v1.rs.data | 289 + ...exemplar_characters_punctuation_v1.rs.data | 688 +++ .../locale_likely_subtags_extended_v1.rs.data | 100 + .../locale_likely_subtags_language_v1.rs.data | 89 + ...le_likely_subtags_script_region_v1.rs.data | 88 + .../data/locale_parents_v1.rs.data | 80 + .../data/locale_script_direction_v1.rs.data | 75 + .../crates/vendor/icu_locale_data/data/mod.rs | 54 + deps/crates/vendor/icu_locale_data/src/lib.rs | 17 + .../vendor/icu_provider/.cargo-checksum.json | 1 + deps/crates/vendor/icu_provider/Cargo.toml | 184 + deps/crates/vendor/icu_provider/LICENSE | 46 + deps/crates/vendor/icu_provider/README.md | 84 + .../icu_provider/benches/data_locale_bench.rs | 69 + deps/crates/vendor/icu_provider/src/baked.rs | 34 + .../vendor/icu_provider/src/baked/zerotrie.rs | 172 + deps/crates/vendor/icu_provider/src/buf.rs | 133 + .../vendor/icu_provider/src/buf/serde.rs | 246 + .../vendor/icu_provider/src/constructors.rs | 226 + .../vendor/icu_provider/src/data_provider.rs | 635 ++ .../crates/vendor/icu_provider/src/dynutil.rs | 184 + deps/crates/vendor/icu_provider/src/error.rs | 281 + .../vendor/icu_provider/src/export/mod.rs | 213 + .../vendor/icu_provider/src/export/payload.rs | 335 ++ .../vendor/icu_provider/src/fallback.rs | 123 + .../vendor/icu_provider/src/hello_world.rs | 402 ++ deps/crates/vendor/icu_provider/src/lib.rs | 228 + deps/crates/vendor/icu_provider/src/marker.rs | 661 +++ .../crates/vendor/icu_provider/src/request.rs | 368 ++ .../vendor/icu_provider/src/response.rs | 1108 ++++ .../icu_provider/src/serde_borrow_de_utils.rs | 82 + .../vendor/icu_provider/src/varule_traits.rs | 123 + .../vendor/ixdtf-0.5.0/.cargo-checksum.json | 1 + deps/crates/vendor/ixdtf-0.5.0/Cargo.toml | 66 + deps/crates/vendor/ixdtf-0.5.0/LICENSE | 46 + deps/crates/vendor/ixdtf-0.5.0/README.md | 380 ++ deps/crates/vendor/ixdtf-0.5.0/src/error.rs | 115 + deps/crates/vendor/ixdtf-0.5.0/src/lib.rs | 399 ++ .../ixdtf-0.5.0/src/parsers/annotations.rs | 175 + .../ixdtf-0.5.0/src/parsers/datetime.rs | 327 + .../ixdtf-0.5.0/src/parsers/duration.rs | 213 + .../vendor/ixdtf-0.5.0/src/parsers/grammar.rs | 169 + .../vendor/ixdtf-0.5.0/src/parsers/mod.rs | 542 ++ .../vendor/ixdtf-0.5.0/src/parsers/records.rs | 359 ++ .../vendor/ixdtf-0.5.0/src/parsers/tests.rs | 1395 +++++ .../vendor/ixdtf-0.5.0/src/parsers/time.rs | 173 + .../ixdtf-0.5.0/src/parsers/timezone.rs | 205 + deps/crates/vendor/ixdtf/.cargo-checksum.json | 1 + deps/crates/vendor/ixdtf/Cargo.toml | 67 + deps/crates/vendor/ixdtf/LICENSE | 46 + deps/crates/vendor/ixdtf/README.md | 380 ++ deps/crates/vendor/ixdtf/src/core.rs | 194 + deps/crates/vendor/ixdtf/src/error.rs | 201 + deps/crates/vendor/ixdtf/src/lib.rs | 404 ++ .../vendor/ixdtf/src/parsers/annotations.rs | 182 + .../vendor/ixdtf/src/parsers/datetime.rs | 342 ++ .../vendor/ixdtf/src/parsers/duration.rs | 226 + .../vendor/ixdtf/src/parsers/grammar.rs | 169 + deps/crates/vendor/ixdtf/src/parsers/mod.rs | 548 ++ deps/crates/vendor/ixdtf/src/parsers/tests.rs | 1522 +++++ deps/crates/vendor/ixdtf/src/parsers/time.rs | 194 + .../vendor/ixdtf/src/parsers/timezone.rs | 230 + deps/crates/vendor/ixdtf/src/records.rs | 361 ++ deps/crates/vendor/libm/.cargo-checksum.json | 1 + deps/crates/vendor/libm/CHANGELOG.md | 229 + deps/crates/vendor/libm/Cargo.toml | 57 + deps/crates/vendor/libm/LICENSE.txt | 258 + deps/crates/vendor/libm/README.md | 42 + deps/crates/vendor/libm/build.rs | 18 + deps/crates/vendor/libm/configure.rs | 189 + deps/crates/vendor/libm/src/lib.rs | 33 + deps/crates/vendor/libm/src/libm_helper.rs | 244 + deps/crates/vendor/libm/src/math/acos.rs | 112 + deps/crates/vendor/libm/src/math/acosf.rs | 79 + deps/crates/vendor/libm/src/math/acosh.rs | 27 + deps/crates/vendor/libm/src/math/acoshf.rs | 26 + .../vendor/libm/src/math/arch/aarch64.rs | 115 + deps/crates/vendor/libm/src/math/arch/i586.rs | 37 + deps/crates/vendor/libm/src/math/arch/mod.rs | 50 + .../vendor/libm/src/math/arch/wasm32.rs | 50 + deps/crates/vendor/libm/src/math/arch/x86.rs | 32 + .../vendor/libm/src/math/arch/x86/detect.rs | 232 + .../vendor/libm/src/math/arch/x86/fma.rs | 135 + deps/crates/vendor/libm/src/math/asin.rs | 115 + deps/crates/vendor/libm/src/math/asinf.rs | 68 + deps/crates/vendor/libm/src/math/asinh.rs | 36 + deps/crates/vendor/libm/src/math/asinhf.rs | 35 + deps/crates/vendor/libm/src/math/atan.rs | 182 + deps/crates/vendor/libm/src/math/atan2.rs | 131 + deps/crates/vendor/libm/src/math/atan2f.rs | 90 + deps/crates/vendor/libm/src/math/atanf.rs | 108 + deps/crates/vendor/libm/src/math/atanh.rs | 33 + deps/crates/vendor/libm/src/math/atanhf.rs | 33 + deps/crates/vendor/libm/src/math/cbrt.rs | 219 + deps/crates/vendor/libm/src/math/cbrtf.rs | 75 + deps/crates/vendor/libm/src/math/ceil.rs | 46 + deps/crates/vendor/libm/src/math/copysign.rs | 88 + deps/crates/vendor/libm/src/math/copysignf.rs | 8 + .../vendor/libm/src/math/copysignf128.rs | 8 + .../vendor/libm/src/math/copysignf16.rs | 8 + deps/crates/vendor/libm/src/math/cos.rs | 77 + deps/crates/vendor/libm/src/math/cosf.rs | 86 + deps/crates/vendor/libm/src/math/cosh.rs | 36 + deps/crates/vendor/libm/src/math/coshf.rs | 36 + deps/crates/vendor/libm/src/math/erf.rs | 314 + deps/crates/vendor/libm/src/math/erff.rs | 226 + deps/crates/vendor/libm/src/math/exp.rs | 150 + deps/crates/vendor/libm/src/math/exp10.rs | 23 + deps/crates/vendor/libm/src/math/exp10f.rs | 23 + deps/crates/vendor/libm/src/math/exp2.rs | 394 ++ deps/crates/vendor/libm/src/math/exp2f.rs | 135 + deps/crates/vendor/libm/src/math/expf.rs | 97 + deps/crates/vendor/libm/src/math/expm1.rs | 144 + deps/crates/vendor/libm/src/math/expm1f.rs | 134 + deps/crates/vendor/libm/src/math/expo2.rs | 14 + deps/crates/vendor/libm/src/math/fabs.rs | 116 + deps/crates/vendor/libm/src/math/fabsf.rs | 39 + deps/crates/vendor/libm/src/math/fabsf128.rs | 31 + deps/crates/vendor/libm/src/math/fabsf16.rs | 31 + deps/crates/vendor/libm/src/math/fdim.rs | 53 + deps/crates/vendor/libm/src/math/fdimf.rs | 12 + deps/crates/vendor/libm/src/math/fdimf128.rs | 12 + deps/crates/vendor/libm/src/math/fdimf16.rs | 12 + deps/crates/vendor/libm/src/math/floor.rs | 46 + deps/crates/vendor/libm/src/math/floorf.rs | 13 + deps/crates/vendor/libm/src/math/floorf128.rs | 7 + deps/crates/vendor/libm/src/math/floorf16.rs | 7 + deps/crates/vendor/libm/src/math/fma.rs | 171 + deps/crates/vendor/libm/src/math/fmin_fmax.rs | 167 + .../vendor/libm/src/math/fminimum_fmaximum.rs | 163 + .../libm/src/math/fminimum_fmaximum_num.rs | 163 + deps/crates/vendor/libm/src/math/fmod.rs | 25 + deps/crates/vendor/libm/src/math/fmodf.rs | 5 + deps/crates/vendor/libm/src/math/fmodf128.rs | 5 + deps/crates/vendor/libm/src/math/fmodf16.rs | 5 + deps/crates/vendor/libm/src/math/frexp.rs | 21 + deps/crates/vendor/libm/src/math/frexpf.rs | 22 + .../vendor/libm/src/math/generic/ceil.rs | 174 + .../vendor/libm/src/math/generic/copysign.rs | 11 + .../vendor/libm/src/math/generic/fabs.rs | 8 + .../vendor/libm/src/math/generic/fdim.rs | 6 + .../vendor/libm/src/math/generic/floor.rs | 157 + .../vendor/libm/src/math/generic/fma.rs | 278 + .../vendor/libm/src/math/generic/fma_wide.rs | 73 + .../vendor/libm/src/math/generic/fmax.rs | 24 + .../vendor/libm/src/math/generic/fmaximum.rs | 28 + .../libm/src/math/generic/fmaximum_num.rs | 27 + .../vendor/libm/src/math/generic/fmin.rs | 24 + .../vendor/libm/src/math/generic/fminimum.rs | 28 + .../libm/src/math/generic/fminimum_num.rs | 27 + .../vendor/libm/src/math/generic/fmod.rs | 68 + .../vendor/libm/src/math/generic/mod.rs | 42 + .../vendor/libm/src/math/generic/rint.rs | 130 + .../vendor/libm/src/math/generic/round.rs | 83 + .../vendor/libm/src/math/generic/scalbn.rs | 121 + .../vendor/libm/src/math/generic/sqrt.rs | 541 ++ .../vendor/libm/src/math/generic/trunc.rs | 148 + deps/crates/vendor/libm/src/math/hypot.rs | 74 + deps/crates/vendor/libm/src/math/hypotf.rs | 43 + deps/crates/vendor/libm/src/math/ilogb.rs | 32 + deps/crates/vendor/libm/src/math/ilogbf.rs | 28 + deps/crates/vendor/libm/src/math/j0.rs | 426 ++ deps/crates/vendor/libm/src/math/j0f.rs | 363 ++ deps/crates/vendor/libm/src/math/j1.rs | 418 ++ deps/crates/vendor/libm/src/math/j1f.rs | 384 ++ deps/crates/vendor/libm/src/math/jn.rs | 339 ++ deps/crates/vendor/libm/src/math/jnf.rs | 253 + deps/crates/vendor/libm/src/math/k_cos.rs | 62 + deps/crates/vendor/libm/src/math/k_cosf.rs | 29 + deps/crates/vendor/libm/src/math/k_expo2.rs | 14 + deps/crates/vendor/libm/src/math/k_expo2f.rs | 14 + deps/crates/vendor/libm/src/math/k_sin.rs | 57 + deps/crates/vendor/libm/src/math/k_sinf.rs | 30 + deps/crates/vendor/libm/src/math/k_tan.rs | 105 + deps/crates/vendor/libm/src/math/k_tanf.rs | 46 + deps/crates/vendor/libm/src/math/ldexp.rs | 21 + deps/crates/vendor/libm/src/math/ldexpf.rs | 4 + deps/crates/vendor/libm/src/math/ldexpf128.rs | 4 + deps/crates/vendor/libm/src/math/ldexpf16.rs | 4 + deps/crates/vendor/libm/src/math/lgamma.rs | 8 + deps/crates/vendor/libm/src/math/lgamma_r.rs | 321 + deps/crates/vendor/libm/src/math/lgammaf.rs | 8 + deps/crates/vendor/libm/src/math/lgammaf_r.rs | 256 + deps/crates/vendor/libm/src/math/log.rs | 118 + deps/crates/vendor/libm/src/math/log10.rs | 118 + deps/crates/vendor/libm/src/math/log10f.rs | 92 + deps/crates/vendor/libm/src/math/log1p.rs | 144 + deps/crates/vendor/libm/src/math/log1pf.rs | 99 + deps/crates/vendor/libm/src/math/log2.rs | 107 + deps/crates/vendor/libm/src/math/log2f.rs | 88 + deps/crates/vendor/libm/src/math/logf.rs | 66 + deps/crates/vendor/libm/src/math/mod.rs | 394 ++ deps/crates/vendor/libm/src/math/modf.rs | 35 + deps/crates/vendor/libm/src/math/modff.rs | 34 + deps/crates/vendor/libm/src/math/nextafter.rs | 37 + .../crates/vendor/libm/src/math/nextafterf.rs | 37 + deps/crates/vendor/libm/src/math/pow.rs | 624 ++ deps/crates/vendor/libm/src/math/powf.rs | 343 ++ deps/crates/vendor/libm/src/math/rem_pio2.rs | 235 + .../vendor/libm/src/math/rem_pio2_large.rs | 468 ++ deps/crates/vendor/libm/src/math/rem_pio2f.rs | 67 + deps/crates/vendor/libm/src/math/remainder.rs | 5 + .../crates/vendor/libm/src/math/remainderf.rs | 5 + deps/crates/vendor/libm/src/math/remquo.rs | 106 + deps/crates/vendor/libm/src/math/remquof.rs | 93 + deps/crates/vendor/libm/src/math/rint.rs | 51 + deps/crates/vendor/libm/src/math/round.rs | 25 + deps/crates/vendor/libm/src/math/roundeven.rs | 36 + deps/crates/vendor/libm/src/math/roundf.rs | 5 + deps/crates/vendor/libm/src/math/roundf128.rs | 5 + deps/crates/vendor/libm/src/math/roundf16.rs | 5 + deps/crates/vendor/libm/src/math/scalbn.rs | 87 + deps/crates/vendor/libm/src/math/scalbnf.rs | 4 + .../crates/vendor/libm/src/math/scalbnf128.rs | 4 + deps/crates/vendor/libm/src/math/scalbnf16.rs | 4 + deps/crates/vendor/libm/src/math/sin.rs | 95 + deps/crates/vendor/libm/src/math/sincos.rs | 137 + deps/crates/vendor/libm/src/math/sincosf.rs | 176 + deps/crates/vendor/libm/src/math/sinf.rs | 96 + deps/crates/vendor/libm/src/math/sinh.rs | 51 + deps/crates/vendor/libm/src/math/sinhf.rs | 30 + deps/crates/vendor/libm/src/math/sqrt.rs | 51 + deps/crates/vendor/libm/src/math/sqrtf.rs | 15 + deps/crates/vendor/libm/src/math/sqrtf128.rs | 5 + deps/crates/vendor/libm/src/math/sqrtf16.rs | 11 + .../vendor/libm/src/math/support/big.rs | 257 + .../vendor/libm/src/math/support/big/tests.rs | 277 + .../vendor/libm/src/math/support/env.rs | 130 + .../libm/src/math/support/feature_detect.rs | 211 + .../libm/src/math/support/float_traits.rs | 551 ++ .../vendor/libm/src/math/support/hex_float.rs | 1181 ++++ .../libm/src/math/support/int_traits.rs | 455 ++ .../vendor/libm/src/math/support/macros.rs | 157 + .../vendor/libm/src/math/support/mod.rs | 32 + deps/crates/vendor/libm/src/math/tan.rs | 74 + deps/crates/vendor/libm/src/math/tanf.rs | 81 + deps/crates/vendor/libm/src/math/tanh.rs | 53 + deps/crates/vendor/libm/src/math/tanhf.rs | 38 + deps/crates/vendor/libm/src/math/tgamma.rs | 209 + deps/crates/vendor/libm/src/math/tgammaf.rs | 7 + deps/crates/vendor/libm/src/math/trunc.rs | 53 + deps/crates/vendor/libm/src/math/truncf.rs | 23 + deps/crates/vendor/libm/src/math/truncf128.rs | 7 + deps/crates/vendor/libm/src/math/truncf16.rs | 7 + .../vendor/litemap/.cargo-checksum.json | 1 + deps/crates/vendor/litemap/Cargo.lock | 1008 ++++ deps/crates/vendor/litemap/Cargo.toml | 148 + deps/crates/vendor/litemap/LICENSE | 46 + deps/crates/vendor/litemap/README.md | 51 + deps/crates/vendor/litemap/benches/litemap.rs | 218 + .../examples/language_names_hash_map.rs | 36 + .../examples/language_names_lite_map.rs | 36 + .../litemap/examples/litemap_bincode.rs | 60 + .../litemap/examples/litemap_postcard.rs | 54 + deps/crates/vendor/litemap/src/databake.rs | 81 + deps/crates/vendor/litemap/src/lib.rs | 83 + deps/crates/vendor/litemap/src/map.rs | 1663 ++++++ deps/crates/vendor/litemap/src/serde.rs | 245 + .../vendor/litemap/src/serde_helpers.rs | 164 + deps/crates/vendor/litemap/src/store/mod.rs | 176 + .../vendor/litemap/src/store/slice_impl.rs | 63 + .../vendor/litemap/src/store/vec_impl.rs | 306 + deps/crates/vendor/litemap/src/testing.rs | 296 + deps/crates/vendor/litemap/tests/rkyv.rs | 98 + deps/crates/vendor/litemap/tests/serde.rs | 22 + deps/crates/vendor/litemap/tests/store.rs | 158 + .../vendor/num-traits/.cargo-checksum.json | 1 + deps/crates/vendor/num-traits/Cargo.toml | 54 + deps/crates/vendor/num-traits/LICENSE-APACHE | 201 + deps/crates/vendor/num-traits/LICENSE-MIT | 25 + deps/crates/vendor/num-traits/README.md | 58 + deps/crates/vendor/num-traits/RELEASES.md | 307 + deps/crates/vendor/num-traits/build.rs | 7 + deps/crates/vendor/num-traits/src/bounds.rs | 148 + deps/crates/vendor/num-traits/src/cast.rs | 770 +++ deps/crates/vendor/num-traits/src/float.rs | 2513 ++++++++ .../vendor/num-traits/src/identities.rs | 238 + deps/crates/vendor/num-traits/src/int.rs | 562 ++ deps/crates/vendor/num-traits/src/lib.rs | 635 ++ deps/crates/vendor/num-traits/src/macros.rs | 44 + .../crates/vendor/num-traits/src/ops/bytes.rs | 317 + .../vendor/num-traits/src/ops/checked.rs | 261 + .../vendor/num-traits/src/ops/euclid.rs | 278 + deps/crates/vendor/num-traits/src/ops/inv.rs | 47 + deps/crates/vendor/num-traits/src/ops/mod.rs | 8 + .../vendor/num-traits/src/ops/mul_add.rs | 149 + .../vendor/num-traits/src/ops/overflowing.rs | 96 + .../vendor/num-traits/src/ops/saturating.rs | 130 + .../vendor/num-traits/src/ops/wrapping.rs | 327 + deps/crates/vendor/num-traits/src/pow.rs | 242 + deps/crates/vendor/num-traits/src/real.rs | 834 +++ deps/crates/vendor/num-traits/src/sign.rs | 216 + deps/crates/vendor/num-traits/tests/cast.rs | 387 ++ .../vendor/potential_utf/.cargo-checksum.json | 1 + deps/crates/vendor/potential_utf/Cargo.toml | 82 + deps/crates/vendor/potential_utf/LICENSE | 46 + deps/crates/vendor/potential_utf/README.md | 11 + deps/crates/vendor/potential_utf/src/lib.rs | 33 + deps/crates/vendor/potential_utf/src/uchar.rs | 375 ++ deps/crates/vendor/potential_utf/src/ustr.rs | 278 + .../vendor/potential_utf/src/writeable.rs | 128 + .../vendor/proc-macro2/.cargo-checksum.json | 1 + deps/crates/vendor/proc-macro2/Cargo.toml | 105 + deps/crates/vendor/proc-macro2/LICENSE-APACHE | 176 + deps/crates/vendor/proc-macro2/LICENSE-MIT | 23 + deps/crates/vendor/proc-macro2/README.md | 94 + deps/crates/vendor/proc-macro2/build.rs | 267 + .../vendor/proc-macro2/rust-toolchain.toml | 2 + .../vendor/proc-macro2/src/detection.rs | 75 + deps/crates/vendor/proc-macro2/src/extra.rs | 151 + .../crates/vendor/proc-macro2/src/fallback.rs | 1256 ++++ deps/crates/vendor/proc-macro2/src/lib.rs | 1495 +++++ .../crates/vendor/proc-macro2/src/location.rs | 29 + deps/crates/vendor/proc-macro2/src/marker.rs | 17 + deps/crates/vendor/proc-macro2/src/num.rs | 17 + deps/crates/vendor/proc-macro2/src/parse.rs | 995 ++++ deps/crates/vendor/proc-macro2/src/probe.rs | 10 + .../proc-macro2/src/probe/proc_macro_span.rs | 51 + .../src/probe/proc_macro_span_file.rs | 14 + .../src/probe/proc_macro_span_location.rs | 21 + deps/crates/vendor/proc-macro2/src/rcvec.rs | 146 + .../proc-macro2/src/rustc_literal_escaper.rs | 701 +++ deps/crates/vendor/proc-macro2/src/wrapper.rs | 984 ++++ .../vendor/proc-macro2/tests/comments.rs | 105 + .../vendor/proc-macro2/tests/features.rs | 10 + .../crates/vendor/proc-macro2/tests/marker.rs | 97 + deps/crates/vendor/proc-macro2/tests/test.rs | 1094 ++++ .../vendor/proc-macro2/tests/test_fmt.rs | 28 + .../vendor/proc-macro2/tests/test_size.rs | 81 + deps/crates/vendor/quote/.cargo-checksum.json | 1 + deps/crates/vendor/quote/Cargo.toml | 70 + deps/crates/vendor/quote/LICENSE-APACHE | 176 + deps/crates/vendor/quote/LICENSE-MIT | 23 + deps/crates/vendor/quote/README.md | 271 + deps/crates/vendor/quote/build.rs | 32 + deps/crates/vendor/quote/rust-toolchain.toml | 2 + deps/crates/vendor/quote/src/ext.rs | 136 + deps/crates/vendor/quote/src/format.rs | 168 + .../crates/vendor/quote/src/ident_fragment.rs | 88 + deps/crates/vendor/quote/src/lib.rs | 1455 +++++ deps/crates/vendor/quote/src/runtime.rs | 503 ++ deps/crates/vendor/quote/src/spanned.rs | 49 + deps/crates/vendor/quote/src/to_tokens.rs | 271 + deps/crates/vendor/quote/tests/compiletest.rs | 7 + deps/crates/vendor/quote/tests/test.rs | 568 ++ .../ui/does-not-have-iter-interpolated-dup.rs | 9 + ...does-not-have-iter-interpolated-dup.stderr | 13 + .../ui/does-not-have-iter-interpolated.rs | 9 + .../ui/does-not-have-iter-interpolated.stderr | 13 + .../tests/ui/does-not-have-iter-separated.rs | 5 + .../ui/does-not-have-iter-separated.stderr | 13 + .../quote/tests/ui/does-not-have-iter.rs | 5 + .../quote/tests/ui/does-not-have-iter.stderr | 13 + .../vendor/quote/tests/ui/not-quotable.rs | 7 + .../vendor/quote/tests/ui/not-quotable.stderr | 20 + .../vendor/quote/tests/ui/not-repeatable.rs | 8 + .../quote/tests/ui/not-repeatable.stderr | 42 + .../vendor/quote/tests/ui/wrong-type-span.rs | 7 + .../quote/tests/ui/wrong-type-span.stderr | 10 + deps/crates/vendor/resb/.cargo-checksum.json | 1 + deps/crates/vendor/resb/Cargo.lock | 125 + deps/crates/vendor/resb/Cargo.toml | 90 + deps/crates/vendor/resb/LICENSE | 46 + deps/crates/vendor/resb/README.md | 17 + .../vendor/resb/examples/data/zoneinfo64.res | Bin 0 -> 148608 bytes .../vendor/resb/examples/data/zoneinfo64.txt | 3478 +++++++++++ deps/crates/vendor/resb/examples/genrb.rs | 28 + deps/crates/vendor/resb/src/binary.rs | 480 ++ .../vendor/resb/src/binary/deserializer.rs | 1267 ++++ deps/crates/vendor/resb/src/binary/header.rs | 154 + deps/crates/vendor/resb/src/binary/helpers.rs | 115 + .../vendor/resb/src/binary/serializer.rs | 1249 ++++ deps/crates/vendor/resb/src/bundle.rs | 151 + deps/crates/vendor/resb/src/lib.rs | 41 + deps/crates/vendor/resb/src/text.rs | 13 + deps/crates/vendor/resb/src/text/reader.rs | 555 ++ .../resb/src/text/reader/parse_state.rs | 193 + deps/crates/vendor/serde/.cargo-checksum.json | 1 + deps/crates/vendor/serde/Cargo.toml | 84 + deps/crates/vendor/serde/LICENSE-APACHE | 176 + deps/crates/vendor/serde/LICENSE-MIT | 23 + deps/crates/vendor/serde/README.md | 114 + deps/crates/vendor/serde/build.rs | 69 + deps/crates/vendor/serde/crates-io.md | 65 + .../vendor/serde/src/core/crate_root.rs | 171 + .../vendor/serde/src/core/de/ignored_any.rs | 238 + deps/crates/vendor/serde/src/core/de/impls.rs | 3173 ++++++++++ deps/crates/vendor/serde/src/core/de/mod.rs | 2392 ++++++++ deps/crates/vendor/serde/src/core/de/value.rs | 1895 ++++++ deps/crates/vendor/serde/src/core/format.rs | 30 + deps/crates/vendor/serde/src/core/lib.rs | 121 + deps/crates/vendor/serde/src/core/macros.rs | 230 + .../vendor/serde/src/core/private/content.rs | 39 + .../vendor/serde/src/core/private/doc.rs | 165 + .../vendor/serde/src/core/private/mod.rs | 21 + .../vendor/serde/src/core/private/seed.rs | 20 + .../serde/src/core/private/size_hint.rs | 30 + .../vendor/serde/src/core/private/string.rs | 23 + deps/crates/vendor/serde/src/core/ser/fmt.rs | 170 + .../crates/vendor/serde/src/core/ser/impls.rs | 1045 ++++ .../vendor/serde/src/core/ser/impossible.rs | 216 + deps/crates/vendor/serde/src/core/ser/mod.rs | 2010 +++++++ .../crates/vendor/serde/src/core/std_error.rs | 48 + deps/crates/vendor/serde/src/integer128.rs | 14 + deps/crates/vendor/serde/src/lib.rs | 285 + deps/crates/vendor/serde/src/private/de.rs | 3501 +++++++++++ deps/crates/vendor/serde/src/private/mod.rs | 18 + deps/crates/vendor/serde/src/private/ser.rs | 1382 +++++ .../vendor/serde_core/.cargo-checksum.json | 1 + deps/crates/vendor/serde_core/Cargo.toml | 87 + deps/crates/vendor/serde_core/LICENSE-APACHE | 176 + deps/crates/vendor/serde_core/LICENSE-MIT | 23 + deps/crates/vendor/serde_core/README.md | 28 + deps/crates/vendor/serde_core/build.rs | 113 + .../vendor/serde_core/src/crate_root.rs | 171 + .../vendor/serde_core/src/de/ignored_any.rs | 238 + deps/crates/vendor/serde_core/src/de/impls.rs | 3173 ++++++++++ deps/crates/vendor/serde_core/src/de/mod.rs | 2392 ++++++++ deps/crates/vendor/serde_core/src/de/value.rs | 1895 ++++++ deps/crates/vendor/serde_core/src/format.rs | 30 + deps/crates/vendor/serde_core/src/lib.rs | 121 + deps/crates/vendor/serde_core/src/macros.rs | 230 + .../vendor/serde_core/src/private/content.rs | 39 + .../vendor/serde_core/src/private/doc.rs | 165 + .../vendor/serde_core/src/private/mod.rs | 21 + .../vendor/serde_core/src/private/seed.rs | 20 + .../serde_core/src/private/size_hint.rs | 30 + .../vendor/serde_core/src/private/string.rs | 23 + deps/crates/vendor/serde_core/src/ser/fmt.rs | 170 + .../crates/vendor/serde_core/src/ser/impls.rs | 1045 ++++ .../vendor/serde_core/src/ser/impossible.rs | 216 + deps/crates/vendor/serde_core/src/ser/mod.rs | 2010 +++++++ .../crates/vendor/serde_core/src/std_error.rs | 48 + .../vendor/serde_derive/.cargo-checksum.json | 1 + deps/crates/vendor/serde_derive/Cargo.toml | 87 + .../crates/vendor/serde_derive/LICENSE-APACHE | 176 + deps/crates/vendor/serde_derive/LICENSE-MIT | 23 + deps/crates/vendor/serde_derive/README.md | 114 + deps/crates/vendor/serde_derive/crates-io.md | 65 + deps/crates/vendor/serde_derive/src/bound.rs | 410 ++ deps/crates/vendor/serde_derive/src/de.rs | 973 +++ .../vendor/serde_derive/src/de/enum_.rs | 96 + .../serde_derive/src/de/enum_adjacently.rs | 323 + .../serde_derive/src/de/enum_externally.rs | 212 + .../serde_derive/src/de/enum_internally.rs | 106 + .../serde_derive/src/de/enum_untagged.rs | 135 + .../vendor/serde_derive/src/de/identifier.rs | 477 ++ .../vendor/serde_derive/src/de/struct_.rs | 697 +++ .../vendor/serde_derive/src/de/tuple.rs | 283 + .../crates/vendor/serde_derive/src/de/unit.rs | 52 + .../vendor/serde_derive/src/deprecated.rs | 56 + deps/crates/vendor/serde_derive/src/dummy.rs | 31 + .../vendor/serde_derive/src/fragment.rs | 74 + .../vendor/serde_derive/src/internals/ast.rs | 218 + .../vendor/serde_derive/src/internals/attr.rs | 1831 ++++++ .../vendor/serde_derive/src/internals/case.rs | 200 + .../serde_derive/src/internals/check.rs | 477 ++ .../vendor/serde_derive/src/internals/ctxt.rs | 68 + .../vendor/serde_derive/src/internals/mod.rs | 28 + .../vendor/serde_derive/src/internals/name.rs | 113 + .../serde_derive/src/internals/receiver.rs | 293 + .../serde_derive/src/internals/respan.rs | 16 + .../serde_derive/src/internals/symbol.rs | 71 + deps/crates/vendor/serde_derive/src/lib.rs | 127 + .../crates/vendor/serde_derive/src/pretend.rs | 188 + deps/crates/vendor/serde_derive/src/ser.rs | 1369 +++++ deps/crates/vendor/serde_derive/src/this.rs | 32 + .../vendor/smallvec/.cargo-checksum.json | 1 + deps/crates/vendor/smallvec/Cargo.toml | 110 + deps/crates/vendor/smallvec/LICENSE-APACHE | 201 + deps/crates/vendor/smallvec/LICENSE-MIT | 25 + deps/crates/vendor/smallvec/README.md | 26 + deps/crates/vendor/smallvec/benches/bench.rs | 312 + .../vendor/smallvec/debug_metadata/README.md | 111 + .../smallvec/debug_metadata/smallvec.natvis | 35 + .../vendor/smallvec/scripts/run_miri.sh | 24 + deps/crates/vendor/smallvec/src/arbitrary.rs | 19 + deps/crates/vendor/smallvec/src/lib.rs | 2605 ++++++++ .../vendor/smallvec/src/specialization.rs | 19 + deps/crates/vendor/smallvec/src/tests.rs | 1136 ++++ .../smallvec/tests/debugger_visualizer.rs | 68 + deps/crates/vendor/smallvec/tests/macro.rs | 24 + .../stable_deref_trait/.cargo-checksum.json | 1 + .../vendor/stable_deref_trait/Cargo.toml | 41 + .../vendor/stable_deref_trait/LICENSE-APACHE | 201 + .../vendor/stable_deref_trait/LICENSE-MIT | 25 + .../vendor/stable_deref_trait/README.md | 23 + .../vendor/stable_deref_trait/src/lib.rs | 202 + deps/crates/vendor/strck/.cargo-checksum.json | 1 + deps/crates/vendor/strck/Cargo.toml | 55 + deps/crates/vendor/strck/LICENSE | 8 + deps/crates/vendor/strck/README.md | 102 + deps/crates/vendor/strck/src/ident/mod.rs | 4 + deps/crates/vendor/strck/src/ident/rust.rs | 141 + deps/crates/vendor/strck/src/ident/unicode.rs | 145 + deps/crates/vendor/strck/src/lib.rs | 544 ++ deps/crates/vendor/strck/src/partial_eq.rs | 94 + deps/crates/vendor/strck/src/serde.rs | 78 + deps/crates/vendor/syn/.cargo-checksum.json | 1 + deps/crates/vendor/syn/Cargo.toml | 272 + deps/crates/vendor/syn/LICENSE-APACHE | 176 + deps/crates/vendor/syn/LICENSE-MIT | 23 + deps/crates/vendor/syn/README.md | 282 + deps/crates/vendor/syn/benches/file.rs | 59 + deps/crates/vendor/syn/benches/rust.rs | 194 + deps/crates/vendor/syn/src/attr.rs | 836 +++ deps/crates/vendor/syn/src/bigint.rs | 66 + deps/crates/vendor/syn/src/buffer.rs | 435 ++ deps/crates/vendor/syn/src/classify.rs | 311 + deps/crates/vendor/syn/src/custom_keyword.rs | 260 + .../vendor/syn/src/custom_punctuation.rs | 305 + deps/crates/vendor/syn/src/data.rs | 424 ++ deps/crates/vendor/syn/src/derive.rs | 259 + deps/crates/vendor/syn/src/discouraged.rs | 225 + deps/crates/vendor/syn/src/drops.rs | 58 + deps/crates/vendor/syn/src/error.rs | 468 ++ deps/crates/vendor/syn/src/export.rs | 73 + deps/crates/vendor/syn/src/expr.rs | 4173 +++++++++++++ deps/crates/vendor/syn/src/ext.rs | 179 + deps/crates/vendor/syn/src/file.rs | 125 + deps/crates/vendor/syn/src/fixup.rs | 773 +++ deps/crates/vendor/syn/src/gen/clone.rs | 2267 +++++++ deps/crates/vendor/syn/src/gen/debug.rs | 3238 ++++++++++ deps/crates/vendor/syn/src/gen/eq.rs | 2306 ++++++++ deps/crates/vendor/syn/src/gen/fold.rs | 3902 ++++++++++++ deps/crates/vendor/syn/src/gen/hash.rs | 2876 +++++++++ deps/crates/vendor/syn/src/gen/token.css | 737 +++ deps/crates/vendor/syn/src/gen/visit.rs | 3941 +++++++++++++ deps/crates/vendor/syn/src/gen/visit_mut.rs | 3759 ++++++++++++ deps/crates/vendor/syn/src/generics.rs | 1477 +++++ deps/crates/vendor/syn/src/group.rs | 294 + deps/crates/vendor/syn/src/ident.rs | 108 + deps/crates/vendor/syn/src/item.rs | 3490 +++++++++++ deps/crates/vendor/syn/src/lib.rs | 1009 ++++ deps/crates/vendor/syn/src/lifetime.rs | 155 + deps/crates/vendor/syn/src/lit.rs | 1918 ++++++ deps/crates/vendor/syn/src/lookahead.rs | 348 ++ deps/crates/vendor/syn/src/mac.rs | 225 + deps/crates/vendor/syn/src/macros.rs | 182 + deps/crates/vendor/syn/src/meta.rs | 427 ++ deps/crates/vendor/syn/src/op.rs | 219 + deps/crates/vendor/syn/src/parse.rs | 1419 +++++ .../vendor/syn/src/parse_macro_input.rs | 128 + deps/crates/vendor/syn/src/parse_quote.rs | 240 + deps/crates/vendor/syn/src/pat.rs | 955 +++ deps/crates/vendor/syn/src/path.rs | 966 +++ deps/crates/vendor/syn/src/precedence.rs | 210 + deps/crates/vendor/syn/src/print.rs | 16 + deps/crates/vendor/syn/src/punctuated.rs | 1169 ++++ deps/crates/vendor/syn/src/restriction.rs | 178 + deps/crates/vendor/syn/src/scan_expr.rs | 268 + deps/crates/vendor/syn/src/sealed.rs | 4 + deps/crates/vendor/syn/src/span.rs | 63 + deps/crates/vendor/syn/src/spanned.rs | 118 + deps/crates/vendor/syn/src/stmt.rs | 484 ++ deps/crates/vendor/syn/src/thread.rs | 60 + deps/crates/vendor/syn/src/token.rs | 1093 ++++ deps/crates/vendor/syn/src/tt.rs | 96 + deps/crates/vendor/syn/src/ty.rs | 1271 ++++ deps/crates/vendor/syn/src/verbatim.rs | 33 + deps/crates/vendor/syn/src/whitespace.rs | 65 + deps/crates/vendor/syn/tests/common/eq.rs | 899 +++ deps/crates/vendor/syn/tests/common/mod.rs | 6 + deps/crates/vendor/syn/tests/common/parse.rs | 52 + deps/crates/vendor/syn/tests/common/visit.rs | 119 + deps/crates/vendor/syn/tests/debug/gen.rs | 5239 +++++++++++++++++ deps/crates/vendor/syn/tests/debug/mod.rs | 147 + deps/crates/vendor/syn/tests/macros/mod.rs | 7 + deps/crates/vendor/syn/tests/regression.rs | 5 + .../vendor/syn/tests/regression/issue1108.rs | 5 + .../vendor/syn/tests/regression/issue1235.rs | 32 + deps/crates/vendor/syn/tests/repo/mod.rs | 630 ++ deps/crates/vendor/syn/tests/repo/progress.rs | 37 + deps/crates/vendor/syn/tests/snapshot/mod.rs | 68 + .../crates/vendor/syn/tests/test_asyncness.rs | 49 + .../crates/vendor/syn/tests/test_attribute.rs | 231 + .../vendor/syn/tests/test_derive_input.rs | 785 +++ deps/crates/vendor/syn/tests/test_expr.rs | 1702 ++++++ deps/crates/vendor/syn/tests/test_generics.rs | 345 ++ deps/crates/vendor/syn/tests/test_grouping.rs | 59 + deps/crates/vendor/syn/tests/test_ident.rs | 87 + deps/crates/vendor/syn/tests/test_item.rs | 316 + deps/crates/vendor/syn/tests/test_lit.rs | 335 ++ deps/crates/vendor/syn/tests/test_meta.rs | 180 + .../vendor/syn/tests/test_parse_buffer.rs | 103 + .../vendor/syn/tests/test_parse_quote.rs | 172 + .../vendor/syn/tests/test_parse_stream.rs | 187 + deps/crates/vendor/syn/tests/test_pat.rs | 158 + deps/crates/vendor/syn/tests/test_path.rs | 116 + .../vendor/syn/tests/test_precedence.rs | 558 ++ .../vendor/syn/tests/test_punctuated.rs | 92 + deps/crates/vendor/syn/tests/test_receiver.rs | 327 + .../vendor/syn/tests/test_round_trip.rs | 256 + deps/crates/vendor/syn/tests/test_shebang.rs | 73 + deps/crates/vendor/syn/tests/test_size.rs | 54 + deps/crates/vendor/syn/tests/test_stmt.rs | 337 ++ .../vendor/syn/tests/test_token_trees.rs | 38 + deps/crates/vendor/syn/tests/test_ty.rs | 471 ++ .../vendor/syn/tests/test_unparenthesize.rs | 70 + .../vendor/syn/tests/test_visibility.rs | 191 + deps/crates/vendor/syn/tests/zzz_stable.rs | 33 + .../vendor/synstructure/.cargo-checksum.json | 1 + deps/crates/vendor/synstructure/Cargo.toml | 75 + deps/crates/vendor/synstructure/LICENSE | 7 + deps/crates/vendor/synstructure/README.md | 157 + deps/crates/vendor/synstructure/src/lib.rs | 2559 ++++++++ deps/crates/vendor/synstructure/src/macros.rs | 262 + .../vendor/temporal_capi/.cargo-checksum.json | 1 + deps/crates/vendor/temporal_capi/Cargo.toml | 83 + .../vendor/temporal_capi/LICENSE-Apache | 201 + deps/crates/vendor/temporal_capi/LICENSE-MIT | 21 + deps/crates/vendor/temporal_capi/README.md | 14 + .../bindings/c/AnyCalendarKind.d.h | 39 + .../bindings/c/AnyCalendarKind.h | 28 + .../bindings/c/ArithmeticOverflow.d.h | 23 + .../bindings/c/ArithmeticOverflow.h | 22 + .../temporal_capi/bindings/c/Calendar.d.h | 19 + .../temporal_capi/bindings/c/Calendar.h | 37 + .../temporal_capi/bindings/c/DateDuration.d.h | 19 + .../temporal_capi/bindings/c/DateDuration.h | 35 + .../bindings/c/DifferenceSettings.d.h | 27 + .../bindings/c/DifferenceSettings.h | 22 + .../bindings/c/Disambiguation.d.h | 25 + .../temporal_capi/bindings/c/Disambiguation.h | 22 + .../bindings/c/DisplayCalendar.d.h | 25 + .../bindings/c/DisplayCalendar.h | 22 + .../bindings/c/DisplayOffset.d.h | 23 + .../temporal_capi/bindings/c/DisplayOffset.h | 22 + .../bindings/c/DisplayTimeZone.d.h | 24 + .../bindings/c/DisplayTimeZone.h | 22 + .../temporal_capi/bindings/c/Duration.d.h | 19 + .../temporal_capi/bindings/c/Duration.h | 106 + .../temporal_capi/bindings/c/ErrorKind.d.h | 26 + .../temporal_capi/bindings/c/ErrorKind.h | 22 + .../bindings/c/I128Nanoseconds.d.h | 23 + .../bindings/c/I128Nanoseconds.h | 24 + .../temporal_capi/bindings/c/Instant.d.h | 19 + .../vendor/temporal_capi/bindings/c/Instant.h | 82 + .../bindings/c/OffsetDisambiguation.d.h | 25 + .../bindings/c/OffsetDisambiguation.h | 22 + .../bindings/c/OwnedRelativeTo.d.h | 25 + .../bindings/c/OwnedRelativeTo.h | 38 + .../temporal_capi/bindings/c/ParsedDate.d.h | 19 + .../temporal_capi/bindings/c/ParsedDate.h | 43 + .../bindings/c/ParsedDateTime.d.h | 19 + .../temporal_capi/bindings/c/ParsedDateTime.h | 31 + .../bindings/c/ParsedZonedDateTime.d.h | 19 + .../bindings/c/ParsedZonedDateTime.h | 38 + .../temporal_capi/bindings/c/PartialDate.d.h | 29 + .../temporal_capi/bindings/c/PartialDate.h | 22 + .../bindings/c/PartialDateTime.d.h | 25 + .../bindings/c/PartialDateTime.h | 22 + .../bindings/c/PartialDuration.d.h | 31 + .../bindings/c/PartialDuration.h | 24 + .../temporal_capi/bindings/c/PartialTime.d.h | 27 + .../temporal_capi/bindings/c/PartialTime.h | 22 + .../bindings/c/PartialZonedDateTime.d.h | 28 + .../bindings/c/PartialZonedDateTime.h | 22 + .../temporal_capi/bindings/c/PlainDate.d.h | 19 + .../temporal_capi/bindings/c/PlainDate.h | 151 + .../bindings/c/PlainDateTime.d.h | 19 + .../temporal_capi/bindings/c/PlainDateTime.h | 161 + .../bindings/c/PlainMonthDay.d.h | 19 + .../temporal_capi/bindings/c/PlainMonthDay.h | 73 + .../temporal_capi/bindings/c/PlainTime.d.h | 19 + .../temporal_capi/bindings/c/PlainTime.h | 100 + .../bindings/c/PlainYearMonth.d.h | 19 + .../temporal_capi/bindings/c/PlainYearMonth.h | 104 + .../temporal_capi/bindings/c/Precision.d.h | 23 + .../temporal_capi/bindings/c/Precision.h | 22 + .../temporal_capi/bindings/c/Provider.d.h | 19 + .../temporal_capi/bindings/c/Provider.h | 31 + .../temporal_capi/bindings/c/RelativeTo.d.h | 25 + .../temporal_capi/bindings/c/RelativeTo.h | 22 + .../temporal_capi/bindings/c/RoundingMode.d.h | 30 + .../temporal_capi/bindings/c/RoundingMode.h | 22 + .../bindings/c/RoundingOptions.d.h | 27 + .../bindings/c/RoundingOptions.h | 22 + .../vendor/temporal_capi/bindings/c/Sign.d.h | 24 + .../vendor/temporal_capi/bindings/c/Sign.h | 22 + .../bindings/c/TemporalError.d.h | 24 + .../temporal_capi/bindings/c/TemporalError.h | 22 + .../temporal_capi/bindings/c/TimeZone.d.h | 25 + .../temporal_capi/bindings/c/TimeZone.h | 57 + .../bindings/c/ToStringRoundingOptions.d.h | 27 + .../bindings/c/ToStringRoundingOptions.h | 22 + .../bindings/c/TransitionDirection.d.h | 23 + .../bindings/c/TransitionDirection.h | 22 + .../vendor/temporal_capi/bindings/c/Unit.d.h | 32 + .../vendor/temporal_capi/bindings/c/Unit.h | 22 + .../bindings/c/UnsignedRoundingMode.d.h | 26 + .../bindings/c/UnsignedRoundingMode.h | 22 + .../bindings/c/ZonedDateTime.d.h | 19 + .../temporal_capi/bindings/c/ZonedDateTime.h | 238 + .../bindings/c/diplomat_runtime.h | 82 + .../cpp/temporal_rs/AnyCalendarKind.d.hpp | 89 + .../cpp/temporal_rs/AnyCalendarKind.hpp | 70 + .../cpp/temporal_rs/ArithmeticOverflow.d.hpp | 49 + .../cpp/temporal_rs/ArithmeticOverflow.hpp | 38 + .../bindings/cpp/temporal_rs/Calendar.d.hpp | 64 + .../bindings/cpp/temporal_rs/Calendar.hpp | 86 + .../cpp/temporal_rs/DateDuration.d.hpp | 55 + .../bindings/cpp/temporal_rs/DateDuration.hpp | 82 + .../cpp/temporal_rs/DifferenceSettings.d.hpp | 48 + .../cpp/temporal_rs/DifferenceSettings.hpp | 47 + .../cpp/temporal_rs/Disambiguation.d.hpp | 53 + .../cpp/temporal_rs/Disambiguation.hpp | 40 + .../cpp/temporal_rs/DisplayCalendar.d.hpp | 53 + .../cpp/temporal_rs/DisplayCalendar.hpp | 40 + .../cpp/temporal_rs/DisplayOffset.d.hpp | 49 + .../cpp/temporal_rs/DisplayOffset.hpp | 38 + .../cpp/temporal_rs/DisplayTimeZone.d.hpp | 51 + .../cpp/temporal_rs/DisplayTimeZone.hpp | 39 + .../bindings/cpp/temporal_rs/Duration.d.hpp | 119 + .../bindings/cpp/temporal_rs/Duration.hpp | 327 + .../bindings/cpp/temporal_rs/ErrorKind.d.hpp | 55 + .../bindings/cpp/temporal_rs/ErrorKind.hpp | 41 + .../cpp/temporal_rs/I128Nanoseconds.d.hpp | 47 + .../cpp/temporal_rs/I128Nanoseconds.hpp | 48 + .../bindings/cpp/temporal_rs/Instant.d.hpp | 97 + .../bindings/cpp/temporal_rs/Instant.hpp | 238 + .../temporal_rs/OffsetDisambiguation.d.hpp | 53 + .../cpp/temporal_rs/OffsetDisambiguation.hpp | 40 + .../cpp/temporal_rs/OwnedRelativeTo.d.hpp | 62 + .../cpp/temporal_rs/OwnedRelativeTo.hpp | 86 + .../bindings/cpp/temporal_rs/ParsedDate.d.hpp | 58 + .../bindings/cpp/temporal_rs/ParsedDate.hpp | 97 + .../cpp/temporal_rs/ParsedDateTime.d.hpp | 50 + .../cpp/temporal_rs/ParsedDateTime.hpp | 65 + .../cpp/temporal_rs/ParsedZonedDateTime.d.hpp | 56 + .../cpp/temporal_rs/ParsedZonedDateTime.hpp | 84 + .../cpp/temporal_rs/PartialDate.d.hpp | 52 + .../bindings/cpp/temporal_rs/PartialDate.hpp | 52 + .../cpp/temporal_rs/PartialDateTime.d.hpp | 44 + .../cpp/temporal_rs/PartialDateTime.hpp | 43 + .../cpp/temporal_rs/PartialDuration.d.hpp | 55 + .../cpp/temporal_rs/PartialDuration.hpp | 64 + .../cpp/temporal_rs/PartialTime.d.hpp | 45 + .../bindings/cpp/temporal_rs/PartialTime.hpp | 49 + .../temporal_rs/PartialZonedDateTime.d.hpp | 50 + .../cpp/temporal_rs/PartialZonedDateTime.hpp | 48 + .../bindings/cpp/temporal_rs/PlainDate.d.hpp | 163 + .../bindings/cpp/temporal_rs/PlainDate.hpp | 455 ++ .../cpp/temporal_rs/PlainDateTime.d.hpp | 172 + .../cpp/temporal_rs/PlainDateTime.hpp | 502 ++ .../cpp/temporal_rs/PlainMonthDay.d.hpp | 93 + .../cpp/temporal_rs/PlainMonthDay.hpp | 204 + .../bindings/cpp/temporal_rs/PlainTime.d.hpp | 109 + .../bindings/cpp/temporal_rs/PlainTime.hpp | 289 + .../cpp/temporal_rs/PlainYearMonth.d.hpp | 122 + .../cpp/temporal_rs/PlainYearMonth.hpp | 313 + .../bindings/cpp/temporal_rs/Precision.d.hpp | 37 + .../bindings/cpp/temporal_rs/Precision.hpp | 41 + .../bindings/cpp/temporal_rs/Provider.d.hpp | 62 + .../bindings/cpp/temporal_rs/Provider.hpp | 70 + .../bindings/cpp/temporal_rs/RelativeTo.d.hpp | 44 + .../bindings/cpp/temporal_rs/RelativeTo.hpp | 43 + .../cpp/temporal_rs/RoundingMode.d.hpp | 63 + .../bindings/cpp/temporal_rs/RoundingMode.hpp | 45 + .../cpp/temporal_rs/RoundingOptions.d.hpp | 48 + .../cpp/temporal_rs/RoundingOptions.hpp | 47 + .../bindings/cpp/temporal_rs/Sign.d.hpp | 51 + .../bindings/cpp/temporal_rs/Sign.hpp | 39 + .../cpp/temporal_rs/TemporalError.d.hpp | 42 + .../cpp/temporal_rs/TemporalError.hpp | 42 + .../bindings/cpp/temporal_rs/TimeZone.d.hpp | 90 + .../bindings/cpp/temporal_rs/TimeZone.hpp | 164 + .../temporal_rs/ToStringRoundingOptions.d.hpp | 48 + .../temporal_rs/ToStringRoundingOptions.hpp | 46 + .../cpp/temporal_rs/TransitionDirection.d.hpp | 49 + .../cpp/temporal_rs/TransitionDirection.hpp | 38 + .../bindings/cpp/temporal_rs/Unit.d.hpp | 67 + .../bindings/cpp/temporal_rs/Unit.hpp | 47 + .../temporal_rs/UnsignedRoundingMode.d.hpp | 55 + .../cpp/temporal_rs/UnsignedRoundingMode.hpp | 41 + .../cpp/temporal_rs/ZonedDateTime.d.hpp | 234 + .../cpp/temporal_rs/ZonedDateTime.hpp | 779 +++ .../cpp/temporal_rs/diplomat_runtime.hpp | 566 ++ .../vendor/temporal_capi/src/calendar.rs | 84 + .../vendor/temporal_capi/src/duration.rs | 335 ++ deps/crates/vendor/temporal_capi/src/error.rs | 46 + .../vendor/temporal_capi/src/instant.rs | 246 + deps/crates/vendor/temporal_capi/src/lib.rs | 40 + .../vendor/temporal_capi/src/options.rs | 175 + .../vendor/temporal_capi/src/plain_date.rs | 469 ++ .../temporal_capi/src/plain_date_time.rs | 401 ++ .../temporal_capi/src/plain_month_day.rs | 150 + .../vendor/temporal_capi/src/plain_time.rs | 239 + .../temporal_capi/src/plain_year_month.rs | 221 + .../vendor/temporal_capi/src/provider.rs | 90 + .../vendor/temporal_capi/src/time_zone.rs | 156 + .../temporal_capi/src/zoned_date_time.rs | 806 +++ .../vendor/temporal_capi/tests/c/Makefile | 25 + .../vendor/temporal_capi/tests/c/simple.c | 33 + .../vendor/temporal_capi/tests/cpp/Makefile | 25 + .../vendor/temporal_capi/tests/cpp/simple.cpp | 15 + .../vendor/temporal_rs/.cargo-checksum.json | 1 + deps/crates/vendor/temporal_rs/CHANGELOG.md | 484 ++ deps/crates/vendor/temporal_rs/Cargo.toml | 114 + deps/crates/vendor/temporal_rs/LICENSE-Apache | 201 + deps/crates/vendor/temporal_rs/LICENSE-MIT | 21 + deps/crates/vendor/temporal_rs/README.md | 295 + .../src/builtins/compiled/duration.rs | 41 + .../src/builtins/compiled/duration/tests.rs | 845 +++ .../src/builtins/compiled/instant.rs | 35 + .../temporal_rs/src/builtins/compiled/mod.rs | 20 + .../temporal_rs/src/builtins/compiled/now.rs | 43 + .../src/builtins/compiled/plain_date.rs | 12 + .../src/builtins/compiled/plain_date_time.rs | 47 + .../src/builtins/compiled/plain_month_day.rs | 9 + .../src/builtins/compiled/plain_year_month.rs | 9 + .../src/builtins/compiled/zoned_date_time.rs | 232 + .../temporal_rs/src/builtins/core/calendar.rs | 992 ++++ .../src/builtins/core/calendar/era.rs | 159 + .../src/builtins/core/calendar/fields.rs | 389 ++ .../src/builtins/core/calendar/types.rs | 790 +++ .../temporal_rs/src/builtins/core/duration.rs | 1595 +++++ .../src/builtins/core/duration/date.rs | 182 + .../src/builtins/core/duration/normalized.rs | 1058 ++++ .../src/builtins/core/duration/tests.rs | 420 ++ .../temporal_rs/src/builtins/core/instant.rs | 834 +++ .../temporal_rs/src/builtins/core/mod.rs | 41 + .../temporal_rs/src/builtins/core/now.rs | 224 + .../src/builtins/core/plain_date.rs | 1044 ++++ .../src/builtins/core/plain_date_time.rs | 1552 +++++ .../src/builtins/core/plain_month_day.rs | 652 ++ .../src/builtins/core/plain_time.rs | 860 +++ .../src/builtins/core/plain_year_month.rs | 1132 ++++ .../src/builtins/core/time_zone.rs | 685 +++ .../src/builtins/core/zoned_date_time.rs | 1585 +++++ .../builtins/core/zoned_date_time/tests.rs | 1145 ++++ .../vendor/temporal_rs/src/builtins/mod.rs | 21 + deps/crates/vendor/temporal_rs/src/error.rs | 386 ++ deps/crates/vendor/temporal_rs/src/host.rs | 62 + deps/crates/vendor/temporal_rs/src/iso.rs | 1097 ++++ deps/crates/vendor/temporal_rs/src/lib.rs | 456 ++ deps/crates/vendor/temporal_rs/src/options.rs | 989 ++++ .../temporal_rs/src/options/increment.rs | 117 + .../temporal_rs/src/options/relative_to.rs | 181 + .../temporal_rs/src/parsed_intermediates.rs | 210 + deps/crates/vendor/temporal_rs/src/parsers.rs | 1025 ++++ .../temporal_rs/src/parsers/time_zone.rs | 66 + .../vendor/temporal_rs/src/primitive.rs | 378 ++ .../crates/vendor/temporal_rs/src/provider.rs | 9 + .../crates/vendor/temporal_rs/src/rounding.rs | 626 ++ deps/crates/vendor/temporal_rs/src/sys.rs | 79 + deps/crates/vendor/temporal_rs/src/tzdb.rs | 68 + deps/crates/vendor/temporal_rs/src/utils.rs | 16 + .../crates/vendor/temporal_rs/tools/README.md | 10 + .../timezone_provider/.cargo-checksum.json | 1 + .../vendor/timezone_provider/Cargo.toml | 121 + .../vendor/timezone_provider/LICENSE-Apache | 201 + .../vendor/timezone_provider/LICENSE-MIT | 21 + .../crates/vendor/timezone_provider/README.md | 63 + .../data/compiled_zoneinfo_provider.rs.data | 16 + .../src/data/iana_normalizer.rs.data | 18 + .../vendor/timezone_provider/src/data/mod.rs | 3 + .../src/epoch_nanoseconds.rs | 63 + .../vendor/timezone_provider/src/error.rs | 7 + .../src/experimental_tzif/datagen.rs | 96 + .../src/experimental_tzif/mod.rs | 66 + .../src/experimental_tzif/posix.rs | 132 + .../vendor/timezone_provider/src/lib.rs | 141 + .../vendor/timezone_provider/src/provider.rs | 377 ++ .../vendor/timezone_provider/src/tzdb.rs | 85 + .../timezone_provider/src/tzdb/datagen.rs | 129 + .../vendor/timezone_provider/src/tzif.rs | 2007 +++++++ .../vendor/timezone_provider/src/utc.rs | 0 .../vendor/timezone_provider/src/utils.rs | 132 + .../src/utils/neri_schneider.rs | 266 + .../timezone_provider/src/zoneinfo64.rs | 166 + .../vendor/tinystr/.cargo-checksum.json | 1 + deps/crates/vendor/tinystr/Cargo.toml | 132 + deps/crates/vendor/tinystr/LICENSE | 46 + deps/crates/vendor/tinystr/README.md | 57 + .../vendor/tinystr/benches/common/mod.rs | 55 + .../vendor/tinystr/benches/construct.rs | 65 + .../crates/vendor/tinystr/benches/overview.rs | 129 + deps/crates/vendor/tinystr/benches/read.rs | 34 + deps/crates/vendor/tinystr/benches/serde.rs | 37 + deps/crates/vendor/tinystr/src/ascii.rs | 1230 ++++ deps/crates/vendor/tinystr/src/asciibyte.rs | 170 + deps/crates/vendor/tinystr/src/databake.rs | 75 + deps/crates/vendor/tinystr/src/error.rs | 18 + deps/crates/vendor/tinystr/src/int_ops.rs | 315 + deps/crates/vendor/tinystr/src/lib.rs | 114 + deps/crates/vendor/tinystr/src/macros.rs | 30 + deps/crates/vendor/tinystr/src/serde.rs | 103 + deps/crates/vendor/tinystr/src/ule.rs | 125 + deps/crates/vendor/tinystr/src/unvalidated.rs | 122 + deps/crates/vendor/tinystr/tests/serde.rs | 39 + .../vendor/unicode-ident/.cargo-checksum.json | 1 + deps/crates/vendor/unicode-ident/Cargo.toml | 84 + .../vendor/unicode-ident/LICENSE-APACHE | 176 + deps/crates/vendor/unicode-ident/LICENSE-MIT | 23 + .../vendor/unicode-ident/LICENSE-UNICODE | 39 + deps/crates/vendor/unicode-ident/README.md | 274 + .../vendor/unicode-ident/benches/xid.rs | 126 + deps/crates/vendor/unicode-ident/src/lib.rs | 281 + .../crates/vendor/unicode-ident/src/tables.rs | 663 +++ .../vendor/unicode-ident/tests/compare.rs | 68 + .../vendor/unicode-ident/tests/fst/mod.rs | 11 + .../unicode-ident/tests/fst/xid_continue.fst | Bin 0 -> 76143 bytes .../unicode-ident/tests/fst/xid_start.fst | Bin 0 -> 67370 bytes .../vendor/unicode-ident/tests/roaring/mod.rs | 23 + .../vendor/unicode-ident/tests/static_size.rs | 95 + .../vendor/unicode-ident/tests/tables/mod.rs | 7 + .../unicode-ident/tests/tables/tables.rs | 361 ++ .../vendor/unicode-ident/tests/trie/mod.rs | 7 + .../vendor/unicode-ident/tests/trie/trie.rs | 453 ++ .../vendor/writeable/.cargo-checksum.json | 1 + deps/crates/vendor/writeable/Cargo.lock | 653 ++ deps/crates/vendor/writeable/Cargo.toml | 79 + deps/crates/vendor/writeable/LICENSE | 46 + deps/crates/vendor/writeable/README.md | 67 + .../vendor/writeable/benches/writeable.rs | 315 + .../writeable/examples/writeable_message.rs | 61 + deps/crates/vendor/writeable/src/cmp.rs | 156 + deps/crates/vendor/writeable/src/either.rs | 49 + deps/crates/vendor/writeable/src/impls.rs | 272 + deps/crates/vendor/writeable/src/lib.rs | 509 ++ deps/crates/vendor/writeable/src/ops.rs | 294 + .../writeable/src/parts_write_adapter.rs | 120 + deps/crates/vendor/writeable/src/testing.rs | 77 + .../writeable/src/to_string_or_borrow.rs | 210 + .../vendor/writeable/src/try_writeable.rs | 443 ++ .../vendor/writeable/tests/data/data.rs | 26 + .../vendor/writeable/tests/writeable.rs | 34 + .../vendor/yoke-derive/.cargo-checksum.json | 1 + deps/crates/vendor/yoke-derive/Cargo.lock | 59 + deps/crates/vendor/yoke-derive/Cargo.toml | 66 + deps/crates/vendor/yoke-derive/LICENSE | 46 + deps/crates/vendor/yoke-derive/README.md | 11 + .../yoke-derive/examples/yoke_derive.rs | 108 + deps/crates/vendor/yoke-derive/src/lib.rs | 277 + deps/crates/vendor/yoke-derive/src/visitor.rs | 113 + deps/crates/vendor/yoke/.cargo-checksum.json | 1 + deps/crates/vendor/yoke/Cargo.toml | 113 + deps/crates/vendor/yoke/LICENSE | 46 + deps/crates/vendor/yoke/README.md | 31 + deps/crates/vendor/yoke/src/cartable_ptr.rs | 445 ++ deps/crates/vendor/yoke/src/either.rs | 88 + deps/crates/vendor/yoke/src/erased.rs | 41 + .../vendor/yoke/src/kinda_sorta_dangling.rs | 95 + deps/crates/vendor/yoke/src/lib.rs | 68 + deps/crates/vendor/yoke/src/macro_impls.rs | 128 + deps/crates/vendor/yoke/src/utils.rs | 25 + deps/crates/vendor/yoke/src/yoke.rs | 2065 +++++++ deps/crates/vendor/yoke/src/yokeable.rs | 360 ++ deps/crates/vendor/yoke/src/zero_from.rs | 44 + deps/crates/vendor/yoke/tests/bincode.rs | 83 + deps/crates/vendor/yoke/tests/miri.rs | 15 + .../zerofrom-derive/.cargo-checksum.json | 1 + deps/crates/vendor/zerofrom-derive/Cargo.lock | 59 + deps/crates/vendor/zerofrom-derive/Cargo.toml | 65 + deps/crates/vendor/zerofrom-derive/LICENSE | 46 + deps/crates/vendor/zerofrom-derive/README.md | 11 + .../zerofrom-derive/examples/zf_derive.rs | 115 + deps/crates/vendor/zerofrom-derive/src/lib.rs | 309 + .../vendor/zerofrom-derive/src/visitor.rs | 120 + .../vendor/zerofrom/.cargo-checksum.json | 1 + deps/crates/vendor/zerofrom/Cargo.toml | 68 + deps/crates/vendor/zerofrom/LICENSE | 46 + deps/crates/vendor/zerofrom/README.md | 13 + deps/crates/vendor/zerofrom/src/lib.rs | 37 + .../crates/vendor/zerofrom/src/macro_impls.rs | 145 + deps/crates/vendor/zerofrom/src/zero_from.rs | 136 + .../vendor/zerotrie/.cargo-checksum.json | 1 + deps/crates/vendor/zerotrie/Cargo.lock | 196 + deps/crates/vendor/zerotrie/Cargo.toml | 151 + deps/crates/vendor/zerotrie/LICENSE | 46 + deps/crates/vendor/zerotrie/README.md | 41 + .../vendor/zerotrie/benches/overview.rs | 198 + .../examples/first_weekday_for_region.rs | 219 + .../zerotrie/src/builder/branch_meta.rs | 29 + .../vendor/zerotrie/src/builder/bytestr.rs | 128 + .../zerotrie/src/builder/konst/builder.rs | 338 ++ .../vendor/zerotrie/src/builder/konst/mod.rs | 9 + .../zerotrie/src/builder/konst/store.rs | 352 ++ .../vendor/zerotrie/src/builder/litemap.rs | 51 + .../crates/vendor/zerotrie/src/builder/mod.rs | 303 + .../zerotrie/src/builder/nonconst/builder.rs | 420 ++ .../zerotrie/src/builder/nonconst/mod.rs | 9 + .../zerotrie/src/builder/nonconst/store.rs | 192 + .../vendor/zerotrie/src/byte_phf/builder.rs | 214 + .../zerotrie/src/byte_phf/cached_owned.rs | 39 + .../vendor/zerotrie/src/byte_phf/mod.rs | 485 ++ deps/crates/vendor/zerotrie/src/cursor.rs | 491 ++ deps/crates/vendor/zerotrie/src/error.rs | 25 + deps/crates/vendor/zerotrie/src/helpers.rs | 122 + deps/crates/vendor/zerotrie/src/lib.rs | 87 + deps/crates/vendor/zerotrie/src/options.rs | 153 + deps/crates/vendor/zerotrie/src/reader.rs | 731 +++ deps/crates/vendor/zerotrie/src/serde.rs | 644 ++ deps/crates/vendor/zerotrie/src/varint.rs | 520 ++ deps/crates/vendor/zerotrie/src/zerotrie.rs | 888 +++ .../vendor/zerotrie/tests/asciitrie_test.rs | 73 + .../vendor/zerotrie/tests/builder_test.rs | 855 +++ .../crates/vendor/zerotrie/tests/data/data.rs | 2210 +++++++ .../vendor/zerotrie/tests/derive_test.rs | 138 + .../vendor/zerotrie/tests/ignorecase_test.rs | 46 + .../vendor/zerotrie/tests/locale_aux_test.rs | 170 + .../zerovec-derive/.cargo-checksum.json | 1 + deps/crates/vendor/zerovec-derive/Cargo.lock | 120 + deps/crates/vendor/zerovec-derive/Cargo.toml | 86 + deps/crates/vendor/zerovec-derive/LICENSE | 46 + deps/crates/vendor/zerovec-derive/README.md | 11 + .../vendor/zerovec-derive/examples/derives.rs | 157 + .../vendor/zerovec-derive/examples/make.rs | 125 + .../zerovec-derive/examples/make_var.rs | 261 + deps/crates/vendor/zerovec-derive/src/lib.rs | 43 + .../vendor/zerovec-derive/src/make_ule.rs | 373 ++ .../vendor/zerovec-derive/src/make_varule.rs | 887 +++ deps/crates/vendor/zerovec-derive/src/ule.rs | 110 + .../crates/vendor/zerovec-derive/src/utils.rs | 403 ++ .../vendor/zerovec-derive/src/varule.rs | 129 + .../vendor/zerovec/.cargo-checksum.json | 1 + deps/crates/vendor/zerovec/Cargo.lock | 152 + deps/crates/vendor/zerovec/Cargo.toml | 145 + deps/crates/vendor/zerovec/LICENSE | 46 + deps/crates/vendor/zerovec/README.md | 197 + deps/crates/vendor/zerovec/benches/vzv.rs | 204 + deps/crates/vendor/zerovec/benches/zeromap.rs | 381 ++ deps/crates/vendor/zerovec/benches/zerovec.rs | 164 + .../vendor/zerovec/benches/zerovec_iai.rs | 64 + .../vendor/zerovec/benches/zerovec_serde.rs | 139 + .../vendor/zerovec/examples/zv_serde.rs | 45 + deps/crates/vendor/zerovec/src/cow.rs | 444 ++ .../vendor/zerovec/src/hashmap/algorithms.rs | 164 + deps/crates/vendor/zerovec/src/hashmap/mod.rs | 239 + .../vendor/zerovec/src/hashmap/serde.rs | 155 + deps/crates/vendor/zerovec/src/lib.rs | 576 ++ .../crates/vendor/zerovec/src/map/borrowed.rs | 317 + .../crates/vendor/zerovec/src/map/databake.rs | 108 + deps/crates/vendor/zerovec/src/map/kv.rs | 137 + deps/crates/vendor/zerovec/src/map/map.rs | 646 ++ deps/crates/vendor/zerovec/src/map/mod.rs | 23 + deps/crates/vendor/zerovec/src/map/serde.rs | 321 + .../vendor/zerovec/src/map/serde_helpers.rs | 164 + deps/crates/vendor/zerovec/src/map/vecs.rs | 572 ++ .../vendor/zerovec/src/map2d/borrowed.rs | 335 ++ .../crates/vendor/zerovec/src/map2d/cursor.rs | 394 ++ .../vendor/zerovec/src/map2d/databake.rs | 146 + deps/crates/vendor/zerovec/src/map2d/map.rs | 874 +++ deps/crates/vendor/zerovec/src/map2d/mod.rs | 18 + deps/crates/vendor/zerovec/src/map2d/serde.rs | 445 ++ deps/crates/vendor/zerovec/src/samples.rs | 74 + deps/crates/vendor/zerovec/src/ule/chars.rs | 193 + deps/crates/vendor/zerovec/src/ule/custom.rs | 145 + deps/crates/vendor/zerovec/src/ule/encode.rs | 438 ++ deps/crates/vendor/zerovec/src/ule/macros.rs | 29 + deps/crates/vendor/zerovec/src/ule/mod.rs | 452 ++ deps/crates/vendor/zerovec/src/ule/multi.rs | 159 + deps/crates/vendor/zerovec/src/ule/niche.rs | 206 + deps/crates/vendor/zerovec/src/ule/option.rs | 264 + deps/crates/vendor/zerovec/src/ule/plain.rs | 399 ++ deps/crates/vendor/zerovec/src/ule/slices.rs | 102 + .../vendor/zerovec/src/ule/test_utils.rs | 30 + deps/crates/vendor/zerovec/src/ule/tuple.rs | 180 + .../crates/vendor/zerovec/src/ule/tuplevar.rs | 307 + .../crates/vendor/zerovec/src/ule/vartuple.rs | 312 + .../zerovec/src/varzerovec/components.rs | 815 +++ .../vendor/zerovec/src/varzerovec/databake.rs | 132 + .../vendor/zerovec/src/varzerovec/error.rs | 24 + .../zerovec/src/varzerovec/lengthless.rs | 116 + .../vendor/zerovec/src/varzerovec/mod.rs | 31 + .../vendor/zerovec/src/varzerovec/owned.rs | 698 +++ .../vendor/zerovec/src/varzerovec/serde.rs | 315 + .../vendor/zerovec/src/varzerovec/slice.rs | 526 ++ .../vendor/zerovec/src/varzerovec/vec.rs | 517 ++ deps/crates/vendor/zerovec/src/yoke_impls.rs | 525 ++ .../vendor/zerovec/src/zerofrom_impls.rs | 108 + .../vendor/zerovec/src/zerovec/databake.rs | 74 + deps/crates/vendor/zerovec/src/zerovec/mod.rs | 1320 +++++ .../vendor/zerovec/src/zerovec/serde.rs | 237 + .../vendor/zerovec/src/zerovec/slice.rs | 627 ++ .../vendor/zoneinfo64/.cargo-checksum.json | 1 + deps/crates/vendor/zoneinfo64/Cargo.toml | 92 + deps/crates/vendor/zoneinfo64/LICENSE | 46 + deps/crates/vendor/zoneinfo64/README.md | 36 + .../vendor/zoneinfo64/src/chrono_impls.rs | 85 + .../vendor/zoneinfo64/src/data/zoneinfo64.res | Bin 0 -> 148608 bytes .../vendor/zoneinfo64/src/deserialize.rs | 291 + deps/crates/vendor/zoneinfo64/src/lib.rs | 982 +++ deps/crates/vendor/zoneinfo64/src/rule.rs | 682 +++ 1564 files changed, 361466 insertions(+) create mode 100644 deps/crates/vendor/autocfg/.cargo-checksum.json create mode 100644 deps/crates/vendor/autocfg/Cargo.lock create mode 100644 deps/crates/vendor/autocfg/Cargo.toml create mode 100644 deps/crates/vendor/autocfg/LICENSE-APACHE create mode 100644 deps/crates/vendor/autocfg/LICENSE-MIT create mode 100644 deps/crates/vendor/autocfg/README.md create mode 100644 deps/crates/vendor/autocfg/examples/integers.rs create mode 100644 deps/crates/vendor/autocfg/examples/nightly.rs create mode 100644 deps/crates/vendor/autocfg/examples/paths.rs create mode 100644 deps/crates/vendor/autocfg/examples/traits.rs create mode 100644 deps/crates/vendor/autocfg/examples/versions.rs create mode 100644 deps/crates/vendor/autocfg/src/error.rs create mode 100644 deps/crates/vendor/autocfg/src/lib.rs create mode 100644 deps/crates/vendor/autocfg/src/rustc.rs create mode 100644 deps/crates/vendor/autocfg/src/tests.rs create mode 100644 deps/crates/vendor/autocfg/src/version.rs create mode 100644 deps/crates/vendor/autocfg/tests/no_std.rs create mode 100644 deps/crates/vendor/autocfg/tests/rustflags.rs create mode 100644 deps/crates/vendor/autocfg/tests/support/mod.rs create mode 100644 deps/crates/vendor/autocfg/tests/tests.rs create mode 100755 deps/crates/vendor/autocfg/tests/wrap_ignored create mode 100644 deps/crates/vendor/autocfg/tests/wrappers.rs create mode 100644 deps/crates/vendor/calendrical_calculations/.cargo-checksum.json create mode 100644 deps/crates/vendor/calendrical_calculations/Cargo.toml create mode 100644 deps/crates/vendor/calendrical_calculations/LICENSE create mode 100644 deps/crates/vendor/calendrical_calculations/README.md create mode 100644 deps/crates/vendor/calendrical_calculations/src/astronomy.rs create mode 100644 deps/crates/vendor/calendrical_calculations/src/chinese_based.rs create mode 100644 deps/crates/vendor/calendrical_calculations/src/coptic.rs create mode 100644 deps/crates/vendor/calendrical_calculations/src/error.rs create mode 100644 deps/crates/vendor/calendrical_calculations/src/ethiopian.rs create mode 100644 deps/crates/vendor/calendrical_calculations/src/gregorian.rs create mode 100644 deps/crates/vendor/calendrical_calculations/src/hebrew.rs create mode 100644 deps/crates/vendor/calendrical_calculations/src/hebrew_keviyah.rs create mode 100644 deps/crates/vendor/calendrical_calculations/src/helpers.rs create mode 100644 deps/crates/vendor/calendrical_calculations/src/islamic.rs create mode 100644 deps/crates/vendor/calendrical_calculations/src/julian.rs create mode 100644 deps/crates/vendor/calendrical_calculations/src/lib.rs create mode 100644 deps/crates/vendor/calendrical_calculations/src/persian.rs create mode 100644 deps/crates/vendor/calendrical_calculations/src/rata_die.rs create mode 100644 deps/crates/vendor/core_maths/.cargo-checksum.json create mode 100644 deps/crates/vendor/core_maths/Cargo.toml create mode 100644 deps/crates/vendor/core_maths/LICENSE create mode 100644 deps/crates/vendor/core_maths/README.md create mode 100644 deps/crates/vendor/core_maths/src/lib.rs create mode 100644 deps/crates/vendor/diplomat-runtime/.cargo-checksum.json create mode 100644 deps/crates/vendor/diplomat-runtime/Cargo.toml create mode 100644 deps/crates/vendor/diplomat-runtime/LICENSE-APACHE create mode 100644 deps/crates/vendor/diplomat-runtime/LICENSE-MIT create mode 100644 deps/crates/vendor/diplomat-runtime/README.md create mode 100644 deps/crates/vendor/diplomat-runtime/src/callback.rs create mode 100644 deps/crates/vendor/diplomat-runtime/src/lib.rs create mode 100644 deps/crates/vendor/diplomat-runtime/src/result.rs create mode 100644 deps/crates/vendor/diplomat-runtime/src/rust_interop.rs create mode 100644 deps/crates/vendor/diplomat-runtime/src/slices.rs create mode 100644 deps/crates/vendor/diplomat-runtime/src/wasm_glue.rs create mode 100644 deps/crates/vendor/diplomat-runtime/src/write.rs create mode 100644 deps/crates/vendor/diplomat/.cargo-checksum.json create mode 100644 deps/crates/vendor/diplomat/Cargo.toml create mode 100644 deps/crates/vendor/diplomat/LICENSE-APACHE create mode 100644 deps/crates/vendor/diplomat/LICENSE-MIT create mode 100644 deps/crates/vendor/diplomat/README.md create mode 100644 deps/crates/vendor/diplomat/src/enum_convert.rs create mode 100644 deps/crates/vendor/diplomat/src/lib.rs create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__both_kinds_of_option.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__callback_arguments.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__cfgd_struct.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__cfged_method-2.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__cfged_method.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_mutable_slice.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_mutable_str.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_owned_slice.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_owned_str.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_slice.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_str.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__mod_with_enum.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__mod_with_rust_result.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__mod_with_write_result.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__multilevel_borrows.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__self_params.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__slices.snap create mode 100644 deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__traits.snap create mode 100644 deps/crates/vendor/diplomat/src/transparent_convert.rs create mode 100644 deps/crates/vendor/diplomat_core/.cargo-checksum.json create mode 100644 deps/crates/vendor/diplomat_core/Cargo.toml create mode 100644 deps/crates/vendor/diplomat_core/LICENSE-APACHE create mode 100644 deps/crates/vendor/diplomat_core/LICENSE-MIT create mode 100644 deps/crates/vendor/diplomat_core/README.md create mode 100644 deps/crates/vendor/diplomat_core/src/ast/attrs.rs create mode 100644 deps/crates/vendor/diplomat_core/src/ast/docs.rs create mode 100644 deps/crates/vendor/diplomat_core/src/ast/enums.rs create mode 100644 deps/crates/vendor/diplomat_core/src/ast/functions.rs create mode 100644 deps/crates/vendor/diplomat_core/src/ast/idents.rs create mode 100644 deps/crates/vendor/diplomat_core/src/ast/lifetimes.rs create mode 100644 deps/crates/vendor/diplomat_core/src/ast/macros.rs create mode 100644 deps/crates/vendor/diplomat_core/src/ast/methods.rs create mode 100644 deps/crates/vendor/diplomat_core/src/ast/mod.rs create mode 100644 deps/crates/vendor/diplomat_core/src/ast/modules.rs create mode 100644 deps/crates/vendor/diplomat_core/src/ast/opaque.rs create mode 100644 deps/crates/vendor/diplomat_core/src/ast/paths.rs create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__attr.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfg_attr.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-2.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-3.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-4.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-5.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__rename-2.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__rename.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__enums__tests__enum_with_discr.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__enums__tests__simple_enum.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__functions__tests__free_function.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__functions__tests__free_function_lifetimes.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__functions__tests__free_function_output.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__cfged_method.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__nonstatic_methods-2.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__nonstatic_methods.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__static_methods-2.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__static_methods.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__modules__tests__import_in_non_diplomat_not_analyzed.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__modules__tests__method_visibility.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__modules__tests__simple_mod.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__structs__tests__simple_struct.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-10.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-11.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-12.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-2.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-3.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-4.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-5.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-6.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-7.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-8.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-9.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_boxes-2.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_boxes.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_named.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_option-2.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_option.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives-2.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives-3.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_references-2.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_references.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-2.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-3.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-4.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__validity__tests__lifetime_in_return.snap create mode 100644 deps/crates/vendor/diplomat_core/src/ast/structs.rs create mode 100644 deps/crates/vendor/diplomat_core/src/ast/traits.rs create mode 100644 deps/crates/vendor/diplomat_core/src/ast/types.rs create mode 100644 deps/crates/vendor/diplomat_core/src/environment.rs create mode 100644 deps/crates/vendor/diplomat_core/src/hir/attrs.rs create mode 100644 deps/crates/vendor/diplomat_core/src/hir/defs.rs create mode 100644 deps/crates/vendor/diplomat_core/src/hir/elision.rs create mode 100644 deps/crates/vendor/diplomat_core/src/hir/lifetimes.rs create mode 100644 deps/crates/vendor/diplomat_core/src/hir/lowering.rs create mode 100644 deps/crates/vendor/diplomat_core/src/hir/methods.rs create mode 100644 deps/crates/vendor/diplomat_core/src/hir/methods/borrowing_field.rs create mode 100644 deps/crates/vendor/diplomat_core/src/hir/methods/borrowing_param.rs create mode 100644 deps/crates/vendor/diplomat_core/src/hir/mod.rs create mode 100644 deps/crates/vendor/diplomat_core/src/hir/paths.rs create mode 100644 deps/crates/vendor/diplomat_core/src/hir/primitives.rs create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__auto.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__comparator.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__iterator.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_non_opaque_type.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_opaque_type.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_unsupported_backend.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__primitive_struct_slices.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__primitive_struct_slices_for_unsupported_backend.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__struct_ref_for_unsupported_backend.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__unsupported_features.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__elision__tests__borrowing_fields.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__elision__tests__elision_in_struct.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__elision__tests__simple_mod.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__basic_lowering.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__callback_borrowing_fails.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__callback_borrowing_fails_with_unsafe_borrows.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__lifetime_in_return.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__mut_struct.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__mut_struct_fails.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__non_opaque_move.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__non_primitive_struct_slices_fails.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_checks_with_error.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_checks_with_safe_use.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_ffi.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__option.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__option_invalid.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__option_valid.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__required_implied_bounds.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__return_struct_slice.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__struct_forbidden.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__struct_ref_fails.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__zst_non_opaque.snap create mode 100644 deps/crates/vendor/diplomat_core/src/hir/ty_position.rs create mode 100644 deps/crates/vendor/diplomat_core/src/hir/type_context.rs create mode 100644 deps/crates/vendor/diplomat_core/src/hir/types.rs create mode 100644 deps/crates/vendor/diplomat_core/src/lib.rs create mode 100644 deps/crates/vendor/displaydoc/.cargo-checksum.json create mode 100644 deps/crates/vendor/displaydoc/CHANGELOG.md create mode 100644 deps/crates/vendor/displaydoc/Cargo.lock create mode 100644 deps/crates/vendor/displaydoc/Cargo.toml create mode 100644 deps/crates/vendor/displaydoc/LICENSE-APACHE create mode 100644 deps/crates/vendor/displaydoc/LICENSE-MIT create mode 100644 deps/crates/vendor/displaydoc/README.md create mode 100644 deps/crates/vendor/displaydoc/README.tpl create mode 100644 deps/crates/vendor/displaydoc/examples/simple.rs create mode 100644 deps/crates/vendor/displaydoc/src/attr.rs create mode 100644 deps/crates/vendor/displaydoc/src/expand.rs create mode 100644 deps/crates/vendor/displaydoc/src/fmt.rs create mode 100644 deps/crates/vendor/displaydoc/src/lib.rs create mode 100644 deps/crates/vendor/displaydoc/tests/compile_tests.rs create mode 100644 deps/crates/vendor/displaydoc/tests/happy.rs create mode 100644 deps/crates/vendor/displaydoc/tests/no_std/enum_prefix.rs create mode 100644 deps/crates/vendor/displaydoc/tests/no_std/enum_prefix_missing.rs create mode 100644 deps/crates/vendor/displaydoc/tests/no_std/enum_prefix_missing.stderr create mode 100644 deps/crates/vendor/displaydoc/tests/no_std/multi_line.rs create mode 100644 deps/crates/vendor/displaydoc/tests/no_std/multi_line.stderr create mode 100644 deps/crates/vendor/displaydoc/tests/no_std/multi_line_allow.rs create mode 100644 deps/crates/vendor/displaydoc/tests/no_std/with.rs create mode 100644 deps/crates/vendor/displaydoc/tests/no_std/without.rs create mode 100644 deps/crates/vendor/displaydoc/tests/no_std/without.stderr create mode 100644 deps/crates/vendor/displaydoc/tests/num_in_field.rs create mode 100644 deps/crates/vendor/displaydoc/tests/std/enum_prefix.rs create mode 100644 deps/crates/vendor/displaydoc/tests/std/enum_prefix_missing.rs create mode 100644 deps/crates/vendor/displaydoc/tests/std/enum_prefix_missing.stderr create mode 100644 deps/crates/vendor/displaydoc/tests/std/multi_line.rs create mode 100644 deps/crates/vendor/displaydoc/tests/std/multi_line.stderr create mode 100644 deps/crates/vendor/displaydoc/tests/std/multi_line_allow.rs create mode 100644 deps/crates/vendor/displaydoc/tests/std/multiple.rs create mode 100644 deps/crates/vendor/displaydoc/tests/std/without.rs create mode 100644 deps/crates/vendor/displaydoc/tests/std/without.stderr create mode 100644 deps/crates/vendor/displaydoc/tests/variantless.rs create mode 100755 deps/crates/vendor/displaydoc/update-readme.sh create mode 100644 deps/crates/vendor/icu_calendar/.cargo-checksum.json create mode 100644 deps/crates/vendor/icu_calendar/Cargo.toml create mode 100644 deps/crates/vendor/icu_calendar/LICENSE create mode 100644 deps/crates/vendor/icu_calendar/README.md create mode 100644 deps/crates/vendor/icu_calendar/benches/convert.rs create mode 100644 deps/crates/vendor/icu_calendar/benches/date.rs create mode 100644 deps/crates/vendor/icu_calendar/benches/fixtures/datetimes.json create mode 100644 deps/crates/vendor/icu_calendar/benches/fixtures/mod.rs create mode 100644 deps/crates/vendor/icu_calendar/src/any_calendar.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/buddhist.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/chinese.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/chinese_based.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/coptic.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/dangi.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/ethiopian.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/gregorian.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/hebrew.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/hijri.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/hijri/ummalqura_data.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/indian.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/iso.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/japanese.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/julian.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/mod.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/persian.rs create mode 100644 deps/crates/vendor/icu_calendar/src/cal/roc.rs create mode 100644 deps/crates/vendor/icu_calendar/src/calendar.rs create mode 100644 deps/crates/vendor/icu_calendar/src/calendar_arithmetic.rs create mode 100644 deps/crates/vendor/icu_calendar/src/date.rs create mode 100644 deps/crates/vendor/icu_calendar/src/duration.rs create mode 100644 deps/crates/vendor/icu_calendar/src/error.rs create mode 100644 deps/crates/vendor/icu_calendar/src/ixdtf.rs create mode 100644 deps/crates/vendor/icu_calendar/src/lib.rs create mode 100644 deps/crates/vendor/icu_calendar/src/provider.rs create mode 100644 deps/crates/vendor/icu_calendar/src/provider/chinese_based.rs create mode 100644 deps/crates/vendor/icu_calendar/src/provider/hijri.rs create mode 100644 deps/crates/vendor/icu_calendar/src/tests/continuity_test.rs create mode 100644 deps/crates/vendor/icu_calendar/src/tests/mod.rs create mode 100644 deps/crates/vendor/icu_calendar/src/types.rs create mode 100644 deps/crates/vendor/icu_calendar/src/week.rs create mode 100644 deps/crates/vendor/icu_calendar_data/.cargo-checksum.json create mode 100644 deps/crates/vendor/icu_calendar_data/Cargo.toml create mode 100644 deps/crates/vendor/icu_calendar_data/LICENSE create mode 100644 deps/crates/vendor/icu_calendar_data/README.md create mode 100644 deps/crates/vendor/icu_calendar_data/build.rs create mode 100644 deps/crates/vendor/icu_calendar_data/data/calendar_chinese_v1.rs.data create mode 100644 deps/crates/vendor/icu_calendar_data/data/calendar_dangi_v1.rs.data create mode 100644 deps/crates/vendor/icu_calendar_data/data/calendar_hijri_simulated_mecca_v1.rs.data create mode 100644 deps/crates/vendor/icu_calendar_data/data/calendar_japanese_extended_v1.rs.data create mode 100644 deps/crates/vendor/icu_calendar_data/data/calendar_japanese_modern_v1.rs.data create mode 100644 deps/crates/vendor/icu_calendar_data/data/calendar_week_v1.rs.data create mode 100644 deps/crates/vendor/icu_calendar_data/data/mod.rs create mode 100644 deps/crates/vendor/icu_calendar_data/src/lib.rs create mode 100644 deps/crates/vendor/icu_collections/.cargo-checksum.json create mode 100644 deps/crates/vendor/icu_collections/Cargo.lock create mode 100644 deps/crates/vendor/icu_collections/Cargo.toml create mode 100644 deps/crates/vendor/icu_collections/LICENSE create mode 100644 deps/crates/vendor/icu_collections/README.md create mode 100644 deps/crates/vendor/icu_collections/benches/codepointtrie.rs create mode 100644 deps/crates/vendor/icu_collections/benches/iai_cpt.rs create mode 100644 deps/crates/vendor/icu_collections/benches/inv_list.rs create mode 100644 deps/crates/vendor/icu_collections/benches/tries/gc_fast.rs create mode 100644 deps/crates/vendor/icu_collections/benches/tries/gc_small.rs create mode 100644 deps/crates/vendor/icu_collections/benches/tries/mod.rs create mode 100644 deps/crates/vendor/icu_collections/examples/unicode_bmp_blocks_selector.rs create mode 100644 deps/crates/vendor/icu_collections/src/char16trie/mod.rs create mode 100644 deps/crates/vendor/icu_collections/src/char16trie/trie.rs create mode 100644 deps/crates/vendor/icu_collections/src/codepointinvlist/builder.rs create mode 100644 deps/crates/vendor/icu_collections/src/codepointinvlist/conversions.rs create mode 100644 deps/crates/vendor/icu_collections/src/codepointinvlist/cpinvlist.rs create mode 100644 deps/crates/vendor/icu_collections/src/codepointinvlist/mod.rs create mode 100644 deps/crates/vendor/icu_collections/src/codepointinvlist/utils.rs create mode 100644 deps/crates/vendor/icu_collections/src/codepointinvliststringlist/mod.rs create mode 100644 deps/crates/vendor/icu_collections/src/codepointtrie/cptrie.rs create mode 100644 deps/crates/vendor/icu_collections/src/codepointtrie/error.rs create mode 100644 deps/crates/vendor/icu_collections/src/codepointtrie/impl_const.rs create mode 100644 deps/crates/vendor/icu_collections/src/codepointtrie/mod.rs create mode 100644 deps/crates/vendor/icu_collections/src/codepointtrie/planes.rs create mode 100644 deps/crates/vendor/icu_collections/src/codepointtrie/serde.rs create mode 100644 deps/crates/vendor/icu_collections/src/codepointtrie/toml.rs create mode 100644 deps/crates/vendor/icu_collections/src/iterator_utils.rs create mode 100644 deps/crates/vendor/icu_collections/src/lib.rs create mode 100644 deps/crates/vendor/icu_collections/tests/char16trie.rs create mode 100644 deps/crates/vendor/icu_collections/tests/cpt.rs create mode 100644 deps/crates/vendor/icu_collections/tests/data/char16trie/empty.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/char16trie/months.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/char16trie/test_a.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/char16trie/test_a_ab.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/char16trie/test_branches.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/char16trie/test_compact.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/char16trie/test_long_branch.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/char16trie/test_long_sequence.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/char16trie/test_shortest_branch.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.32.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.8.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.small16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.32.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.8.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.small16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/planes.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.32.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.8.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.small16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.32.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.8.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.small16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set1.16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set1.32.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set1.8.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set1.small16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set2-overlap.16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set2-overlap.32.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set2-overlap.small16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.32.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.8.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.small16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/short-all-same.16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/short-all-same.8.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/short-all-same.small16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.16.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.32.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.8.toml create mode 100644 deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.small16.toml create mode 100644 deps/crates/vendor/icu_locale/.cargo-checksum.json create mode 100644 deps/crates/vendor/icu_locale/Cargo.toml create mode 100644 deps/crates/vendor/icu_locale/LICENSE create mode 100644 deps/crates/vendor/icu_locale/README.md create mode 100644 deps/crates/vendor/icu_locale/benches/fixtures/locales.json create mode 100644 deps/crates/vendor/icu_locale/benches/fixtures/uncanonicalized-locales.json create mode 100644 deps/crates/vendor/icu_locale/benches/locale_canonicalizer.rs create mode 100644 deps/crates/vendor/icu_locale/src/canonicalizer.rs create mode 100644 deps/crates/vendor/icu_locale/src/directionality.rs create mode 100644 deps/crates/vendor/icu_locale/src/exemplar_chars.rs create mode 100644 deps/crates/vendor/icu_locale/src/expander.rs create mode 100644 deps/crates/vendor/icu_locale/src/fallback/algorithms.rs create mode 100644 deps/crates/vendor/icu_locale/src/fallback/mod.rs create mode 100644 deps/crates/vendor/icu_locale/src/lib.rs create mode 100644 deps/crates/vendor/icu_locale/src/provider.rs create mode 100644 deps/crates/vendor/icu_locale/tests/fixtures/canonicalize.json create mode 100644 deps/crates/vendor/icu_locale/tests/fixtures/maximize.json create mode 100644 deps/crates/vendor/icu_locale/tests/fixtures/minimize.json create mode 100644 deps/crates/vendor/icu_locale/tests/fixtures/mod.rs create mode 100644 deps/crates/vendor/icu_locale/tests/locale_canonicalizer.rs create mode 100644 deps/crates/vendor/icu_locale_core/.cargo-checksum.json create mode 100644 deps/crates/vendor/icu_locale_core/Cargo.toml create mode 100644 deps/crates/vendor/icu_locale_core/LICENSE create mode 100644 deps/crates/vendor/icu_locale_core/README.md create mode 100644 deps/crates/vendor/icu_locale_core/benches/fixtures/langid.json create mode 100644 deps/crates/vendor/icu_locale_core/benches/fixtures/locale.json create mode 100644 deps/crates/vendor/icu_locale_core/benches/fixtures/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/benches/fixtures/subtags.json create mode 100644 deps/crates/vendor/icu_locale_core/benches/helpers/macros.rs create mode 100644 deps/crates/vendor/icu_locale_core/benches/helpers/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/benches/iai_langid.rs create mode 100644 deps/crates/vendor/icu_locale_core/benches/langid.rs create mode 100644 deps/crates/vendor/icu_locale_core/benches/locale.rs create mode 100644 deps/crates/vendor/icu_locale_core/benches/subtags.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/data.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/databake.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/other/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/private/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/private/other.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/transform/fields.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/transform/key.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/transform/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/transform/value.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/unicode/attribute.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/unicode/attributes.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/unicode/key.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/unicode/keywords.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/unicode/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/unicode/subdivision.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/unicode/value.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/helpers.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/langid.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/lib.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/locale.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/macros.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/parser/errors.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/parser/langid.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/parser/locale.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/parser/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/errors.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/calendar.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/collation.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/currency.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/currency_format.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/dictionary_break.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/emoji.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/first_day.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/hour_cycle.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/line_break.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/line_break_word.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/measurement_system.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/measurement_unit_override.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/numbering_system.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/region_override.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/regional_subdivision.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/sentence_supression.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/timezone.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/variant.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/macros/enum_keyword.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/macros/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/macros/struct_keyword.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/locale.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/serde.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/shortvec/litemap.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/shortvec/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/subtags/language.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/subtags/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/subtags/region.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/subtags/script.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/subtags/variant.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/subtags/variants.rs create mode 100644 deps/crates/vendor/icu_locale_core/src/zerovec.rs create mode 100644 deps/crates/vendor/icu_locale_core/tests/fixtures/canonicalize.json create mode 100644 deps/crates/vendor/icu_locale_core/tests/fixtures/invalid-extensions.json create mode 100644 deps/crates/vendor/icu_locale_core/tests/fixtures/invalid.json create mode 100644 deps/crates/vendor/icu_locale_core/tests/fixtures/langid.json create mode 100644 deps/crates/vendor/icu_locale_core/tests/fixtures/locale.json create mode 100644 deps/crates/vendor/icu_locale_core/tests/fixtures/mod.rs create mode 100644 deps/crates/vendor/icu_locale_core/tests/langid.rs create mode 100644 deps/crates/vendor/icu_locale_core/tests/locale.rs create mode 100644 deps/crates/vendor/icu_locale_data/.cargo-checksum.json create mode 100644 deps/crates/vendor/icu_locale_data/Cargo.toml create mode 100644 deps/crates/vendor/icu_locale_data/LICENSE create mode 100644 deps/crates/vendor/icu_locale_data/README.md create mode 100644 deps/crates/vendor/icu_locale_data/build.rs create mode 100644 deps/crates/vendor/icu_locale_data/data/locale_aliases_v1.rs.data create mode 100644 deps/crates/vendor/icu_locale_data/data/locale_exemplar_characters_auxiliary_v1.rs.data create mode 100644 deps/crates/vendor/icu_locale_data/data/locale_exemplar_characters_index_v1.rs.data create mode 100644 deps/crates/vendor/icu_locale_data/data/locale_exemplar_characters_main_v1.rs.data create mode 100644 deps/crates/vendor/icu_locale_data/data/locale_exemplar_characters_numbers_v1.rs.data create mode 100644 deps/crates/vendor/icu_locale_data/data/locale_exemplar_characters_punctuation_v1.rs.data create mode 100644 deps/crates/vendor/icu_locale_data/data/locale_likely_subtags_extended_v1.rs.data create mode 100644 deps/crates/vendor/icu_locale_data/data/locale_likely_subtags_language_v1.rs.data create mode 100644 deps/crates/vendor/icu_locale_data/data/locale_likely_subtags_script_region_v1.rs.data create mode 100644 deps/crates/vendor/icu_locale_data/data/locale_parents_v1.rs.data create mode 100644 deps/crates/vendor/icu_locale_data/data/locale_script_direction_v1.rs.data create mode 100644 deps/crates/vendor/icu_locale_data/data/mod.rs create mode 100644 deps/crates/vendor/icu_locale_data/src/lib.rs create mode 100644 deps/crates/vendor/icu_provider/.cargo-checksum.json create mode 100644 deps/crates/vendor/icu_provider/Cargo.toml create mode 100644 deps/crates/vendor/icu_provider/LICENSE create mode 100644 deps/crates/vendor/icu_provider/README.md create mode 100644 deps/crates/vendor/icu_provider/benches/data_locale_bench.rs create mode 100644 deps/crates/vendor/icu_provider/src/baked.rs create mode 100644 deps/crates/vendor/icu_provider/src/baked/zerotrie.rs create mode 100644 deps/crates/vendor/icu_provider/src/buf.rs create mode 100644 deps/crates/vendor/icu_provider/src/buf/serde.rs create mode 100644 deps/crates/vendor/icu_provider/src/constructors.rs create mode 100644 deps/crates/vendor/icu_provider/src/data_provider.rs create mode 100644 deps/crates/vendor/icu_provider/src/dynutil.rs create mode 100644 deps/crates/vendor/icu_provider/src/error.rs create mode 100644 deps/crates/vendor/icu_provider/src/export/mod.rs create mode 100644 deps/crates/vendor/icu_provider/src/export/payload.rs create mode 100644 deps/crates/vendor/icu_provider/src/fallback.rs create mode 100644 deps/crates/vendor/icu_provider/src/hello_world.rs create mode 100644 deps/crates/vendor/icu_provider/src/lib.rs create mode 100644 deps/crates/vendor/icu_provider/src/marker.rs create mode 100644 deps/crates/vendor/icu_provider/src/request.rs create mode 100644 deps/crates/vendor/icu_provider/src/response.rs create mode 100644 deps/crates/vendor/icu_provider/src/serde_borrow_de_utils.rs create mode 100644 deps/crates/vendor/icu_provider/src/varule_traits.rs create mode 100644 deps/crates/vendor/ixdtf-0.5.0/.cargo-checksum.json create mode 100644 deps/crates/vendor/ixdtf-0.5.0/Cargo.toml create mode 100644 deps/crates/vendor/ixdtf-0.5.0/LICENSE create mode 100644 deps/crates/vendor/ixdtf-0.5.0/README.md create mode 100644 deps/crates/vendor/ixdtf-0.5.0/src/error.rs create mode 100644 deps/crates/vendor/ixdtf-0.5.0/src/lib.rs create mode 100644 deps/crates/vendor/ixdtf-0.5.0/src/parsers/annotations.rs create mode 100644 deps/crates/vendor/ixdtf-0.5.0/src/parsers/datetime.rs create mode 100644 deps/crates/vendor/ixdtf-0.5.0/src/parsers/duration.rs create mode 100644 deps/crates/vendor/ixdtf-0.5.0/src/parsers/grammar.rs create mode 100644 deps/crates/vendor/ixdtf-0.5.0/src/parsers/mod.rs create mode 100644 deps/crates/vendor/ixdtf-0.5.0/src/parsers/records.rs create mode 100644 deps/crates/vendor/ixdtf-0.5.0/src/parsers/tests.rs create mode 100644 deps/crates/vendor/ixdtf-0.5.0/src/parsers/time.rs create mode 100644 deps/crates/vendor/ixdtf-0.5.0/src/parsers/timezone.rs create mode 100644 deps/crates/vendor/ixdtf/.cargo-checksum.json create mode 100644 deps/crates/vendor/ixdtf/Cargo.toml create mode 100644 deps/crates/vendor/ixdtf/LICENSE create mode 100644 deps/crates/vendor/ixdtf/README.md create mode 100644 deps/crates/vendor/ixdtf/src/core.rs create mode 100644 deps/crates/vendor/ixdtf/src/error.rs create mode 100644 deps/crates/vendor/ixdtf/src/lib.rs create mode 100644 deps/crates/vendor/ixdtf/src/parsers/annotations.rs create mode 100644 deps/crates/vendor/ixdtf/src/parsers/datetime.rs create mode 100644 deps/crates/vendor/ixdtf/src/parsers/duration.rs create mode 100644 deps/crates/vendor/ixdtf/src/parsers/grammar.rs create mode 100644 deps/crates/vendor/ixdtf/src/parsers/mod.rs create mode 100644 deps/crates/vendor/ixdtf/src/parsers/tests.rs create mode 100644 deps/crates/vendor/ixdtf/src/parsers/time.rs create mode 100644 deps/crates/vendor/ixdtf/src/parsers/timezone.rs create mode 100644 deps/crates/vendor/ixdtf/src/records.rs create mode 100644 deps/crates/vendor/libm/.cargo-checksum.json create mode 100644 deps/crates/vendor/libm/CHANGELOG.md create mode 100644 deps/crates/vendor/libm/Cargo.toml create mode 100644 deps/crates/vendor/libm/LICENSE.txt create mode 100644 deps/crates/vendor/libm/README.md create mode 100644 deps/crates/vendor/libm/build.rs create mode 100644 deps/crates/vendor/libm/configure.rs create mode 100644 deps/crates/vendor/libm/src/lib.rs create mode 100644 deps/crates/vendor/libm/src/libm_helper.rs create mode 100644 deps/crates/vendor/libm/src/math/acos.rs create mode 100644 deps/crates/vendor/libm/src/math/acosf.rs create mode 100644 deps/crates/vendor/libm/src/math/acosh.rs create mode 100644 deps/crates/vendor/libm/src/math/acoshf.rs create mode 100644 deps/crates/vendor/libm/src/math/arch/aarch64.rs create mode 100644 deps/crates/vendor/libm/src/math/arch/i586.rs create mode 100644 deps/crates/vendor/libm/src/math/arch/mod.rs create mode 100644 deps/crates/vendor/libm/src/math/arch/wasm32.rs create mode 100644 deps/crates/vendor/libm/src/math/arch/x86.rs create mode 100644 deps/crates/vendor/libm/src/math/arch/x86/detect.rs create mode 100644 deps/crates/vendor/libm/src/math/arch/x86/fma.rs create mode 100644 deps/crates/vendor/libm/src/math/asin.rs create mode 100644 deps/crates/vendor/libm/src/math/asinf.rs create mode 100644 deps/crates/vendor/libm/src/math/asinh.rs create mode 100644 deps/crates/vendor/libm/src/math/asinhf.rs create mode 100644 deps/crates/vendor/libm/src/math/atan.rs create mode 100644 deps/crates/vendor/libm/src/math/atan2.rs create mode 100644 deps/crates/vendor/libm/src/math/atan2f.rs create mode 100644 deps/crates/vendor/libm/src/math/atanf.rs create mode 100644 deps/crates/vendor/libm/src/math/atanh.rs create mode 100644 deps/crates/vendor/libm/src/math/atanhf.rs create mode 100644 deps/crates/vendor/libm/src/math/cbrt.rs create mode 100644 deps/crates/vendor/libm/src/math/cbrtf.rs create mode 100644 deps/crates/vendor/libm/src/math/ceil.rs create mode 100644 deps/crates/vendor/libm/src/math/copysign.rs create mode 100644 deps/crates/vendor/libm/src/math/copysignf.rs create mode 100644 deps/crates/vendor/libm/src/math/copysignf128.rs create mode 100644 deps/crates/vendor/libm/src/math/copysignf16.rs create mode 100644 deps/crates/vendor/libm/src/math/cos.rs create mode 100644 deps/crates/vendor/libm/src/math/cosf.rs create mode 100644 deps/crates/vendor/libm/src/math/cosh.rs create mode 100644 deps/crates/vendor/libm/src/math/coshf.rs create mode 100644 deps/crates/vendor/libm/src/math/erf.rs create mode 100644 deps/crates/vendor/libm/src/math/erff.rs create mode 100644 deps/crates/vendor/libm/src/math/exp.rs create mode 100644 deps/crates/vendor/libm/src/math/exp10.rs create mode 100644 deps/crates/vendor/libm/src/math/exp10f.rs create mode 100644 deps/crates/vendor/libm/src/math/exp2.rs create mode 100644 deps/crates/vendor/libm/src/math/exp2f.rs create mode 100644 deps/crates/vendor/libm/src/math/expf.rs create mode 100644 deps/crates/vendor/libm/src/math/expm1.rs create mode 100644 deps/crates/vendor/libm/src/math/expm1f.rs create mode 100644 deps/crates/vendor/libm/src/math/expo2.rs create mode 100644 deps/crates/vendor/libm/src/math/fabs.rs create mode 100644 deps/crates/vendor/libm/src/math/fabsf.rs create mode 100644 deps/crates/vendor/libm/src/math/fabsf128.rs create mode 100644 deps/crates/vendor/libm/src/math/fabsf16.rs create mode 100644 deps/crates/vendor/libm/src/math/fdim.rs create mode 100644 deps/crates/vendor/libm/src/math/fdimf.rs create mode 100644 deps/crates/vendor/libm/src/math/fdimf128.rs create mode 100644 deps/crates/vendor/libm/src/math/fdimf16.rs create mode 100644 deps/crates/vendor/libm/src/math/floor.rs create mode 100644 deps/crates/vendor/libm/src/math/floorf.rs create mode 100644 deps/crates/vendor/libm/src/math/floorf128.rs create mode 100644 deps/crates/vendor/libm/src/math/floorf16.rs create mode 100644 deps/crates/vendor/libm/src/math/fma.rs create mode 100644 deps/crates/vendor/libm/src/math/fmin_fmax.rs create mode 100644 deps/crates/vendor/libm/src/math/fminimum_fmaximum.rs create mode 100644 deps/crates/vendor/libm/src/math/fminimum_fmaximum_num.rs create mode 100644 deps/crates/vendor/libm/src/math/fmod.rs create mode 100644 deps/crates/vendor/libm/src/math/fmodf.rs create mode 100644 deps/crates/vendor/libm/src/math/fmodf128.rs create mode 100644 deps/crates/vendor/libm/src/math/fmodf16.rs create mode 100644 deps/crates/vendor/libm/src/math/frexp.rs create mode 100644 deps/crates/vendor/libm/src/math/frexpf.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/ceil.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/copysign.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/fabs.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/fdim.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/floor.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/fma.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/fma_wide.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/fmax.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/fmaximum.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/fmaximum_num.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/fmin.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/fminimum.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/fminimum_num.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/fmod.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/mod.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/rint.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/round.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/scalbn.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/sqrt.rs create mode 100644 deps/crates/vendor/libm/src/math/generic/trunc.rs create mode 100644 deps/crates/vendor/libm/src/math/hypot.rs create mode 100644 deps/crates/vendor/libm/src/math/hypotf.rs create mode 100644 deps/crates/vendor/libm/src/math/ilogb.rs create mode 100644 deps/crates/vendor/libm/src/math/ilogbf.rs create mode 100644 deps/crates/vendor/libm/src/math/j0.rs create mode 100644 deps/crates/vendor/libm/src/math/j0f.rs create mode 100644 deps/crates/vendor/libm/src/math/j1.rs create mode 100644 deps/crates/vendor/libm/src/math/j1f.rs create mode 100644 deps/crates/vendor/libm/src/math/jn.rs create mode 100644 deps/crates/vendor/libm/src/math/jnf.rs create mode 100644 deps/crates/vendor/libm/src/math/k_cos.rs create mode 100644 deps/crates/vendor/libm/src/math/k_cosf.rs create mode 100644 deps/crates/vendor/libm/src/math/k_expo2.rs create mode 100644 deps/crates/vendor/libm/src/math/k_expo2f.rs create mode 100644 deps/crates/vendor/libm/src/math/k_sin.rs create mode 100644 deps/crates/vendor/libm/src/math/k_sinf.rs create mode 100644 deps/crates/vendor/libm/src/math/k_tan.rs create mode 100644 deps/crates/vendor/libm/src/math/k_tanf.rs create mode 100644 deps/crates/vendor/libm/src/math/ldexp.rs create mode 100644 deps/crates/vendor/libm/src/math/ldexpf.rs create mode 100644 deps/crates/vendor/libm/src/math/ldexpf128.rs create mode 100644 deps/crates/vendor/libm/src/math/ldexpf16.rs create mode 100644 deps/crates/vendor/libm/src/math/lgamma.rs create mode 100644 deps/crates/vendor/libm/src/math/lgamma_r.rs create mode 100644 deps/crates/vendor/libm/src/math/lgammaf.rs create mode 100644 deps/crates/vendor/libm/src/math/lgammaf_r.rs create mode 100644 deps/crates/vendor/libm/src/math/log.rs create mode 100644 deps/crates/vendor/libm/src/math/log10.rs create mode 100644 deps/crates/vendor/libm/src/math/log10f.rs create mode 100644 deps/crates/vendor/libm/src/math/log1p.rs create mode 100644 deps/crates/vendor/libm/src/math/log1pf.rs create mode 100644 deps/crates/vendor/libm/src/math/log2.rs create mode 100644 deps/crates/vendor/libm/src/math/log2f.rs create mode 100644 deps/crates/vendor/libm/src/math/logf.rs create mode 100644 deps/crates/vendor/libm/src/math/mod.rs create mode 100644 deps/crates/vendor/libm/src/math/modf.rs create mode 100644 deps/crates/vendor/libm/src/math/modff.rs create mode 100644 deps/crates/vendor/libm/src/math/nextafter.rs create mode 100644 deps/crates/vendor/libm/src/math/nextafterf.rs create mode 100644 deps/crates/vendor/libm/src/math/pow.rs create mode 100644 deps/crates/vendor/libm/src/math/powf.rs create mode 100644 deps/crates/vendor/libm/src/math/rem_pio2.rs create mode 100644 deps/crates/vendor/libm/src/math/rem_pio2_large.rs create mode 100644 deps/crates/vendor/libm/src/math/rem_pio2f.rs create mode 100644 deps/crates/vendor/libm/src/math/remainder.rs create mode 100644 deps/crates/vendor/libm/src/math/remainderf.rs create mode 100644 deps/crates/vendor/libm/src/math/remquo.rs create mode 100644 deps/crates/vendor/libm/src/math/remquof.rs create mode 100644 deps/crates/vendor/libm/src/math/rint.rs create mode 100644 deps/crates/vendor/libm/src/math/round.rs create mode 100644 deps/crates/vendor/libm/src/math/roundeven.rs create mode 100644 deps/crates/vendor/libm/src/math/roundf.rs create mode 100644 deps/crates/vendor/libm/src/math/roundf128.rs create mode 100644 deps/crates/vendor/libm/src/math/roundf16.rs create mode 100644 deps/crates/vendor/libm/src/math/scalbn.rs create mode 100644 deps/crates/vendor/libm/src/math/scalbnf.rs create mode 100644 deps/crates/vendor/libm/src/math/scalbnf128.rs create mode 100644 deps/crates/vendor/libm/src/math/scalbnf16.rs create mode 100644 deps/crates/vendor/libm/src/math/sin.rs create mode 100644 deps/crates/vendor/libm/src/math/sincos.rs create mode 100644 deps/crates/vendor/libm/src/math/sincosf.rs create mode 100644 deps/crates/vendor/libm/src/math/sinf.rs create mode 100644 deps/crates/vendor/libm/src/math/sinh.rs create mode 100644 deps/crates/vendor/libm/src/math/sinhf.rs create mode 100644 deps/crates/vendor/libm/src/math/sqrt.rs create mode 100644 deps/crates/vendor/libm/src/math/sqrtf.rs create mode 100644 deps/crates/vendor/libm/src/math/sqrtf128.rs create mode 100644 deps/crates/vendor/libm/src/math/sqrtf16.rs create mode 100644 deps/crates/vendor/libm/src/math/support/big.rs create mode 100644 deps/crates/vendor/libm/src/math/support/big/tests.rs create mode 100644 deps/crates/vendor/libm/src/math/support/env.rs create mode 100644 deps/crates/vendor/libm/src/math/support/feature_detect.rs create mode 100644 deps/crates/vendor/libm/src/math/support/float_traits.rs create mode 100644 deps/crates/vendor/libm/src/math/support/hex_float.rs create mode 100644 deps/crates/vendor/libm/src/math/support/int_traits.rs create mode 100644 deps/crates/vendor/libm/src/math/support/macros.rs create mode 100644 deps/crates/vendor/libm/src/math/support/mod.rs create mode 100644 deps/crates/vendor/libm/src/math/tan.rs create mode 100644 deps/crates/vendor/libm/src/math/tanf.rs create mode 100644 deps/crates/vendor/libm/src/math/tanh.rs create mode 100644 deps/crates/vendor/libm/src/math/tanhf.rs create mode 100644 deps/crates/vendor/libm/src/math/tgamma.rs create mode 100644 deps/crates/vendor/libm/src/math/tgammaf.rs create mode 100644 deps/crates/vendor/libm/src/math/trunc.rs create mode 100644 deps/crates/vendor/libm/src/math/truncf.rs create mode 100644 deps/crates/vendor/libm/src/math/truncf128.rs create mode 100644 deps/crates/vendor/libm/src/math/truncf16.rs create mode 100644 deps/crates/vendor/litemap/.cargo-checksum.json create mode 100644 deps/crates/vendor/litemap/Cargo.lock create mode 100644 deps/crates/vendor/litemap/Cargo.toml create mode 100644 deps/crates/vendor/litemap/LICENSE create mode 100644 deps/crates/vendor/litemap/README.md create mode 100644 deps/crates/vendor/litemap/benches/litemap.rs create mode 100644 deps/crates/vendor/litemap/examples/language_names_hash_map.rs create mode 100644 deps/crates/vendor/litemap/examples/language_names_lite_map.rs create mode 100644 deps/crates/vendor/litemap/examples/litemap_bincode.rs create mode 100644 deps/crates/vendor/litemap/examples/litemap_postcard.rs create mode 100644 deps/crates/vendor/litemap/src/databake.rs create mode 100644 deps/crates/vendor/litemap/src/lib.rs create mode 100644 deps/crates/vendor/litemap/src/map.rs create mode 100644 deps/crates/vendor/litemap/src/serde.rs create mode 100644 deps/crates/vendor/litemap/src/serde_helpers.rs create mode 100644 deps/crates/vendor/litemap/src/store/mod.rs create mode 100644 deps/crates/vendor/litemap/src/store/slice_impl.rs create mode 100644 deps/crates/vendor/litemap/src/store/vec_impl.rs create mode 100644 deps/crates/vendor/litemap/src/testing.rs create mode 100644 deps/crates/vendor/litemap/tests/rkyv.rs create mode 100644 deps/crates/vendor/litemap/tests/serde.rs create mode 100644 deps/crates/vendor/litemap/tests/store.rs create mode 100644 deps/crates/vendor/num-traits/.cargo-checksum.json create mode 100644 deps/crates/vendor/num-traits/Cargo.toml create mode 100644 deps/crates/vendor/num-traits/LICENSE-APACHE create mode 100644 deps/crates/vendor/num-traits/LICENSE-MIT create mode 100644 deps/crates/vendor/num-traits/README.md create mode 100644 deps/crates/vendor/num-traits/RELEASES.md create mode 100644 deps/crates/vendor/num-traits/build.rs create mode 100644 deps/crates/vendor/num-traits/src/bounds.rs create mode 100644 deps/crates/vendor/num-traits/src/cast.rs create mode 100644 deps/crates/vendor/num-traits/src/float.rs create mode 100644 deps/crates/vendor/num-traits/src/identities.rs create mode 100644 deps/crates/vendor/num-traits/src/int.rs create mode 100644 deps/crates/vendor/num-traits/src/lib.rs create mode 100644 deps/crates/vendor/num-traits/src/macros.rs create mode 100644 deps/crates/vendor/num-traits/src/ops/bytes.rs create mode 100644 deps/crates/vendor/num-traits/src/ops/checked.rs create mode 100644 deps/crates/vendor/num-traits/src/ops/euclid.rs create mode 100644 deps/crates/vendor/num-traits/src/ops/inv.rs create mode 100644 deps/crates/vendor/num-traits/src/ops/mod.rs create mode 100644 deps/crates/vendor/num-traits/src/ops/mul_add.rs create mode 100644 deps/crates/vendor/num-traits/src/ops/overflowing.rs create mode 100644 deps/crates/vendor/num-traits/src/ops/saturating.rs create mode 100644 deps/crates/vendor/num-traits/src/ops/wrapping.rs create mode 100644 deps/crates/vendor/num-traits/src/pow.rs create mode 100644 deps/crates/vendor/num-traits/src/real.rs create mode 100644 deps/crates/vendor/num-traits/src/sign.rs create mode 100644 deps/crates/vendor/num-traits/tests/cast.rs create mode 100644 deps/crates/vendor/potential_utf/.cargo-checksum.json create mode 100644 deps/crates/vendor/potential_utf/Cargo.toml create mode 100644 deps/crates/vendor/potential_utf/LICENSE create mode 100644 deps/crates/vendor/potential_utf/README.md create mode 100644 deps/crates/vendor/potential_utf/src/lib.rs create mode 100644 deps/crates/vendor/potential_utf/src/uchar.rs create mode 100644 deps/crates/vendor/potential_utf/src/ustr.rs create mode 100644 deps/crates/vendor/potential_utf/src/writeable.rs create mode 100644 deps/crates/vendor/proc-macro2/.cargo-checksum.json create mode 100644 deps/crates/vendor/proc-macro2/Cargo.toml create mode 100644 deps/crates/vendor/proc-macro2/LICENSE-APACHE create mode 100644 deps/crates/vendor/proc-macro2/LICENSE-MIT create mode 100644 deps/crates/vendor/proc-macro2/README.md create mode 100644 deps/crates/vendor/proc-macro2/build.rs create mode 100644 deps/crates/vendor/proc-macro2/rust-toolchain.toml create mode 100644 deps/crates/vendor/proc-macro2/src/detection.rs create mode 100644 deps/crates/vendor/proc-macro2/src/extra.rs create mode 100644 deps/crates/vendor/proc-macro2/src/fallback.rs create mode 100644 deps/crates/vendor/proc-macro2/src/lib.rs create mode 100644 deps/crates/vendor/proc-macro2/src/location.rs create mode 100644 deps/crates/vendor/proc-macro2/src/marker.rs create mode 100644 deps/crates/vendor/proc-macro2/src/num.rs create mode 100644 deps/crates/vendor/proc-macro2/src/parse.rs create mode 100644 deps/crates/vendor/proc-macro2/src/probe.rs create mode 100644 deps/crates/vendor/proc-macro2/src/probe/proc_macro_span.rs create mode 100644 deps/crates/vendor/proc-macro2/src/probe/proc_macro_span_file.rs create mode 100644 deps/crates/vendor/proc-macro2/src/probe/proc_macro_span_location.rs create mode 100644 deps/crates/vendor/proc-macro2/src/rcvec.rs create mode 100644 deps/crates/vendor/proc-macro2/src/rustc_literal_escaper.rs create mode 100644 deps/crates/vendor/proc-macro2/src/wrapper.rs create mode 100644 deps/crates/vendor/proc-macro2/tests/comments.rs create mode 100644 deps/crates/vendor/proc-macro2/tests/features.rs create mode 100644 deps/crates/vendor/proc-macro2/tests/marker.rs create mode 100644 deps/crates/vendor/proc-macro2/tests/test.rs create mode 100644 deps/crates/vendor/proc-macro2/tests/test_fmt.rs create mode 100644 deps/crates/vendor/proc-macro2/tests/test_size.rs create mode 100644 deps/crates/vendor/quote/.cargo-checksum.json create mode 100644 deps/crates/vendor/quote/Cargo.toml create mode 100644 deps/crates/vendor/quote/LICENSE-APACHE create mode 100644 deps/crates/vendor/quote/LICENSE-MIT create mode 100644 deps/crates/vendor/quote/README.md create mode 100644 deps/crates/vendor/quote/build.rs create mode 100644 deps/crates/vendor/quote/rust-toolchain.toml create mode 100644 deps/crates/vendor/quote/src/ext.rs create mode 100644 deps/crates/vendor/quote/src/format.rs create mode 100644 deps/crates/vendor/quote/src/ident_fragment.rs create mode 100644 deps/crates/vendor/quote/src/lib.rs create mode 100644 deps/crates/vendor/quote/src/runtime.rs create mode 100644 deps/crates/vendor/quote/src/spanned.rs create mode 100644 deps/crates/vendor/quote/src/to_tokens.rs create mode 100644 deps/crates/vendor/quote/tests/compiletest.rs create mode 100644 deps/crates/vendor/quote/tests/test.rs create mode 100644 deps/crates/vendor/quote/tests/ui/does-not-have-iter-interpolated-dup.rs create mode 100644 deps/crates/vendor/quote/tests/ui/does-not-have-iter-interpolated-dup.stderr create mode 100644 deps/crates/vendor/quote/tests/ui/does-not-have-iter-interpolated.rs create mode 100644 deps/crates/vendor/quote/tests/ui/does-not-have-iter-interpolated.stderr create mode 100644 deps/crates/vendor/quote/tests/ui/does-not-have-iter-separated.rs create mode 100644 deps/crates/vendor/quote/tests/ui/does-not-have-iter-separated.stderr create mode 100644 deps/crates/vendor/quote/tests/ui/does-not-have-iter.rs create mode 100644 deps/crates/vendor/quote/tests/ui/does-not-have-iter.stderr create mode 100644 deps/crates/vendor/quote/tests/ui/not-quotable.rs create mode 100644 deps/crates/vendor/quote/tests/ui/not-quotable.stderr create mode 100644 deps/crates/vendor/quote/tests/ui/not-repeatable.rs create mode 100644 deps/crates/vendor/quote/tests/ui/not-repeatable.stderr create mode 100644 deps/crates/vendor/quote/tests/ui/wrong-type-span.rs create mode 100644 deps/crates/vendor/quote/tests/ui/wrong-type-span.stderr create mode 100644 deps/crates/vendor/resb/.cargo-checksum.json create mode 100644 deps/crates/vendor/resb/Cargo.lock create mode 100644 deps/crates/vendor/resb/Cargo.toml create mode 100644 deps/crates/vendor/resb/LICENSE create mode 100644 deps/crates/vendor/resb/README.md create mode 100644 deps/crates/vendor/resb/examples/data/zoneinfo64.res create mode 100644 deps/crates/vendor/resb/examples/data/zoneinfo64.txt create mode 100644 deps/crates/vendor/resb/examples/genrb.rs create mode 100644 deps/crates/vendor/resb/src/binary.rs create mode 100644 deps/crates/vendor/resb/src/binary/deserializer.rs create mode 100644 deps/crates/vendor/resb/src/binary/header.rs create mode 100644 deps/crates/vendor/resb/src/binary/helpers.rs create mode 100644 deps/crates/vendor/resb/src/binary/serializer.rs create mode 100644 deps/crates/vendor/resb/src/bundle.rs create mode 100644 deps/crates/vendor/resb/src/lib.rs create mode 100644 deps/crates/vendor/resb/src/text.rs create mode 100644 deps/crates/vendor/resb/src/text/reader.rs create mode 100644 deps/crates/vendor/resb/src/text/reader/parse_state.rs create mode 100644 deps/crates/vendor/serde/.cargo-checksum.json create mode 100644 deps/crates/vendor/serde/Cargo.toml create mode 100644 deps/crates/vendor/serde/LICENSE-APACHE create mode 100644 deps/crates/vendor/serde/LICENSE-MIT create mode 100644 deps/crates/vendor/serde/README.md create mode 100644 deps/crates/vendor/serde/build.rs create mode 100644 deps/crates/vendor/serde/crates-io.md create mode 100644 deps/crates/vendor/serde/src/core/crate_root.rs create mode 100644 deps/crates/vendor/serde/src/core/de/ignored_any.rs create mode 100644 deps/crates/vendor/serde/src/core/de/impls.rs create mode 100644 deps/crates/vendor/serde/src/core/de/mod.rs create mode 100644 deps/crates/vendor/serde/src/core/de/value.rs create mode 100644 deps/crates/vendor/serde/src/core/format.rs create mode 100644 deps/crates/vendor/serde/src/core/lib.rs create mode 100644 deps/crates/vendor/serde/src/core/macros.rs create mode 100644 deps/crates/vendor/serde/src/core/private/content.rs create mode 100644 deps/crates/vendor/serde/src/core/private/doc.rs create mode 100644 deps/crates/vendor/serde/src/core/private/mod.rs create mode 100644 deps/crates/vendor/serde/src/core/private/seed.rs create mode 100644 deps/crates/vendor/serde/src/core/private/size_hint.rs create mode 100644 deps/crates/vendor/serde/src/core/private/string.rs create mode 100644 deps/crates/vendor/serde/src/core/ser/fmt.rs create mode 100644 deps/crates/vendor/serde/src/core/ser/impls.rs create mode 100644 deps/crates/vendor/serde/src/core/ser/impossible.rs create mode 100644 deps/crates/vendor/serde/src/core/ser/mod.rs create mode 100644 deps/crates/vendor/serde/src/core/std_error.rs create mode 100644 deps/crates/vendor/serde/src/integer128.rs create mode 100644 deps/crates/vendor/serde/src/lib.rs create mode 100644 deps/crates/vendor/serde/src/private/de.rs create mode 100644 deps/crates/vendor/serde/src/private/mod.rs create mode 100644 deps/crates/vendor/serde/src/private/ser.rs create mode 100644 deps/crates/vendor/serde_core/.cargo-checksum.json create mode 100644 deps/crates/vendor/serde_core/Cargo.toml create mode 100644 deps/crates/vendor/serde_core/LICENSE-APACHE create mode 100644 deps/crates/vendor/serde_core/LICENSE-MIT create mode 100644 deps/crates/vendor/serde_core/README.md create mode 100644 deps/crates/vendor/serde_core/build.rs create mode 100644 deps/crates/vendor/serde_core/src/crate_root.rs create mode 100644 deps/crates/vendor/serde_core/src/de/ignored_any.rs create mode 100644 deps/crates/vendor/serde_core/src/de/impls.rs create mode 100644 deps/crates/vendor/serde_core/src/de/mod.rs create mode 100644 deps/crates/vendor/serde_core/src/de/value.rs create mode 100644 deps/crates/vendor/serde_core/src/format.rs create mode 100644 deps/crates/vendor/serde_core/src/lib.rs create mode 100644 deps/crates/vendor/serde_core/src/macros.rs create mode 100644 deps/crates/vendor/serde_core/src/private/content.rs create mode 100644 deps/crates/vendor/serde_core/src/private/doc.rs create mode 100644 deps/crates/vendor/serde_core/src/private/mod.rs create mode 100644 deps/crates/vendor/serde_core/src/private/seed.rs create mode 100644 deps/crates/vendor/serde_core/src/private/size_hint.rs create mode 100644 deps/crates/vendor/serde_core/src/private/string.rs create mode 100644 deps/crates/vendor/serde_core/src/ser/fmt.rs create mode 100644 deps/crates/vendor/serde_core/src/ser/impls.rs create mode 100644 deps/crates/vendor/serde_core/src/ser/impossible.rs create mode 100644 deps/crates/vendor/serde_core/src/ser/mod.rs create mode 100644 deps/crates/vendor/serde_core/src/std_error.rs create mode 100644 deps/crates/vendor/serde_derive/.cargo-checksum.json create mode 100644 deps/crates/vendor/serde_derive/Cargo.toml create mode 100644 deps/crates/vendor/serde_derive/LICENSE-APACHE create mode 100644 deps/crates/vendor/serde_derive/LICENSE-MIT create mode 100644 deps/crates/vendor/serde_derive/README.md create mode 100644 deps/crates/vendor/serde_derive/crates-io.md create mode 100644 deps/crates/vendor/serde_derive/src/bound.rs create mode 100644 deps/crates/vendor/serde_derive/src/de.rs create mode 100644 deps/crates/vendor/serde_derive/src/de/enum_.rs create mode 100644 deps/crates/vendor/serde_derive/src/de/enum_adjacently.rs create mode 100644 deps/crates/vendor/serde_derive/src/de/enum_externally.rs create mode 100644 deps/crates/vendor/serde_derive/src/de/enum_internally.rs create mode 100644 deps/crates/vendor/serde_derive/src/de/enum_untagged.rs create mode 100644 deps/crates/vendor/serde_derive/src/de/identifier.rs create mode 100644 deps/crates/vendor/serde_derive/src/de/struct_.rs create mode 100644 deps/crates/vendor/serde_derive/src/de/tuple.rs create mode 100644 deps/crates/vendor/serde_derive/src/de/unit.rs create mode 100644 deps/crates/vendor/serde_derive/src/deprecated.rs create mode 100644 deps/crates/vendor/serde_derive/src/dummy.rs create mode 100644 deps/crates/vendor/serde_derive/src/fragment.rs create mode 100644 deps/crates/vendor/serde_derive/src/internals/ast.rs create mode 100644 deps/crates/vendor/serde_derive/src/internals/attr.rs create mode 100644 deps/crates/vendor/serde_derive/src/internals/case.rs create mode 100644 deps/crates/vendor/serde_derive/src/internals/check.rs create mode 100644 deps/crates/vendor/serde_derive/src/internals/ctxt.rs create mode 100644 deps/crates/vendor/serde_derive/src/internals/mod.rs create mode 100644 deps/crates/vendor/serde_derive/src/internals/name.rs create mode 100644 deps/crates/vendor/serde_derive/src/internals/receiver.rs create mode 100644 deps/crates/vendor/serde_derive/src/internals/respan.rs create mode 100644 deps/crates/vendor/serde_derive/src/internals/symbol.rs create mode 100644 deps/crates/vendor/serde_derive/src/lib.rs create mode 100644 deps/crates/vendor/serde_derive/src/pretend.rs create mode 100644 deps/crates/vendor/serde_derive/src/ser.rs create mode 100644 deps/crates/vendor/serde_derive/src/this.rs create mode 100644 deps/crates/vendor/smallvec/.cargo-checksum.json create mode 100644 deps/crates/vendor/smallvec/Cargo.toml create mode 100644 deps/crates/vendor/smallvec/LICENSE-APACHE create mode 100644 deps/crates/vendor/smallvec/LICENSE-MIT create mode 100644 deps/crates/vendor/smallvec/README.md create mode 100644 deps/crates/vendor/smallvec/benches/bench.rs create mode 100644 deps/crates/vendor/smallvec/debug_metadata/README.md create mode 100644 deps/crates/vendor/smallvec/debug_metadata/smallvec.natvis create mode 100644 deps/crates/vendor/smallvec/scripts/run_miri.sh create mode 100644 deps/crates/vendor/smallvec/src/arbitrary.rs create mode 100644 deps/crates/vendor/smallvec/src/lib.rs create mode 100644 deps/crates/vendor/smallvec/src/specialization.rs create mode 100644 deps/crates/vendor/smallvec/src/tests.rs create mode 100644 deps/crates/vendor/smallvec/tests/debugger_visualizer.rs create mode 100644 deps/crates/vendor/smallvec/tests/macro.rs create mode 100644 deps/crates/vendor/stable_deref_trait/.cargo-checksum.json create mode 100644 deps/crates/vendor/stable_deref_trait/Cargo.toml create mode 100644 deps/crates/vendor/stable_deref_trait/LICENSE-APACHE create mode 100644 deps/crates/vendor/stable_deref_trait/LICENSE-MIT create mode 100644 deps/crates/vendor/stable_deref_trait/README.md create mode 100644 deps/crates/vendor/stable_deref_trait/src/lib.rs create mode 100644 deps/crates/vendor/strck/.cargo-checksum.json create mode 100644 deps/crates/vendor/strck/Cargo.toml create mode 100644 deps/crates/vendor/strck/LICENSE create mode 100644 deps/crates/vendor/strck/README.md create mode 100644 deps/crates/vendor/strck/src/ident/mod.rs create mode 100644 deps/crates/vendor/strck/src/ident/rust.rs create mode 100644 deps/crates/vendor/strck/src/ident/unicode.rs create mode 100644 deps/crates/vendor/strck/src/lib.rs create mode 100644 deps/crates/vendor/strck/src/partial_eq.rs create mode 100644 deps/crates/vendor/strck/src/serde.rs create mode 100644 deps/crates/vendor/syn/.cargo-checksum.json create mode 100644 deps/crates/vendor/syn/Cargo.toml create mode 100644 deps/crates/vendor/syn/LICENSE-APACHE create mode 100644 deps/crates/vendor/syn/LICENSE-MIT create mode 100644 deps/crates/vendor/syn/README.md create mode 100644 deps/crates/vendor/syn/benches/file.rs create mode 100644 deps/crates/vendor/syn/benches/rust.rs create mode 100644 deps/crates/vendor/syn/src/attr.rs create mode 100644 deps/crates/vendor/syn/src/bigint.rs create mode 100644 deps/crates/vendor/syn/src/buffer.rs create mode 100644 deps/crates/vendor/syn/src/classify.rs create mode 100644 deps/crates/vendor/syn/src/custom_keyword.rs create mode 100644 deps/crates/vendor/syn/src/custom_punctuation.rs create mode 100644 deps/crates/vendor/syn/src/data.rs create mode 100644 deps/crates/vendor/syn/src/derive.rs create mode 100644 deps/crates/vendor/syn/src/discouraged.rs create mode 100644 deps/crates/vendor/syn/src/drops.rs create mode 100644 deps/crates/vendor/syn/src/error.rs create mode 100644 deps/crates/vendor/syn/src/export.rs create mode 100644 deps/crates/vendor/syn/src/expr.rs create mode 100644 deps/crates/vendor/syn/src/ext.rs create mode 100644 deps/crates/vendor/syn/src/file.rs create mode 100644 deps/crates/vendor/syn/src/fixup.rs create mode 100644 deps/crates/vendor/syn/src/gen/clone.rs create mode 100644 deps/crates/vendor/syn/src/gen/debug.rs create mode 100644 deps/crates/vendor/syn/src/gen/eq.rs create mode 100644 deps/crates/vendor/syn/src/gen/fold.rs create mode 100644 deps/crates/vendor/syn/src/gen/hash.rs create mode 100644 deps/crates/vendor/syn/src/gen/token.css create mode 100644 deps/crates/vendor/syn/src/gen/visit.rs create mode 100644 deps/crates/vendor/syn/src/gen/visit_mut.rs create mode 100644 deps/crates/vendor/syn/src/generics.rs create mode 100644 deps/crates/vendor/syn/src/group.rs create mode 100644 deps/crates/vendor/syn/src/ident.rs create mode 100644 deps/crates/vendor/syn/src/item.rs create mode 100644 deps/crates/vendor/syn/src/lib.rs create mode 100644 deps/crates/vendor/syn/src/lifetime.rs create mode 100644 deps/crates/vendor/syn/src/lit.rs create mode 100644 deps/crates/vendor/syn/src/lookahead.rs create mode 100644 deps/crates/vendor/syn/src/mac.rs create mode 100644 deps/crates/vendor/syn/src/macros.rs create mode 100644 deps/crates/vendor/syn/src/meta.rs create mode 100644 deps/crates/vendor/syn/src/op.rs create mode 100644 deps/crates/vendor/syn/src/parse.rs create mode 100644 deps/crates/vendor/syn/src/parse_macro_input.rs create mode 100644 deps/crates/vendor/syn/src/parse_quote.rs create mode 100644 deps/crates/vendor/syn/src/pat.rs create mode 100644 deps/crates/vendor/syn/src/path.rs create mode 100644 deps/crates/vendor/syn/src/precedence.rs create mode 100644 deps/crates/vendor/syn/src/print.rs create mode 100644 deps/crates/vendor/syn/src/punctuated.rs create mode 100644 deps/crates/vendor/syn/src/restriction.rs create mode 100644 deps/crates/vendor/syn/src/scan_expr.rs create mode 100644 deps/crates/vendor/syn/src/sealed.rs create mode 100644 deps/crates/vendor/syn/src/span.rs create mode 100644 deps/crates/vendor/syn/src/spanned.rs create mode 100644 deps/crates/vendor/syn/src/stmt.rs create mode 100644 deps/crates/vendor/syn/src/thread.rs create mode 100644 deps/crates/vendor/syn/src/token.rs create mode 100644 deps/crates/vendor/syn/src/tt.rs create mode 100644 deps/crates/vendor/syn/src/ty.rs create mode 100644 deps/crates/vendor/syn/src/verbatim.rs create mode 100644 deps/crates/vendor/syn/src/whitespace.rs create mode 100644 deps/crates/vendor/syn/tests/common/eq.rs create mode 100644 deps/crates/vendor/syn/tests/common/mod.rs create mode 100644 deps/crates/vendor/syn/tests/common/parse.rs create mode 100644 deps/crates/vendor/syn/tests/common/visit.rs create mode 100644 deps/crates/vendor/syn/tests/debug/gen.rs create mode 100644 deps/crates/vendor/syn/tests/debug/mod.rs create mode 100644 deps/crates/vendor/syn/tests/macros/mod.rs create mode 100644 deps/crates/vendor/syn/tests/regression.rs create mode 100644 deps/crates/vendor/syn/tests/regression/issue1108.rs create mode 100644 deps/crates/vendor/syn/tests/regression/issue1235.rs create mode 100644 deps/crates/vendor/syn/tests/repo/mod.rs create mode 100644 deps/crates/vendor/syn/tests/repo/progress.rs create mode 100644 deps/crates/vendor/syn/tests/snapshot/mod.rs create mode 100644 deps/crates/vendor/syn/tests/test_asyncness.rs create mode 100644 deps/crates/vendor/syn/tests/test_attribute.rs create mode 100644 deps/crates/vendor/syn/tests/test_derive_input.rs create mode 100644 deps/crates/vendor/syn/tests/test_expr.rs create mode 100644 deps/crates/vendor/syn/tests/test_generics.rs create mode 100644 deps/crates/vendor/syn/tests/test_grouping.rs create mode 100644 deps/crates/vendor/syn/tests/test_ident.rs create mode 100644 deps/crates/vendor/syn/tests/test_item.rs create mode 100644 deps/crates/vendor/syn/tests/test_lit.rs create mode 100644 deps/crates/vendor/syn/tests/test_meta.rs create mode 100644 deps/crates/vendor/syn/tests/test_parse_buffer.rs create mode 100644 deps/crates/vendor/syn/tests/test_parse_quote.rs create mode 100644 deps/crates/vendor/syn/tests/test_parse_stream.rs create mode 100644 deps/crates/vendor/syn/tests/test_pat.rs create mode 100644 deps/crates/vendor/syn/tests/test_path.rs create mode 100644 deps/crates/vendor/syn/tests/test_precedence.rs create mode 100644 deps/crates/vendor/syn/tests/test_punctuated.rs create mode 100644 deps/crates/vendor/syn/tests/test_receiver.rs create mode 100644 deps/crates/vendor/syn/tests/test_round_trip.rs create mode 100644 deps/crates/vendor/syn/tests/test_shebang.rs create mode 100644 deps/crates/vendor/syn/tests/test_size.rs create mode 100644 deps/crates/vendor/syn/tests/test_stmt.rs create mode 100644 deps/crates/vendor/syn/tests/test_token_trees.rs create mode 100644 deps/crates/vendor/syn/tests/test_ty.rs create mode 100644 deps/crates/vendor/syn/tests/test_unparenthesize.rs create mode 100644 deps/crates/vendor/syn/tests/test_visibility.rs create mode 100644 deps/crates/vendor/syn/tests/zzz_stable.rs create mode 100644 deps/crates/vendor/synstructure/.cargo-checksum.json create mode 100644 deps/crates/vendor/synstructure/Cargo.toml create mode 100644 deps/crates/vendor/synstructure/LICENSE create mode 100644 deps/crates/vendor/synstructure/README.md create mode 100644 deps/crates/vendor/synstructure/src/lib.rs create mode 100644 deps/crates/vendor/synstructure/src/macros.rs create mode 100644 deps/crates/vendor/temporal_capi/.cargo-checksum.json create mode 100644 deps/crates/vendor/temporal_capi/Cargo.toml create mode 100644 deps/crates/vendor/temporal_capi/LICENSE-Apache create mode 100644 deps/crates/vendor/temporal_capi/LICENSE-MIT create mode 100644 deps/crates/vendor/temporal_capi/README.md create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/AnyCalendarKind.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/AnyCalendarKind.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/ArithmeticOverflow.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/ArithmeticOverflow.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Calendar.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Calendar.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/DateDuration.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/DateDuration.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/DifferenceSettings.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/DifferenceSettings.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Disambiguation.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Disambiguation.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/DisplayCalendar.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/DisplayCalendar.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/DisplayOffset.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/DisplayOffset.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/DisplayTimeZone.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/DisplayTimeZone.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Duration.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Duration.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/ErrorKind.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/ErrorKind.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/I128Nanoseconds.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/I128Nanoseconds.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Instant.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Instant.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/OffsetDisambiguation.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/OffsetDisambiguation.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/OwnedRelativeTo.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/OwnedRelativeTo.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/ParsedDate.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/ParsedDate.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/ParsedDateTime.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/ParsedDateTime.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/ParsedZonedDateTime.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/ParsedZonedDateTime.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PartialDate.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PartialDate.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PartialDateTime.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PartialDateTime.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PartialDuration.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PartialDuration.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PartialTime.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PartialTime.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PartialZonedDateTime.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PartialZonedDateTime.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PlainDate.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PlainDate.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PlainDateTime.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PlainDateTime.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PlainMonthDay.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PlainMonthDay.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PlainTime.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PlainTime.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PlainYearMonth.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/PlainYearMonth.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Precision.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Precision.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Provider.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Provider.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/RelativeTo.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/RelativeTo.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/RoundingMode.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/RoundingMode.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/RoundingOptions.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/RoundingOptions.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Sign.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Sign.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/TemporalError.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/TemporalError.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/TimeZone.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/TimeZone.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/ToStringRoundingOptions.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/ToStringRoundingOptions.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/TransitionDirection.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/TransitionDirection.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Unit.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/Unit.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/UnsignedRoundingMode.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/UnsignedRoundingMode.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/ZonedDateTime.d.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/ZonedDateTime.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/c/diplomat_runtime.h create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/AnyCalendarKind.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/AnyCalendarKind.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/ArithmeticOverflow.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/ArithmeticOverflow.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Calendar.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Calendar.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/DateDuration.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/DateDuration.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/DifferenceSettings.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/DifferenceSettings.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Disambiguation.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Disambiguation.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/DisplayCalendar.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/DisplayCalendar.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/DisplayOffset.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/DisplayOffset.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/DisplayTimeZone.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/DisplayTimeZone.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Duration.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Duration.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/ErrorKind.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/ErrorKind.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/I128Nanoseconds.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/I128Nanoseconds.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Instant.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Instant.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/OffsetDisambiguation.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/OffsetDisambiguation.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/OwnedRelativeTo.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/OwnedRelativeTo.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/ParsedDate.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/ParsedDate.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/ParsedDateTime.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/ParsedDateTime.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/ParsedZonedDateTime.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/ParsedZonedDateTime.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PartialDate.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PartialDate.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PartialDateTime.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PartialDateTime.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PartialDuration.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PartialDuration.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PartialTime.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PartialTime.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PartialZonedDateTime.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PartialZonedDateTime.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PlainDate.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PlainDate.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PlainDateTime.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PlainMonthDay.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PlainMonthDay.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PlainTime.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PlainTime.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PlainYearMonth.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/PlainYearMonth.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Precision.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Precision.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Provider.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Provider.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/RelativeTo.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/RelativeTo.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/RoundingMode.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/RoundingMode.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/RoundingOptions.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/RoundingOptions.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Sign.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Sign.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/TemporalError.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/TemporalError.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/TimeZone.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/TimeZone.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/ToStringRoundingOptions.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/ToStringRoundingOptions.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/TransitionDirection.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/TransitionDirection.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Unit.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/Unit.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/UnsignedRoundingMode.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/UnsignedRoundingMode.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/ZonedDateTime.d.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/ZonedDateTime.hpp create mode 100644 deps/crates/vendor/temporal_capi/bindings/cpp/temporal_rs/diplomat_runtime.hpp create mode 100644 deps/crates/vendor/temporal_capi/src/calendar.rs create mode 100644 deps/crates/vendor/temporal_capi/src/duration.rs create mode 100644 deps/crates/vendor/temporal_capi/src/error.rs create mode 100644 deps/crates/vendor/temporal_capi/src/instant.rs create mode 100644 deps/crates/vendor/temporal_capi/src/lib.rs create mode 100644 deps/crates/vendor/temporal_capi/src/options.rs create mode 100644 deps/crates/vendor/temporal_capi/src/plain_date.rs create mode 100644 deps/crates/vendor/temporal_capi/src/plain_date_time.rs create mode 100644 deps/crates/vendor/temporal_capi/src/plain_month_day.rs create mode 100644 deps/crates/vendor/temporal_capi/src/plain_time.rs create mode 100644 deps/crates/vendor/temporal_capi/src/plain_year_month.rs create mode 100644 deps/crates/vendor/temporal_capi/src/provider.rs create mode 100644 deps/crates/vendor/temporal_capi/src/time_zone.rs create mode 100644 deps/crates/vendor/temporal_capi/src/zoned_date_time.rs create mode 100644 deps/crates/vendor/temporal_capi/tests/c/Makefile create mode 100644 deps/crates/vendor/temporal_capi/tests/c/simple.c create mode 100644 deps/crates/vendor/temporal_capi/tests/cpp/Makefile create mode 100644 deps/crates/vendor/temporal_capi/tests/cpp/simple.cpp create mode 100644 deps/crates/vendor/temporal_rs/.cargo-checksum.json create mode 100644 deps/crates/vendor/temporal_rs/CHANGELOG.md create mode 100644 deps/crates/vendor/temporal_rs/Cargo.toml create mode 100644 deps/crates/vendor/temporal_rs/LICENSE-Apache create mode 100644 deps/crates/vendor/temporal_rs/LICENSE-MIT create mode 100644 deps/crates/vendor/temporal_rs/README.md create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/compiled/duration.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/compiled/duration/tests.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/compiled/instant.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/compiled/mod.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/compiled/now.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/compiled/plain_date.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/compiled/plain_date_time.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/compiled/plain_month_day.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/compiled/plain_year_month.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/compiled/zoned_date_time.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/calendar.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/calendar/era.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/calendar/fields.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/calendar/types.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/duration.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/duration/date.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/duration/normalized.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/duration/tests.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/instant.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/mod.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/now.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/plain_date.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/plain_date_time.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/plain_month_day.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/plain_time.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/plain_year_month.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/time_zone.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/zoned_date_time.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/core/zoned_date_time/tests.rs create mode 100644 deps/crates/vendor/temporal_rs/src/builtins/mod.rs create mode 100644 deps/crates/vendor/temporal_rs/src/error.rs create mode 100644 deps/crates/vendor/temporal_rs/src/host.rs create mode 100644 deps/crates/vendor/temporal_rs/src/iso.rs create mode 100644 deps/crates/vendor/temporal_rs/src/lib.rs create mode 100644 deps/crates/vendor/temporal_rs/src/options.rs create mode 100644 deps/crates/vendor/temporal_rs/src/options/increment.rs create mode 100644 deps/crates/vendor/temporal_rs/src/options/relative_to.rs create mode 100644 deps/crates/vendor/temporal_rs/src/parsed_intermediates.rs create mode 100644 deps/crates/vendor/temporal_rs/src/parsers.rs create mode 100644 deps/crates/vendor/temporal_rs/src/parsers/time_zone.rs create mode 100644 deps/crates/vendor/temporal_rs/src/primitive.rs create mode 100644 deps/crates/vendor/temporal_rs/src/provider.rs create mode 100644 deps/crates/vendor/temporal_rs/src/rounding.rs create mode 100644 deps/crates/vendor/temporal_rs/src/sys.rs create mode 100644 deps/crates/vendor/temporal_rs/src/tzdb.rs create mode 100644 deps/crates/vendor/temporal_rs/src/utils.rs create mode 100644 deps/crates/vendor/temporal_rs/tools/README.md create mode 100644 deps/crates/vendor/timezone_provider/.cargo-checksum.json create mode 100644 deps/crates/vendor/timezone_provider/Cargo.toml create mode 100644 deps/crates/vendor/timezone_provider/LICENSE-Apache create mode 100644 deps/crates/vendor/timezone_provider/LICENSE-MIT create mode 100644 deps/crates/vendor/timezone_provider/README.md create mode 100644 deps/crates/vendor/timezone_provider/src/data/compiled_zoneinfo_provider.rs.data create mode 100644 deps/crates/vendor/timezone_provider/src/data/iana_normalizer.rs.data create mode 100644 deps/crates/vendor/timezone_provider/src/data/mod.rs create mode 100644 deps/crates/vendor/timezone_provider/src/epoch_nanoseconds.rs create mode 100644 deps/crates/vendor/timezone_provider/src/error.rs create mode 100644 deps/crates/vendor/timezone_provider/src/experimental_tzif/datagen.rs create mode 100644 deps/crates/vendor/timezone_provider/src/experimental_tzif/mod.rs create mode 100644 deps/crates/vendor/timezone_provider/src/experimental_tzif/posix.rs create mode 100644 deps/crates/vendor/timezone_provider/src/lib.rs create mode 100644 deps/crates/vendor/timezone_provider/src/provider.rs create mode 100644 deps/crates/vendor/timezone_provider/src/tzdb.rs create mode 100644 deps/crates/vendor/timezone_provider/src/tzdb/datagen.rs create mode 100644 deps/crates/vendor/timezone_provider/src/tzif.rs create mode 100644 deps/crates/vendor/timezone_provider/src/utc.rs create mode 100644 deps/crates/vendor/timezone_provider/src/utils.rs create mode 100644 deps/crates/vendor/timezone_provider/src/utils/neri_schneider.rs create mode 100644 deps/crates/vendor/timezone_provider/src/zoneinfo64.rs create mode 100644 deps/crates/vendor/tinystr/.cargo-checksum.json create mode 100644 deps/crates/vendor/tinystr/Cargo.toml create mode 100644 deps/crates/vendor/tinystr/LICENSE create mode 100644 deps/crates/vendor/tinystr/README.md create mode 100644 deps/crates/vendor/tinystr/benches/common/mod.rs create mode 100644 deps/crates/vendor/tinystr/benches/construct.rs create mode 100644 deps/crates/vendor/tinystr/benches/overview.rs create mode 100644 deps/crates/vendor/tinystr/benches/read.rs create mode 100644 deps/crates/vendor/tinystr/benches/serde.rs create mode 100644 deps/crates/vendor/tinystr/src/ascii.rs create mode 100644 deps/crates/vendor/tinystr/src/asciibyte.rs create mode 100644 deps/crates/vendor/tinystr/src/databake.rs create mode 100644 deps/crates/vendor/tinystr/src/error.rs create mode 100644 deps/crates/vendor/tinystr/src/int_ops.rs create mode 100644 deps/crates/vendor/tinystr/src/lib.rs create mode 100644 deps/crates/vendor/tinystr/src/macros.rs create mode 100644 deps/crates/vendor/tinystr/src/serde.rs create mode 100644 deps/crates/vendor/tinystr/src/ule.rs create mode 100644 deps/crates/vendor/tinystr/src/unvalidated.rs create mode 100644 deps/crates/vendor/tinystr/tests/serde.rs create mode 100644 deps/crates/vendor/unicode-ident/.cargo-checksum.json create mode 100644 deps/crates/vendor/unicode-ident/Cargo.toml create mode 100644 deps/crates/vendor/unicode-ident/LICENSE-APACHE create mode 100644 deps/crates/vendor/unicode-ident/LICENSE-MIT create mode 100644 deps/crates/vendor/unicode-ident/LICENSE-UNICODE create mode 100644 deps/crates/vendor/unicode-ident/README.md create mode 100644 deps/crates/vendor/unicode-ident/benches/xid.rs create mode 100644 deps/crates/vendor/unicode-ident/src/lib.rs create mode 100644 deps/crates/vendor/unicode-ident/src/tables.rs create mode 100644 deps/crates/vendor/unicode-ident/tests/compare.rs create mode 100644 deps/crates/vendor/unicode-ident/tests/fst/mod.rs create mode 100644 deps/crates/vendor/unicode-ident/tests/fst/xid_continue.fst create mode 100644 deps/crates/vendor/unicode-ident/tests/fst/xid_start.fst create mode 100644 deps/crates/vendor/unicode-ident/tests/roaring/mod.rs create mode 100644 deps/crates/vendor/unicode-ident/tests/static_size.rs create mode 100644 deps/crates/vendor/unicode-ident/tests/tables/mod.rs create mode 100644 deps/crates/vendor/unicode-ident/tests/tables/tables.rs create mode 100644 deps/crates/vendor/unicode-ident/tests/trie/mod.rs create mode 100644 deps/crates/vendor/unicode-ident/tests/trie/trie.rs create mode 100644 deps/crates/vendor/writeable/.cargo-checksum.json create mode 100644 deps/crates/vendor/writeable/Cargo.lock create mode 100644 deps/crates/vendor/writeable/Cargo.toml create mode 100644 deps/crates/vendor/writeable/LICENSE create mode 100644 deps/crates/vendor/writeable/README.md create mode 100644 deps/crates/vendor/writeable/benches/writeable.rs create mode 100644 deps/crates/vendor/writeable/examples/writeable_message.rs create mode 100644 deps/crates/vendor/writeable/src/cmp.rs create mode 100644 deps/crates/vendor/writeable/src/either.rs create mode 100644 deps/crates/vendor/writeable/src/impls.rs create mode 100644 deps/crates/vendor/writeable/src/lib.rs create mode 100644 deps/crates/vendor/writeable/src/ops.rs create mode 100644 deps/crates/vendor/writeable/src/parts_write_adapter.rs create mode 100644 deps/crates/vendor/writeable/src/testing.rs create mode 100644 deps/crates/vendor/writeable/src/to_string_or_borrow.rs create mode 100644 deps/crates/vendor/writeable/src/try_writeable.rs create mode 100644 deps/crates/vendor/writeable/tests/data/data.rs create mode 100644 deps/crates/vendor/writeable/tests/writeable.rs create mode 100644 deps/crates/vendor/yoke-derive/.cargo-checksum.json create mode 100644 deps/crates/vendor/yoke-derive/Cargo.lock create mode 100644 deps/crates/vendor/yoke-derive/Cargo.toml create mode 100644 deps/crates/vendor/yoke-derive/LICENSE create mode 100644 deps/crates/vendor/yoke-derive/README.md create mode 100644 deps/crates/vendor/yoke-derive/examples/yoke_derive.rs create mode 100644 deps/crates/vendor/yoke-derive/src/lib.rs create mode 100644 deps/crates/vendor/yoke-derive/src/visitor.rs create mode 100644 deps/crates/vendor/yoke/.cargo-checksum.json create mode 100644 deps/crates/vendor/yoke/Cargo.toml create mode 100644 deps/crates/vendor/yoke/LICENSE create mode 100644 deps/crates/vendor/yoke/README.md create mode 100644 deps/crates/vendor/yoke/src/cartable_ptr.rs create mode 100644 deps/crates/vendor/yoke/src/either.rs create mode 100644 deps/crates/vendor/yoke/src/erased.rs create mode 100644 deps/crates/vendor/yoke/src/kinda_sorta_dangling.rs create mode 100644 deps/crates/vendor/yoke/src/lib.rs create mode 100644 deps/crates/vendor/yoke/src/macro_impls.rs create mode 100644 deps/crates/vendor/yoke/src/utils.rs create mode 100644 deps/crates/vendor/yoke/src/yoke.rs create mode 100644 deps/crates/vendor/yoke/src/yokeable.rs create mode 100644 deps/crates/vendor/yoke/src/zero_from.rs create mode 100644 deps/crates/vendor/yoke/tests/bincode.rs create mode 100644 deps/crates/vendor/yoke/tests/miri.rs create mode 100644 deps/crates/vendor/zerofrom-derive/.cargo-checksum.json create mode 100644 deps/crates/vendor/zerofrom-derive/Cargo.lock create mode 100644 deps/crates/vendor/zerofrom-derive/Cargo.toml create mode 100644 deps/crates/vendor/zerofrom-derive/LICENSE create mode 100644 deps/crates/vendor/zerofrom-derive/README.md create mode 100644 deps/crates/vendor/zerofrom-derive/examples/zf_derive.rs create mode 100644 deps/crates/vendor/zerofrom-derive/src/lib.rs create mode 100644 deps/crates/vendor/zerofrom-derive/src/visitor.rs create mode 100644 deps/crates/vendor/zerofrom/.cargo-checksum.json create mode 100644 deps/crates/vendor/zerofrom/Cargo.toml create mode 100644 deps/crates/vendor/zerofrom/LICENSE create mode 100644 deps/crates/vendor/zerofrom/README.md create mode 100644 deps/crates/vendor/zerofrom/src/lib.rs create mode 100644 deps/crates/vendor/zerofrom/src/macro_impls.rs create mode 100644 deps/crates/vendor/zerofrom/src/zero_from.rs create mode 100644 deps/crates/vendor/zerotrie/.cargo-checksum.json create mode 100644 deps/crates/vendor/zerotrie/Cargo.lock create mode 100644 deps/crates/vendor/zerotrie/Cargo.toml create mode 100644 deps/crates/vendor/zerotrie/LICENSE create mode 100644 deps/crates/vendor/zerotrie/README.md create mode 100644 deps/crates/vendor/zerotrie/benches/overview.rs create mode 100644 deps/crates/vendor/zerotrie/examples/first_weekday_for_region.rs create mode 100644 deps/crates/vendor/zerotrie/src/builder/branch_meta.rs create mode 100644 deps/crates/vendor/zerotrie/src/builder/bytestr.rs create mode 100644 deps/crates/vendor/zerotrie/src/builder/konst/builder.rs create mode 100644 deps/crates/vendor/zerotrie/src/builder/konst/mod.rs create mode 100644 deps/crates/vendor/zerotrie/src/builder/konst/store.rs create mode 100644 deps/crates/vendor/zerotrie/src/builder/litemap.rs create mode 100644 deps/crates/vendor/zerotrie/src/builder/mod.rs create mode 100644 deps/crates/vendor/zerotrie/src/builder/nonconst/builder.rs create mode 100644 deps/crates/vendor/zerotrie/src/builder/nonconst/mod.rs create mode 100644 deps/crates/vendor/zerotrie/src/builder/nonconst/store.rs create mode 100644 deps/crates/vendor/zerotrie/src/byte_phf/builder.rs create mode 100644 deps/crates/vendor/zerotrie/src/byte_phf/cached_owned.rs create mode 100644 deps/crates/vendor/zerotrie/src/byte_phf/mod.rs create mode 100644 deps/crates/vendor/zerotrie/src/cursor.rs create mode 100644 deps/crates/vendor/zerotrie/src/error.rs create mode 100644 deps/crates/vendor/zerotrie/src/helpers.rs create mode 100644 deps/crates/vendor/zerotrie/src/lib.rs create mode 100644 deps/crates/vendor/zerotrie/src/options.rs create mode 100644 deps/crates/vendor/zerotrie/src/reader.rs create mode 100644 deps/crates/vendor/zerotrie/src/serde.rs create mode 100644 deps/crates/vendor/zerotrie/src/varint.rs create mode 100644 deps/crates/vendor/zerotrie/src/zerotrie.rs create mode 100644 deps/crates/vendor/zerotrie/tests/asciitrie_test.rs create mode 100644 deps/crates/vendor/zerotrie/tests/builder_test.rs create mode 100644 deps/crates/vendor/zerotrie/tests/data/data.rs create mode 100644 deps/crates/vendor/zerotrie/tests/derive_test.rs create mode 100644 deps/crates/vendor/zerotrie/tests/ignorecase_test.rs create mode 100644 deps/crates/vendor/zerotrie/tests/locale_aux_test.rs create mode 100644 deps/crates/vendor/zerovec-derive/.cargo-checksum.json create mode 100644 deps/crates/vendor/zerovec-derive/Cargo.lock create mode 100644 deps/crates/vendor/zerovec-derive/Cargo.toml create mode 100644 deps/crates/vendor/zerovec-derive/LICENSE create mode 100644 deps/crates/vendor/zerovec-derive/README.md create mode 100644 deps/crates/vendor/zerovec-derive/examples/derives.rs create mode 100644 deps/crates/vendor/zerovec-derive/examples/make.rs create mode 100644 deps/crates/vendor/zerovec-derive/examples/make_var.rs create mode 100644 deps/crates/vendor/zerovec-derive/src/lib.rs create mode 100644 deps/crates/vendor/zerovec-derive/src/make_ule.rs create mode 100644 deps/crates/vendor/zerovec-derive/src/make_varule.rs create mode 100644 deps/crates/vendor/zerovec-derive/src/ule.rs create mode 100644 deps/crates/vendor/zerovec-derive/src/utils.rs create mode 100644 deps/crates/vendor/zerovec-derive/src/varule.rs create mode 100644 deps/crates/vendor/zerovec/.cargo-checksum.json create mode 100644 deps/crates/vendor/zerovec/Cargo.lock create mode 100644 deps/crates/vendor/zerovec/Cargo.toml create mode 100644 deps/crates/vendor/zerovec/LICENSE create mode 100644 deps/crates/vendor/zerovec/README.md create mode 100644 deps/crates/vendor/zerovec/benches/vzv.rs create mode 100644 deps/crates/vendor/zerovec/benches/zeromap.rs create mode 100644 deps/crates/vendor/zerovec/benches/zerovec.rs create mode 100644 deps/crates/vendor/zerovec/benches/zerovec_iai.rs create mode 100644 deps/crates/vendor/zerovec/benches/zerovec_serde.rs create mode 100644 deps/crates/vendor/zerovec/examples/zv_serde.rs create mode 100644 deps/crates/vendor/zerovec/src/cow.rs create mode 100644 deps/crates/vendor/zerovec/src/hashmap/algorithms.rs create mode 100644 deps/crates/vendor/zerovec/src/hashmap/mod.rs create mode 100644 deps/crates/vendor/zerovec/src/hashmap/serde.rs create mode 100644 deps/crates/vendor/zerovec/src/lib.rs create mode 100644 deps/crates/vendor/zerovec/src/map/borrowed.rs create mode 100644 deps/crates/vendor/zerovec/src/map/databake.rs create mode 100644 deps/crates/vendor/zerovec/src/map/kv.rs create mode 100644 deps/crates/vendor/zerovec/src/map/map.rs create mode 100644 deps/crates/vendor/zerovec/src/map/mod.rs create mode 100644 deps/crates/vendor/zerovec/src/map/serde.rs create mode 100644 deps/crates/vendor/zerovec/src/map/serde_helpers.rs create mode 100644 deps/crates/vendor/zerovec/src/map/vecs.rs create mode 100644 deps/crates/vendor/zerovec/src/map2d/borrowed.rs create mode 100644 deps/crates/vendor/zerovec/src/map2d/cursor.rs create mode 100644 deps/crates/vendor/zerovec/src/map2d/databake.rs create mode 100644 deps/crates/vendor/zerovec/src/map2d/map.rs create mode 100644 deps/crates/vendor/zerovec/src/map2d/mod.rs create mode 100644 deps/crates/vendor/zerovec/src/map2d/serde.rs create mode 100644 deps/crates/vendor/zerovec/src/samples.rs create mode 100644 deps/crates/vendor/zerovec/src/ule/chars.rs create mode 100644 deps/crates/vendor/zerovec/src/ule/custom.rs create mode 100644 deps/crates/vendor/zerovec/src/ule/encode.rs create mode 100644 deps/crates/vendor/zerovec/src/ule/macros.rs create mode 100644 deps/crates/vendor/zerovec/src/ule/mod.rs create mode 100644 deps/crates/vendor/zerovec/src/ule/multi.rs create mode 100644 deps/crates/vendor/zerovec/src/ule/niche.rs create mode 100644 deps/crates/vendor/zerovec/src/ule/option.rs create mode 100644 deps/crates/vendor/zerovec/src/ule/plain.rs create mode 100644 deps/crates/vendor/zerovec/src/ule/slices.rs create mode 100644 deps/crates/vendor/zerovec/src/ule/test_utils.rs create mode 100644 deps/crates/vendor/zerovec/src/ule/tuple.rs create mode 100644 deps/crates/vendor/zerovec/src/ule/tuplevar.rs create mode 100644 deps/crates/vendor/zerovec/src/ule/vartuple.rs create mode 100644 deps/crates/vendor/zerovec/src/varzerovec/components.rs create mode 100644 deps/crates/vendor/zerovec/src/varzerovec/databake.rs create mode 100644 deps/crates/vendor/zerovec/src/varzerovec/error.rs create mode 100644 deps/crates/vendor/zerovec/src/varzerovec/lengthless.rs create mode 100644 deps/crates/vendor/zerovec/src/varzerovec/mod.rs create mode 100644 deps/crates/vendor/zerovec/src/varzerovec/owned.rs create mode 100644 deps/crates/vendor/zerovec/src/varzerovec/serde.rs create mode 100644 deps/crates/vendor/zerovec/src/varzerovec/slice.rs create mode 100644 deps/crates/vendor/zerovec/src/varzerovec/vec.rs create mode 100644 deps/crates/vendor/zerovec/src/yoke_impls.rs create mode 100644 deps/crates/vendor/zerovec/src/zerofrom_impls.rs create mode 100644 deps/crates/vendor/zerovec/src/zerovec/databake.rs create mode 100644 deps/crates/vendor/zerovec/src/zerovec/mod.rs create mode 100644 deps/crates/vendor/zerovec/src/zerovec/serde.rs create mode 100644 deps/crates/vendor/zerovec/src/zerovec/slice.rs create mode 100644 deps/crates/vendor/zoneinfo64/.cargo-checksum.json create mode 100644 deps/crates/vendor/zoneinfo64/Cargo.toml create mode 100644 deps/crates/vendor/zoneinfo64/LICENSE create mode 100644 deps/crates/vendor/zoneinfo64/README.md create mode 100644 deps/crates/vendor/zoneinfo64/src/chrono_impls.rs create mode 100644 deps/crates/vendor/zoneinfo64/src/data/zoneinfo64.res create mode 100644 deps/crates/vendor/zoneinfo64/src/deserialize.rs create mode 100644 deps/crates/vendor/zoneinfo64/src/lib.rs create mode 100644 deps/crates/vendor/zoneinfo64/src/rule.rs diff --git a/deps/crates/vendor/autocfg/.cargo-checksum.json b/deps/crates/vendor/autocfg/.cargo-checksum.json new file mode 100644 index 00000000000000..64152cc71efb71 --- /dev/null +++ b/deps/crates/vendor/autocfg/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.lock":"152ebf71feed214951186ccc738958236b493bacf634d48ce422371c92ef0b07","Cargo.toml":"919934158a57ad16895ec2e937c5c14e3cef405b168c191d64dc81b69b9abe4a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"27995d58ad5c1145c1a8cd86244ce844886958a35eb2b78c6b772748669999ac","README.md":"fbd8762dcc681074fb3862e5d2168299fedb08d08bcadbff2713e2f956a79f82","examples/integers.rs":"589ff4271566dfa322becddf3e2c7b592e6e0bc97b02892ce75619b7e452e930","examples/nightly.rs":"ac8b5a9aa1e04465e44f5053b3c899b635e07af058c73aa8b45176bf4b5912f9","examples/paths.rs":"1b30e466b824ce8df7ad0a55334424131d9d2573d6cf9f7d5d50c09c8901d526","examples/traits.rs":"cbee6a3e1f7db60b02ae25b714926517144a77cb492021f492774cf0e1865a9e","examples/versions.rs":"38535e6d9f5bfae0de474a3db79a40e8f5da8ba9334c5ff4c363de9bc99d4d12","src/error.rs":"fd8ff67c64f7cd1b9f81325a81de4baa34c39d6ae298bdb33f9829cc91acac39","src/lib.rs":"772630d0e09d06f343fd72284c8330eacde87d2a4ee22f70af62a0e2119fbf05","src/rustc.rs":"a8a213ddb64a05c1a1af933bcb331a98879e942b167c33d8f94f9f60ebb14e29","src/tests.rs":"b39f4d880ad343e65307a9e0c381954ea27adce4732f825516ce7952e2e5a91d","src/version.rs":"4f7d23b36f01c7be1871be86c038d6cb4689e145d67c82d3793690e9aa05b133","tests/no_std.rs":"18859dc4992fe1769887bde05f03d28f1ce524eafd17646d3fbcb4379422761a","tests/rustflags.rs":"e8ded4d57ba25379a38ab48456d67df14f82abbbb5f6bb66221c6decbcb517a3","tests/support/mod.rs":"32087d365b438ac3f62df9bb066d8d648b80cb130a5c777afcb2f21fbb68d88e","tests/tests.rs":"39149fe69a45f577eeb531587a5e600d8bc9f8d937480172dac9402939d856f0","tests/wrap_ignored":"a9e241edf584a0702066b25bc15c5bbfd8a1019e14fb655fc4f47a67360065ca","tests/wrappers.rs":"b5137fe36768eaef277fb8650b0fe45b2c675d9e60b1b49d39f2ec95082c285b"},"package":"c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"} \ No newline at end of file diff --git a/deps/crates/vendor/autocfg/Cargo.lock b/deps/crates/vendor/autocfg/Cargo.lock new file mode 100644 index 00000000000000..45f1f18ec94cbc --- /dev/null +++ b/deps/crates/vendor/autocfg/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "autocfg" +version = "1.5.0" + diff --git a/deps/crates/vendor/autocfg/Cargo.toml b/deps/crates/vendor/autocfg/Cargo.toml new file mode 100644 index 00000000000000..005f56dcdd7722 --- /dev/null +++ b/deps/crates/vendor/autocfg/Cargo.toml @@ -0,0 +1,76 @@ +# 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] +rust-version = "1.0" +name = "autocfg" +version = "1.5.0" +authors = ["Josh Stone "] +build = false +exclude = ["/.github/**"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Automatic cfg for Rust compiler features" +documentation = "https://docs.rs/autocfg/" +readme = "README.md" +keywords = [ + "rustc", + "build", + "autoconf", +] +categories = ["development-tools::build-utils"] +license = "Apache-2.0 OR MIT" +repository = "https://github.com/cuviper/autocfg" + +[lib] +name = "autocfg" +path = "src/lib.rs" + +[[example]] +name = "integers" +path = "examples/integers.rs" + +[[example]] +name = "nightly" +path = "examples/nightly.rs" + +[[example]] +name = "paths" +path = "examples/paths.rs" + +[[example]] +name = "traits" +path = "examples/traits.rs" + +[[example]] +name = "versions" +path = "examples/versions.rs" + +[[test]] +name = "no_std" +path = "tests/no_std.rs" + +[[test]] +name = "rustflags" +path = "tests/rustflags.rs" + +[[test]] +name = "tests" +path = "tests/tests.rs" + +[[test]] +name = "wrappers" +path = "tests/wrappers.rs" + +[dependencies] diff --git a/deps/crates/vendor/autocfg/LICENSE-APACHE b/deps/crates/vendor/autocfg/LICENSE-APACHE new file mode 100644 index 00000000000000..16fe87b06e802f --- /dev/null +++ b/deps/crates/vendor/autocfg/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/deps/crates/vendor/autocfg/LICENSE-MIT b/deps/crates/vendor/autocfg/LICENSE-MIT new file mode 100644 index 00000000000000..44fbc4d8b90dbe --- /dev/null +++ b/deps/crates/vendor/autocfg/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2018 Josh Stone + +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/deps/crates/vendor/autocfg/README.md b/deps/crates/vendor/autocfg/README.md new file mode 100644 index 00000000000000..a3d8ac4995c6b4 --- /dev/null +++ b/deps/crates/vendor/autocfg/README.md @@ -0,0 +1,117 @@ +autocfg +======= + +[![autocfg crate](https://img.shields.io/crates/v/autocfg.svg)](https://crates.io/crates/autocfg) +[![autocfg documentation](https://docs.rs/autocfg/badge.svg)](https://docs.rs/autocfg) +![minimum rustc 1.0](https://img.shields.io/badge/rustc-1.0+-red.svg) +![build status](https://github.com/cuviper/autocfg/workflows/CI/badge.svg) + +A Rust library for build scripts to automatically configure code based on +compiler support. Code snippets are dynamically tested to see if the `rustc` +will accept them, rather than hard-coding specific version support. + + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[build-dependencies] +autocfg = "1" +``` + +Then use it in your `build.rs` script to detect compiler features. For +example, to test for 128-bit integer support, it might look like: + +```rust +extern crate autocfg; + +fn main() { + let ac = autocfg::new(); + ac.emit_has_type("i128"); + + // (optional) We don't need to rerun for anything external. + autocfg::rerun_path("build.rs"); +} +``` + +If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line +for Cargo, which translates to Rust arguments `--cfg has_i128`. Then in the +rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that +should only be used when the compiler supports it. + + +## Release Notes + +- 1.5.0 (2025-06-17) + + - Add `edition` and `set_edition` to control the Rust edition used in probes. + - Remove probe result files so they don't pollute the output directory. + +- 1.4.0 (2024-09-26) + + - Add `emit_possibility` for Rust 1.80's [checked cfgs], and call that + automatically for methods that conditionally `emit`, by @Techcable. + +[checked cfgs]: https://blog.rust-lang.org/2024/05/06/check-cfg.html + +- 1.3.0 (2024-05-03) + + - Add `probe_raw` for direct control of the code that will be test-compiled. + - Use wrappers when querying the `rustc` version information too. + +- 1.2.0 (2024-03-25) + + - Add `no_std` and `set_no_std` to control the use of `#![no_std]` in probes. + - Use `RUSTC_WRAPPER` and `RUSTC_WORKSPACE_WRAPPER` when they are set. + +- 1.1.0 (2022-02-07) + - Use `CARGO_ENCODED_RUSTFLAGS` when it is set. + +- 1.0.1 (2020-08-20) + - Apply `RUSTFLAGS` for more `--target` scenarios, by @adamreichold. + +- 1.0.0 (2020-01-08) + - 🎉 Release 1.0! 🎉 (no breaking changes) + - Add `probe_expression` and `emit_expression_cfg` to test arbitrary expressions. + - Add `probe_constant` and `emit_constant_cfg` to test arbitrary constant expressions. + +- 0.1.7 (2019-10-20) + - Apply `RUSTFLAGS` when probing `$TARGET != $HOST`, mainly for sysroot, by @roblabla. + +- 0.1.6 (2019-08-19) + - Add `probe`/`emit_sysroot_crate`, by @leo60228. + +- 0.1.5 (2019-07-16) + - Mask some warnings from newer rustc. + +- 0.1.4 (2019-05-22) + - Relax `std`/`no_std` probing to a warning instead of an error. + - Improve `rustc` bootstrap compatibility. + +- 0.1.3 (2019-05-21) + - Auto-detects if `#![no_std]` is needed for the `$TARGET`. + +- 0.1.2 (2019-01-16) + - Add `rerun_env(ENV)` to print `cargo:rerun-if-env-changed=ENV`. + - Add `rerun_path(PATH)` to print `cargo:rerun-if-changed=PATH`. + + +## Minimum Rust version policy + +This crate's minimum supported `rustc` version is `1.0.0`. Compatibility is +its entire reason for existence, so this crate will be extremely conservative +about raising this requirement. If this is ever deemed necessary, it will be +treated as a major breaking change for semver purposes. + + +## License + +This project is licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or + https://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or + https://opensource.org/licenses/MIT) + +at your option. diff --git a/deps/crates/vendor/autocfg/examples/integers.rs b/deps/crates/vendor/autocfg/examples/integers.rs new file mode 100644 index 00000000000000..23d4cba6ee3e96 --- /dev/null +++ b/deps/crates/vendor/autocfg/examples/integers.rs @@ -0,0 +1,9 @@ +extern crate autocfg; + +fn main() { + // Normally, cargo will set `OUT_DIR` for build scripts. + let ac = autocfg::AutoCfg::with_dir("target").unwrap(); + for i in 3..8 { + ac.emit_has_type(&format!("i{}", 1 << i)); + } +} diff --git a/deps/crates/vendor/autocfg/examples/nightly.rs b/deps/crates/vendor/autocfg/examples/nightly.rs new file mode 100644 index 00000000000000..955e63d74c4c9a --- /dev/null +++ b/deps/crates/vendor/autocfg/examples/nightly.rs @@ -0,0 +1,18 @@ +extern crate autocfg; + +fn main() { + // Normally, cargo will set `OUT_DIR` for build scripts. + let ac = autocfg::AutoCfg::with_dir("target").unwrap(); + + // When this feature was stabilized, it also renamed the method to + // `chunk_by`, so it's important to *use* the feature in your probe. + let code = r#" + #![feature(slice_group_by)] + pub fn probe(slice: &[i32]) -> impl Iterator { + slice.group_by(|a, b| a == b) + } + "#; + if ac.probe_raw(code).is_ok() { + autocfg::emit("has_slice_group_by"); + } +} diff --git a/deps/crates/vendor/autocfg/examples/paths.rs b/deps/crates/vendor/autocfg/examples/paths.rs new file mode 100644 index 00000000000000..b7a6ca7a25f7b3 --- /dev/null +++ b/deps/crates/vendor/autocfg/examples/paths.rs @@ -0,0 +1,22 @@ +extern crate autocfg; + +fn main() { + // Normally, cargo will set `OUT_DIR` for build scripts. + let ac = autocfg::AutoCfg::with_dir("target").unwrap(); + + // since ancient times... + ac.emit_has_path("std::vec::Vec"); + ac.emit_path_cfg("std::vec::Vec", "has_vec"); + + // rustc 1.10.0 + ac.emit_has_path("std::panic::PanicInfo"); + ac.emit_path_cfg("std::panic::PanicInfo", "has_panic_info"); + + // rustc 1.20.0 + ac.emit_has_path("std::mem::ManuallyDrop"); + ac.emit_path_cfg("std::mem::ManuallyDrop", "has_manually_drop"); + + // rustc 1.25.0 + ac.emit_has_path("std::ptr::NonNull"); + ac.emit_path_cfg("std::ptr::NonNull", "has_non_null"); +} diff --git a/deps/crates/vendor/autocfg/examples/traits.rs b/deps/crates/vendor/autocfg/examples/traits.rs new file mode 100644 index 00000000000000..c1ca00385cd403 --- /dev/null +++ b/deps/crates/vendor/autocfg/examples/traits.rs @@ -0,0 +1,26 @@ +extern crate autocfg; + +fn main() { + // Normally, cargo will set `OUT_DIR` for build scripts. + let ac = autocfg::AutoCfg::with_dir("target").unwrap(); + + // since ancient times... + ac.emit_has_trait("std::ops::Add"); + ac.emit_trait_cfg("std::ops::Add", "has_ops"); + + // trait parameters have to be provided + ac.emit_has_trait("std::borrow::Borrow"); + ac.emit_trait_cfg("std::borrow::Borrow", "has_borrow"); + + // rustc 1.8.0 + ac.emit_has_trait("std::ops::AddAssign"); + ac.emit_trait_cfg("std::ops::AddAssign", "has_assign_ops"); + + // rustc 1.12.0 + ac.emit_has_trait("std::iter::Sum"); + ac.emit_trait_cfg("std::iter::Sum", "has_sum"); + + // rustc 1.28.0 + ac.emit_has_trait("std::alloc::GlobalAlloc"); + ac.emit_trait_cfg("std::alloc::GlobalAlloc", "has_global_alloc"); +} diff --git a/deps/crates/vendor/autocfg/examples/versions.rs b/deps/crates/vendor/autocfg/examples/versions.rs new file mode 100644 index 00000000000000..992919b7c64280 --- /dev/null +++ b/deps/crates/vendor/autocfg/examples/versions.rs @@ -0,0 +1,9 @@ +extern crate autocfg; + +fn main() { + // Normally, cargo will set `OUT_DIR` for build scripts. + let ac = autocfg::AutoCfg::with_dir("target").unwrap(); + for i in 0..100 { + ac.emit_rustc_version(1, i); + } +} diff --git a/deps/crates/vendor/autocfg/src/error.rs b/deps/crates/vendor/autocfg/src/error.rs new file mode 100644 index 00000000000000..7839ee9a2fd498 --- /dev/null +++ b/deps/crates/vendor/autocfg/src/error.rs @@ -0,0 +1,81 @@ +use std::error; +use std::fmt; +use std::io; +use std::num; +use std::process; +use std::str; + +/// A common error type for the `autocfg` crate. +#[derive(Debug)] +pub struct Error { + kind: ErrorKind, +} + +impl error::Error for Error { + fn description(&self) -> &str { + "AutoCfg error" + } + + fn cause(&self) -> Option<&error::Error> { + match self.kind { + ErrorKind::Io(ref e) => Some(e), + ErrorKind::Num(ref e) => Some(e), + ErrorKind::Utf8(ref e) => Some(e), + ErrorKind::Process(_) | ErrorKind::Other(_) => None, + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match self.kind { + ErrorKind::Io(ref e) => e.fmt(f), + ErrorKind::Num(ref e) => e.fmt(f), + ErrorKind::Utf8(ref e) => e.fmt(f), + ErrorKind::Process(ref status) => { + // Same message as the newer `ExitStatusError` + write!(f, "process exited unsuccessfully: {}", status) + } + ErrorKind::Other(s) => s.fmt(f), + } + } +} + +#[derive(Debug)] +enum ErrorKind { + Io(io::Error), + Num(num::ParseIntError), + Process(process::ExitStatus), + Utf8(str::Utf8Error), + Other(&'static str), +} + +pub fn from_exit(status: process::ExitStatus) -> Error { + Error { + kind: ErrorKind::Process(status), + } +} + +pub fn from_io(e: io::Error) -> Error { + Error { + kind: ErrorKind::Io(e), + } +} + +pub fn from_num(e: num::ParseIntError) -> Error { + Error { + kind: ErrorKind::Num(e), + } +} + +pub fn from_utf8(e: str::Utf8Error) -> Error { + Error { + kind: ErrorKind::Utf8(e), + } +} + +pub fn from_str(s: &'static str) -> Error { + Error { + kind: ErrorKind::Other(s), + } +} diff --git a/deps/crates/vendor/autocfg/src/lib.rs b/deps/crates/vendor/autocfg/src/lib.rs new file mode 100644 index 00000000000000..69e6ffcf363dd9 --- /dev/null +++ b/deps/crates/vendor/autocfg/src/lib.rs @@ -0,0 +1,636 @@ +//! A Rust library for build scripts to automatically configure code based on +//! compiler support. Code snippets are dynamically tested to see if the `rustc` +//! will accept them, rather than hard-coding specific version support. +//! +//! +//! ## Usage +//! +//! Add this to your `Cargo.toml`: +//! +//! ```toml +//! [build-dependencies] +//! autocfg = "1" +//! ``` +//! +//! Then use it in your `build.rs` script to detect compiler features. For +//! example, to test for 128-bit integer support, it might look like: +//! +//! ```rust +//! extern crate autocfg; +//! +//! fn main() { +//! # // Normally, cargo will set `OUT_DIR` for build scripts. +//! # let exe = std::env::current_exe().unwrap(); +//! # std::env::set_var("OUT_DIR", exe.parent().unwrap()); +//! let ac = autocfg::new(); +//! ac.emit_has_type("i128"); +//! +//! // (optional) We don't need to rerun for anything external. +//! autocfg::rerun_path("build.rs"); +//! } +//! ``` +//! +//! If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line +//! for Cargo, which translates to Rust arguments `--cfg has_i128`. Then in the +//! rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that +//! should only be used when the compiler supports it. +//! +//! ## Caution +//! +//! Many of the probing methods of `AutoCfg` document the particular template they +//! use, **subject to change**. The inputs are not validated to make sure they are +//! semantically correct for their expected use, so it's _possible_ to escape and +//! inject something unintended. However, such abuse is unsupported and will not +//! be considered when making changes to the templates. + +#![deny(missing_debug_implementations)] +#![deny(missing_docs)] +// allow future warnings that can't be fixed while keeping 1.0 compatibility +#![allow(unknown_lints)] +#![allow(bare_trait_objects)] +#![allow(ellipsis_inclusive_range_patterns)] + +/// Local macro to avoid `std::try!`, deprecated in Rust 1.39. +macro_rules! try { + ($result:expr) => { + match $result { + Ok(value) => value, + Err(error) => return Err(error), + } + }; +} + +use std::env; +use std::ffi::OsString; +use std::fmt::Arguments; +use std::fs; +use std::io::{stderr, Write}; +use std::path::{Path, PathBuf}; +use std::process::Stdio; +#[allow(deprecated)] +use std::sync::atomic::ATOMIC_USIZE_INIT; +use std::sync::atomic::{AtomicUsize, Ordering}; + +mod error; +pub use error::Error; + +mod rustc; +use rustc::Rustc; + +mod version; +use version::Version; + +#[cfg(test)] +mod tests; + +/// Helper to detect compiler features for `cfg` output in build scripts. +#[derive(Clone, Debug)] +pub struct AutoCfg { + out_dir: PathBuf, + rustc: Rustc, + rustc_version: Version, + target: Option, + no_std: bool, + edition: Option, + rustflags: Vec, + uuid: u64, +} + +/// Writes a config flag for rustc on standard out. +/// +/// This looks like: `cargo:rustc-cfg=CFG` +/// +/// Cargo will use this in arguments to rustc, like `--cfg CFG`. +/// +/// This does not automatically call [`emit_possibility`] +/// so the compiler my generate an [`unexpected_cfgs` warning][check-cfg-flags]. +/// However, all the builtin emit methods on [`AutoCfg`] call [`emit_possibility`] automatically. +/// +/// [check-cfg-flags]: https://blog.rust-lang.org/2024/05/06/check-cfg.html +pub fn emit(cfg: &str) { + println!("cargo:rustc-cfg={}", cfg); +} + +/// Writes a line telling Cargo to rerun the build script if `path` changes. +/// +/// This looks like: `cargo:rerun-if-changed=PATH` +/// +/// This requires at least cargo 0.7.0, corresponding to rustc 1.6.0. Earlier +/// versions of cargo will simply ignore the directive. +pub fn rerun_path(path: &str) { + println!("cargo:rerun-if-changed={}", path); +} + +/// Writes a line telling Cargo to rerun the build script if the environment +/// variable `var` changes. +/// +/// This looks like: `cargo:rerun-if-env-changed=VAR` +/// +/// This requires at least cargo 0.21.0, corresponding to rustc 1.20.0. Earlier +/// versions of cargo will simply ignore the directive. +pub fn rerun_env(var: &str) { + println!("cargo:rerun-if-env-changed={}", var); +} + +/// Indicates to rustc that a config flag should not generate an [`unexpected_cfgs` warning][check-cfg-flags] +/// +/// This looks like `cargo:rustc-check-cfg=cfg(VAR)` +/// +/// As of rust 1.80, the compiler does [automatic checking of cfgs at compile time][check-cfg-flags]. +/// All custom configuration flags must be known to rustc, or they will generate a warning. +/// This is done automatically when calling the builtin emit methods on [`AutoCfg`], +/// but not when calling [`autocfg::emit`](crate::emit) directly. +/// +/// Versions before rust 1.80 will simply ignore this directive. +/// +/// This function indicates to the compiler that the config flag never has a value. +/// If this is not desired, see [the blog post][check-cfg]. +/// +/// [check-cfg-flags]: https://blog.rust-lang.org/2024/05/06/check-cfg.html +pub fn emit_possibility(cfg: &str) { + println!("cargo:rustc-check-cfg=cfg({})", cfg); +} + +/// Creates a new `AutoCfg` instance. +/// +/// # Panics +/// +/// Panics if `AutoCfg::new()` returns an error. +pub fn new() -> AutoCfg { + AutoCfg::new().unwrap() +} + +impl AutoCfg { + /// Creates a new `AutoCfg` instance. + /// + /// # Common errors + /// + /// - `rustc` can't be executed, from `RUSTC` or in the `PATH`. + /// - The version output from `rustc` can't be parsed. + /// - `OUT_DIR` is not set in the environment, or is not a writable directory. + /// + pub fn new() -> Result { + match env::var_os("OUT_DIR") { + Some(d) => Self::with_dir(d), + None => Err(error::from_str("no OUT_DIR specified!")), + } + } + + /// Creates a new `AutoCfg` instance with the specified output directory. + /// + /// # Common errors + /// + /// - `rustc` can't be executed, from `RUSTC` or in the `PATH`. + /// - The version output from `rustc` can't be parsed. + /// - `dir` is not a writable directory. + /// + pub fn with_dir>(dir: T) -> Result { + let rustc = Rustc::new(); + let rustc_version = try!(rustc.version()); + + let target = env::var_os("TARGET"); + + // Sanity check the output directory + let dir = dir.into(); + let meta = try!(fs::metadata(&dir).map_err(error::from_io)); + if !meta.is_dir() || meta.permissions().readonly() { + return Err(error::from_str("output path is not a writable directory")); + } + + let mut ac = AutoCfg { + rustflags: rustflags(&target, &dir), + out_dir: dir, + rustc: rustc, + rustc_version: rustc_version, + target: target, + no_std: false, + edition: None, + uuid: new_uuid(), + }; + + // Sanity check with and without `std`. + if ac.probe_raw("").is_err() { + if ac.probe_raw("#![no_std]").is_ok() { + ac.no_std = true; + } else { + // Neither worked, so assume nothing... + let warning = b"warning: autocfg could not probe for `std`\n"; + stderr().write_all(warning).ok(); + } + } + Ok(ac) + } + + /// Returns whether `AutoCfg` is using `#![no_std]` in its probes. + /// + /// This is automatically detected during construction -- if an empty probe + /// fails while one with `#![no_std]` succeeds, then the attribute will be + /// used for all further probes. This is usually only necessary when the + /// `TARGET` lacks `std` altogether. If neither succeeds, `no_std` is not + /// set, but that `AutoCfg` will probably only work for version checks. + /// + /// This attribute changes the implicit [prelude] from `std` to `core`, + /// which may affect the paths you need to use in other probes. It also + /// restricts some types that otherwise get additional methods in `std`, + /// like floating-point trigonometry and slice sorting. + /// + /// See also [`set_no_std`](#method.set_no_std). + /// + /// [prelude]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute + pub fn no_std(&self) -> bool { + self.no_std + } + + /// Sets whether `AutoCfg` should use `#![no_std]` in its probes. + /// + /// See also [`no_std`](#method.no_std). + pub fn set_no_std(&mut self, no_std: bool) { + self.no_std = no_std; + } + + /// Returns the `--edition` string that is currently being passed to `rustc`, if any, + /// as configured by the [`set_edition`][Self::set_edition] method. + pub fn edition(&self) -> Option<&str> { + match self.edition { + Some(ref edition) => Some(&**edition), + None => None, + } + } + + /// Sets the `--edition` string that will be passed to `rustc`, + /// or `None` to leave the compiler at its default edition. + /// + /// See also [The Rust Edition Guide](https://doc.rust-lang.org/edition-guide/). + /// + /// **Warning:** Setting an unsupported edition will likely cause **all** subsequent probes to + /// fail! As of this writing, the known editions and their minimum Rust versions are: + /// + /// | Edition | Version | + /// | ------- | ---------- | + /// | 2015 | 1.27.0[^1] | + /// | 2018 | 1.31.0 | + /// | 2021 | 1.56.0 | + /// | 2024 | 1.85.0 | + /// + /// [^1]: Prior to 1.27.0, Rust was effectively 2015 Edition by default, but the concept hadn't + /// been established yet, so the explicit `--edition` flag wasn't supported either. + pub fn set_edition(&mut self, edition: Option) { + self.edition = edition; + } + + /// Tests whether the current `rustc` reports a version greater than + /// or equal to "`major`.`minor`". + pub fn probe_rustc_version(&self, major: usize, minor: usize) -> bool { + self.rustc_version >= Version::new(major, minor, 0) + } + + /// Sets a `cfg` value of the form `rustc_major_minor`, like `rustc_1_29`, + /// if the current `rustc` is at least that version. + pub fn emit_rustc_version(&self, major: usize, minor: usize) { + let cfg_flag = format!("rustc_{}_{}", major, minor); + emit_possibility(&cfg_flag); + if self.probe_rustc_version(major, minor) { + emit(&cfg_flag); + } + } + + /// Returns a new (hopefully unique) crate name for probes. + fn new_crate_name(&self) -> String { + #[allow(deprecated)] + static ID: AtomicUsize = ATOMIC_USIZE_INIT; + + let id = ID.fetch_add(1, Ordering::Relaxed); + format!("autocfg_{:016x}_{}", self.uuid, id) + } + + fn probe_fmt<'a>(&self, source: Arguments<'a>) -> Result<(), Error> { + let crate_name = self.new_crate_name(); + let mut command = self.rustc.command(); + command + .arg("--crate-name") + .arg(&crate_name) + .arg("--crate-type=lib") + .arg("--out-dir") + .arg(&self.out_dir) + .arg("--emit=llvm-ir"); + + if let Some(edition) = self.edition.as_ref() { + command.arg("--edition").arg(edition); + } + + if let Some(target) = self.target.as_ref() { + command.arg("--target").arg(target); + } + + command.args(&self.rustflags); + + command.arg("-").stdin(Stdio::piped()); + let mut child = try!(command.spawn().map_err(error::from_io)); + let mut stdin = child.stdin.take().expect("rustc stdin"); + + try!(stdin.write_fmt(source).map_err(error::from_io)); + drop(stdin); + + match child.wait() { + Ok(status) if status.success() => { + // Try to remove the output file so it doesn't look like a build product for + // systems like bazel -- but this is best-effort, so we can ignore failure. + // The probe itself is already considered successful at this point. + let mut file = self.out_dir.join(crate_name); + file.set_extension("ll"); + let _ = fs::remove_file(file); + + Ok(()) + } + Ok(status) => Err(error::from_exit(status)), + Err(error) => Err(error::from_io(error)), + } + } + + fn probe<'a>(&self, code: Arguments<'a>) -> bool { + let result = if self.no_std { + self.probe_fmt(format_args!("#![no_std]\n{}", code)) + } else { + self.probe_fmt(code) + }; + result.is_ok() + } + + /// Tests whether the given code can be compiled as a Rust library. + /// + /// This will only return `Ok` if the compiler ran and exited successfully, + /// per `ExitStatus::success()`. + /// The code is passed to the compiler exactly as-is, notably not even + /// adding the [`#![no_std]`][Self::no_std] attribute like other probes. + /// + /// Raw probes are useful for testing functionality that's not yet covered + /// by the rest of the `AutoCfg` API. For example, the following attribute + /// **must** be used at the crate level, so it wouldn't work within the code + /// templates used by other `probe_*` methods. + /// + /// ``` + /// # extern crate autocfg; + /// # // Normally, cargo will set `OUT_DIR` for build scripts. + /// # let exe = std::env::current_exe().unwrap(); + /// # std::env::set_var("OUT_DIR", exe.parent().unwrap()); + /// let ac = autocfg::new(); + /// assert!(ac.probe_raw("#![no_builtins]").is_ok()); + /// ``` + /// + /// Rust nightly features could be tested as well -- ideally including a + /// code sample to ensure the unstable feature still works as expected. + /// For example, `slice::group_by` was renamed to `chunk_by` when it was + /// stabilized, even though the feature name was unchanged, so testing the + /// `#![feature(..)]` alone wouldn't reveal that. For larger snippets, + /// [`include_str!`] may be useful to load them from separate files. + /// + /// ``` + /// # extern crate autocfg; + /// # // Normally, cargo will set `OUT_DIR` for build scripts. + /// # let exe = std::env::current_exe().unwrap(); + /// # std::env::set_var("OUT_DIR", exe.parent().unwrap()); + /// let ac = autocfg::new(); + /// let code = r#" + /// #![feature(slice_group_by)] + /// pub fn probe(slice: &[i32]) -> impl Iterator { + /// slice.group_by(|a, b| a == b) + /// } + /// "#; + /// if ac.probe_raw(code).is_ok() { + /// autocfg::emit("has_slice_group_by"); + /// } + /// ``` + pub fn probe_raw(&self, code: &str) -> Result<(), Error> { + self.probe_fmt(format_args!("{}", code)) + } + + /// Tests whether the given sysroot crate can be used. + /// + /// The test code is subject to change, but currently looks like: + /// + /// ```ignore + /// extern crate CRATE as probe; + /// ``` + pub fn probe_sysroot_crate(&self, name: &str) -> bool { + // Note: `as _` wasn't stabilized until Rust 1.33 + self.probe(format_args!("extern crate {} as probe;", name)) + } + + /// Emits a config value `has_CRATE` if `probe_sysroot_crate` returns true. + pub fn emit_sysroot_crate(&self, name: &str) { + let cfg_flag = format!("has_{}", mangle(name)); + emit_possibility(&cfg_flag); + if self.probe_sysroot_crate(name) { + emit(&cfg_flag); + } + } + + /// Tests whether the given path can be used. + /// + /// The test code is subject to change, but currently looks like: + /// + /// ```ignore + /// pub use PATH; + /// ``` + pub fn probe_path(&self, path: &str) -> bool { + self.probe(format_args!("pub use {};", path)) + } + + /// Emits a config value `has_PATH` if `probe_path` returns true. + /// + /// Any non-identifier characters in the `path` will be replaced with + /// `_` in the generated config value. + pub fn emit_has_path(&self, path: &str) { + self.emit_path_cfg(path, &format!("has_{}", mangle(path))); + } + + /// Emits the given `cfg` value if `probe_path` returns true. + pub fn emit_path_cfg(&self, path: &str, cfg: &str) { + emit_possibility(cfg); + if self.probe_path(path) { + emit(cfg); + } + } + + /// Tests whether the given trait can be used. + /// + /// The test code is subject to change, but currently looks like: + /// + /// ```ignore + /// pub trait Probe: TRAIT + Sized {} + /// ``` + pub fn probe_trait(&self, name: &str) -> bool { + self.probe(format_args!("pub trait Probe: {} + Sized {{}}", name)) + } + + /// Emits a config value `has_TRAIT` if `probe_trait` returns true. + /// + /// Any non-identifier characters in the trait `name` will be replaced with + /// `_` in the generated config value. + pub fn emit_has_trait(&self, name: &str) { + self.emit_trait_cfg(name, &format!("has_{}", mangle(name))); + } + + /// Emits the given `cfg` value if `probe_trait` returns true. + pub fn emit_trait_cfg(&self, name: &str, cfg: &str) { + emit_possibility(cfg); + if self.probe_trait(name) { + emit(cfg); + } + } + + /// Tests whether the given type can be used. + /// + /// The test code is subject to change, but currently looks like: + /// + /// ```ignore + /// pub type Probe = TYPE; + /// ``` + pub fn probe_type(&self, name: &str) -> bool { + self.probe(format_args!("pub type Probe = {};", name)) + } + + /// Emits a config value `has_TYPE` if `probe_type` returns true. + /// + /// Any non-identifier characters in the type `name` will be replaced with + /// `_` in the generated config value. + pub fn emit_has_type(&self, name: &str) { + self.emit_type_cfg(name, &format!("has_{}", mangle(name))); + } + + /// Emits the given `cfg` value if `probe_type` returns true. + pub fn emit_type_cfg(&self, name: &str, cfg: &str) { + emit_possibility(cfg); + if self.probe_type(name) { + emit(cfg); + } + } + + /// Tests whether the given expression can be used. + /// + /// The test code is subject to change, but currently looks like: + /// + /// ```ignore + /// pub fn probe() { let _ = EXPR; } + /// ``` + pub fn probe_expression(&self, expr: &str) -> bool { + self.probe(format_args!("pub fn probe() {{ let _ = {}; }}", expr)) + } + + /// Emits the given `cfg` value if `probe_expression` returns true. + pub fn emit_expression_cfg(&self, expr: &str, cfg: &str) { + emit_possibility(cfg); + if self.probe_expression(expr) { + emit(cfg); + } + } + + /// Tests whether the given constant expression can be used. + /// + /// The test code is subject to change, but currently looks like: + /// + /// ```ignore + /// pub const PROBE: () = ((), EXPR).0; + /// ``` + pub fn probe_constant(&self, expr: &str) -> bool { + self.probe(format_args!("pub const PROBE: () = ((), {}).0;", expr)) + } + + /// Emits the given `cfg` value if `probe_constant` returns true. + pub fn emit_constant_cfg(&self, expr: &str, cfg: &str) { + emit_possibility(cfg); + if self.probe_constant(expr) { + emit(cfg); + } + } +} + +fn mangle(s: &str) -> String { + s.chars() + .map(|c| match c { + 'A'...'Z' | 'a'...'z' | '0'...'9' => c, + _ => '_', + }) + .collect() +} + +fn dir_contains_target( + target: &Option, + dir: &Path, + cargo_target_dir: Option, +) -> bool { + target + .as_ref() + .and_then(|target| { + dir.to_str().and_then(|dir| { + let mut cargo_target_dir = cargo_target_dir + .map(PathBuf::from) + .unwrap_or_else(|| PathBuf::from("target")); + cargo_target_dir.push(target); + + cargo_target_dir + .to_str() + .map(|cargo_target_dir| dir.contains(cargo_target_dir)) + }) + }) + .unwrap_or(false) +} + +fn rustflags(target: &Option, dir: &Path) -> Vec { + // Starting with rust-lang/cargo#9601, shipped in Rust 1.55, Cargo always sets + // CARGO_ENCODED_RUSTFLAGS for any host/target build script invocation. This + // includes any source of flags, whether from the environment, toml config, or + // whatever may come in the future. The value is either an empty string, or a + // list of arguments separated by the ASCII unit separator (US), 0x1f. + if let Ok(a) = env::var("CARGO_ENCODED_RUSTFLAGS") { + return if a.is_empty() { + Vec::new() + } else { + a.split('\x1f').map(str::to_string).collect() + }; + } + + // Otherwise, we have to take a more heuristic approach, and we don't + // support values from toml config at all. + // + // Cargo only applies RUSTFLAGS for building TARGET artifact in + // cross-compilation environment. Sadly, we don't have a way to detect + // when we're building HOST artifact in a cross-compilation environment, + // so for now we only apply RUSTFLAGS when cross-compiling an artifact. + // + // See https://github.com/cuviper/autocfg/pull/10#issuecomment-527575030. + if *target != env::var_os("HOST") + || dir_contains_target(target, dir, env::var_os("CARGO_TARGET_DIR")) + { + if let Ok(rustflags) = env::var("RUSTFLAGS") { + // This is meant to match how cargo handles the RUSTFLAGS environment variable. + // See https://github.com/rust-lang/cargo/blob/69aea5b6f69add7c51cca939a79644080c0b0ba0/src/cargo/core/compiler/build_context/target_info.rs#L434-L441 + return rustflags + .split(' ') + .map(str::trim) + .filter(|s| !s.is_empty()) + .map(str::to_string) + .collect(); + } + } + + Vec::new() +} + +/// Generates a numeric ID to use in probe crate names. +/// +/// This attempts to be random, within the constraints of Rust 1.0 and no dependencies. +fn new_uuid() -> u64 { + const FNV_OFFSET_BASIS: u64 = 0xcbf2_9ce4_8422_2325; + const FNV_PRIME: u64 = 0x100_0000_01b3; + + // This set should have an actual random hasher. + let set: std::collections::HashSet = (0..256).collect(); + + // Feed the `HashSet`-shuffled order into FNV-1a. + let mut hash: u64 = FNV_OFFSET_BASIS; + for x in set { + hash = (hash ^ x).wrapping_mul(FNV_PRIME); + } + hash +} diff --git a/deps/crates/vendor/autocfg/src/rustc.rs b/deps/crates/vendor/autocfg/src/rustc.rs new file mode 100644 index 00000000000000..e324ed18c1f3ba --- /dev/null +++ b/deps/crates/vendor/autocfg/src/rustc.rs @@ -0,0 +1,89 @@ +use std::env; +use std::ffi::OsString; +use std::path::PathBuf; +use std::process::Command; + +use super::error::Error; +use super::version::Version; + +#[derive(Clone, Debug)] +pub struct Rustc { + rustc: PathBuf, + rustc_wrapper: Option, + rustc_workspace_wrapper: Option, +} + +impl Rustc { + pub fn new() -> Self { + Rustc { + rustc: env::var_os("RUSTC") + .unwrap_or_else(|| "rustc".into()) + .into(), + rustc_wrapper: get_rustc_wrapper(false), + rustc_workspace_wrapper: get_rustc_wrapper(true), + } + } + + /// Build the command with possible wrappers. + pub fn command(&self) -> Command { + let mut rustc = self + .rustc_wrapper + .iter() + .chain(self.rustc_workspace_wrapper.iter()) + .chain(Some(&self.rustc)); + let mut command = Command::new(rustc.next().unwrap()); + for arg in rustc { + command.arg(arg); + } + command + } + + /// Try to get the `rustc` version. + pub fn version(&self) -> Result { + // Some wrappers like clippy-driver don't pass through version commands, + // so we try to fall back to combinations without each wrapper. + macro_rules! try_version { + ($command:expr) => { + if let Ok(value) = Version::from_command($command) { + return Ok(value); + } + }; + } + + let rustc = &self.rustc; + if let Some(ref rw) = self.rustc_wrapper { + if let Some(ref rww) = self.rustc_workspace_wrapper { + try_version!(Command::new(rw).args(&[rww, rustc])); + } + try_version!(Command::new(rw).arg(rustc)); + } + if let Some(ref rww) = self.rustc_workspace_wrapper { + try_version!(Command::new(rww).arg(rustc)); + } + Version::from_command(&mut Command::new(rustc)) + } +} + +fn get_rustc_wrapper(workspace: bool) -> Option { + // We didn't really know whether the workspace wrapper is applicable until Cargo started + // deliberately setting or unsetting it in rust-lang/cargo#9601. We'll use the encoded + // rustflags as a proxy for that change for now, but we could instead check version 1.55. + if workspace && env::var_os("CARGO_ENCODED_RUSTFLAGS").is_none() { + return None; + } + + let name = if workspace { + "RUSTC_WORKSPACE_WRAPPER" + } else { + "RUSTC_WRAPPER" + }; + + if let Some(wrapper) = env::var_os(name) { + // NB: `OsStr` didn't get `len` or `is_empty` until 1.9. + if wrapper != OsString::new() { + return Some(wrapper.into()); + } + } + + None +} diff --git a/deps/crates/vendor/autocfg/src/tests.rs b/deps/crates/vendor/autocfg/src/tests.rs new file mode 100644 index 00000000000000..19188c12caa36d --- /dev/null +++ b/deps/crates/vendor/autocfg/src/tests.rs @@ -0,0 +1,54 @@ +use std::path::Path; + +#[test] +fn version_cmp() { + use super::version::Version; + let v123 = Version::new(1, 2, 3); + + assert!(Version::new(1, 0, 0) < v123); + assert!(Version::new(1, 2, 2) < v123); + assert!(Version::new(1, 2, 3) == v123); + assert!(Version::new(1, 2, 4) > v123); + assert!(Version::new(1, 10, 0) > v123); + assert!(Version::new(2, 0, 0) > v123); +} + +#[test] +fn dir_does_not_contain_target() { + assert!(!super::dir_contains_target( + &Some("x86_64-unknown-linux-gnu".into()), + Path::new("/project/target/debug/build/project-ea75983148559682/out"), + None, + )); +} + +#[test] +fn dir_does_contain_target() { + assert!(super::dir_contains_target( + &Some("x86_64-unknown-linux-gnu".into()), + Path::new( + "/project/target/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out" + ), + None, + )); +} + +#[test] +fn dir_does_not_contain_target_with_custom_target_dir() { + assert!(!super::dir_contains_target( + &Some("x86_64-unknown-linux-gnu".into()), + Path::new("/project/custom/debug/build/project-ea75983148559682/out"), + Some("custom".into()), + )); +} + +#[test] +fn dir_does_contain_target_with_custom_target_dir() { + assert!(super::dir_contains_target( + &Some("x86_64-unknown-linux-gnu".into()), + Path::new( + "/project/custom/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out" + ), + Some("custom".into()), + )); +} diff --git a/deps/crates/vendor/autocfg/src/version.rs b/deps/crates/vendor/autocfg/src/version.rs new file mode 100644 index 00000000000000..9cf5b121fe5839 --- /dev/null +++ b/deps/crates/vendor/autocfg/src/version.rs @@ -0,0 +1,65 @@ +use std::process::Command; +use std::str; + +use super::{error, Error}; + +/// A version structure for making relative comparisons. +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Version { + major: usize, + minor: usize, + patch: usize, +} + +impl Version { + /// Creates a `Version` instance for a specific `major.minor.patch` version. + pub fn new(major: usize, minor: usize, patch: usize) -> Self { + Version { + major: major, + minor: minor, + patch: patch, + } + } + + pub fn from_command(command: &mut Command) -> Result { + // Get rustc's verbose version + let output = try!(command + .args(&["--version", "--verbose"]) + .output() + .map_err(error::from_io)); + if !output.status.success() { + return Err(error::from_str("could not execute rustc")); + } + let output = try!(str::from_utf8(&output.stdout).map_err(error::from_utf8)); + + // Find the release line in the verbose version output. + let release = match output.lines().find(|line| line.starts_with("release: ")) { + Some(line) => &line["release: ".len()..], + None => return Err(error::from_str("could not find rustc release")), + }; + + // Strip off any extra channel info, e.g. "-beta.N", "-nightly" + let version = match release.find('-') { + Some(i) => &release[..i], + None => release, + }; + + // Split the version into semver components. + let mut iter = version.splitn(3, '.'); + let major = try!(iter + .next() + .ok_or_else(|| error::from_str("missing major version"))); + let minor = try!(iter + .next() + .ok_or_else(|| error::from_str("missing minor version"))); + let patch = try!(iter + .next() + .ok_or_else(|| error::from_str("missing patch version"))); + + Ok(Version::new( + try!(major.parse().map_err(error::from_num)), + try!(minor.parse().map_err(error::from_num)), + try!(patch.parse().map_err(error::from_num)), + )) + } +} diff --git a/deps/crates/vendor/autocfg/tests/no_std.rs b/deps/crates/vendor/autocfg/tests/no_std.rs new file mode 100644 index 00000000000000..05ab445af3f552 --- /dev/null +++ b/deps/crates/vendor/autocfg/tests/no_std.rs @@ -0,0 +1,28 @@ +extern crate autocfg; + +use std::env; + +mod support; + +/// Tests that we can control the use of `#![no_std]`. +#[test] +fn no_std() { + // Clear the CI `TARGET`, if any, so we're just dealing with the + // host target which always has `std` available. + env::remove_var("TARGET"); + + // Use the same path as this test binary. + let out = support::out_dir(); + + let mut ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap(); + assert!(!ac.no_std()); + assert!(ac.probe_path("std::mem")); + + // `#![no_std]` was stabilized in Rust 1.6 + if ac.probe_rustc_version(1, 6) { + ac.set_no_std(true); + assert!(ac.no_std()); + assert!(!ac.probe_path("std::mem")); + assert!(ac.probe_path("core::mem")); + } +} diff --git a/deps/crates/vendor/autocfg/tests/rustflags.rs b/deps/crates/vendor/autocfg/tests/rustflags.rs new file mode 100644 index 00000000000000..8038a0c4d51cc3 --- /dev/null +++ b/deps/crates/vendor/autocfg/tests/rustflags.rs @@ -0,0 +1,34 @@ +extern crate autocfg; + +use std::env; + +mod support; + +/// Tests that autocfg uses the RUSTFLAGS or CARGO_ENCODED_RUSTFLAGS +/// environment variables when running rustc. +#[test] +fn test_with_sysroot() { + let dir = support::exe_dir(); + let out = support::out_dir(); + + // If we have encoded rustflags, they take precedence, even if empty. + env::set_var("CARGO_ENCODED_RUSTFLAGS", ""); + env::set_var("RUSTFLAGS", &format!("-L {}", dir.display())); + let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap(); + assert!(ac.probe_sysroot_crate("std")); + assert!(!ac.probe_sysroot_crate("autocfg")); + + // Now try again with useful encoded args. + env::set_var( + "CARGO_ENCODED_RUSTFLAGS", + &format!("-L\x1f{}", dir.display()), + ); + let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap(); + assert!(ac.probe_sysroot_crate("autocfg")); + + // Try the old-style RUSTFLAGS, ensuring HOST != TARGET. + env::remove_var("CARGO_ENCODED_RUSTFLAGS"); + env::set_var("HOST", "lol"); + let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap(); + assert!(ac.probe_sysroot_crate("autocfg")); +} diff --git a/deps/crates/vendor/autocfg/tests/support/mod.rs b/deps/crates/vendor/autocfg/tests/support/mod.rs new file mode 100644 index 00000000000000..f50e7176f5e914 --- /dev/null +++ b/deps/crates/vendor/autocfg/tests/support/mod.rs @@ -0,0 +1,21 @@ +use std::borrow::Cow; +use std::env; +use std::path::{Path, PathBuf}; + +/// The directory containing this test binary. +pub fn exe_dir() -> PathBuf { + let exe = env::current_exe().unwrap(); + exe.parent().unwrap().to_path_buf() +} + +/// The directory to use for test probes. +pub fn out_dir() -> Cow<'static, Path> { + if let Some(tmpdir) = option_env!("CARGO_TARGET_TMPDIR") { + Cow::Borrowed(tmpdir.as_ref()) + } else if let Some(tmpdir) = env::var_os("TESTS_TARGET_DIR") { + Cow::Owned(tmpdir.into()) + } else { + // Use the same path as this test binary. + Cow::Owned(exe_dir()) + } +} diff --git a/deps/crates/vendor/autocfg/tests/tests.rs b/deps/crates/vendor/autocfg/tests/tests.rs new file mode 100644 index 00000000000000..bd069ee4720cf5 --- /dev/null +++ b/deps/crates/vendor/autocfg/tests/tests.rs @@ -0,0 +1,189 @@ +extern crate autocfg; + +use autocfg::AutoCfg; + +mod support; + +fn core_std(ac: &AutoCfg, path: &str) -> String { + let krate = if ac.no_std() { "core" } else { "std" }; + format!("{}::{}", krate, path) +} + +fn assert_std(ac: &AutoCfg, probe_result: bool) { + assert_eq!(!ac.no_std(), probe_result); +} + +fn assert_min(ac: &AutoCfg, major: usize, minor: usize, probe_result: bool) { + assert_eq!(ac.probe_rustc_version(major, minor), probe_result); +} + +fn autocfg_for_test() -> AutoCfg { + AutoCfg::with_dir(support::out_dir().as_ref()).unwrap() +} + +#[test] +fn autocfg_version() { + let ac = autocfg_for_test(); + assert!(ac.probe_rustc_version(1, 0)); +} + +#[test] +fn probe_add() { + let ac = autocfg_for_test(); + let add = core_std(&ac, "ops::Add"); + let add_rhs = add.clone() + ""; + let add_rhs_output = add.clone() + ""; + let dyn_add_rhs_output = "dyn ".to_string() + &*add_rhs_output; + assert!(ac.probe_path(&add)); + assert!(ac.probe_trait(&add)); + assert!(ac.probe_trait(&add_rhs)); + assert!(ac.probe_trait(&add_rhs_output)); + assert_min(&ac, 1, 27, ac.probe_type(&dyn_add_rhs_output)); +} + +#[test] +fn probe_as_ref() { + let ac = autocfg_for_test(); + let as_ref = core_std(&ac, "convert::AsRef"); + let as_ref_str = as_ref.clone() + ""; + let dyn_as_ref_str = "dyn ".to_string() + &*as_ref_str; + assert!(ac.probe_path(&as_ref)); + assert!(ac.probe_trait(&as_ref_str)); + assert!(ac.probe_type(&as_ref_str)); + assert_min(&ac, 1, 27, ac.probe_type(&dyn_as_ref_str)); +} + +#[test] +fn probe_i128() { + let ac = autocfg_for_test(); + let i128_path = core_std(&ac, "i128"); + assert_min(&ac, 1, 26, ac.probe_path(&i128_path)); + assert_min(&ac, 1, 26, ac.probe_type("i128")); +} + +#[test] +fn probe_sum() { + let ac = autocfg_for_test(); + let sum = core_std(&ac, "iter::Sum"); + let sum_i32 = sum.clone() + ""; + let dyn_sum_i32 = "dyn ".to_string() + &*sum_i32; + assert_min(&ac, 1, 12, ac.probe_path(&sum)); + assert_min(&ac, 1, 12, ac.probe_trait(&sum)); + assert_min(&ac, 1, 12, ac.probe_trait(&sum_i32)); + assert_min(&ac, 1, 12, ac.probe_type(&sum_i32)); + assert_min(&ac, 1, 27, ac.probe_type(&dyn_sum_i32)); +} + +#[test] +fn probe_std() { + let ac = autocfg_for_test(); + assert_std(&ac, ac.probe_sysroot_crate("std")); +} + +#[test] +fn probe_alloc() { + let ac = autocfg_for_test(); + assert_min(&ac, 1, 36, ac.probe_sysroot_crate("alloc")); +} + +#[test] +fn probe_bad_sysroot_crate() { + let ac = autocfg_for_test(); + assert!(!ac.probe_sysroot_crate("doesnt_exist")); +} + +#[test] +fn probe_no_std() { + let ac = autocfg_for_test(); + assert!(ac.probe_type("i32")); + assert!(ac.probe_type("[i32]")); + assert_std(&ac, ac.probe_type("Vec")); +} + +#[test] +fn probe_expression() { + let ac = autocfg_for_test(); + assert!(ac.probe_expression(r#""test".trim_left()"#)); + assert_min(&ac, 1, 30, ac.probe_expression(r#""test".trim_start()"#)); + assert_std(&ac, ac.probe_expression("[1, 2, 3].to_vec()")); +} + +#[test] +fn probe_constant() { + let ac = autocfg_for_test(); + assert!(ac.probe_constant("1 + 2 + 3")); + assert_min( + &ac, + 1, + 33, + ac.probe_constant("{ let x = 1 + 2 + 3; x * x }"), + ); + assert_min(&ac, 1, 39, ac.probe_constant(r#""test".len()"#)); +} + +#[test] +fn probe_raw() { + let ac = autocfg_for_test(); + let prefix = if ac.no_std() { "#![no_std]\n" } else { "" }; + let f = |s| format!("{}{}", prefix, s); + + // This attribute **must** be used at the crate level. + assert!(ac.probe_raw(&f("#![no_builtins]")).is_ok()); + + assert!(ac.probe_raw(&f("#![deny(dead_code)] fn x() {}")).is_err()); + assert!(ac.probe_raw(&f("#![allow(dead_code)] fn x() {}")).is_ok()); + assert!(ac + .probe_raw(&f("#![deny(dead_code)] pub fn x() {}")) + .is_ok()); +} + +#[test] +fn probe_cleanup() { + let dir = support::out_dir().join("autocfg_test_probe_cleanup"); + std::fs::create_dir(&dir).unwrap(); + + let ac = AutoCfg::with_dir(&dir).unwrap(); + assert!(ac.probe_type("i32")); + + // NB: this is not `remove_dir_all`, so it will only work if the directory + // is empty -- i.e. the probe should have removed any output files. + std::fs::remove_dir(&dir).unwrap(); +} + +#[test] +fn editions() { + let mut ac = autocfg_for_test(); + assert!(ac.edition().is_none()); + assert!(ac.probe_raw("").is_ok()); + + for (edition, minor) in vec![(2015, 27), (2018, 31), (2021, 56), (2024, 85)] { + let edition = edition.to_string(); + ac.set_edition(Some(edition.clone())); + assert_eq!(ac.edition(), Some(&*edition)); + assert_min(&ac, 1, minor, ac.probe_raw("").is_ok()); + } + + ac.set_edition(Some("invalid".into())); + assert_eq!(ac.edition(), Some("invalid")); + assert!(ac.probe_raw("").is_err()); + + ac.set_edition(None); + assert!(ac.edition().is_none()); + assert!(ac.probe_raw("").is_ok()); +} + +#[test] +fn edition_keyword_try() { + let mut ac = autocfg_for_test(); + + if ac.probe_rustc_version(1, 27) { + ac.set_edition(Some(2015.to_string())); + } + assert!(ac.probe_expression("{ let try = 0; try }")); + + if ac.probe_rustc_version(1, 31) { + ac.set_edition(Some(2018.to_string())); + assert!(!ac.probe_expression("{ let try = 0; try }")); + assert!(ac.probe_expression("{ let r#try = 0; r#try }")); + } +} diff --git a/deps/crates/vendor/autocfg/tests/wrap_ignored b/deps/crates/vendor/autocfg/tests/wrap_ignored new file mode 100755 index 00000000000000..5e577d0b26bc5f --- /dev/null +++ b/deps/crates/vendor/autocfg/tests/wrap_ignored @@ -0,0 +1,12 @@ +#!/bin/bash + +for arg in "$@"; do + case "$arg" in + # Add our own version so we can check that the wrapper is used for that. + "--version") echo "release: 12345.6789.0" ;; + # Read all input so the writer doesn't get EPIPE when we exit. + "-") read -d "" PROBE ;; + esac +done + +exit 0 diff --git a/deps/crates/vendor/autocfg/tests/wrappers.rs b/deps/crates/vendor/autocfg/tests/wrappers.rs new file mode 100644 index 00000000000000..cacca71aaede0b --- /dev/null +++ b/deps/crates/vendor/autocfg/tests/wrappers.rs @@ -0,0 +1,56 @@ +extern crate autocfg; + +use std::env; + +mod support; + +/// Tests that autocfg uses the RUSTC_WRAPPER and/or RUSTC_WORKSPACE_WRAPPER +/// environment variables when running rustc. +#[test] +#[cfg(unix)] // we're using system binaries as wrappers +fn test_wrappers() { + fn set(name: &str, value: Option) { + match value { + Some(true) => env::set_var(name, "/usr/bin/env"), + Some(false) => env::set_var(name, "/bin/false"), + None => env::remove_var(name), + } + } + + let out = support::out_dir(); + + // This is used as a heuristic to detect rust-lang/cargo#9601. + env::set_var("CARGO_ENCODED_RUSTFLAGS", ""); + + // No wrapper, a good pass-through wrapper, and a bad wrapper. + let variants = [None, Some(true), Some(false)]; + + for &workspace in &variants { + for &rustc in &variants { + set("RUSTC_WRAPPER", rustc); + set("RUSTC_WORKSPACE_WRAPPER", workspace); + + let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap(); + if rustc == Some(false) || workspace == Some(false) { + // Everything should fail with bad wrappers. + assert!(!ac.probe_type("usize")); + } else { + // Try known good and bad types for the wrapped rustc. + assert!(ac.probe_type("usize")); + assert!(!ac.probe_type("mesize")); + } + // Either way, we should have found the inner rustc version. + assert!(ac.probe_rustc_version(1, 0)); + } + } + + // Finally, make sure that `RUSTC_WRAPPER` is applied outermost + // by using something that doesn't pass through at all. + env::set_var("RUSTC_WRAPPER", "./tests/wrap_ignored"); + env::set_var("RUSTC_WORKSPACE_WRAPPER", "/bin/false"); + let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap(); + assert!(ac.probe_type("mesize")); // anything goes! + + // Make sure we also got the version from that wrapper. + assert!(ac.probe_rustc_version(12345, 6789)); +} diff --git a/deps/crates/vendor/calendrical_calculations/.cargo-checksum.json b/deps/crates/vendor/calendrical_calculations/.cargo-checksum.json new file mode 100644 index 00000000000000..852d8188cadf3f --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"64612ed43dee9fb91b5fa663ccdf144052e1a1a5a490fca524c346a8cc29dade","LICENSE":"192ea857d1bff2b87c174de36cbae5c173234726c6b8eceab9790a535d7dbc95","README.md":"cdffd3b4ab1a4efad95de0dcdf0b097fce24fedf04d076e8ab3909ac2e2accb5","src/astronomy.rs":"4c6b5cc40c9d791f6b874794218f45759bb15e022e62218c1c2b88f56a435fd2","src/chinese_based.rs":"5aff15ea2afd3c94a0aaae968ddda74ec6635ef1d5bc875d17f426c918fdd3d4","src/coptic.rs":"4ef26fbc10d7e81057f7a9876951e1a62758a7881c58dab9428dccee2e5fd25f","src/error.rs":"40dcbc44560061cfadd6f1c42ecb0c6eeb6cf8cc8f5f7bfb8a24496b0d46476d","src/ethiopian.rs":"ee85be0a7713e551d94bcf51c2029cb73c509488d3b158c798842654af960f04","src/gregorian.rs":"c2e5a86ef8d9b59d7eda557dc471d431eb248b3543d96d4447b8ea3ba893c938","src/hebrew.rs":"fd50a3ea21eb0eb9db071734df0c30ce891e08ffac9705340f50a983e911ea62","src/hebrew_keviyah.rs":"538b06690510244f6989b7955ce775baf6a2ad31915641e4a195399fe59fcf67","src/helpers.rs":"3173f8cda623121cbaba91fdfe1647342b2b5c01df6a1f9e896c6721f70c8e35","src/islamic.rs":"2ed75d8ca7f356b05160d980179a65edc383865d75a1e503195d2c9e9339ddb0","src/julian.rs":"5b18160dbb5547cfab10444f30dc284c93614407e1d144ec78eedacee8acc674","src/lib.rs":"2c9e26e99be71cc66fa64d419fbddc03859778809e2a68357aefe05e97e98b93","src/persian.rs":"bfd4dc26461999a1eeb172eaca94ff48694ccf6eebed9dc13d2612e685b6e89a","src/rata_die.rs":"e7c4ff9b460b012efa83251f49b0fbaa76244c6e9565bd16d8a552be104a8082"},"package":"3a0b39595c6ee54a8d0900204ba4c401d0ab4eb45adaf07178e8d017541529e7"} \ No newline at end of file diff --git a/deps/crates/vendor/calendrical_calculations/Cargo.toml b/deps/crates/vendor/calendrical_calculations/Cargo.toml new file mode 100644 index 00000000000000..8420b6241bc920 --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/Cargo.toml @@ -0,0 +1,77 @@ +# 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.82" +name = "calendrical_calculations" +version = "0.2.3" +authors = ["The ICU4X Project Developers"] +build = false +include = [ + "data/**/*", + "src/**/*", + "examples/**/*", + "benches/**/*", + "tests/**/*", + "Cargo.toml", + "LICENSE", + "README.md", + "build.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Calendrical calculations in Rust" +readme = "README.md" +keywords = [ + "zerocopy", + "serialization", + "zero-copy", + "serde", +] +categories = [ + "rust-patterns", + "memory-management", + "caching", + "no-std", + "data-structures", +] +license = "Apache-2.0" +repository = "https://github.com/unicode-org/icu4x" + +[package.metadata.workspaces] +independent = true + +[package.metadata.docs.rs] +all-features = true + +[features] +logging = ["dep:log"] + +[lib] +name = "calendrical_calculations" +path = "src/lib.rs" + +[dependencies.core_maths] +version = "0.1.0" +default-features = false + +[dependencies.displaydoc] +version = "0.2.3" +default-features = false + +[dependencies.log] +version = "0.4.17" +optional = true +default-features = false diff --git a/deps/crates/vendor/calendrical_calculations/LICENSE b/deps/crates/vendor/calendrical_calculations/LICENSE new file mode 100644 index 00000000000000..76b537c5e902b1 --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 The Unicode Consortium + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/deps/crates/vendor/calendrical_calculations/README.md b/deps/crates/vendor/calendrical_calculations/README.md new file mode 100644 index 00000000000000..6b2c559cff78d2 --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/README.md @@ -0,0 +1,21 @@ +# calendrical_calculations [![crates.io](https://img.shields.io/crates/v/calendrical_calculations)](https://crates.io/crates/calendrical_calculations) + + + +Calendrical calculations + +This crate implements algorithms from +Calendrical Calculations by Reingold & Dershowitz, Cambridge University Press, 4th edition (2018) +as needed by [ICU4X](https://github.com/unicode-org/icu4x). + +Most of these algorithms can be found as lisp code in the book or +[on GithHub](https://github.com/EdReingold/calendar-code2/blob/main/calendar.l). + +The primary purpose of this crate is use by ICU4X, however if non-ICU4X users need this we are happy +to add more structure to this crate as needed. + + + +## More Information + +For more information on development, authorship, contributing etc. please visit [`ICU4X home page`](https://github.com/unicode-org/icu4x). diff --git a/deps/crates/vendor/calendrical_calculations/src/astronomy.rs b/deps/crates/vendor/calendrical_calculations/src/astronomy.rs new file mode 100644 index 00000000000000..ad07dfc4afb25b --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/src/astronomy.rs @@ -0,0 +1,2631 @@ +// This file is part of ICU4X. +// +// The contents of this file implement algorithms from Calendrical Calculations +// by Reingold & Dershowitz, Cambridge University Press, 4th edition (2018), +// which have been released as Lisp code at +// under the Apache-2.0 license. Accordingly, this file is released under +// the Apache License, Version 2.0 which can be found at the calendrical_calculations +// package root or at http://www.apache.org/licenses/LICENSE-2.0. + +//! This file contains important structs and functions relating to location, +//! time, and astronomy; these are intended for calender calculations and based off +//! _Calendrical Calculations_ by Reingold & Dershowitz. + +// TODO(#3709): Address inconcistencies with existing ICU code for extreme dates. + +use crate::error::LocationOutOfBoundsError; +use crate::helpers::{binary_search, i64_to_i32, invert_angular, next_moment, poly}; +use crate::rata_die::{Moment, RataDie}; +use core::f64::consts::PI; +#[allow(unused_imports)] +use core_maths::*; + +// TODO: this isn't f64::div_euclid as defined in std. Figure out what the call sites +// mean to do. +fn div_euclid_f64(n: f64, d: f64) -> f64 { + debug_assert!(d > 0.0); + let (a, b) = (n / d, n % d); + if n >= 0.0 || b == 0.0 { + a + } else { + a - 1.0 + } +} + +#[derive(Debug, Copy, Clone, PartialEq)] +/// A Location on the Earth given as a latitude, longitude, elevation, and standard time zone. +/// Latitude is given in degrees from -90 to 90, longitude in degrees from -180 to 180, +/// elevation in meters, and zone as a UTC offset in fractional days (ex. UTC+1 would have zone = 1.0 / 24.0) +#[allow(clippy::exhaustive_structs)] // This is all that is needed by the book algorithms +pub struct Location { + /// latitude from -90 to 90 + pub(crate) latitude: f64, + /// longitude from -180 to 180 + pub(crate) longitude: f64, + /// elevation in meters + pub(crate) elevation: f64, + /// UTC timezone offset in fractional days (1 hr = 1.0 / 24.0 day) + pub(crate) utc_offset: f64, +} + +/// The mean synodic month in days of 86400 atomic seconds +/// (86400 seconds = 24 hours * 60 minutes/hour * 60 seconds/minute) +/// +/// This is defined in _Calendrical Calculations_ by Reingold & Dershowitz. +/// Reference lisp code: +pub const MEAN_SYNODIC_MONTH: f64 = 29.530588861; + +/// The Moment of noon on January 1, 2000 +pub const J2000: Moment = Moment::new(730120.5); + +/// The mean tropical year in days +/// +/// This is defined in _Calendrical Calculations_ by Reingold & Dershowitz. +/// Reference lisp code: +pub const MEAN_TROPICAL_YEAR: f64 = 365.242189; + +/// The minimum allowable UTC offset (-12 hours) in fractional days (-0.5 days) +pub const MIN_UTC_OFFSET: f64 = -0.5; + +/// The maximum allowable UTC offset (+14 hours) in fractional days (14.0 / 24.0 days) +pub const MAX_UTC_OFFSET: f64 = 14.0 / 24.0; + +/// The angle of winter for the purposes of solar calculations +pub const WINTER: f64 = 270.0; + +/// The moment of the first new moon of the CE, which occurred on January 11, 1 CE. +pub const NEW_MOON_ZERO: Moment = Moment::new(11.458922815770109); + +impl Location { + /// Create a location; latitude is from -90 to 90, and longitude is from -180 to 180; + /// attempting to create a location outside of these bounds will result in a LocationOutOfBoundsError. + #[allow(dead_code)] // TODO: Remove dead_code tag after use + pub(crate) fn try_new( + latitude: f64, + longitude: f64, + elevation: f64, + utc_offset: f64, + ) -> Result { + if !(-90.0..=90.0).contains(&latitude) { + return Err(LocationOutOfBoundsError::Latitude(latitude)); + } + if !(-180.0..=180.0).contains(&longitude) { + return Err(LocationOutOfBoundsError::Longitude(longitude)); + } + if !(MIN_UTC_OFFSET..=MAX_UTC_OFFSET).contains(&utc_offset) { + return Err(LocationOutOfBoundsError::Offset( + utc_offset, + MIN_UTC_OFFSET, + MAX_UTC_OFFSET, + )); + } + Ok(Location { + latitude, + longitude, + elevation, + utc_offset, + }) + } + + /// Get the longitude of a Location + #[allow(dead_code)] + pub(crate) fn longitude(&self) -> f64 { + self.longitude + } + + /// Get the latitude of a Location + #[allow(dead_code)] + pub(crate) fn latitude(&self) -> f64 { + self.latitude + } + + /// Get the elevation of a Location + #[allow(dead_code)] + pub(crate) fn elevation(&self) -> f64 { + self.elevation + } + + /// Get the utc-offset of a Location + #[allow(dead_code)] + pub(crate) fn zone(&self) -> f64 { + self.utc_offset + } + + /// Convert a longitude into a mean time zone; + /// this yields the difference in Moment given a longitude + /// e.g. a longitude of 90 degrees is 0.25 (90 / 360) days ahead + /// of a location with a longitude of 0 degrees. + pub(crate) fn zone_from_longitude(longitude: f64) -> f64 { + longitude / (360.0) + } + + /// Convert standard time to local mean time given a location and a time zone with given offset + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + #[allow(dead_code)] + pub(crate) fn standard_from_local(standard_time: Moment, location: Location) -> Moment { + Self::standard_from_universal( + Self::universal_from_local(standard_time, location), + location, + ) + } + + /// Convert from local mean time to universal time given a location + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub(crate) fn universal_from_local(local_time: Moment, location: Location) -> Moment { + local_time - Self::zone_from_longitude(location.longitude) + } + + /// Convert from universal time to local time given a location + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + #[allow(dead_code)] // TODO: Remove dead_code tag after use + pub(crate) fn local_from_universal(universal_time: Moment, location: Location) -> Moment { + universal_time + Self::zone_from_longitude(location.longitude) + } + + /// Given a UTC-offset in hours and a Moment in standard time, + /// return the Moment in universal time from the time zone with the given offset. + /// The field utc_offset should be within the range of possible offsets given by + /// the constand fields `MIN_UTC_OFFSET` and `MAX_UTC_OFFSET`. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub(crate) fn universal_from_standard(standard_moment: Moment, location: Location) -> Moment { + debug_assert!(location.utc_offset > MIN_UTC_OFFSET && location.utc_offset < MAX_UTC_OFFSET, "UTC offset {0} was not within the possible range of offsets (see astronomy::MIN_UTC_OFFSET and astronomy::MAX_UTC_OFFSET)", location.utc_offset); + standard_moment - location.utc_offset + } + /// Given a Moment in standard time and UTC-offset in hours, + /// return the Moment in standard time from the time zone with the given offset. + /// The field utc_offset should be within the range of possible offsets given by + /// the constand fields `MIN_UTC_OFFSET` and `MAX_UTC_OFFSET`. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + #[allow(dead_code)] + pub(crate) fn standard_from_universal(standard_time: Moment, location: Location) -> Moment { + debug_assert!(location.utc_offset > MIN_UTC_OFFSET && location.utc_offset < MAX_UTC_OFFSET, "UTC offset {0} was not within the possible range of offsets (see astronomy::MIN_UTC_OFFSET and astronomy::MAX_UTC_OFFSET)", location.utc_offset); + standard_time + location.utc_offset + } +} + +#[derive(Debug)] +/// The Astronomical struct provides functions which support astronomical +/// calculations used by many observational calendars. +#[allow(clippy::exhaustive_structs)] // only exists to collect methods +pub struct Astronomical; + +impl Astronomical { + /// Function for the ephemeris correction, which corrects the + /// somewhat-unpredictable discrepancy between dynamical time + /// and universal time + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from _Astronomical Algorithms_ by Jean Meeus (1991) with data from NASA. + /// Reference lisp code: + pub fn ephemeris_correction(moment: Moment) -> f64 { + // TODO: Change this to directly convert from moment to Gregorian year through a separate fn + let year = moment.inner() / 365.2425; + // Note: Converting to int handles negative number Euclidean division skew. + let year_int = (if year > 0.0 { year + 1.0 } else { year }) as i32; + let fixed_mid_year = crate::gregorian::fixed_from_gregorian(year_int, 7, 1); + let c = ((fixed_mid_year.to_i64_date() as f64) - 693596.0) / 36525.0; + let y2000 = (year_int - 2000) as f64; + let y1700 = (year_int - 1700) as f64; + let y1600 = (year_int - 1600) as f64; + let y1000 = ((year_int - 1000) as f64) / 100.0; + let y0 = year_int as f64 / 100.0; + let y1820 = ((year_int - 1820) as f64) / 100.0; + + if (2051..=2150).contains(&year_int) { + (-20.0 + + 32.0 * (((year_int - 1820) * (year_int - 1820)) as f64 / 10000.0) + + 0.5628 * (2150 - year_int) as f64) + / 86400.0 + } else if (2006..=2050).contains(&year_int) { + (62.92 + 0.32217 * y2000 + 0.005589 * y2000 * y2000) / 86400.0 + } else if (1987..=2005).contains(&year_int) { + // This polynomial is written out manually instead of using pow for optimization, see #3743 + (63.86 + 0.3345 * y2000 - 0.060374 * y2000 * y2000 + + 0.0017275 * y2000 * y2000 * y2000 + + 0.000651814 * y2000 * y2000 * y2000 * y2000 + + 0.00002373599 * y2000 * y2000 * y2000 * y2000 * y2000) + / 86400.0 + } else if (1900..=1986).contains(&year_int) { + // This polynomial is written out manually instead of using a fn like pow for optimization, see #3743 + -0.00002 + 0.000297 * c + 0.025184 * c * c - 0.181133 * c * c * c + + 0.553040 * c * c * c * c + - 0.861938 * c * c * c * c * c + + 0.677066 * c * c * c * c * c * c + - 0.212591 * c * c * c * c * c * c * c + } else if (1800..=1899).contains(&year_int) { + // This polynomial is written out manually instead of using a fn like pow for optimization, see #3743 + -0.000009 + + 0.003844 * c + + 0.083563 * c * c + + 0.865736 * c * c * c + + 4.867575 * c * c * c * c + + 15.845535 * c * c * c * c * c + + 31.332267 * c * c * c * c * c * c + + 38.291999 * c * c * c * c * c * c * c + + 28.316289 * c * c * c * c * c * c * c * c + + 11.636204 * c * c * c * c * c * c * c * c * c + + 2.043794 * c * c * c * c * c * c * c * c * c * c + } else if (1700..=1799).contains(&year_int) { + // This polynomial is written out manually instead of using a fn like pow for optimization, see #3743 + (8.118780842 - 0.005092142 * y1700 + 0.003336121 * y1700 * y1700 + - 0.0000266484 * y1700 * y1700 * y1700) + / 86400.0 + } else if (1600..=1699).contains(&year_int) { + // This polynomial is written out manually instead of using a fn like pow for optimization, see #3743 + (120.0 - 0.9808 * y1600 - 0.01532 * y1600 * y1600 + + 0.000140272128 * y1600 * y1600 * y1600) + / 86400.0 + } else if (500..=1599).contains(&year_int) { + // This polynomial is written out manually instead of using a fn like pow for optimization, see #3743 + (1574.2 - 556.01 * y1000 + 71.23472 * y1000 * y1000 + 0.319781 * y1000 * y1000 * y1000 + - 0.8503463 * y1000 * y1000 * y1000 * y1000 + - 0.005050998 * y1000 * y1000 * y1000 * y1000 * y1000 + + 0.0083572073 * y1000 * y1000 * y1000 * y1000 * y1000 * y1000) + / 86400.0 + } else if (-499..=499).contains(&year_int) { + // This polynomial is written out manually instead of using a fn like pow for optimization, see #3743 + (10583.6 - 1014.41 * y0 + 33.78311 * y0 * y0 + - 5.952053 * y0 * y0 * y0 + - 0.1798452 * y0 * y0 * y0 * y0 + + 0.022174192 * y0 * y0 * y0 * y0 * y0 + + 0.0090316521 * y0 * y0 * y0 * y0 * y0 * y0) + / 86400.0 + } else { + (-20.0 + 32.0 * y1820 * y1820) / 86400.0 + } + } + + /// Include the ephemeris correction to universal time, yielding dynamical time + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn dynamical_from_universal(universal: Moment) -> Moment { + // TODO: Determine correct naming scheme for "dynamical" + universal + Self::ephemeris_correction(universal) + } + + /// Remove the ephemeris correction from dynamical time, yielding universal time + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn universal_from_dynamical(dynamical: Moment) -> Moment { + // TODO: Determine correct naming scheme for "dynamical" + dynamical - Self::ephemeris_correction(dynamical) + } + + /// The number of uniform length centuries (36525 days measured in dynamical time) + /// before or after noon on January 1, 2000 + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn julian_centuries(moment: Moment) -> f64 { + let intermediate = Self::dynamical_from_universal(moment); + (intermediate - J2000) / 36525.0 + } + + /// The equation of time, which approximates the difference between apparent solar time and + /// mean time; for example, the difference between when the sun is highest in the sky (solar noon) + /// and noon as measured by a clock adjusted to the local longitude. This varies throughout the + /// year and the difference is given by the equation of time. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from _Astronomical Algorithms_ by Jean Meeus, 2nd edn., 1998, p. 185. + /// Reference lisp code: + pub fn equation_of_time(moment: Moment) -> f64 { + let c = Self::julian_centuries(moment); + let lambda = poly(c, &[280.46645, 36000.76983, 0.0003032]); + let anomaly = poly(c, &[357.52910, 35999.05030, -0.0001559, -0.00000048]); + let eccentricity = poly(c, &[0.016708617, -0.000042037, -0.0000001236]); + let varepsilon = Self::obliquity(moment); + let y = (varepsilon / 2.0).to_radians().tan(); + let y = y * y; + let equation = (y * (2.0 * lambda).to_radians().sin() + - 2.0 * eccentricity * anomaly.to_radians().sin() + + 4.0 + * eccentricity + * y + * anomaly.to_radians().sin() + * (2.0 * lambda).to_radians().cos() + - 0.5 * y * y * (4.0 * lambda).to_radians().sin() + - 1.25 * eccentricity * eccentricity * (2.0 * anomaly).to_radians().sin()) + / (2.0 * PI); + + equation.signum() * equation.abs().min(12.0 / 24.0) + } + + /// The standard time of dusk at a given location on a given date, or `None` if there is no + /// dusk on that date. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn dusk(date: f64, location: Location, alpha: f64) -> Option { + let evening = false; + let moment_of_depression = Self::moment_of_depression( + Moment::new(date + (18.0 / 24.0)), + location, + alpha, + evening, + )?; + Some(Location::standard_from_local( + moment_of_depression, + location, + )) + } + + /// Calculates the obliquity of the ecliptic at a given moment, meaning the angle of the Earth's + /// axial tilt with respect to the plane of its orbit around the sun (currently ~23.4 deg) + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn obliquity(moment: Moment) -> f64 { + let c = Self::julian_centuries(moment); + let angle = 23.0 + 26.0 / 60.0 + 21.448 / 3600.0; + let coefs = &[0.0, -46.8150 / 3600.0, -0.00059 / 3600.0, 0.001813 / 3600.0]; + angle + poly(c, coefs) + } + + /// Calculates the declination at a given [`Moment`] of UTC time of an object at ecliptic latitude `beta` and ecliptic longitude `lambda`; all angles are in degrees. + /// the declination is the angular distance north or south of an object in the sky with respect to the plane + /// of the Earth's equator; analogous to latitude. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn declination(moment: Moment, beta: f64, lambda: f64) -> f64 { + let varepsilon = Self::obliquity(moment); + (beta.to_radians().sin() * varepsilon.to_radians().cos() + + beta.to_radians().cos() * varepsilon.to_radians().sin() * lambda.to_radians().sin()) + .asin() + .to_degrees() + .rem_euclid(360.0) + } + + /// Calculates the right ascension at a given [`Moment`] of UTC time of an object at ecliptic latitude `beta` and ecliptic longitude `lambda`; all angles are in degrees. + /// the right ascension is the angular distance east or west of an object in the sky with respect to the plane + /// of the vernal equinox, which is the celestial coordinate point at which the ecliptic intersects the celestial + /// equator marking spring in the northern hemisphere; analogous to longitude. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn right_ascension(moment: Moment, beta: f64, lambda: f64) -> f64 { + let varepsilon = Self::obliquity(moment); + + let y = lambda.to_radians().sin() * varepsilon.to_radians().cos() + - beta.to_radians().tan() * varepsilon.to_radians().sin(); + let x = lambda.to_radians().cos(); + + // Arctangent of y/x in degrees, handling zero cases + y.atan2(x).to_degrees().rem_euclid(360.0) + } + + /// Local time from apparent solar time at a given location + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn local_from_apparent(moment: Moment, location: Location) -> Moment { + moment - Self::equation_of_time(Location::universal_from_local(moment, location)) + } + + /// Approx moment in local time near `moment` at which the depression angle of the sun is `alpha` (negative if + /// the sun is above the horizon) at the given location; since the same angle of depression of the sun + /// can exist twice in a day, early is set to true to specify the morning moment, and false for the + /// evening. Returns `None` if the specified angle is not reached. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn approx_moment_of_depression( + moment: Moment, + location: Location, + alpha: f64, + early: bool, /* TODO: Replace this bool with an enum with Morning and Evening, or Early and Late */ + ) -> Option { + let date = moment.as_rata_die().to_f64_date().floor(); + let alt = if alpha >= 0.0 { + if early { + date + } else { + date + 1.0 + } + } else { + date + 12.0 / 24.0 + }; + + let value = if Self::sine_offset(moment, location, alpha).abs() > 1.0 { + Self::sine_offset(Moment::new(alt), location, alpha) + } else { + Self::sine_offset(moment, location, alpha) + }; + + if value.abs() <= 1.0 { + let offset = + (value.asin().to_degrees().rem_euclid(360.0) / 360.0 + 0.5).rem_euclid(1.0) - 0.5; + + let moment = Moment::new( + date + if early { + (6.0 / 24.0) - offset + } else { + (18.0 / 24.0) + offset + }, + ); + Some(Self::local_from_apparent(moment, location)) + } else { + None + } + } + + /// Moment in local time near `approx` at which the depression angle of the sun is `alpha` (negative if + /// the sun is above the horizon) at the given location; since the same angle of depression of the sun + /// can exist twice in a day, early is set to true to specify the morning moment, and false for the + /// evening. Returns `None` if the specified angle is not reached. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn moment_of_depression( + approx: Moment, + location: Location, + alpha: f64, + early: bool, /* TODO: Replace this bool with an enum with Morning and Evening, or Early and Late */ + ) -> Option { + let moment = Self::approx_moment_of_depression(approx, location, alpha, early)?; + if (approx - moment).abs() < 30.0 { + Some(moment) + } else { + Self::moment_of_depression(moment, location, alpha, early) + } + } + + /// The angle of refraction caused by Earth's atmosphere at a given location. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn refraction(location: Location) -> f64 { + // The moment is not used. + let h = location.elevation.max(0.0); + let earth_r = 6.372e6; // Radius of Earth. + let dip = (earth_r / (earth_r + h)).acos().to_degrees(); + + (34.0 / 60.0) + dip + ((19.0 / 3600.0) * h.sqrt()) + } + + /// The moment (in universal time) of the nth new moon after + /// (or before if n is negative) the new moon of January 11, 1 CE, + /// which is the first new moon after R.D. 0. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from _Astronomical Algorithms_ by Jean Meeus, corrected 2nd edn., 2005. + /// Reference code: + pub fn nth_new_moon(n: i32) -> Moment { + // The following polynomials are written out instead of using pow for optimization, see #3743 + let n0 = 24724.0; + let k = (n as f64) - n0; + let c = k / 1236.85; + let approx = J2000 + + (5.09766 + (MEAN_SYNODIC_MONTH * 1236.85 * c) + (0.00015437 * c * c) + - (0.00000015 * c * c * c) + + (0.00000000073 * c * c * c * c)); + let e = 1.0 - (0.002516 * c) - (0.0000074 * c * c); + let solar_anomaly = + 2.5534 + (1236.85 * 29.10535670 * c) - (0.0000014 * c * c) - (0.00000011 * c * c * c); + let lunar_anomaly = 201.5643 + + (385.81693528 * 1236.85 * c) + + (0.0107582 * c * c) + + (0.00001238 * c * c * c) + - (0.000000058 * c * c * c * c); + let moon_argument = 160.7108 + (390.67050284 * 1236.85 * c) + - (0.0016118 * c * c) + - (0.00000227 * c * c * c) + + (0.000000011 * c * c * c * c); + let omega = + 124.7746 + (-1.56375588 * 1236.85 * c) + (0.0020672 * c * c) + (0.00000215 * c * c * c); + + let mut st = ( + 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, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + ); + let [v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23] = [ + -0.40720, 0.17241, 0.01608, 0.01039, 0.00739, -0.00514, 0.00208, -0.00111, -0.00057, + 0.00056, -0.00042, 0.00042, 0.00038, -0.00024, -0.00007, 0.00004, 0.00004, 0.00003, + 0.00003, -0.00003, 0.00003, -0.00002, -0.00002, 0.00002, + ]; + let [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23] = [ + 0.0, 1.0, 0.0, 0.0, -1.0, 1.0, 2.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, -1.0, 2.0, 0.0, 3.0, + 1.0, 0.0, 1.0, -1.0, -1.0, 1.0, 0.0, + ]; + let [y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15, y16, y17, y18, y19, y20, y21, y22, y23] = [ + 1.0, 0.0, 2.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 2.0, 3.0, 0.0, 0.0, 2.0, 1.0, 2.0, 0.0, + 1.0, 2.0, 1.0, 1.0, 1.0, 3.0, 4.0, + ]; + let [z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15, z16, z17, z18, z19, z20, z21, z22, z23] = [ + 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, -2.0, 2.0, 0.0, 0.0, 2.0, -2.0, 0.0, 0.0, -2.0, 0.0, + -2.0, 2.0, 2.0, 2.0, -2.0, 0.0, 0.0, + ]; + + let mut at = ( + 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, + ); + let [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] = [ + 251.88, 251.83, 349.42, 84.66, 141.74, 207.14, 154.84, 34.52, 207.19, 291.34, 161.72, + 239.56, 331.55, + ]; + let [j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12] = [ + 0.016321, 26.651886, 36.412478, 18.206239, 53.303771, 2.453732, 7.306860, 27.261239, + 0.121824, 1.844379, 24.198154, 25.513099, 3.592518, + ]; + let [l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12] = [ + 0.000165, 0.000164, 0.000126, 0.000110, 0.000062, 0.000060, 0.000056, 0.000047, + 0.000042, 0.000040, 0.000037, 0.000035, 0.000023, + ]; + + let mut correction = -0.00017 * omega.to_radians().sin(); + + // This summation is unrolled for optimization, see #3743 + st.0 = v0 + * (x0 * solar_anomaly + y0 * lunar_anomaly + z0 * moon_argument) + .to_radians() + .sin(); + st.1 = v1 + * e + * (x1 * solar_anomaly + y1 * lunar_anomaly + z1 * moon_argument) + .to_radians() + .sin(); + st.2 = v2 + * (x2 * solar_anomaly + y2 * lunar_anomaly + z2 * moon_argument) + .to_radians() + .sin(); + st.3 = v3 + * (x3 * solar_anomaly + y3 * lunar_anomaly + z3 * moon_argument) + .to_radians() + .sin(); + st.4 = v4 + * e + * (x4 * solar_anomaly + y4 * lunar_anomaly + z4 * moon_argument) + .to_radians() + .sin(); + st.5 = v5 + * e + * (x5 * solar_anomaly + y5 * lunar_anomaly + z5 * moon_argument) + .to_radians() + .sin(); + st.6 = v6 + * e + * e + * (x6 * solar_anomaly + y6 * lunar_anomaly + z6 * moon_argument) + .to_radians() + .sin(); + st.7 = v7 + * (x7 * solar_anomaly + y7 * lunar_anomaly + z7 * moon_argument) + .to_radians() + .sin(); + st.8 = v8 + * (x8 * solar_anomaly + y8 * lunar_anomaly + z8 * moon_argument) + .to_radians() + .sin(); + st.9 = v9 + * e + * (x9 * solar_anomaly + y9 * lunar_anomaly + z9 * moon_argument) + .to_radians() + .sin(); + st.10 = v10 + * (x10 * solar_anomaly + y10 * lunar_anomaly + z10 * moon_argument) + .to_radians() + .sin(); + st.11 = v11 + * e + * (x11 * solar_anomaly + y11 * lunar_anomaly + z11 * moon_argument) + .to_radians() + .sin(); + st.12 = v12 + * e + * (x12 * solar_anomaly + y12 * lunar_anomaly + z12 * moon_argument) + .to_radians() + .sin(); + st.13 = v13 + * e + * (x13 * solar_anomaly + y13 * lunar_anomaly + z13 * moon_argument) + .to_radians() + .sin(); + st.14 = v14 + * (x14 * solar_anomaly + y14 * lunar_anomaly + z14 * moon_argument) + .to_radians() + .sin(); + st.15 = v15 + * (x15 * solar_anomaly + y15 * lunar_anomaly + z15 * moon_argument) + .to_radians() + .sin(); + st.16 = v16 + * (x16 * solar_anomaly + y16 * lunar_anomaly + z16 * moon_argument) + .to_radians() + .sin(); + st.17 = v17 + * (x17 * solar_anomaly + y17 * lunar_anomaly + z17 * moon_argument) + .to_radians() + .sin(); + st.18 = v18 + * (x18 * solar_anomaly + y18 * lunar_anomaly + z18 * moon_argument) + .to_radians() + .sin(); + st.19 = v19 + * (x19 * solar_anomaly + y19 * lunar_anomaly + z19 * moon_argument) + .to_radians() + .sin(); + st.20 = v20 + * (x20 * solar_anomaly + y20 * lunar_anomaly + z20 * moon_argument) + .to_radians() + .sin(); + st.21 = v21 + * (x21 * solar_anomaly + y21 * lunar_anomaly + z21 * moon_argument) + .to_radians() + .sin(); + st.22 = v22 + * (x22 * solar_anomaly + y22 * lunar_anomaly + z22 * moon_argument) + .to_radians() + .sin(); + st.23 = v23 + * (x23 * solar_anomaly + y23 * lunar_anomaly + z23 * moon_argument) + .to_radians() + .sin(); + + let sum = st.0 + + st.1 + + st.2 + + st.3 + + st.4 + + st.5 + + st.6 + + st.7 + + st.8 + + st.9 + + st.10 + + st.11 + + st.12 + + st.13 + + st.14 + + st.15 + + st.16 + + st.17 + + st.18 + + st.19 + + st.20 + + st.21 + + st.22 + + st.23; + + correction += sum; + let extra = 0.000325 + * (299.77 + (132.8475848 * c) - (0.009173 * c * c)) + .to_radians() + .sin(); + + at.0 = l0 * (i0 + j0 * k).to_radians().sin(); + at.1 = l1 * (i1 + j1 * k).to_radians().sin(); + at.2 = l2 * (i2 + j2 * k).to_radians().sin(); + at.3 = l3 * (i3 + j3 * k).to_radians().sin(); + at.4 = l4 * (i4 + j4 * k).to_radians().sin(); + at.5 = l5 * (i5 + j5 * k).to_radians().sin(); + at.6 = l6 * (i6 + j6 * k).to_radians().sin(); + at.7 = l7 * (i7 + j7 * k).to_radians().sin(); + at.8 = l8 * (i8 + j8 * k).to_radians().sin(); + at.9 = l9 * (i9 + j9 * k).to_radians().sin(); + at.10 = l10 * (i10 + j10 * k).to_radians().sin(); + at.11 = l11 * (i11 + j11 * k).to_radians().sin(); + at.12 = l12 * (i12 + j12 * k).to_radians().sin(); + + let additional = at.0 + + at.1 + + at.2 + + at.3 + + at.4 + + at.5 + + at.6 + + at.7 + + at.8 + + at.9 + + at.10 + + at.11 + + at.12; + Self::universal_from_dynamical(approx + correction + extra + additional) + } + + /// Sidereal time, as the hour angle between the meridian and the vernal equinox, + /// from a given moment. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from _Astronomical Algorithms_ by Meeus, 2nd edition (1988), p. 88. + /// Reference lisp code: + #[allow(dead_code)] // TODO: Remove dead code tag after use + pub fn sidereal_from_moment(moment: Moment) -> f64 { + let c = (moment - J2000) / 36525.0; + let coefficients = &[ + (280.46061837), + (36525.0 * 360.98564736629), + (0.000387933), + (-1.0 / 38710000.0), + ]; + + let angle = poly(c, coefficients); + + angle.rem_euclid(360.0) + } + + /// Ecliptic (aka celestial) latitude of the moon (in degrees) + /// + /// This is not a geocentric or geodetic latitude, it does not take into account the + /// rotation of the Earth and is instead measured from the ecliptic. + /// + /// `julian_centuries` is the result of calling `Self::julian_centuries(moment)`. + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from _Astronomical Algorithms_ by Jean Meeus, 2nd edn., 1998, pp. 338-342. + /// Reference code: + pub fn lunar_latitude(julian_centuries: f64) -> f64 { + let c = julian_centuries; + let l = Self::mean_lunar_longitude(c); + let d = Self::lunar_elongation(c); + let ms = Self::solar_anomaly(c); + let ml = Self::lunar_anomaly(c); + let f = Self::moon_node(c); + let e = 1.0 - (0.002516 * c) - (0.0000074 * c * c); + + let mut ct = ( + 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, 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, 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, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + ); + + let [w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43, w44, w45, w46, w47, w48, w49, w50, w51, w52, w53, w54, w55, w56, w57, w58, w59] = [ + 0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 0.0, 2.0, 0.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 0.0, 4.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 4.0, 4.0, 0.0, 4.0, 2.0, 2.0, + 2.0, 2.0, 0.0, 2.0, 2.0, 2.0, 2.0, 4.0, 2.0, 2.0, 0.0, 2.0, 1.0, 1.0, 0.0, 2.0, 1.0, + 2.0, 0.0, 4.0, 4.0, 1.0, 4.0, 1.0, 4.0, 2.0, + ]; + + let [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59] = [ + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, -1.0, -1.0, + -1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, -1.0, -2.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 0.0, -1.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, -1.0, -2.0, + ]; + + let [y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15, y16, y17, y18, y19, y20, y21, y22, y23, y24, y25, y26, y27, y28, y29, y30, y31, y32, y33, y34, y35, y36, y37, y38, y39, y40, y41, y42, y43, y44, y45, y46, y47, y48, y49, y50, y51, y52, y53, y54, y55, y56, y57, y58, y59] = [ + 0.0, 1.0, 1.0, 0.0, -1.0, -1.0, 0.0, 2.0, 1.0, 2.0, 0.0, -2.0, 1.0, 0.0, -1.0, 0.0, + -1.0, -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 3.0, 0.0, -1.0, 1.0, -2.0, + 0.0, 2.0, 1.0, -2.0, 3.0, 2.0, -3.0, -1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, + -2.0, -1.0, 1.0, -2.0, 2.0, -2.0, -1.0, 1.0, 1.0, -1.0, 0.0, 0.0, + ]; + + let [z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15, z16, z17, z18, z19, z20, z21, z22, z23, z24, z25, z26, z27, z28, z29, z30, z31, z32, z33, z34, z35, z36, z37, z38, z39, z40, z41, z42, z43, z44, z45, z46, z47, z48, z49, z50, z51, z52, z53, z54, z55, z56, z57, z58, z59] = [ + 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, + -1.0, -1.0, -1.0, 1.0, 3.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -3.0, 1.0, + -3.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 3.0, -1.0, -1.0, 1.0, + -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, + ]; + + let [v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59] = [ + 5128122.0, 280602.0, 277693.0, 173237.0, 55413.0, 46271.0, 32573.0, 17198.0, 9266.0, + 8822.0, 8216.0, 4324.0, 4200.0, -3359.0, 2463.0, 2211.0, 2065.0, -1870.0, 1828.0, + -1794.0, -1749.0, -1565.0, -1491.0, -1475.0, -1410.0, -1344.0, -1335.0, 1107.0, 1021.0, + 833.0, 777.0, 671.0, 607.0, 596.0, 491.0, -451.0, 439.0, 422.0, 421.0, -366.0, -351.0, + 331.0, 315.0, 302.0, -283.0, -229.0, 223.0, 223.0, -220.0, -220.0, -185.0, 181.0, + -177.0, 176.0, 166.0, -164.0, 132.0, -119.0, 115.0, 107.0, + ]; + + // This summation is unrolled for optimization, see #3743 + ct.0 = v0 * (w0 * d + x0 * ms + y0 * ml + z0 * f).to_radians().sin(); + ct.1 = v1 * (w1 * d + x1 * ms + y1 * ml + z1 * f).to_radians().sin(); + ct.2 = v2 * (w2 * d + x2 * ms + y2 * ml + z2 * f).to_radians().sin(); + ct.3 = v3 * (w3 * d + x3 * ms + y3 * ml + z3 * f).to_radians().sin(); + ct.4 = v4 * (w4 * d + x4 * ms + y4 * ml + z4 * f).to_radians().sin(); + ct.5 = v5 * (w5 * d + x5 * ms + y5 * ml + z5 * f).to_radians().sin(); + ct.6 = v6 * (w6 * d + x6 * ms + y6 * ml + z6 * f).to_radians().sin(); + ct.7 = v7 * (w7 * d + x7 * ms + y7 * ml + z7 * f).to_radians().sin(); + ct.8 = v8 * (w8 * d + x8 * ms + y8 * ml + z8 * f).to_radians().sin(); + ct.9 = v9 * (w9 * d + x9 * ms + y9 * ml + z9 * f).to_radians().sin(); + ct.10 = v10 * e * (w10 * d + x10 * ms + y10 * ml + z10 * f).to_radians().sin(); + ct.11 = v11 * (w11 * d + x11 * ms + y11 * ml + z11 * f).to_radians().sin(); + ct.12 = v12 * (w12 * d + x12 * ms + y12 * ml + z12 * f).to_radians().sin(); + ct.13 = v13 * e * (w13 * d + x13 * ms + y13 * ml + z13 * f).to_radians().sin(); + ct.14 = v14 * e * (w14 * d + x14 * ms + y14 * ml + z14 * f).to_radians().sin(); + ct.15 = v15 * e * (w15 * d + x15 * ms + y15 * ml + z15 * f).to_radians().sin(); + ct.16 = v16 * e * (w16 * d + x16 * ms + y16 * ml + z16 * f).to_radians().sin(); + ct.17 = v17 * e * (w17 * d + x17 * ms + y17 * ml + z17 * f).to_radians().sin(); + ct.18 = v18 * (w18 * d + x18 * ms + y18 * ml + z18 * f).to_radians().sin(); + ct.19 = v19 * e * (w19 * d + x19 * ms + y19 * ml + z19 * f).to_radians().sin(); + ct.20 = v20 * (w20 * d + x20 * ms + y20 * ml + z20 * f).to_radians().sin(); + ct.21 = v21 * e * (w21 * d + x21 * ms + y21 * ml + z21 * f).to_radians().sin(); + ct.22 = v22 * (w22 * d + x22 * ms + y22 * ml + z22 * f).to_radians().sin(); + ct.23 = v23 * e * (w23 * d + x23 * ms + y23 * ml + z23 * f).to_radians().sin(); + ct.24 = v24 * e * (w24 * d + x24 * ms + y24 * ml + z24 * f).to_radians().sin(); + ct.25 = v25 * e * (w25 * d + x25 * ms + y25 * ml + z25 * f).to_radians().sin(); + ct.26 = v26 * (w26 * d + x26 * ms + y26 * ml + z26 * f).to_radians().sin(); + ct.27 = v27 * (w27 * d + x27 * ms + y27 * ml + z27 * f).to_radians().sin(); + ct.28 = v28 * (w28 * d + x28 * ms + y28 * ml + z28 * f).to_radians().sin(); + ct.29 = v29 * (w29 * d + x29 * ms + y29 * ml + z29 * f).to_radians().sin(); + ct.30 = v30 * (w30 * d + x30 * ms + y30 * ml + z30 * f).to_radians().sin(); + ct.31 = v31 * (w31 * d + x31 * ms + y31 * ml + z31 * f).to_radians().sin(); + ct.32 = v32 * (w32 * d + x32 * ms + y32 * ml + z32 * f).to_radians().sin(); + ct.33 = v33 * (w33 * d + x33 * ms + y33 * ml + z33 * f).to_radians().sin(); + ct.34 = v34 * e * (w34 * d + x34 * ms + y34 * ml + z34 * f).to_radians().sin(); + ct.35 = v35 * (w35 * d + x35 * ms + y35 * ml + z35 * f).to_radians().sin(); + ct.36 = v36 * (w36 * d + x36 * ms + y36 * ml + z36 * f).to_radians().sin(); + ct.37 = v37 * (w37 * d + x37 * ms + y37 * ml + z37 * f).to_radians().sin(); + ct.38 = v38 * (w38 * d + x38 * ms + y38 * ml + z38 * f).to_radians().sin(); + ct.39 = v39 * e * (w39 * d + x39 * ms + y39 * ml + z39 * f).to_radians().sin(); + ct.40 = v40 * e * (w40 * d + x40 * ms + y40 * ml + z40 * f).to_radians().sin(); + ct.41 = v41 * (w41 * d + x41 * ms + y41 * ml + z41 * f).to_radians().sin(); + ct.42 = v42 * e * (w42 * d + x42 * ms + y42 * ml + z42 * f).to_radians().sin(); + ct.43 = v43 * e * e * (w43 * d + x43 * ms + y43 * ml + z43 * f).to_radians().sin(); + ct.44 = v44 * (w44 * d + x44 * ms + y44 * ml + z44 * f).to_radians().sin(); + ct.45 = v45 * e * (w45 * d + x45 * ms + y45 * ml + z45 * f).to_radians().sin(); + ct.46 = v46 * e * (w46 * d + x46 * ms + y46 * ml + z46 * f).to_radians().sin(); + ct.47 = v47 * e * (w47 * d + x47 * ms + y47 * ml + z47 * f).to_radians().sin(); + ct.48 = v48 * e * (w48 * d + x48 * ms + y48 * ml + z48 * f).to_radians().sin(); + ct.49 = v49 * e * (w49 * d + x49 * ms + y49 * ml + z49 * f).to_radians().sin(); + ct.50 = v50 * (w50 * d + x50 * ms + y50 * ml + z50 * f).to_radians().sin(); + ct.51 = v51 * e * (w51 * d + x51 * ms + y51 * ml + z51 * f).to_radians().sin(); + ct.52 = v52 * e * (w52 * d + x52 * ms + y52 * ml + z52 * f).to_radians().sin(); + ct.53 = v53 * (w53 * d + x53 * ms + y53 * ml + z53 * f).to_radians().sin(); + ct.54 = v54 * e * (w54 * d + x54 * ms + y54 * ml + z54 * f).to_radians().sin(); + ct.55 = v55 * (w55 * d + x55 * ms + y55 * ml + z55 * f).to_radians().sin(); + ct.56 = v56 * (w56 * d + x56 * ms + y56 * ml + z56 * f).to_radians().sin(); + ct.57 = v57 * (w57 * d + x57 * ms + y57 * ml + z57 * f).to_radians().sin(); + ct.58 = v58 * e * (w58 * d + x58 * ms + y58 * ml + z58 * f).to_radians().sin(); + ct.59 = v59 * e * e * (w59 * d + x59 * ms + y59 * ml + z59 * f).to_radians().sin(); + + let mut correction = ct.0 + + ct.1 + + ct.2 + + ct.3 + + ct.4 + + ct.5 + + ct.6 + + ct.7 + + ct.8 + + ct.9 + + ct.10 + + ct.11 + + ct.12 + + ct.13 + + ct.14 + + ct.15 + + ct.16 + + ct.17 + + ct.18 + + ct.19 + + ct.20 + + ct.21 + + ct.22 + + ct.23 + + ct.24 + + ct.25 + + ct.26 + + ct.27 + + ct.28 + + ct.29 + + ct.30 + + ct.31 + + ct.32 + + ct.33 + + ct.34 + + ct.35 + + ct.36 + + ct.37 + + ct.38 + + ct.39 + + ct.40 + + ct.41 + + ct.42 + + ct.43 + + ct.44 + + ct.45 + + ct.46 + + ct.47 + + ct.48 + + ct.49 + + ct.50 + + ct.51 + + ct.52 + + ct.53 + + ct.54 + + ct.55 + + ct.56 + + ct.57 + + ct.58 + + ct.59; + + correction /= 1_000_000.0; + + let venus = (175.0 + * ((119.75 + c * 131.849 + f).to_radians().sin() + + (119.75 + c * 131.849 - f).to_radians().sin())) + / 1_000_000.0; + + let flat_earth = (-2235.0 * l.to_radians().sin() + + 127.0 * (l - ml).to_radians().sin() + + -115.0 * (l + ml).to_radians().sin()) + / 1_000_000.0; + + let extra = (382.0 * (313.45 + (c * 481266.484)).to_radians().sin()) / 1_000_000.0; + + correction + venus + flat_earth + extra + } + + /// Ecliptic (aka celestial) longitude of the moon (in degrees) + /// + /// This is not a geocentric or geodetic longitude, it does not take into account the + /// rotation of the Earth and is instead measured from the ecliptic and the vernal equinox. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from _Astronomical Algorithms_ by Jean Meeus, 2nd edn., 1998, pp. 338-342. + /// Reference code: + pub fn lunar_longitude(julian_centuries: f64) -> f64 { + let c = julian_centuries; + let l = Self::mean_lunar_longitude(c); + let d = Self::lunar_elongation(c); + let ms = Self::solar_anomaly(c); + let ml = Self::lunar_anomaly(c); + let f = Self::moon_node(c); + let e = 1.0 - (0.002516 * c) - (0.0000074 * c * c); + + let mut ct = ( + 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, 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, 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, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + ); + + let [v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58] = [ + 6288774.0, 1274027.0, 658314.0, 213618.0, -185116.0, -114332.0, 58793.0, 57066.0, + 53322.0, 45758.0, -40923.0, -34720.0, -30383.0, 15327.0, -12528.0, 10980.0, 10675.0, + 10034.0, 8548.0, -7888.0, -6766.0, -5163.0, 4987.0, 4036.0, 3994.0, 3861.0, 3665.0, + -2689.0, -2602.0, 2390.0, -2348.0, 2236.0, -2120.0, -2069.0, 2048.0, -1773.0, -1595.0, + 1215.0, -1110.0, -892.0, -810.0, 759.0, -713.0, -700.0, 691.0, 596.0, 549.0, 537.0, + 520.0, -487.0, -399.0, -381.0, 351.0, -340.0, 330.0, 327.0, -323.0, 299.0, 294.0, + ]; + let [w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43, w44, w45, w46, w47, w48, w49, w50, w51, w52, w53, w54, w55, w56, w57, w58] = [ + 0.0, 2.0, 2.0, 0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 0.0, 1.0, 0.0, 2.0, 0.0, 0.0, 4.0, + 0.0, 4.0, 2.0, 2.0, 1.0, 1.0, 2.0, 2.0, 4.0, 2.0, 0.0, 2.0, 2.0, 1.0, 2.0, 0.0, 0.0, + 2.0, 2.0, 2.0, 4.0, 0.0, 3.0, 2.0, 4.0, 0.0, 2.0, 2.0, 2.0, 4.0, 0.0, 4.0, 1.0, 2.0, + 0.0, 1.0, 3.0, 4.0, 2.0, 0.0, 1.0, 2.0, + ]; + let [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58] = [ + 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0, 0.0, -1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, -1.0, 0.0, -2.0, 1.0, 2.0, + -2.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, -1.0, 2.0, 2.0, 1.0, -1.0, 0.0, 0.0, -1.0, 0.0, + 1.0, 0.0, 1.0, 0.0, 0.0, -1.0, 2.0, 1.0, 0.0, + ]; + let [y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15, y16, y17, y18, y19, y20, y21, y22, y23, y24, y25, y26, y27, y28, y29, y30, y31, y32, y33, y34, y35, y36, y37, y38, y39, y40, y41, y42, y43, y44, y45, y46, y47, y48, y49, y50, y51, y52, y53, y54, y55, y56, y57, y58] = [ + 1.0, -1.0, 0.0, 2.0, 0.0, 0.0, -2.0, -1.0, 1.0, 0.0, -1.0, 0.0, 1.0, 0.0, 1.0, 1.0, + -1.0, 3.0, -2.0, -1.0, 0.0, -1.0, 0.0, 1.0, 2.0, 0.0, -3.0, -2.0, -1.0, -2.0, 1.0, 0.0, + 2.0, 0.0, -1.0, 1.0, 0.0, -1.0, 2.0, -1.0, 1.0, -2.0, -1.0, -1.0, -2.0, 0.0, 1.0, 4.0, + 0.0, -2.0, 0.0, 2.0, 1.0, -2.0, -3.0, 2.0, 1.0, -1.0, 3.0, + ]; + let [z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15, z16, z17, z18, z19, z20, z21, z22, z23, z24, z25, z26, z27, z28, z29, z30, z31, z32, z33, z34, z35, z36, z37, z38, z39, z40, z41, z42, z43, z44, z45, z46, z47, z48, z49, z50, z51, z52, z53, z54, z55, z56, z57, z58] = [ + 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, 2.0, -2.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, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, -2.0, 2.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, 0.0, 0.0, 0.0, 0.0, -2.0, + -2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + ]; + + // This summation is unrolled for optimization, see #3743 + ct.0 = v0 * (w0 * d + x0 * ms + y0 * ml + z0 * f).to_radians().sin(); + ct.1 = v1 * (w1 * d + x1 * ms + y1 * ml + z1 * f).to_radians().sin(); + ct.2 = v2 * (w2 * d + x2 * ms + y2 * ml + z2 * f).to_radians().sin(); + ct.3 = v3 * (w3 * d + x3 * ms + y3 * ml + z3 * f).to_radians().sin(); + ct.4 = v4 * e * (w4 * d + x4 * ms + y4 * ml + z4 * f).to_radians().sin(); + ct.5 = v5 * (w5 * d + x5 * ms + y5 * ml + z5 * f).to_radians().sin(); + ct.6 = v6 * (w6 * d + x6 * ms + y6 * ml + z6 * f).to_radians().sin(); + ct.7 = v7 * e * (w7 * d + x7 * ms + y7 * ml + z7 * f).to_radians().sin(); + ct.8 = v8 * (w8 * d + x8 * ms + y8 * ml + z8 * f).to_radians().sin(); + ct.9 = v9 * e * (w9 * d + x9 * ms + y9 * ml + z9 * f).to_radians().sin(); + ct.10 = v10 * e * (w10 * d + x10 * ms + y10 * ml + z10 * f).to_radians().sin(); + ct.11 = v11 * (w11 * d + x11 * ms + y11 * ml + z11 * f).to_radians().sin(); + ct.12 = v12 * e * (w12 * d + x12 * ms + y12 * ml + z12 * f).to_radians().sin(); + ct.13 = v13 * (w13 * d + x13 * ms + y13 * ml + z13 * f).to_radians().sin(); + ct.14 = v14 * (w14 * d + x14 * ms + y14 * ml + z14 * f).to_radians().sin(); + ct.15 = v15 * (w15 * d + x15 * ms + y15 * ml + z15 * f).to_radians().sin(); + ct.16 = v16 * (w16 * d + x16 * ms + y16 * ml + z16 * f).to_radians().sin(); + ct.17 = v17 * (w17 * d + x17 * ms + y17 * ml + z17 * f).to_radians().sin(); + ct.18 = v18 * (w18 * d + x18 * ms + y18 * ml + z18 * f).to_radians().sin(); + ct.19 = v19 * e * (w19 * d + x19 * ms + y19 * ml + z19 * f).to_radians().sin(); + ct.20 = v20 * e * (w20 * d + x20 * ms + y20 * ml + z20 * f).to_radians().sin(); + ct.21 = v21 * (w21 * d + x21 * ms + y21 * ml + z21 * f).to_radians().sin(); + ct.22 = v22 * e * (w22 * d + x22 * ms + y22 * ml + z22 * f).to_radians().sin(); + ct.23 = v23 * e * (w23 * d + x23 * ms + y23 * ml + z23 * f).to_radians().sin(); + ct.24 = v24 * (w24 * d + x24 * ms + y24 * ml + z24 * f).to_radians().sin(); + ct.25 = v25 * (w25 * d + x25 * ms + y25 * ml + z25 * f).to_radians().sin(); + ct.26 = v26 * (w26 * d + x26 * ms + y26 * ml + z26 * f).to_radians().sin(); + ct.27 = v27 * e * (w27 * d + x27 * ms + y27 * ml + z27 * f).to_radians().sin(); + ct.28 = v28 * (w28 * d + x28 * ms + y28 * ml + z28 * f).to_radians().sin(); + ct.29 = v29 * e * (w29 * d + x29 * ms + y29 * ml + z29 * f).to_radians().sin(); + ct.30 = v30 * (w30 * d + x30 * ms + y30 * ml + z30 * f).to_radians().sin(); + ct.31 = v31 * e * e * (w31 * d + x31 * ms + y31 * ml + z31 * f).to_radians().sin(); + ct.32 = v32 * e * (w32 * d + x32 * ms + y32 * ml + z32 * f).to_radians().sin(); + ct.33 = v33 * e * e * (w33 * d + x33 * ms + y33 * ml + z33 * f).to_radians().sin(); + ct.34 = v34 * e * e * (w34 * d + x34 * ms + y34 * ml + z34 * f).to_radians().sin(); + ct.35 = v35 * (w35 * d + x35 * ms + y35 * ml + z35 * f).to_radians().sin(); + ct.36 = v36 * (w36 * d + x36 * ms + y36 * ml + z36 * f).to_radians().sin(); + ct.37 = v37 * e * (w37 * d + x37 * ms + y37 * ml + z37 * f).to_radians().sin(); + ct.38 = v38 * (w38 * d + x38 * ms + y38 * ml + z38 * f).to_radians().sin(); + ct.39 = v39 * (w39 * d + x39 * ms + y39 * ml + z39 * f).to_radians().sin(); + ct.40 = v40 * e * (w40 * d + x40 * ms + y40 * ml + z40 * f).to_radians().sin(); + ct.41 = v41 * e * (w41 * d + x41 * ms + y41 * ml + z41 * f).to_radians().sin(); + ct.42 = v42 * e * e * (w42 * d + x42 * ms + y42 * ml + z42 * f).to_radians().sin(); + ct.43 = v43 * e * e * (w43 * d + x43 * ms + y43 * ml + z43 * f).to_radians().sin(); + ct.44 = v44 * e * (w44 * d + x44 * ms + y44 * ml + z44 * f).to_radians().sin(); + ct.45 = v45 * e * (w45 * d + x45 * ms + y45 * ml + z45 * f).to_radians().sin(); + ct.46 = v46 * (w46 * d + x46 * ms + y46 * ml + z46 * f).to_radians().sin(); + ct.47 = v47 * (w47 * d + x47 * ms + y47 * ml + z47 * f).to_radians().sin(); + ct.48 = v48 * e * (w48 * d + x48 * ms + y48 * ml + z48 * f).to_radians().sin(); + ct.49 = v49 * (w49 * d + x49 * ms + y49 * ml + z49 * f).to_radians().sin(); + ct.50 = v50 * e * (w50 * d + x50 * ms + y50 * ml + z50 * f).to_radians().sin(); + ct.51 = v51 * (w51 * d + x51 * ms + y51 * ml + z51 * f).to_radians().sin(); + ct.52 = v52 * e * (w52 * d + x52 * ms + y52 * ml + z52 * f).to_radians().sin(); + ct.53 = v53 * (w53 * d + x53 * ms + y53 * ml + z53 * f).to_radians().sin(); + ct.54 = v54 * (w54 * d + x54 * ms + y54 * ml + z54 * f).to_radians().sin(); + ct.55 = v55 * e * (w55 * d + x55 * ms + y55 * ml + z55 * f).to_radians().sin(); + ct.56 = v56 * e * e * (w56 * d + x56 * ms + y56 * ml + z56 * f).to_radians().sin(); + ct.57 = v57 * e * (w57 * d + x57 * ms + y57 * ml + z57 * f).to_radians().sin(); + ct.58 = v58 * (w58 * d + x58 * ms + y58 * ml + z58 * f).to_radians().sin(); + + let mut correction = ct.0 + + ct.1 + + ct.2 + + ct.3 + + ct.4 + + ct.5 + + ct.6 + + ct.7 + + ct.8 + + ct.9 + + ct.10 + + ct.11 + + ct.12 + + ct.13 + + ct.14 + + ct.15 + + ct.16 + + ct.17 + + ct.18 + + ct.19 + + ct.20 + + ct.21 + + ct.22 + + ct.23 + + ct.24 + + ct.25 + + ct.26 + + ct.27 + + ct.28 + + ct.29 + + ct.30 + + ct.31 + + ct.32 + + ct.33 + + ct.34 + + ct.35 + + ct.36 + + ct.37 + + ct.38 + + ct.39 + + ct.40 + + ct.41 + + ct.42 + + ct.43 + + ct.44 + + ct.45 + + ct.46 + + ct.47 + + ct.48 + + ct.49 + + ct.50 + + ct.51 + + ct.52 + + ct.53 + + ct.54 + + ct.55 + + ct.56 + + ct.57 + + ct.58; + + correction /= 1000000.0; + let venus = 3958.0 / 1000000.0 * (119.75 + c * 131.849).to_radians().sin(); + let jupiter = 318.0 / 1000000.0 * (53.09 + c * 479264.29).to_radians().sin(); + let flat_earth = 1962.0 / 1000000.0 * (l - f).to_radians().sin(); + (l + correction + venus + jupiter + flat_earth + Self::nutation(julian_centuries)) + .rem_euclid(360.0) + } + + /// Mean longitude of the moon (in degrees) at a given Moment in Julian centuries. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from _Astronomical Algorithms_ by Jean Meeus, 2nd edn., 1998, pp. 336-340. + /// Reference code: + fn mean_lunar_longitude(c: f64) -> f64 { + // This polynomial is written out manually instead of using a fn like pow for optimization, see #3743 + let n = 218.3164477 + + c * (481267.88123421 - 0.0015786 * c + c * c / 538841.0 - c * c * c / 65194000.0); + + n.rem_euclid(360.0) + } + + /// Closest fixed date on or after `date` on the eve of which crescent moon first became visible at `location`. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn phasis_on_or_after( + date: RataDie, + location: Location, + lunar_phase: Option, + ) -> RataDie { + let lunar_phase = + lunar_phase.unwrap_or_else(|| Self::calculate_new_moon_at_or_before(date)); + let age = date.to_f64_date() - lunar_phase; + let tau = if age <= 4.0 || Self::visible_crescent((date - 1).as_moment(), location) { + lunar_phase + 29.0 // Next new moon + } else { + date.to_f64_date() + }; + next_moment(Moment::new(tau), location, Self::visible_crescent) + } + + /// Closest fixed date on or before `date` when crescent moon first became visible at `location`. + /// Lunar phase is the result of calling `lunar_phase(moment, julian_centuries) in an earlier function. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn phasis_on_or_before( + date: RataDie, + location: Location, + lunar_phase: Option, + ) -> RataDie { + let lunar_phase = + lunar_phase.unwrap_or_else(|| Self::calculate_new_moon_at_or_before(date)); + let age = date.to_f64_date() - lunar_phase; + let tau = if age <= 3.0 && !Self::visible_crescent((date).as_moment(), location) { + lunar_phase - 30.0 // Previous new moon + } else { + lunar_phase + }; + next_moment(Moment::new(tau), location, Self::visible_crescent) + } + + /// Calculate the day that the new moon occurred on or before the given date. + pub fn calculate_new_moon_at_or_before(date: RataDie) -> f64 { + Self::lunar_phase_at_or_before(0.0, date.as_moment()) + .inner() + .floor() + } + + /// Length of the lunar month containing `date` in days, based on observability at `location`. + /// Calculates the month length for the Islamic Observational Calendar + /// Can return 31 days due to the imprecise nature of trying to approximate an observational calendar. (See page 294 of the Calendrical Calculations book) + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn month_length(date: RataDie, location: Location) -> u8 { + let moon = Self::phasis_on_or_after(date + 1, location, None); + let prev = Self::phasis_on_or_before(date, location, None); + + debug_assert!(moon > prev); + debug_assert!(moon - prev < u8::MAX.into()); + (moon - prev) as u8 + } + + /// Lunar elongation (the moon's angular distance east of the Sun) at a given Moment in Julian centuries + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from _Astronomical Algorithms_ by Jean Meeus, 2nd edn., 1998, p. 338. + /// Reference code: + fn lunar_elongation(c: f64) -> f64 { + // This polynomial is written out manually instead of using a fn like pow for optimization, see #3743 + (297.85019021 + 445267.1114034 * c - 0.0018819 * c * c + c * c * c / 545868.0 + - c * c * c * c / 113065000.0) + .rem_euclid(360.0) + } + + /// Altitude of the moon (in degrees) at a given moment + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from _Astronomical Algorithms_ by Jean Meeus, 2nd edn., 1998. + /// Lisp code reference: + pub fn lunar_altitude(moment: Moment, location: Location) -> f64 { + let phi = location.latitude; + let psi = location.longitude; + let c = Self::julian_centuries(moment); + let lambda = Self::lunar_longitude(c); + let beta = Self::lunar_latitude(c); + let alpha = Self::right_ascension(moment, beta, lambda); + let delta = Self::declination(moment, beta, lambda); + let theta0 = Self::sidereal_from_moment(moment); + let cap_h = (theta0 + psi - alpha).rem_euclid(360.0); + + let altitude = (phi.to_radians().sin() * delta.to_radians().sin() + + phi.to_radians().cos() * delta.to_radians().cos() * cap_h.to_radians().cos()) + .asin() + .to_degrees(); + + (altitude + 180.0).rem_euclid(360.0) - 180.0 + } + + /// Distance to the moon in meters at the given moment. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from _Astronomical Algorithms_ by Jean Meeus, 2nd edn., 1998, pp. 338-342. + /// Lisp code reference: + #[allow(dead_code)] + pub fn lunar_distance(moment: Moment) -> f64 { + let c = Self::julian_centuries(moment); + let cap_d = Self::lunar_elongation(c); + let cap_m = Self::solar_anomaly(c); + let cap_m_prime = Self::lunar_anomaly(c); + let cap_f = Self::moon_node(c); + let cap_e = 1.0 - (0.002516 * c) - (0.0000074 * c * c); + + let args_lunar_elongation = [ + 0.0, 2.0, 2.0, 0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 0.0, 1.0, 0.0, 2.0, 0.0, 0.0, 4.0, + 0.0, 4.0, 2.0, 2.0, 1.0, 1.0, 2.0, 2.0, 4.0, 2.0, 0.0, 2.0, 2.0, 1.0, 2.0, 0.0, 0.0, + 2.0, 2.0, 2.0, 4.0, 0.0, 3.0, 2.0, 4.0, 0.0, 2.0, 2.0, 2.0, 4.0, 0.0, 4.0, 1.0, 2.0, + 0.0, 1.0, 3.0, 4.0, 2.0, 0.0, 1.0, 2.0, 2.0, + ]; + + let args_solar_anomaly = [ + 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0, 0.0, -1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, -1.0, 0.0, -2.0, 1.0, 2.0, + -2.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, -1.0, 2.0, 2.0, 1.0, -1.0, 0.0, 0.0, -1.0, 0.0, + 1.0, 0.0, 1.0, 0.0, 0.0, -1.0, 2.0, 1.0, 0.0, 0.0, + ]; + + let args_lunar_anomaly = [ + 1.0, -1.0, 0.0, 2.0, 0.0, 0.0, -2.0, -1.0, 1.0, 0.0, -1.0, 0.0, 1.0, 0.0, 1.0, 1.0, + -1.0, 3.0, -2.0, -1.0, 0.0, -1.0, 0.0, 1.0, 2.0, 0.0, -3.0, -2.0, -1.0, -2.0, 1.0, 0.0, + 2.0, 0.0, -1.0, 1.0, 0.0, -1.0, 2.0, -1.0, 1.0, -2.0, -1.0, -1.0, -2.0, 0.0, 1.0, 4.0, + 0.0, -2.0, 0.0, 2.0, 1.0, -2.0, -3.0, 2.0, 1.0, -1.0, 3.0, -1.0, + ]; + + let args_moon_node = [ + 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, 2.0, -2.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, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, -2.0, 2.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, 0.0, 0.0, 0.0, 0.0, -2.0, + -2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.0, + ]; + + let cosine_coeff = [ + -20905355.0, + -3699111.0, + -2955968.0, + -569925.0, + 48888.0, + -3149.0, + 246158.0, + -152138.0, + -170733.0, + -204586.0, + -129620.0, + 108743.0, + 104755.0, + 10321.0, + 0.0, + 79661.0, + -34782.0, + -23210.0, + -21636.0, + 24208.0, + 30824.0, + -8379.0, + -16675.0, + -12831.0, + -10445.0, + -11650.0, + 14403.0, + -7003.0, + 0.0, + 10056.0, + 6322.0, + -9884.0, + 5751.0, + 0.0, + -4950.0, + 4130.0, + 0.0, + -3958.0, + 0.0, + 3258.0, + 2616.0, + -1897.0, + -2117.0, + 2354.0, + 0.0, + 0.0, + -1423.0, + -1117.0, + -1571.0, + -1739.0, + 0.0, + -4421.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1165.0, + 0.0, + 0.0, + 8752.0, + ]; + + let correction: f64 = cosine_coeff + .iter() + .zip(args_lunar_elongation.iter()) + .zip(args_solar_anomaly.iter()) + .zip(args_lunar_anomaly.iter()) + .zip(args_moon_node.iter()) + .map(|((((&v, &w), &x), &y), &z)| { + v * cap_e.powf(x.abs()) + * (w * cap_d + x * cap_m + y * cap_m_prime + z * cap_f) + .to_radians() + .cos() + }) + .sum(); + + 385000560.0 + correction + } + + /// The parallax of the moon, meaning the difference in angle of the direction of the moon + /// as measured from a given location and from the center of the Earth, in degrees. + /// Note: the location is encoded as the `lunar_altitude_val` which is the result of `lunar_altitude(moment,location)`. + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from _Astronomical Algorithms_ by Jean Meeus, 2nd edn., 1998. + /// Lisp code reference: + pub fn lunar_parallax(lunar_altitude_val: f64, moment: Moment) -> f64 { + let cap_delta = Self::lunar_distance(moment); + let alt = 6378140.0 / cap_delta; + let arg = alt * lunar_altitude_val.to_radians().cos(); + arg.asin().to_degrees().rem_euclid(360.0) + } + + /// Topocentric altitude of the moon. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Lisp code reference: + fn topocentric_lunar_altitude(moment: Moment, location: Location) -> f64 { + let lunar_altitude = Self::lunar_altitude(moment, location); + lunar_altitude - Self::lunar_parallax(lunar_altitude, moment) + } + + /// Observed altitude of upper limb of moon at moment at location. + /// /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Lisp code reference: + fn observed_lunar_altitude(moment: Moment, location: Location) -> f64 { + let r = Self::topocentric_lunar_altitude(moment, location); + let y = Self::refraction(location); + let z = 16.0 / 60.0; + + r + y + z + } + + /// Average anomaly of the sun (in degrees) at a given Moment in Julian centuries. + /// See: https://en.wikipedia.org/wiki/Mean_anomaly + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from _Astronomical Algorithms_ by Jean Meeus, 2nd edn., 1998, p. 338. + /// Lisp code reference: + fn solar_anomaly(c: f64) -> f64 { + // This polynomial is written out manually instead of using a fn like pow for optimization, see #3743 + (357.5291092 + 35999.0502909 * c - 0.0001536 * c * c + c * c * c / 24490000.0) + .rem_euclid(360.0) + } + + /// Average anomaly of the moon (in degrees) at a given Moment in Julian centuries + /// See: https://en.wikipedia.org/wiki/Mean_anomaly + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from _Astronomical Algorithms_ by Jean Meeus, 2nd edn., 1998, p. 338. + /// Lisp code reference: + fn lunar_anomaly(c: f64) -> f64 { + // This polynomial is written out manually instead of using a fn like pow for optimization, see #3743 + (134.9633964 + 477198.8675055 * c + 0.0087414 * c * c + c * c * c / 69699.0 + - c * c * c * c / 14712000.0) + .rem_euclid(360.0) + } + + /// The moon's argument of latitude, in degrees, at the moment given by `c` in Julian centuries. + /// The argument of latitude is used to define the position of a body moving in a Kepler orbit. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from _Astronomical Algorithms_ by Jean Meeus, 2nd edn., 1998, p. 338. + /// Lisp code reference: + fn moon_node(c: f64) -> f64 { + // This polynomial is written out manually instead of using a fn like pow for optimization, see #3743 + (93.2720950 + 483202.0175233 * c - 0.0036539 * c * c - c * c * c / 3526000.0 + + c * c * c * c / 863310000.0) + .rem_euclid(360.0) + } + + /// Standard time of moonset on the date of the given moment and at the given location. + /// Returns `None` if there is no such moonset. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Lisp code reference: + #[allow(dead_code)] // TODO: Remove dead code tag after use + fn moonset(date: Moment, location: Location) -> Option { + let moment = Location::universal_from_standard(date, location); + let waxing = Self::lunar_phase(date, Self::julian_centuries(date)) < 180.0; + let alt = Self::observed_lunar_altitude(moment, location); + let lat = location.latitude; + let offset = alt / (4.0 * (90.0 - lat.abs())); + + let approx = if waxing { + if offset > 0.0 { + moment + offset + } else { + moment + 1.0 + offset + } + } else { + moment - offset + 0.5 + }; + + let set = Moment::new(binary_search( + approx.inner() - (6.0 / 24.0), + approx.inner() + (6.0 / 24.0), + |x| Self::observed_lunar_altitude(Moment::new(x), location) < 0.0, + 1.0 / 24.0 / 60.0, + )); + + if set < moment + 1.0 { + let std = Moment::new( + Location::standard_from_universal(set, location) + .inner() + .max(date.inner()), + ); + debug_assert!(std >= date, "std should not be less than date"); + if std < date { + return None; + } + Some(std) + } else { + None + } + } + + /// Standard time of sunset on the date of the given moment and at the given location. + /// Returns `None` if there is no such sunset. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Lisp code reference: + #[allow(dead_code)] + pub fn sunset(date: Moment, location: Location) -> Option { + let alpha = Self::refraction(location) + (16.0 / 60.0); + Self::dusk(date.inner(), location, alpha) + } + + /// Time between sunset and moonset on the date of the given moment at the given location. + /// Returns `None` if there is no such sunset. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Lisp code reference: + pub fn moonlag(date: Moment, location: Location) -> Option { + if let Some(sun) = Self::sunset(date, location) { + if let Some(moon) = Self::moonset(date, location) { + Some(moon - sun) + } else { + Some(1.0) + } + } else { + None + } + } + + /// Longitudinal nutation (periodic variation in the inclination of the Earth's axis) at a given Moment. + /// Argument comes from the result of calling `Self::julian_centuries(moment)` in an earlier function. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference code: + fn nutation(julian_centuries: f64) -> f64 { + // This polynomial is written out manually instead of using a fn like pow for optimization, see #3743 + let c = julian_centuries; + let a = 124.90 - 1934.134 * c + 0.002063 * c * c; + let b = 201.11 + 72001.5377 * c + 0.00057 * c * c; + -0.004778 * a.to_radians().sin() - 0.0003667 * b.to_radians().sin() + } + + /// The phase of the moon at a given Moment, defined as the difference in longitudes + /// of the sun and the moon. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference code: + pub fn lunar_phase(moment: Moment, julian_centuries: f64) -> f64 { + let t0 = NEW_MOON_ZERO; + let maybe_n = i64_to_i32(div_euclid_f64(moment - t0, MEAN_SYNODIC_MONTH).round() as i64); + debug_assert!( + maybe_n.is_ok(), + "Lunar phase moment should be in range of i32" + ); + let n = maybe_n.unwrap_or_else(|e| e.saturate()); + let a = (Self::lunar_longitude(julian_centuries) - Self::solar_longitude(julian_centuries)) + .rem_euclid(360.0); + let b = 360.0 * ((moment - Self::nth_new_moon(n)) / MEAN_SYNODIC_MONTH).rem_euclid(1.0); + if (a - b).abs() > 180.0 { + b + } else { + a + } + } + + /// Moment in universal time of the last time at or before the given moment when the lunar phase + /// was equal to the `phase` given. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference code: + pub fn lunar_phase_at_or_before(phase: f64, moment: Moment) -> Moment { + let julian_centuries = Self::julian_centuries(moment); + let tau = moment.inner() + - (MEAN_SYNODIC_MONTH / 360.0) + * ((Self::lunar_phase(moment, julian_centuries) - phase) % 360.0); + let a = tau - 2.0; + let b = moment.inner().min(tau + 2.0); + + let lunar_phase_f64 = |x: f64| -> f64 { + Self::lunar_phase(Moment::new(x), Self::julian_centuries(Moment::new(x))) + }; + + Moment::new(invert_angular(lunar_phase_f64, phase, (a, b))) + } + + /// The longitude of the Sun at a given Moment in degrees. + /// Moment is not directly used but is enconded from the argument `julian_centuries` which is the result of calling `Self::julian_centuries(moment) in an earlier function`. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, + /// originally from "Planetary Programs and Tables from -4000 to +2800" by Bretagnon & Simon, 1986. + /// Reference code: + pub fn solar_longitude(julian_centuries: f64) -> f64 { + let c: f64 = julian_centuries; + let mut lt = ( + 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, 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, 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, 0.0, + ); + let [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48] = [ + 403406.0, 195207.0, 119433.0, 112392.0, 3891.0, 2819.0, 1721.0, 660.0, 350.0, 334.0, + 314.0, 268.0, 242.0, 234.0, 158.0, 132.0, 129.0, 114.0, 99.0, 93.0, 86.0, 78.0, 72.0, + 68.0, 64.0, 46.0, 38.0, 37.0, 32.0, 29.0, 28.0, 27.0, 27.0, 25.0, 24.0, 21.0, 21.0, + 20.0, 18.0, 17.0, 14.0, 13.0, 13.0, 13.0, 12.0, 10.0, 10.0, 10.0, 10.0, + ]; + let [y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15, y16, y17, y18, y19, y20, y21, y22, y23, y24, y25, y26, y27, y28, y29, y30, y31, y32, y33, y34, y35, y36, y37, y38, y39, y40, y41, y42, y43, y44, y45, y46, y47, y48] = [ + 270.54861, 340.19128, 63.91854, 331.26220, 317.843, 86.631, 240.052, 310.26, 247.23, + 260.87, 297.82, 343.14, 166.79, 81.53, 3.50, 132.75, 182.95, 162.03, 29.8, 266.4, + 249.2, 157.6, 257.8, 185.1, 69.9, 8.0, 197.1, 250.4, 65.3, 162.7, 341.5, 291.6, 98.5, + 146.7, 110.0, 5.2, 342.6, 230.9, 256.1, 45.3, 242.9, 115.2, 151.8, 285.3, 53.3, 126.6, + 205.7, 85.9, 146.1, + ]; + let [z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15, z16, z17, z18, z19, z20, z21, z22, z23, z24, z25, z26, z27, z28, z29, z30, z31, z32, z33, z34, z35, z36, z37, z38, z39, z40, z41, z42, z43, z44, z45, z46, z47, z48] = [ + 0.9287892, + 35999.1376958, + 35999.4089666, + 35998.7287385, + 71998.20261, + 71998.4403, + 36000.35726, + 71997.4812, + 32964.4678, + -19.4410, + 445267.1117, + 45036.8840, + 3.1008, + 22518.4434, + -19.9739, + 65928.9345, + 9038.0293, + 3034.7684, + 33718.148, + 3034.448, + -2280.773, + 29929.992, + 31556.493, + 149.588, + 9037.750, + 107997.405, + -4444.176, + 151.771, + 67555.316, + 31556.080, + -4561.540, + 107996.706, + 1221.655, + 62894.167, + 31437.369, + 14578.298, + -31931.757, + 34777.243, + 1221.999, + 62894.511, + -4442.039, + 107997.909, + 119.066, + 16859.071, + -4.578, + 26895.292, + -39.127, + 12297.536, + 90073.778, + ]; + + // This summation is unrolled for optimization, see #3743 + lt.0 = x0 * (y0 + z0 * c).to_radians().sin(); + lt.1 = x1 * (y1 + z1 * c).to_radians().sin(); + lt.2 = x2 * (y2 + z2 * c).to_radians().sin(); + lt.3 = x3 * (y3 + z3 * c).to_radians().sin(); + lt.4 = x4 * (y4 + z4 * c).to_radians().sin(); + lt.5 = x5 * (y5 + z5 * c).to_radians().sin(); + lt.6 = x6 * (y6 + z6 * c).to_radians().sin(); + lt.7 = x7 * (y7 + z7 * c).to_radians().sin(); + lt.8 = x8 * (y8 + z8 * c).to_radians().sin(); + lt.9 = x9 * (y9 + z9 * c).to_radians().sin(); + lt.10 = x10 * (y10 + z10 * c).to_radians().sin(); + lt.11 = x11 * (y11 + z11 * c).to_radians().sin(); + lt.12 = x12 * (y12 + z12 * c).to_radians().sin(); + lt.13 = x13 * (y13 + z13 * c).to_radians().sin(); + lt.14 = x14 * (y14 + z14 * c).to_radians().sin(); + lt.15 = x15 * (y15 + z15 * c).to_radians().sin(); + lt.16 = x16 * (y16 + z16 * c).to_radians().sin(); + lt.17 = x17 * (y17 + z17 * c).to_radians().sin(); + lt.18 = x18 * (y18 + z18 * c).to_radians().sin(); + lt.19 = x19 * (y19 + z19 * c).to_radians().sin(); + lt.20 = x20 * (y20 + z20 * c).to_radians().sin(); + lt.21 = x21 * (y21 + z21 * c).to_radians().sin(); + lt.22 = x22 * (y22 + z22 * c).to_radians().sin(); + lt.23 = x23 * (y23 + z23 * c).to_radians().sin(); + lt.24 = x24 * (y24 + z24 * c).to_radians().sin(); + lt.25 = x25 * (y25 + z25 * c).to_radians().sin(); + lt.26 = x26 * (y26 + z26 * c).to_radians().sin(); + lt.27 = x27 * (y27 + z27 * c).to_radians().sin(); + lt.28 = x28 * (y28 + z28 * c).to_radians().sin(); + lt.29 = x29 * (y29 + z29 * c).to_radians().sin(); + lt.30 = x30 * (y30 + z30 * c).to_radians().sin(); + lt.31 = x31 * (y31 + z31 * c).to_radians().sin(); + lt.32 = x32 * (y32 + z32 * c).to_radians().sin(); + lt.33 = x33 * (y33 + z33 * c).to_radians().sin(); + lt.34 = x34 * (y34 + z34 * c).to_radians().sin(); + lt.35 = x35 * (y35 + z35 * c).to_radians().sin(); + lt.36 = x36 * (y36 + z36 * c).to_radians().sin(); + lt.37 = x37 * (y37 + z37 * c).to_radians().sin(); + lt.38 = x38 * (y38 + z38 * c).to_radians().sin(); + lt.39 = x39 * (y39 + z39 * c).to_radians().sin(); + lt.40 = x40 * (y40 + z40 * c).to_radians().sin(); + lt.41 = x41 * (y41 + z41 * c).to_radians().sin(); + lt.42 = x42 * (y42 + z42 * c).to_radians().sin(); + lt.43 = x43 * (y43 + z43 * c).to_radians().sin(); + lt.44 = x44 * (y44 + z44 * c).to_radians().sin(); + lt.45 = x45 * (y45 + z45 * c).to_radians().sin(); + lt.46 = x46 * (y46 + z46 * c).to_radians().sin(); + lt.47 = x47 * (y47 + z47 * c).to_radians().sin(); + lt.48 = x48 * (y48 + z48 * c).to_radians().sin(); + + let mut lambda = lt.0 + + lt.1 + + lt.2 + + lt.3 + + lt.4 + + lt.5 + + lt.6 + + lt.7 + + lt.8 + + lt.9 + + lt.10 + + lt.11 + + lt.12 + + lt.13 + + lt.14 + + lt.15 + + lt.16 + + lt.17 + + lt.18 + + lt.19 + + lt.20 + + lt.21 + + lt.22 + + lt.23 + + lt.24 + + lt.25 + + lt.26 + + lt.27 + + lt.28 + + lt.29 + + lt.30 + + lt.31 + + lt.32 + + lt.33 + + lt.34 + + lt.35 + + lt.36 + + lt.37 + + lt.38 + + lt.39 + + lt.40 + + lt.41 + + lt.42 + + lt.43 + + lt.44 + + lt.45 + + lt.46 + + lt.47 + + lt.48; + lambda *= 0.000005729577951308232; + lambda += 282.7771834 + 36000.76953744 * c; + (lambda + Self::aberration(c) + Self::nutation(julian_centuries)).rem_euclid(360.0) + } + + /// The best viewing time (UT) in the evening for viewing the young moon from `location` on `date`. This is defined as + /// the time when the sun is 4.5 degrees below the horizon, or `date + 1` if there is no such time. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + fn simple_best_view(date: RataDie, location: Location) -> Moment { + let dark = Self::dusk(date.to_f64_date(), location, 4.5); + let best = dark.unwrap_or((date + 1).as_moment()); + + Location::universal_from_standard(best, location) + } + + /// Angular separation of the sun and moon at `moment`, for the purposes of determining the likely + /// visibility of the crescent moon. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + fn arc_of_light(moment: Moment) -> f64 { + let julian_centuries = Self::julian_centuries(moment); + (Self::lunar_latitude(julian_centuries).to_radians().cos() + * Self::lunar_phase(moment, julian_centuries) + .to_radians() + .cos()) + .acos() + .to_degrees() + } + + /// Criterion for likely visibility of the crescent moon on the eve of `date` at `location`, + /// not intended for high altitudes or polar regions, as defined by S.K. Shaukat. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Reference lisp code: + pub fn shaukat_criterion(date: Moment, location: Location) -> bool { + let tee = Self::simple_best_view((date - 1.0).as_rata_die(), location); + let phase = Self::lunar_phase(tee, Self::julian_centuries(tee)); + let h = Self::lunar_altitude(tee, location); + let cap_arcl = Self::arc_of_light(tee); + + let new = 0.0; + let first_quarter = 90.0; + let deg_10_6 = 10.6; + let deg_90 = 90.0; + let deg_4_1 = 4.1; + + if phase > new + && phase < first_quarter + && cap_arcl >= deg_10_6 + && cap_arcl <= deg_90 + && h > deg_4_1 + { + return true; + } + + false + } + + /// Criterion for possible visibility of crescent moon on the eve of `date` at `location`; + /// currently, this calls `shaukat_criterion`, but this can be replaced with another implementation. + pub fn visible_crescent(date: Moment, location: Location) -> bool { + Self::shaukat_criterion(date, location) + } + + /// Given an `angle` and a [`Moment`] `moment`, approximate the `Moment` at or before moment + /// at which solar longitude exceeded the given angle. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Lisp code reference: + pub fn estimate_prior_solar_longitude(angle: f64, moment: Moment) -> Moment { + let rate = MEAN_TROPICAL_YEAR / 360.0; + let julian_centuries = Self::julian_centuries(moment); + let tau = + moment - rate * (Self::solar_longitude(julian_centuries) - angle).rem_euclid(360.0); + let delta = (Self::solar_longitude(Self::julian_centuries(tau)) - angle + 180.0) + .rem_euclid(360.0) + - 180.0; + let result_rhs = tau - rate * delta; + if moment < result_rhs { + moment + } else { + result_rhs + } + } + + /// Aberration at the time given in Julian centuries. + /// See: https://sceweb.sce.uhcl.edu/helm/WEB-Positional%20Astronomy/Tutorial/Aberration/Aberration.html + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Lisp code reference: + fn aberration(c: f64) -> f64 { + // This code differs from the lisp/book code by taking in a julian centuries value instead of + // a Moment; this is because aberration is only ever called in the fn solar_longitude, which + // already converts moment to julian centuries. Thus this function takes the julian centuries + // to avoid unnecessarily calculating the same value twice. + 0.0000974 * (177.63 + 35999.01848 * c).to_radians().cos() - 0.005575 + } + + /// Find the time of the new moon preceding a given Moment (the last new moon before the moment) + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Most of the math performed in the equivalent book/lisp function is done in [`Self::num_of_new_moon_at_or_after`]. + /// Lisp code reference: + pub fn new_moon_before(moment: Moment) -> Moment { + Self::nth_new_moon(Self::num_of_new_moon_at_or_after(moment) - 1) + } + + /// Find the time of the new moon following a given Moment (the first new moon before the moment) + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Most of the math performed in the equivalent book/lisp function is done in [`Self::num_of_new_moon_at_or_after`]. + /// Lisp code reference: + pub fn new_moon_at_or_after(moment: Moment) -> Moment { + Self::nth_new_moon(Self::num_of_new_moon_at_or_after(moment)) + } + + /// Function to find the number of the new moon at or after a given moment; + /// helper function for `new_moon_before` and `new_moon_at_or_after`. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// This function incorporates code from the book/lisp equivalent functions + /// of [`Self::new_moon_before`] and [`Self::new_moon_at_or_after`]. + /// Lisp code reference: + pub fn num_of_new_moon_at_or_after(moment: Moment) -> i32 { + let t0: Moment = NEW_MOON_ZERO; + let phi = Self::lunar_phase(moment, Self::julian_centuries(moment)); + let maybe_n = i64_to_i32( + (div_euclid_f64(moment - t0, MEAN_SYNODIC_MONTH) - phi / 360.0).round() as i64, + ); + debug_assert!(maybe_n.is_ok(), "Num of new moon should be in range of i32"); + let n = maybe_n.unwrap_or_else(|e| e.saturate()); + let mut result = n; + let mut iters = 0; + let max_iters = 31; + while iters < max_iters && Self::nth_new_moon(result) < moment { + iters += 1; + result += 1; + } + result + } + + /// Sine of angle between the position of the sun at the given moment in local time and the moment + /// at which the angle of depression of the sun from the given location is equal to `alpha`. + /// + /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. + /// Lisp code reference: + pub fn sine_offset(moment: Moment, location: Location, alpha: f64) -> f64 { + let phi = location.latitude; + let tee_prime = Location::universal_from_local(moment, location); + let delta = Self::declination( + tee_prime, + 0.0, + Self::solar_longitude(Self::julian_centuries(tee_prime)), + ); + + phi.to_radians().tan() * delta.to_radians().tan() + + alpha.to_radians().sin() / (delta.to_radians().cos() * phi.to_radians().cos()) + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + // Constants applied to provide a margin of error when comparing floating-point values in tests. + const TEST_LOWER_BOUND_FACTOR: f64 = 0.9999999; + const TEST_UPPER_BOUND_FACTOR: f64 = 1.0000001; + + macro_rules! assert_eq_f64 { + ($expected_value:expr, $value:expr, $moment:expr) => { + if $expected_value > 0.0 { + assert!($value > $expected_value * TEST_LOWER_BOUND_FACTOR, + "calculation failed for the test case:\n\n\tMoment: {:?} with expected: {} and calculated: {}\n\n", + $moment, $expected_value, $value); + assert!($value < $expected_value * TEST_UPPER_BOUND_FACTOR, + "calculation failed for the test case:\n\n\tMoment: {:?} with expected: {} and calculated: {}\n\n", + $moment, $expected_value, $value); + } else { + assert!($value > $expected_value * TEST_UPPER_BOUND_FACTOR, + "calculation failed for the test case:\n\n\tMoment: {:?} with expected: {} and calculated: {}\n\n", + $moment, $expected_value, $value); + assert!($value < $expected_value * TEST_LOWER_BOUND_FACTOR, + "calculation failed for the test case:\n\n\tMoment: {:?} with expected: {} and calculated: {}\n\n", + $moment, $expected_value, $value); + } + } + } + + #[test] + // Checks that ephemeris_correction gives the same values as the lisp reference code for the given RD test cases + // (See function definition for lisp reference) + fn check_ephemeris_correction() { + let rd_vals = [ + -214193, -61387, 25469, 49217, 171307, 210155, 253427, 369740, 400085, 434355, 452605, + 470160, 473837, 507850, 524156, 544676, 567118, 569477, 601716, 613424, 626596, 645554, + 664224, 671401, 694799, 704424, 708842, 709409, 709580, 727274, 728714, 744313, 764652, + ]; + let expected_ephemeris = [ + 0.2141698518518519, + 0.14363257367091617, + 0.11444429141515931, + 0.10718320232694657, + 0.06949806372337948, + 0.05750681225096574, + 0.04475812294339828, + 0.017397257248984357, + 0.012796798891589713, + 0.008869421568656596, + 0.007262628304956149, + 0.005979700330107665, + 0.005740181544555194, + 0.0038756713829057486, + 0.0031575183970409424, + 0.0023931271439193596, + 0.0017316532690131062, + 0.0016698814624679225, + 6.150149905066665E-4, + 1.7716816592592584E-4, + 1.016458530046296E-4, + 1.7152348357870364E-4, + 1.3696411598154996E-4, + 6.153868613872005E-5, + 1.4168812498149138E-5, + 2.767107192307865E-4, + 2.9636802723679223E-4, + 3.028239003387824E-4, + 3.028239003387824E-4, + 6.75088347496296E-4, + 7.128242445629627E-4, + 9.633446296296293E-4, + 0.0029138888888888877, + ]; + for (rd, expected_ephemeris) in rd_vals.iter().zip(expected_ephemeris.iter()) { + let moment: Moment = Moment::new(*rd as f64); + let ephemeris = Astronomical::ephemeris_correction(moment); + let expected_ephemeris_value = expected_ephemeris; + assert!(ephemeris > expected_ephemeris_value * TEST_LOWER_BOUND_FACTOR, "Ephemeris correction calculation failed for the test case:\n\n\tMoment: {moment:?} with expected: {expected_ephemeris_value} and calculated: {ephemeris}\n\n"); + assert!(ephemeris < expected_ephemeris_value * TEST_UPPER_BOUND_FACTOR, "Ephemeris correction calculation failed for the test case:\n\n\tMoment: {moment:?} with expected: {expected_ephemeris_value} and calculated: {ephemeris}\n\n"); + } + } + + #[test] + // Checks that solar_longitude gives the same values as the lisp reference code for the given RD test cases + // (See function definition for lisp reference) + fn check_solar_longitude() { + let rd_vals = [ + -214193, -61387, 25469, 49217, 171307, 210155, 253427, 369740, 400085, 434355, 452605, + 470160, 473837, 507850, 524156, 544676, 567118, 569477, 601716, 613424, 626596, 645554, + 664224, 671401, 694799, 704424, 708842, 709409, 709580, 727274, 728714, 744313, 764652, + ]; + let expected_solar_long = [ + 119.47343190503307, + 254.2489611345809, + 181.43599673954304, + 188.66392267483752, + 289.0915666249348, + 59.11974154849304, + 228.31455470912624, + 34.46076992887538, + 63.18799596698955, + 2.4575913259759545, + 350.475934906397, + 13.498220866371412, + 37.403920329437824, + 81.02813003520714, + 313.86049865107634, + 19.95443016415811, + 176.05943166351062, + 344.92295174632454, + 79.96492181924987, + 99.30231774304411, + 121.53530416596914, + 88.56742889029556, + 129.289884101192, + 6.146910693067184, + 28.25199345351575, + 151.7806330331332, + 185.94586701843946, + 28.55560762159439, + 193.3478921554779, + 357.15125499424175, + 336.1706924761211, + 228.18487947607719, + 116.43935225951282, + ]; + for (rd, expected_solar_long) in rd_vals.iter().zip(expected_solar_long.iter()) { + let moment: Moment = Moment::new(*rd as f64); + let solar_long = + Astronomical::solar_longitude(Astronomical::julian_centuries(moment + 0.5)); + let expected_solar_long_value = expected_solar_long; + assert!(solar_long > expected_solar_long_value * TEST_LOWER_BOUND_FACTOR, "Solar longitude calculation failed for the test case:\n\n\tMoment: {moment:?} with expected: {expected_solar_long_value} and calculated: {solar_long}\n\n"); + assert!(solar_long < expected_solar_long_value * TEST_UPPER_BOUND_FACTOR, "Solar longitude calculation failed for the test case:\n\n\tMoment: {moment:?} with expected: {expected_solar_long_value} and calculated: {solar_long}\n\n"); + } + } + + #[test] + // Checks that lunar_latitude gives the same values as the lisp reference code for the given RD test cases + // (See function definition for lisp reference) + + fn check_lunar_latitude() { + let rd_vals = [ + -214193, -61387, 25469, 49217, 171307, 210155, 253427, 369740, 400085, 434355, 452605, + 470160, 473837, 507850, 524156, 544676, 567118, 569477, 601716, 613424, 626596, 645554, + 664224, 671401, 694799, 704424, 708842, 709409, 709580, 727274, 728714, 744313, 764652, + ]; + + let expected_lunar_lat = [ + 2.4527590208461576, + -4.90223034654341, + -2.9394693592610484, + 5.001904508580623, + -3.208909826304433, + 0.894361559890105, + -3.8633355687979827, + -2.5224444701068927, + 1.0320696124422062, + 3.005689926794408, + 1.613842956502888, + 4.766740664556875, + 4.899202930916035, + 4.838473946607273, + 2.301475724501815, + -0.8905637199828537, + 4.7657836433468495, + -2.737358003826797, + -4.035652608005429, + -3.157214517184652, + -1.8796147336498752, + -3.379519408995276, + -4.398341468078228, + 2.099198567294447, + 5.268746128633113, + -1.6722994521634027, + 4.6820126551666865, + 3.705518210116447, + 2.493964063649065, + -4.167774638752936, + -2.873757531859998, + -4.667251128743298, + 5.138562328560728, + ]; + + for (rd, expected_lunar_lat) in rd_vals.iter().zip(expected_lunar_lat.iter()) { + let moment: Moment = Moment::new(*rd as f64); + let lunar_lat = Astronomical::lunar_latitude(Astronomical::julian_centuries(moment)); + let expected_lunar_lat_value = *expected_lunar_lat; + + assert_eq_f64!(expected_lunar_lat_value, lunar_lat, moment) + } + } + + #[test] + // Checks that lunar_longitude gives the same values as the lisp reference code for the given RD test cases + // (See function definition for lisp reference) + fn check_lunar_longitude() { + let rd_vals = [ + -214193, -61387, 25469, 49217, 171307, 210155, 253427, 369740, 400085, 434355, 452605, + 470160, 473837, 507850, 524156, 544676, 567118, 569477, 601716, 613424, 626596, 645554, + 664224, 671401, 694799, 704424, 708842, 709409, 709580, 727274, 728714, 744313, 764652, + ]; + let expected_lunar_long = [ + 244.85390528515035, + 208.85673853696503, + 213.74684265158967, + 292.04624333935743, + 156.81901407583166, + 108.0556329349528, + 39.35609790324581, + 98.56585102192106, + 332.95829627335894, + 92.25965175091615, + 78.13202909213766, + 274.9469953879383, + 128.3628442664409, + 89.51845094326185, + 24.607322526832988, + 53.4859568448797, + 187.89852001941696, + 320.1723620959754, + 314.0425667275923, + 145.47406514043587, + 185.03050779751646, + 142.18913274552065, + 253.74337531953228, + 151.64868501335397, + 287.9877436469169, + 25.626707154435444, + 290.28830064619893, + 189.91314245171338, + 284.93173002623826, + 152.3390442635215, + 51.66226507971774, + 26.68206023138705, + 175.5008226195208, + ]; + for (rd, expected_lunar_long) in rd_vals.iter().zip(expected_lunar_long.iter()) { + let moment: Moment = Moment::new(*rd as f64); + let lunar_long = Astronomical::lunar_longitude(Astronomical::julian_centuries(moment)); + let expected_lunar_long_value = *expected_lunar_long; + + assert_eq_f64!(expected_lunar_long_value, lunar_long, moment) + } + } + + #[test] + fn check_lunar_altitude() { + let rd_vals = [ + -214193, -61387, 25469, 49217, 171307, 210155, 253427, 369740, 400085, 434355, 452605, + 470160, 473837, 507850, 524156, 544676, 567118, 569477, 601716, 613424, 626596, 645554, + 664224, 671401, 694799, 704424, 708842, 709409, 709580, 727274, 728714, 744313, 764652, + ]; + + let expected_altitude_deg: [f64; 33] = [ + -13.163184128188277, + -7.281425833096932, + -77.1499009115812, + -30.401178593900795, + 71.84857827681589, + -43.79857984753659, + 40.65320421851649, + -40.2787255279427, + 29.611156512065406, + -19.973178784428228, + -23.740743779700097, + 30.956688013173505, + -18.88869091014726, + -32.16116202243495, + -45.68091943596022, + -50.292110029959986, + -54.3453056090807, + -34.56600009726776, + 44.13198955291821, + -57.539862986917285, + -62.08243959461623, + -54.07209109276471, + -16.120452006695814, + 23.864594681196934, + 32.95014668614863, + 72.69165128891194, + -29.849481790038908, + 31.610644151367637, + -42.21968940776054, + 28.6478092363985, + -38.95055354031621, + 27.601977078963245, + -54.85468160086816, + ]; + + for (rd, expected_alt) in rd_vals.iter().zip(expected_altitude_deg.iter()) { + let moment: Moment = Moment::new(*rd as f64); + let lunar_alt = Astronomical::lunar_altitude(moment, crate::islamic::MECCA); + let expected_alt_value = *expected_alt; + + assert_eq_f64!(expected_alt_value, lunar_alt, moment) + } + } + + #[test] + fn check_lunar_distance() { + let rd_vals = [ + -214193, -61387, 25469, 49217, 171307, 210155, 253427, 369740, 400085, 434355, 452605, + 470160, 473837, 507850, 524156, 544676, 567118, 569477, 601716, 613424, 626596, 645554, + 664224, 671401, 694799, 704424, 708842, 709409, 709580, 727274, 728714, 744313, 764652, + ]; + + let expected_distances = [ + 387624532.22874624, + 393677431.9167689, + 402232943.80299366, + 392558548.8426357, + 366799795.8707107, + 365107305.3822873, + 401995197.0122423, + 404025417.6150537, + 377671971.8515077, + 403160628.6150732, + 375160036.9057225, + 369934038.34809774, + 402543074.28064245, + 374847147.6967837, + 403469151.42100906, + 386211365.4436033, + 385336015.6086019, + 400371744.7464432, + 395970218.00750065, + 383858113.5538787, + 389634540.7722341, + 390868707.6609328, + 368015493.693663, + 399800095.77937233, + 404273360.3039046, + 382777325.7053601, + 378047375.3350678, + 385774023.9948239, + 371763698.0990588, + 362461692.8996066, + 394214466.3812425, + 405787977.04490376, + 404202826.42484397, + ]; + + for (rd, expected_distance) in rd_vals.iter().zip(expected_distances.iter()) { + let moment: Moment = Moment::new(*rd as f64); + let distance = Astronomical::lunar_distance(moment); + let expected_distance_val = *expected_distance; + + assert_eq_f64!(expected_distance_val, distance, moment) + } + } + + #[test] + fn check_lunar_parallax() { + let rd_vals = [ + -214193, -61387, 25469, 49217, 171307, 210155, 253427, 369740, 400085, 434355, 452605, + 470160, 473837, 507850, 524156, 544676, 567118, 569477, 601716, 613424, 626596, 645554, + 664224, 671401, 694799, 704424, 708842, 709409, 709580, 727274, 728714, 744313, 764652, + ]; + + let expected_parallax = [ + 0.9180377088277034, + 0.9208275970231943, + 0.20205836298974478, + 0.8029475944705559, + 0.3103764190238057, + 0.7224552232666479, + 0.6896953754669151, + 0.6900664438899986, + 0.8412721901635796, + 0.8519504336914271, + 0.8916972264563727, + 0.8471706468502866, + 0.8589744596828851, + 0.8253387743371953, + 0.6328154405175959, + 0.60452566100182, + 0.5528114670829496, + 0.7516491660573382, + 0.6624140811593374, + 0.5109678575066725, + 0.4391324179474404, + 0.5486027633624313, + 0.9540023420545446, + 0.835939538308717, + 0.7585615249134946, + 0.284040095327141, + 0.8384425157447107, + 0.8067682261382678, + 0.7279971552035109, + 0.8848306274359499, + 0.720943806048675, + 0.7980998225232075, + 0.5204553405568378, + ]; + + for (rd, parallax) in rd_vals.iter().zip(expected_parallax.iter()) { + let moment: Moment = Moment::new(*rd as f64); + let lunar_altitude_val = Astronomical::lunar_altitude(moment, crate::islamic::MECCA); + let parallax_val = Astronomical::lunar_parallax(lunar_altitude_val, moment); + let expected_parallax_val = *parallax; + + assert_eq_f64!(expected_parallax_val, parallax_val, moment); + } + } + + #[test] + fn check_moonset() { + let rd_vals = [ + -214193.0, -61387.0, 25469.0, 49217.0, 171307.0, 210155.0, 253427.0, 369740.0, + 400085.0, 434355.0, 452605.0, 470160.0, 473837.0, 507850.0, 524156.0, 544676.0, + 567118.0, 569477.0, 601716.0, 613424.0, 626596.0, 645554.0, 664224.0, 671401.0, + 694799.0, 704424.0, 708842.0, 709409.0, 709580.0, 727274.0, 728714.0, 744313.0, + 764652.0, + ]; + + let expected_values = [ + -214192.91577491348, + -61386.372392431986, + 25469.842646633304, + 49217.03030766261, + 171307.41988615665, + 210155.96578468647, + 253427.2528524993, + 0.0, + 400085.5281194299, + 434355.0524936674, + 452605.0379962325, + 470160.4931771927, + 473837.06032208423, + 507850.8560177605, + 0.0, + 544676.908706548, + 567118.8180096536, + 569477.7141856537, + 601716.4168627897, + 613424.9325031227, + 626596.9563783304, + 645554.9526297608, + 664224.070965863, + 671401.2004198332, + 694799.4892001058, + 704424.4299627786, + 708842.0314145002, + 709409.2245215117, + 0.0, + 727274.2148254914, + 0.0, + 744313.2118589033, + 764652.9631741203, + ]; + + for (rd, expected_val) in rd_vals.iter().zip(expected_values.iter()) { + let moment: Moment = Moment::new(*rd); + let moonset_val = Astronomical::moonset(moment, crate::islamic::MECCA); + let expected_moonset_val = *expected_val; + if let Some(moonset_val) = moonset_val { + assert_eq_f64!(expected_moonset_val, moonset_val.inner(), moment); + } else { + assert_eq!(expected_moonset_val, 0.0); + } + } + } + + #[test] + fn check_sunset() { + let rd_vals = [ + -214193.0, -61387.0, 25469.0, 49217.0, 171307.0, 210155.0, 253427.0, 369740.0, + 400085.0, 434355.0, 452605.0, 470160.0, 473837.0, 507850.0, 524156.0, 544676.0, + 567118.0, 569477.0, 601716.0, 613424.0, 626596.0, 645554.0, 664224.0, 671401.0, + 694799.0, 704424.0, 708842.0, 709409.0, 709580.0, 727274.0, 728714.0, 744313.0, + 764652.0, + ]; + + let expected_values = [ + -214192.2194436165, + -61386.30267524347, + 25469.734889564967, + 49217.72851448112, + 171307.70878832813, + 210155.77420199668, + 253427.70087725233, + 369740.7627365203, + 400085.77677703864, + 434355.74808897293, + 452605.7425360138, + 470160.75310216413, + 473837.76440251875, + 507850.7840412511, + 524156.7225351998, + 544676.7561346035, + 567118.7396585084, + 569477.7396636717, + 601716.784057734, + 613424.7870863203, + 626596.781969136, + 645554.7863087669, + 664224.778132625, + 671401.7496876866, + 694799.7602310368, + 704424.7619096127, + 708842.730647343, + 709409.7603906896, + 709580.7240122546, + 727274.745361792, + 728714.734750938, + 744313.699821144, + 764652.7844809336, + ]; + + let jerusalem = Location { + latitude: 31.78, + longitude: 35.24, + elevation: 740.0, + utc_offset: (1_f64 / 12_f64), + }; + + for (rd, expected_sunset_value) in rd_vals.iter().zip(expected_values.iter()) { + let moment = Moment::new(*rd); + let sunset_value = Astronomical::sunset(moment, jerusalem).unwrap(); + let expected_sunset_val = *expected_sunset_value; + assert_eq_f64!(expected_sunset_val, sunset_value.inner(), moment) + } + } + + #[test] + // Checks that next_new_moon gives the same values as the lisp reference code for the given RD test cases + // (See function definition for lisp reference) + fn check_next_new_moon() { + let rd_vals = [ + -214193, -61387, 25469, 49217, 171307, 210155, 253427, 369740, 400085, 434355, 452605, + 470160, 473837, 507850, 524156, 544676, 567118, 569477, 601716, 613424, 626596, 645554, + 664224, 671401, 694799, 704424, 708842, 709409, 709580, 727274, 728714, 744313, 764652, + ]; + let expected_next_new_moon = [ + -214174.60582868298, + -61382.99532831192, + 25495.80977675628, + 49238.50244808781, + 171318.43531326813, + 210180.69184966758, + 253442.85936730343, + 369763.74641362444, + 400091.5783431683, + 434376.5781067696, + 452627.1919724953, + 470167.57836052414, + 473858.8532764285, + 507878.6668429224, + 524179.2470620894, + 544702.7538732041, + 567146.5131819838, + 569479.2032589674, + 601727.0335578924, + 613449.7621296605, + 626620.3698017383, + 645579.0767485882, + 664242.8867184789, + 671418.970538101, + 694807.5633711396, + 704433.4911827276, + 708863.5970001582, + 709424.4049294397, + 709602.0826867367, + 727291.2094001573, + 728737.4476913146, + 744329.5739998783, + 764676.1912733881, + ]; + for (rd, expected_next_new_moon) in rd_vals.iter().zip(expected_next_new_moon.iter()) { + let moment: Moment = Moment::new(*rd as f64); + let next_new_moon = Astronomical::new_moon_at_or_after(moment); + let expected_next_new_moon_moment = Moment::new(*expected_next_new_moon); + if *expected_next_new_moon > 0.0 { + assert!(expected_next_new_moon_moment.inner() > next_new_moon.inner() * TEST_LOWER_BOUND_FACTOR, "New moon calculation failed for the test case:\n\n\tMoment: {moment:?} with expected: {expected_next_new_moon_moment:?} and calculated: {next_new_moon:?}\n\n"); + assert!(expected_next_new_moon_moment.inner() < next_new_moon.inner() * TEST_UPPER_BOUND_FACTOR, "New moon calculation failed for the test case:\n\n\tMoment: {moment:?} with expected: {expected_next_new_moon_moment:?} and calculated: {next_new_moon:?}\n\n"); + } else { + assert!(expected_next_new_moon_moment.inner() > next_new_moon.inner() * TEST_UPPER_BOUND_FACTOR, "New moon calculation failed for the test case:\n\n\tMoment: {moment:?} with expected: {expected_next_new_moon_moment:?} and calculated: {next_new_moon:?}\n\n"); + assert!(expected_next_new_moon_moment.inner() < next_new_moon.inner() * TEST_LOWER_BOUND_FACTOR, "New moon calculation failed for the test case:\n\n\tMoment: {moment:?} with expected: {expected_next_new_moon_moment:?} and calculated: {next_new_moon:?}\n\n"); + } + } + } + + #[test] + fn check_astronomy_0th_new_moon() { + // Checks the accuracy of the 0th new moon to be on January 11th + let zeroth_new_moon = Astronomical::nth_new_moon(0); + assert_eq!( + zeroth_new_moon.inner() as i32, + 11, + "0th new moon check failed with nth_new_moon(0) = {zeroth_new_moon:?}" + ); + } + + #[test] + fn check_num_of_new_moon_0() { + // Tests the function num_of_new_moon_at_or_after() returns 0 for moment 0 + assert_eq!( + Astronomical::num_of_new_moon_at_or_after(Moment::new(0.0)), + 0 + ); + } + + #[test] + fn check_new_moon_directionality() { + // Checks that new_moon_before is less than new_moon_at_or_after for a large number of Moments + let mut moment: Moment = Moment::new(-15500.0); + let max_moment = Moment::new(15501.0); + let mut iters: i32 = 0; + let max_iters = 10000; + while iters < max_iters && moment < max_moment { + let before = Astronomical::new_moon_before(moment); + let at_or_after = Astronomical::new_moon_at_or_after(moment); + assert!(before < at_or_after, "Directionality of fns new_moon_before and new_moon_at_or_after failed for Moment: {moment:?}"); + iters += 1; + moment += 31.0; + } + assert!( + iters > 500, + "Testing failed: less than the expected number of testing iterations" + ); + assert!( + iters < max_iters, + "Testing failed: more than the expected number of testing iterations" + ); + } + + #[test] + fn check_location_valid_case() { + // Checks that location construction and functions work for various valid lats and longs + let mut long = -180.0; + let mut lat = -90.0; + let zone = 0.0; + while long <= 180.0 { + while lat <= 90.0 { + let location: Location = Location::try_new(lat, long, 1000.0, zone).unwrap(); + assert_eq!(lat, location.latitude()); + assert_eq!(long, location.longitude()); + + lat += 1.0; + } + long += 1.0; + } + } + + #[test] + fn check_location_errors() { + let lat_too_small = Location::try_new(-90.1, 15.0, 1000.0, 0.0).unwrap_err(); + assert_eq!(lat_too_small, LocationOutOfBoundsError::Latitude(-90.1)); + let lat_too_large = Location::try_new(90.1, -15.0, 1000.0, 0.0).unwrap_err(); + assert_eq!(lat_too_large, LocationOutOfBoundsError::Latitude(90.1)); + let long_too_small = Location::try_new(15.0, 180.1, 1000.0, 0.0).unwrap_err(); + assert_eq!(long_too_small, LocationOutOfBoundsError::Longitude(180.1)); + let long_too_large = Location::try_new(-15.0, -180.1, 1000.0, 0.0).unwrap_err(); + assert_eq!(long_too_large, LocationOutOfBoundsError::Longitude(-180.1)); + } + + #[test] + fn check_obliquity() { + let rd_vals = [ + -214193, -61387, 25469, 49217, 171307, 210155, 253427, 369740, 400085, 434355, 452605, + 470160, 473837, 507850, 524156, 544676, 567118, 569477, 601716, 613424, 626596, 645554, + 664224, 671401, 694799, 704424, 708842, 709409, 709580, 727274, 728714, 744313, 764652, + ]; + + let expected_obliquity_val = [ + 23.766686762858193, + 23.715893268155952, + 23.68649428364133, + 23.678396646319815, + 23.636406172247575, + 23.622930685681105, + 23.607863050353394, + 23.567099369895143, + 23.556410268115442, + 23.544315732982724, + 23.5378658942414, + 23.531656189162007, + 23.53035487913322, + 23.518307553466993, + 23.512526100422757, + 23.50524564635773, + 23.49727762748816, + 23.49643975090472, + 23.48498365949255, + 23.48082101433542, + 23.476136639530452, + 23.469392588649566, + 23.46274905945532, + 23.460194773340504, + 23.451866181318085, + 23.44843969966849, + 23.44686683973517, + 23.446664978744177, + 23.44660409993624, + 23.440304562352033, + 23.43979187336218, + 23.434238093381342, + 23.426996977623215, + ]; + + for (rd, expected_obl_val) in rd_vals.iter().zip(expected_obliquity_val.iter()) { + let moment = Moment::new(*rd as f64); + let obl_val = Astronomical::obliquity(moment); + let expected_val = *expected_obl_val; + + assert_eq_f64!(expected_val, obl_val, moment) + } + } +} diff --git a/deps/crates/vendor/calendrical_calculations/src/chinese_based.rs b/deps/crates/vendor/calendrical_calculations/src/chinese_based.rs new file mode 100644 index 00000000000000..f84d8b7a38e77f --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/src/chinese_based.rs @@ -0,0 +1,815 @@ +use crate::astronomy::{self, Astronomical, MEAN_SYNODIC_MONTH, MEAN_TROPICAL_YEAR}; +use crate::gregorian::{fixed_from_gregorian, gregorian_from_fixed}; +use crate::helpers::i64_to_i32; +use crate::rata_die::{Moment, RataDie}; +use core::num::NonZeroU8; +use core::ops::Range; +#[allow(unused_imports)] +use core_maths::*; + +// Don't iterate more than 14 times (which accounts for checking for 13 months) +const MAX_ITERS_FOR_MONTHS_OF_YEAR: u8 = 14; + +/// For astronomical calendars in this module, the range in which they are expected to be well-behaved. +/// +/// With astronomical calendars, for dates in the far past or far future, floating point error, algorithm inaccuracies, +/// and other issues may cause the calendar algorithm to behave unexpectedly. +/// +/// Our code has a number of debug assertions for various calendrical invariants (for example, lunar calendar months +/// must be 29 or 30 days), but it will turn these off outside of these ranges. +/// +/// Consumers of this code are encouraged to disallow such out-of-range values; or, if allowing them, not expect too +/// much in terms of calendrical invariants. Once we have proleptic approximations of these calendars (#5778), +/// developers will be encouraged to use them when dates are out of range. +/// +/// This value is not stable and may change. It's currently somewhat arbitrarily chosen to be +/// approximately ±10,000 years from 0 CE. +// +// NOTE: this value is doc(inline)d in islamic.rs; if you wish to change this consider if you wish to also +// change the value there, or if it should be split. +pub const WELL_BEHAVED_ASTRONOMICAL_RANGE: Range = + RataDie::new(365 * -10_000)..RataDie::new(365 * 10_000); + +/// The trait ChineseBased is used by Chinese-based calendars to perform computations shared by such calendar. +/// To do so, calendars should: +/// +/// - Implement `fn location` by providing a location at which observations of the moon are recorded, which +/// may change over time (the zone is important, long, lat, and elevation are not relevant for these calculations) +/// - Define `const EPOCH` as a `RataDie` marking the start date of the era of the Calendar for internal use, +/// which may not accurately reflect how years or eras are marked traditionally or seen by end-users +pub trait ChineseBased { + /// Given a fixed date, return the UTC offset used for observations of the new moon in order to + /// calculate the beginning of months. For multiple Chinese-based lunar calendars, this has + /// changed over the years, and can cause differences in calendar date. + fn utc_offset(fixed: RataDie) -> f64; + + /// The RataDie of the beginning of the epoch used for internal computation; this may not + /// reflect traditional methods of year-tracking or eras, since Chinese-based calendars + /// may not track years ordinally in the same way many western calendars do. + const EPOCH: RataDie; + + /// The name of the calendar for debugging. + const DEBUG_NAME: &'static str; +} + +/// Given an ISO year, return the extended year +#[deprecated(since = "0.2.3", note = "extended year calculation subject to removal")] +pub fn extended_from_iso(iso_year: i32) -> i32 { + iso_year + - const { + let Ok(y) = crate::gregorian::year_from_fixed(C::EPOCH) else { + panic!() + }; + y - 1 + } +} +/// Given an extended year, return the ISO year +#[deprecated(since = "0.2.3", note = "extended year calculation subject to removal")] +pub fn iso_from_extended(extended_year: i32) -> i32 { + extended_year + + const { + let Ok(y) = crate::gregorian::year_from_fixed(C::EPOCH) else { + panic!() + }; + y - 1 + } +} + +/// A type implementing [`ChineseBased`] for the Chinese calendar +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Default, Hash)] +#[allow(clippy::exhaustive_structs)] // newtype +pub struct Chinese; + +/// A type implementing [`ChineseBased`] for the Dangi (Korean) calendar +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Default, Hash)] +#[allow(clippy::exhaustive_structs)] // newtype +pub struct Dangi; + +impl ChineseBased for Chinese { + fn utc_offset(fixed: RataDie) -> f64 { + use crate::gregorian::fixed_from_gregorian as gregorian; + // Before 1929, local time was used, represented as UTC+(1397/180 h). + // In 1929, China adopted a standard time zone based on 120 degrees of longitude, meaning + // from 1929 onward, all new moon calculations are based on UTC+8h. + if fixed < const { gregorian(1929, 1, 1) } { + 1397.0 / 180.0 / 24.0 + } else { + 8.0 / 24.0 + } + } + + /// The equivalent first day in the Chinese calendar (based on inception of the calendar), Feb. 15, -2636 + const EPOCH: RataDie = crate::gregorian::fixed_from_gregorian(-2636, 2, 15); + const DEBUG_NAME: &'static str = "chinese"; +} + +impl ChineseBased for Dangi { + fn utc_offset(fixed: RataDie) -> f64 { + use crate::gregorian::fixed_from_gregorian as gregorian; + // Before 1908, local time was used, represented as UTC+(3809/450 h). + // This changed multiple times as different standard timezones were adopted in Korea. + // Currently, UTC+9h is used. + if fixed < const { gregorian(1908, 4, 1) } { + 3809.0 / 450.0 / 24.0 + } else if fixed < const { gregorian(1912, 1, 1) } { + 8.5 / 24.0 + } else if fixed < const { gregorian(1954, 3, 21) } { + 9.0 / 24.0 + } else if fixed < const { gregorian(1961, 8, 10) } { + 8.5 / 24.0 + } else { + 9.0 / 24.0 + } + } + + /// The first day in the Korean Dangi calendar (based on the founding of Gojoseon), lunar new year -2332 + const EPOCH: RataDie = crate::gregorian::fixed_from_gregorian(-2332, 2, 15); + const DEBUG_NAME: &'static str = "dangi"; +} + +/// Marks the bounds of a lunar year +#[derive(Debug, Copy, Clone)] +#[allow(clippy::exhaustive_structs)] // we're comfortable making frequent breaking changes to this crate +pub struct YearBounds { + /// The date marking the start of the current lunar year + pub new_year: RataDie, + /// The date marking the start of the next lunar year + pub next_new_year: RataDie, +} + +impl YearBounds { + /// Compute the YearBounds for the lunar year (年) containing `date`, + /// as well as the corresponding solar year (歲). Note that since the two + /// years overlap significantly but not entirely, the solstice bounds for the solar + /// year *may* not include `date`. + #[inline] + pub fn compute(date: RataDie) -> Self { + let prev_solstice = winter_solstice_on_or_before::(date); + let (new_year, next_solstice) = new_year_on_or_before_fixed_date::(date, prev_solstice); + // Using 400 here since new years can be up to 390 days apart, and we add some padding + let next_new_year = new_year_on_or_before_fixed_date::(new_year + 400, next_solstice).0; + + Self { + new_year, + next_new_year, + } + } + + /// The number of days in this year + pub fn count_days(self) -> u16 { + let result = self.next_new_year - self.new_year; + debug_assert!( + ((u16::MIN as i64)..=(u16::MAX as i64)).contains(&result), + "Days in year should be in range of u16." + ); + result as u16 + } + + /// Whether or not this is a leap year + pub fn is_leap(self) -> bool { + let difference = self.next_new_year - self.new_year; + difference > 365 + } +} + +/// Get the current major solar term of a fixed date, output as an integer from 1..=12. +/// +/// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. +/// Lisp reference code: https://github.com/EdReingold/calendar-code2/blob/main/calendar.l#L5273-L5281 +pub(crate) fn major_solar_term_from_fixed(date: RataDie) -> u32 { + let moment: Moment = date.as_moment(); + let universal = moment - C::utc_offset(date); + let solar_longitude = + i64_to_i32(Astronomical::solar_longitude(Astronomical::julian_centuries(universal)) as i64); + debug_assert!( + solar_longitude.is_ok(), + "Solar longitude should be in range of i32" + ); + let s = solar_longitude.unwrap_or_else(|e| e.saturate()); + let result_signed = (2 + s.div_euclid(30) - 1).rem_euclid(12) + 1; + debug_assert!(result_signed >= 0); + result_signed as u32 +} + +/// The fixed date in standard time at the observation location of the next new moon on or after a given Moment. +/// +/// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. +/// Lisp reference code: https://github.com/EdReingold/calendar-code2/blob/main/calendar.l#L5329-L5338 +pub(crate) fn new_moon_on_or_after(moment: Moment) -> RataDie { + let new_moon_moment = Astronomical::new_moon_at_or_after(midnight::(moment)); + let utc_offset = C::utc_offset(new_moon_moment.as_rata_die()); + (new_moon_moment + utc_offset).as_rata_die() +} + +/// The fixed date in standard time at the observation location of the previous new moon before a given Moment. +/// +/// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. +/// Lisp reference code: https://github.com/EdReingold/calendar-code2/blob/main/calendar.l#L5318-L5327 +pub(crate) fn new_moon_before(moment: Moment) -> RataDie { + let new_moon_moment = Astronomical::new_moon_before(midnight::(moment)); + let utc_offset = C::utc_offset(new_moon_moment.as_rata_die()); + (new_moon_moment + utc_offset).as_rata_die() +} + +/// Universal time of midnight at start of a Moment's day at the observation location +/// +/// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. +/// Lisp reference code: https://github.com/EdReingold/calendar-code2/blob/main/calendar.l#L5353-L5357 +pub(crate) fn midnight(moment: Moment) -> Moment { + moment - C::utc_offset(moment.as_rata_die()) +} + +/// Determines the fixed date of the lunar new year given the start of its corresponding solar year (歲), which is +/// also the winter solstice +/// +/// Calls to `no_major_solar_term` have been inlined for increased efficiency. +/// +/// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. +/// Lisp reference code: https://github.com/EdReingold/calendar-code2/blob/main/calendar.l#L5370-L5394 +pub(crate) fn new_year_in_sui(prior_solstice: RataDie) -> (RataDie, RataDie) { + // s1 is prior_solstice + // Using 370 here since solstices are ~365 days apart + // Both solstices should fall on December 20, 21, 22, or 23. The calendrical calculations + // drift away from this for large positive and negative years, so we artifically bind them + // to this range in order for other code invariants to be upheld. + let prior_solstice = bind_winter_solstice::(prior_solstice); + let following_solstice = + bind_winter_solstice::(winter_solstice_on_or_before::(prior_solstice + 370)); // s2 + let month_after_eleventh = new_moon_on_or_after::((prior_solstice + 1).as_moment()); // m12 + debug_assert!( + month_after_eleventh - prior_solstice >= 0 + || !WELL_BEHAVED_ASTRONOMICAL_RANGE.contains(&prior_solstice) + ); + let month_after_twelfth = new_moon_on_or_after::((month_after_eleventh + 1).as_moment()); // m13 + let month_after_thirteenth = new_moon_on_or_after::((month_after_twelfth + 1).as_moment()); + debug_assert!( + month_after_twelfth - month_after_eleventh >= 29 + || !WELL_BEHAVED_ASTRONOMICAL_RANGE.contains(&prior_solstice) + ); + let next_eleventh_month = new_moon_before::((following_solstice + 1).as_moment()); // next-m11 + let lhs_argument = + ((next_eleventh_month - month_after_eleventh) as f64 / MEAN_SYNODIC_MONTH).round() as i64; + let solar_term_a = major_solar_term_from_fixed::(month_after_eleventh); + let solar_term_b = major_solar_term_from_fixed::(month_after_twelfth); + let solar_term_c = major_solar_term_from_fixed::(month_after_thirteenth); + if lhs_argument == 12 && (solar_term_a == solar_term_b || solar_term_b == solar_term_c) { + (month_after_thirteenth, following_solstice) + } else { + (month_after_twelfth, following_solstice) + } +} + +/// This function forces the RataDie to be on December 20, 21, 22, or 23. It was +/// created for practical considerations and is not in the text. +/// +/// See: +fn bind_winter_solstice(solstice: RataDie) -> RataDie { + let (gregorian_year, gregorian_month, gregorian_day) = match gregorian_from_fixed(solstice) { + Ok(ymd) => ymd, + Err(_) => { + debug_assert!(false, "Solstice REALLY out of bounds: {solstice:?}"); + return solstice; + } + }; + let resolved_solstice = if gregorian_month < 12 || gregorian_day < 20 { + fixed_from_gregorian(gregorian_year, 12, 20) + } else if gregorian_day > 23 { + fixed_from_gregorian(gregorian_year, 12, 23) + } else { + solstice + }; + if resolved_solstice != solstice { + if !(0..=4000).contains(&gregorian_year) { + #[cfg(feature = "logging")] + log::trace!("({}) Solstice out of bounds: {solstice:?}", C::DEBUG_NAME); + } else { + debug_assert!( + false, + "({}) Solstice out of bounds: {solstice:?}", + C::DEBUG_NAME + ); + } + } + resolved_solstice +} + +/// Get the fixed date of the nearest winter solstice, in the Chinese time zone, +/// on or before a given fixed date. +/// +/// This is valid for several thousand years, but it drifts for large positive +/// and negative years. See [`bind_winter_solstice`]. +/// +/// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. +/// Lisp reference code: https://github.com/EdReingold/calendar-code2/blob/main/calendar.l#L5359-L5368 +pub(crate) fn winter_solstice_on_or_before(date: RataDie) -> RataDie { + let approx = Astronomical::estimate_prior_solar_longitude( + astronomy::WINTER, + midnight::((date + 1).as_moment()), + ); + let mut iters = 0; + let mut day = Moment::new((approx.inner() - 1.0).floor()); + while iters < MAX_ITERS_FOR_MONTHS_OF_YEAR + && astronomy::WINTER + >= Astronomical::solar_longitude(Astronomical::julian_centuries(midnight::( + day + 1.0, + ))) + { + iters += 1; + day += 1.0; + } + debug_assert!( + iters < MAX_ITERS_FOR_MONTHS_OF_YEAR || !WELL_BEHAVED_ASTRONOMICAL_RANGE.contains(&date), + "Number of iterations was higher than expected" + ); + day.as_rata_die() +} + +/// Get the fixed date of the nearest Lunar New Year on or before a given fixed date. +/// This function also returns the solstice following a given date for optimization (see #3743). +/// +/// To call this function you must precompute the value of the prior solstice, which +/// is the result of winter_solstice_on_or_before +/// +/// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. +/// Lisp reference code: https://github.com/EdReingold/calendar-code2/blob/main/calendar.l#L5396-L5405 +pub(crate) fn new_year_on_or_before_fixed_date( + date: RataDie, + prior_solstice: RataDie, +) -> (RataDie, RataDie) { + let new_year = new_year_in_sui::(prior_solstice); + if date >= new_year.0 { + new_year + } else { + // This happens when we're at the end of the current lunar year + // and the solstice has already happened. Thus the relevant solstice + // for the current lunar year is the previous one, which we calculate by offsetting + // back by a year. + let date_in_last_sui = date - 180; // This date is in the current lunar year, but the last solar year + let prior_solstice = winter_solstice_on_or_before::(date_in_last_sui); + new_year_in_sui::(prior_solstice) + } +} + +/// Get a RataDie in the middle of a year. +/// +/// This is not necessarily meant for direct use in +/// calculations; rather, it is useful for getting a RataDie guaranteed to be in a given year +/// as input for other calculations like calculating the leap month in a year. +/// +/// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz +/// Lisp reference code: +pub fn fixed_mid_year_from_year(elapsed_years: i32) -> RataDie { + let cycle = (elapsed_years - 1).div_euclid(60) + 1; + let year = (elapsed_years - 1).rem_euclid(60) + 1; + C::EPOCH + ((((cycle - 1) * 60 + year - 1) as f64 + 0.5) * MEAN_TROPICAL_YEAR) as i64 +} + +/// Whether this year is a leap year +pub fn is_leap_year(year: i32) -> bool { + let mid_year = fixed_mid_year_from_year::(year); + YearBounds::compute::(mid_year).is_leap() +} + +/// The last month and day in this year +pub fn last_month_day_in_year(year: i32) -> (u8, u8) { + let mid_year = fixed_mid_year_from_year::(year); + let year_bounds = YearBounds::compute::(mid_year); + let last_day = year_bounds.next_new_year - 1; + let month = if year_bounds.is_leap() { 13 } else { 12 }; + let day = last_day - new_moon_before::(last_day.as_moment()) + 1; + (month, day as u8) +} + +/// Calculated the numbers of days in the given year +pub fn days_in_provided_year(year: i32) -> u16 { + let mid_year = fixed_mid_year_from_year::(year); + let bounds = YearBounds::compute::(mid_year); + + bounds.count_days() +} + +/// chinese_based_date_from_fixed returns extra things for use in caching +#[derive(Debug)] +#[non_exhaustive] +pub struct ChineseFromFixedResult { + /// The chinese year + pub year: i32, + /// The chinese month + pub month: u8, + /// The chinese day + pub day: u8, + /// The bounds of the current lunar year + pub year_bounds: YearBounds, + /// The index of the leap month, if any + pub leap_month: Option, +} + +/// Get a chinese based date from a fixed date, with the related Gregorian year +/// +/// Months are calculated by iterating through the dates of new moons until finding the last month which +/// does not exceed the given fixed date. The day of month is calculated by subtracting the fixed date +/// from the fixed date of the beginning of the month. +/// +/// The calculation for `elapsed_years` and `month` in this function are based on code from _Calendrical Calculations_ by Reingold & Dershowitz. +/// Lisp reference code: +pub fn chinese_based_date_from_fixed(date: RataDie) -> ChineseFromFixedResult { + let year_bounds = YearBounds::compute::(date); + let first_day_of_year = year_bounds.new_year; + + let year_float = + (1.5 - 1.0 / 12.0 + ((first_day_of_year - C::EPOCH) as f64) / MEAN_TROPICAL_YEAR).floor(); + let year_int = i64_to_i32(year_float as i64); + debug_assert!(year_int.is_ok(), "Year should be in range of i32"); + let year = year_int.unwrap_or_else(|e| e.saturate()); + + let new_moon = new_moon_before::((date + 1).as_moment()); + let month_i64 = ((new_moon - first_day_of_year) as f64 / MEAN_SYNODIC_MONTH).round() as i64 + 1; + debug_assert!( + ((u8::MIN as i64)..=(u8::MAX as i64)).contains(&month_i64), + "Month should be in range of u8! Value {month_i64} failed for RD {date:?}" + ); + let month = month_i64 as u8; + let day_i64 = date - new_moon + 1; + debug_assert!( + ((u8::MIN as i64)..=(u8::MAX as i64)).contains(&month_i64), + "Day should be in range of u8! Value {month_i64} failed for RD {date:?}" + ); + let day = day_i64 as u8; + let leap_month = if year_bounds.is_leap() { + // This doesn't need to be checked for `None`, since `get_leap_month_from_new_year` + // will always return a number greater than or equal to 1, and less than 14. + NonZeroU8::new(get_leap_month_from_new_year::(first_day_of_year)) + } else { + None + }; + + ChineseFromFixedResult { + year, + month, + day, + year_bounds, + leap_month, + } +} + +/// Given that `new_year` is the first day of a leap year, find which month in the year is a leap month. +/// +/// Since the first month in which there are no major solar terms is a leap month, this function +/// cycles through months until it finds the leap month, then returns the number of that month. This +/// function assumes the date passed in is in a leap year and tests to ensure this is the case in debug +/// mode by asserting that no more than thirteen months are analyzed. +/// +/// Calls to `no_major_solar_term` have been inlined for increased efficiency. +/// +/// Conceptually similar to code from _Calendrical Calculations_ by Reingold & Dershowitz +/// Lisp reference code: +pub fn get_leap_month_from_new_year(new_year: RataDie) -> u8 { + let mut cur = new_year; + let mut result = 1; + let mut solar_term = major_solar_term_from_fixed::(cur); + loop { + let next = new_moon_on_or_after::((cur + 1).as_moment()); + let next_solar_term = major_solar_term_from_fixed::(next); + if result >= MAX_ITERS_FOR_MONTHS_OF_YEAR || solar_term == next_solar_term { + break; + } + cur = next; + solar_term = next_solar_term; + result += 1; + } + debug_assert!(result < MAX_ITERS_FOR_MONTHS_OF_YEAR, "The given year was not a leap year and an unexpected number of iterations occurred searching for a leap month."); + result +} + +/// Returns the number of days in the given (year, month). +/// +/// In the Chinese calendar, months start at each +/// new moon, so this function finds the number of days between the new moon at the beginning of the given +/// month and the new moon at the beginning of the next month. +pub fn month_days(year: i32, month: u8) -> u8 { + let mid_year = fixed_mid_year_from_year::(year); + let prev_solstice = winter_solstice_on_or_before::(mid_year); + let new_year = new_year_on_or_before_fixed_date::(mid_year, prev_solstice).0; + days_in_month::(month, new_year, None).0 +} + +/// Returns the number of days in the given `month` after the given `new_year`. +/// Also returns the RataDie of the new moon beginning the next month. +pub fn days_in_month( + month: u8, + new_year: RataDie, + prev_new_moon: Option, +) -> (u8, RataDie) { + let approx = new_year + ((month - 1) as i64 * 29); + let prev_new_moon = if let Some(prev_moon) = prev_new_moon { + prev_moon + } else { + new_moon_before::((approx + 15).as_moment()) + }; + let next_new_moon = new_moon_on_or_after::((approx + 15).as_moment()); + let result = (next_new_moon - prev_new_moon) as u8; + debug_assert!( + result == 29 || result == 30 || !WELL_BEHAVED_ASTRONOMICAL_RANGE.contains(&new_year) + ); + (result, next_new_moon) +} + +/// Given a new year, calculate the number of days in the previous year +pub fn days_in_prev_year(new_year: RataDie) -> u16 { + let date = new_year - 300; + let prev_solstice = winter_solstice_on_or_before::(date); + let (prev_new_year, _) = new_year_on_or_before_fixed_date::(date, prev_solstice); + u16::try_from(new_year - prev_new_year).unwrap_or(360) +} + +/// Returns the length of each month in the year, as well as a leap month index (1-indexed) if any. +/// +/// Month lengths are stored as true for 30-day, false for 29-day. +/// In the case of no leap months, month 13 will have value false. +pub fn month_structure_for_year( + new_year: RataDie, + next_new_year: RataDie, +) -> ([bool; 13], Option) { + let mut ret = [false; 13]; + + let mut current_month_start = new_year; + let mut current_month_major_solar_term = major_solar_term_from_fixed::(new_year); + let mut leap_month_index = None; + for i in 0u8..12 { + let next_month_start = new_moon_on_or_after::((current_month_start + 28).as_moment()); + let next_month_major_solar_term = major_solar_term_from_fixed::(next_month_start); + + if next_month_major_solar_term == current_month_major_solar_term { + leap_month_index = Some(i + 1); + } + + let diff = next_month_start - current_month_start; + debug_assert!( + diff == 29 || diff == 30 || !WELL_BEHAVED_ASTRONOMICAL_RANGE.contains(&new_year) + ); + #[expect(clippy::indexing_slicing)] // array is of length 13, we iterate till i=11 + if diff == 30 { + ret[usize::from(i)] = true; + } + + current_month_start = next_month_start; + current_month_major_solar_term = next_month_major_solar_term; + } + + if current_month_start == next_new_year { + // not all months without solar terms are leap months; they are only leap months if + // the year can admit them + // + // From Reingold & Dershowitz (p 311): + // + // The leap month of a 13-month winter-solstice-to-winter-solstice period is the first month + // that does not contain a major solar term — that is, the first lunar month that is wholly within a solar month. + // + // As such, if a month without a solar term is found in a non-leap year, we just ingnore it. + leap_month_index = None; + } else { + let diff = next_new_year - current_month_start; + debug_assert!( + diff == 29 || diff == 30 || !WELL_BEHAVED_ASTRONOMICAL_RANGE.contains(&new_year) + ); + if diff == 30 { + ret[12] = true; + } + } + if current_month_start != next_new_year && leap_month_index.is_none() { + leap_month_index = Some(13); // The last month is a leap month + debug_assert!( + major_solar_term_from_fixed::(current_month_start) == current_month_major_solar_term + || !WELL_BEHAVED_ASTRONOMICAL_RANGE.contains(&new_year), + "A leap month is required here, but it had a major solar term!" + ); + } + + (ret, leap_month_index) +} + +/// Given the new year and a month/day pair, calculate the number of days until the first day of the given month +pub fn days_until_month(new_year: RataDie, month: u8) -> u16 { + let month_approx = 28_u16.saturating_mul(u16::from(month) - 1); + + let new_moon = new_moon_on_or_after::(new_year.as_moment() + (month_approx as f64)); + let result = new_moon - new_year; + debug_assert!(((u16::MIN as i64)..=(u16::MAX as i64)).contains(&result), "Result {result} from new moon: {new_moon:?} and new year: {new_year:?} should be in range of u16!"); + result as u16 +} + +#[cfg(test)] +mod test { + + use super::*; + use crate::rata_die::Moment; + + #[test] + fn check_epochs() { + assert_eq!( + YearBounds::compute::(Dangi::EPOCH).new_year, + Dangi::EPOCH + ); + assert_eq!( + YearBounds::compute::(Chinese::EPOCH).new_year, + Chinese::EPOCH + ); + } + + #[test] + fn test_chinese_new_moon_directionality() { + for i in (-1000..1000).step_by(31) { + let moment = Moment::new(i as f64); + let before = new_moon_before::(moment); + let after = new_moon_on_or_after::(moment); + assert!(before < after, "Chinese new moon directionality failed for Moment: {moment:?}, with:\n\tBefore: {before:?}\n\tAfter: {after:?}"); + } + } + + #[test] + fn test_chinese_new_year_on_or_before() { + let fixed = crate::gregorian::fixed_from_gregorian(2023, 6, 22); + let prev_solstice = winter_solstice_on_or_before::(fixed); + let result_fixed = new_year_on_or_before_fixed_date::(fixed, prev_solstice).0; + let (y, m, d) = crate::gregorian::gregorian_from_fixed(result_fixed).unwrap(); + assert_eq!(y, 2023); + assert_eq!(m, 1); + assert_eq!(d, 22); + } + + fn seollal_on_or_before(fixed: RataDie) -> RataDie { + let prev_solstice = winter_solstice_on_or_before::(fixed); + new_year_on_or_before_fixed_date::(fixed, prev_solstice).0 + } + + #[test] + fn test_month_structure() { + // Mostly just tests that the assertions aren't hit + for year in 1900..2050 { + let fixed = crate::gregorian::fixed_from_gregorian(year, 1, 1); + let chinese_year = chinese_based_date_from_fixed::(fixed); + let (month_lengths, leap) = month_structure_for_year::( + chinese_year.year_bounds.new_year, + chinese_year.year_bounds.next_new_year, + ); + + for (i, month_is_30) in month_lengths.into_iter().enumerate() { + if leap.is_none() && i == 12 { + // month_days has no defined behavior for month 13 on non-leap-years + continue; + } + let month_len = 29 + i32::from(month_is_30); + let month_days = month_days::(chinese_year.year, i as u8 + 1); + assert_eq!( + month_len, + i32::from(month_days), + "Month length for month {} must be the same", + i + 1 + ); + } + println!( + "{year} (chinese {}): {month_lengths:?} {leap:?}", + chinese_year.year + ); + } + } + + #[test] + fn test_seollal() { + #[derive(Debug)] + struct TestCase { + gregorian_year: i32, + gregorian_month: u8, + gregorian_day: u8, + expected_year: i32, + expected_month: u8, + expected_day: u8, + } + + let cases = [ + TestCase { + gregorian_year: 2024, + gregorian_month: 6, + gregorian_day: 6, + expected_year: 2024, + expected_month: 2, + expected_day: 10, + }, + TestCase { + gregorian_year: 2024, + gregorian_month: 2, + gregorian_day: 9, + expected_year: 2023, + expected_month: 1, + expected_day: 22, + }, + TestCase { + gregorian_year: 2023, + gregorian_month: 1, + gregorian_day: 22, + expected_year: 2023, + expected_month: 1, + expected_day: 22, + }, + TestCase { + gregorian_year: 2023, + gregorian_month: 1, + gregorian_day: 21, + expected_year: 2022, + expected_month: 2, + expected_day: 1, + }, + TestCase { + gregorian_year: 2022, + gregorian_month: 6, + gregorian_day: 6, + expected_year: 2022, + expected_month: 2, + expected_day: 1, + }, + TestCase { + gregorian_year: 2021, + gregorian_month: 6, + gregorian_day: 6, + expected_year: 2021, + expected_month: 2, + expected_day: 12, + }, + TestCase { + gregorian_year: 2020, + gregorian_month: 6, + gregorian_day: 6, + expected_year: 2020, + expected_month: 1, + expected_day: 25, + }, + TestCase { + gregorian_year: 2019, + gregorian_month: 6, + gregorian_day: 6, + expected_year: 2019, + expected_month: 2, + expected_day: 5, + }, + TestCase { + gregorian_year: 2018, + gregorian_month: 6, + gregorian_day: 6, + expected_year: 2018, + expected_month: 2, + expected_day: 16, + }, + TestCase { + gregorian_year: 2025, + gregorian_month: 6, + gregorian_day: 6, + expected_year: 2025, + expected_month: 1, + expected_day: 29, + }, + TestCase { + gregorian_year: 2026, + gregorian_month: 8, + gregorian_day: 8, + expected_year: 2026, + expected_month: 2, + expected_day: 17, + }, + TestCase { + gregorian_year: 2027, + gregorian_month: 4, + gregorian_day: 4, + expected_year: 2027, + expected_month: 2, + expected_day: 7, + }, + TestCase { + gregorian_year: 2028, + gregorian_month: 9, + gregorian_day: 21, + expected_year: 2028, + expected_month: 1, + expected_day: 27, + }, + ]; + + for case in cases { + let fixed = crate::gregorian::fixed_from_gregorian( + case.gregorian_year, + case.gregorian_month, + case.gregorian_day, + ); + let seollal = seollal_on_or_before(fixed); + let (y, m, d) = crate::gregorian::gregorian_from_fixed(seollal).unwrap(); + assert_eq!( + y, case.expected_year, + "Year check failed for case: {case:?}" + ); + assert_eq!( + m, case.expected_month, + "Month check failed for case: {case:?}" + ); + assert_eq!(d, case.expected_day, "Day check failed for case: {case:?}"); + } + } +} diff --git a/deps/crates/vendor/calendrical_calculations/src/coptic.rs b/deps/crates/vendor/calendrical_calculations/src/coptic.rs new file mode 100644 index 00000000000000..85b917ee7dfebe --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/src/coptic.rs @@ -0,0 +1,32 @@ +// This file is part of ICU4X. +// +// The contents of this file implement algorithms from Calendrical Calculations +// by Reingold & Dershowitz, Cambridge University Press, 4th edition (2018), +// which have been released as Lisp code at +// under the Apache-2.0 license. Accordingly, this file is released under +// the Apache License, Version 2.0 which can be found at the calendrical_calculations +// package root or at http://www.apache.org/licenses/LICENSE-2.0. + +use crate::helpers::{i64_to_i32, I32CastError}; +use crate::rata_die::RataDie; + +pub(crate) const COPTIC_EPOCH: RataDie = crate::julian::fixed_from_julian(284, 8, 29); + +/// Lisp code reference: +pub fn fixed_from_coptic(year: i32, month: u8, day: u8) -> RataDie { + COPTIC_EPOCH - 1 + + 365 * (year as i64 - 1) + + year.div_euclid(4) as i64 + + 30 * (month as i64 - 1) + + day as i64 +} + +/// Lisp code reference: +pub fn coptic_from_fixed(date: RataDie) -> Result<(i32, u8, u8), I32CastError> { + let year = (4 * (date - COPTIC_EPOCH) + 1463).div_euclid(1461); + let year = i64_to_i32(year)?; + let month = ((date - fixed_from_coptic(year, 1, 1)).div_euclid(30) + 1) as u8; // <= 12 < u8::MAX + let day = (date + 1 - fixed_from_coptic(year, month, 1)) as u8; // <= days_in_month < u8::MAX + + Ok((year, month, day)) +} diff --git a/deps/crates/vendor/calendrical_calculations/src/error.rs b/deps/crates/vendor/calendrical_calculations/src/error.rs new file mode 100644 index 00000000000000..657d5113121090 --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/src/error.rs @@ -0,0 +1,29 @@ +// This file is part of ICU4X. +// +// The contents of this file implement algorithms from Calendrical Calculations +// by Reingold & Dershowitz, Cambridge University Press, 4th edition (2018), +// which have been released as Lisp code at +// under the Apache-2.0 license. Accordingly, this file is released under +// the Apache License, Version 2.0 which can be found at the calendrical_calculations +// package root or at http://www.apache.org/licenses/LICENSE-2.0. + +use displaydoc::Display; + +/// A list of error outcomes for exceeding location bounds +#[derive(Display, Debug, Copy, Clone, PartialEq)] +#[non_exhaustive] +pub enum LocationOutOfBoundsError { + /// Latitude value was out of bounds + #[displaydoc("Latitude {0} outside bounds of -90 to 90")] + Latitude(f64), + + /// Longitude value was out of bounds + #[displaydoc("Longitude {0} outside bounds of -180 to 180")] + Longitude(f64), + + /// Offset value was out of bounds + #[displaydoc("Offset {0} outside bounds of {1} to {2}")] + Offset(f64, f64, f64), +} + +impl core::error::Error for LocationOutOfBoundsError {} diff --git a/deps/crates/vendor/calendrical_calculations/src/ethiopian.rs b/deps/crates/vendor/calendrical_calculations/src/ethiopian.rs new file mode 100644 index 00000000000000..f6ca5293baf886 --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/src/ethiopian.rs @@ -0,0 +1,24 @@ +// This file is part of ICU4X. +// +// The contents of this file implement algorithms from Calendrical Calculations +// by Reingold & Dershowitz, Cambridge University Press, 4th edition (2018), +// which have been released as Lisp code at +// under the Apache-2.0 license. Accordingly, this file is released under +// the Apache License, Version 2.0 which can be found at the calendrical_calculations +// package root or at http://www.apache.org/licenses/LICENSE-2.0. + +use crate::helpers::I32CastError; +use crate::rata_die::RataDie; + +const ETHIOPIC_TO_COPTIC_OFFSET: i64 = + super::coptic::COPTIC_EPOCH.since(crate::julian::fixed_from_julian(8, 8, 29)); + +/// Lisp code reference: +pub fn fixed_from_ethiopian(year: i32, month: u8, day: u8) -> RataDie { + crate::coptic::fixed_from_coptic(year, month, day) - ETHIOPIC_TO_COPTIC_OFFSET +} + +/// Lisp code reference: +pub fn ethiopian_from_fixed(date: RataDie) -> Result<(i32, u8, u8), I32CastError> { + crate::coptic::coptic_from_fixed(date + ETHIOPIC_TO_COPTIC_OFFSET) +} diff --git a/deps/crates/vendor/calendrical_calculations/src/gregorian.rs b/deps/crates/vendor/calendrical_calculations/src/gregorian.rs new file mode 100644 index 00000000000000..6da3d1bce842d1 --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/src/gregorian.rs @@ -0,0 +1,151 @@ +// This file is part of ICU4X. +// +// The contents of this file implement algorithms from Calendrical Calculations +// by Reingold & Dershowitz, Cambridge University Press, 4th edition (2018), +// which have been released as Lisp code at +// under the Apache-2.0 license. Accordingly, this file is released under +// the Apache License, Version 2.0 which can be found at the calendrical_calculations +// package root or at http://www.apache.org/licenses/LICENSE-2.0. + +use crate::helpers::{i64_to_i32, k_day_after, I32CastError}; +use crate::rata_die::RataDie; + +// The Gregorian epoch is equivalent to first day in fixed day measurement +const EPOCH: RataDie = RataDie::new(1); + +const DAYS_IN_YEAR: i64 = 365; + +// One leap year every 4 years +const DAYS_IN_4_YEAR_CYCLE: i64 = DAYS_IN_YEAR * 4 + 1; + +// No leap year every 100 years +const DAYS_IN_100_YEAR_CYCLE: i64 = 25 * DAYS_IN_4_YEAR_CYCLE - 1; + +// One extra leap year every 400 years +/// The number of days in the 400 year cycle. +pub const DAYS_IN_400_YEAR_CYCLE: i64 = 4 * DAYS_IN_100_YEAR_CYCLE + 1; + +/// Whether or not `year` is a leap year +/// +/// Inspired by Neri-Schneider +pub const fn is_leap_year(year: i32) -> bool { + // This is branch-free, as it compiles to a conditional move + if year % 25 != 0 { + year % 4 == 0 + } else { + year % 16 == 0 + } +} + +// Fixed is day count representation of calendars starting from Jan 1st of year 1. +// The fixed calculations algorithms are from the Calendrical Calculations book. +// +/// Lisp code reference: +pub const fn fixed_from_gregorian(year: i32, month: u8, day: u8) -> RataDie { + day_before_year(year) + .add(days_before_month(year, month) as i64) + .add(day as i64) +} + +/// The number of days in this year before this month starts +/// +/// Inspired by Neri-Schneider +pub const fn days_before_month(year: i32, month: u8) -> u16 { + if month < 3 { + // This compiles to a conditional move, so there's only one branch in this function + if month == 1 { + 0 + } else { + 31 + } + } else { + 31 + 28 + is_leap_year(year) as u16 + ((979 * (month as u32) - 2919) >> 5) as u16 + } +} + +/// Lisp code reference: +pub const fn year_from_fixed(date: RataDie) -> Result { + // Shouldn't overflow because it's not possbile to construct extreme values of RataDie + let date = date.since(EPOCH); + + let (n_400, date) = ( + date.div_euclid(DAYS_IN_400_YEAR_CYCLE), + date.rem_euclid(DAYS_IN_400_YEAR_CYCLE), + ); + + let (n_100, date) = (date / DAYS_IN_100_YEAR_CYCLE, date % DAYS_IN_100_YEAR_CYCLE); + + let (n_4, date) = (date / DAYS_IN_4_YEAR_CYCLE, date % DAYS_IN_4_YEAR_CYCLE); + + let n_1 = date / DAYS_IN_YEAR; + + let year = 400 * n_400 + 100 * n_100 + 4 * n_4 + n_1 + (n_100 != 4 && n_1 != 4) as i64; + + i64_to_i32(year) +} + +/// Calculates the day before Jan 1 of `year`. +pub const fn day_before_year(year: i32) -> RataDie { + let prev_year = (year as i64) - 1; + // Calculate days per year + let mut fixed: i64 = DAYS_IN_YEAR * prev_year; + // Adjust for leap year logic. We can avoid the branch of div_euclid by making prev_year positive: + // YEAR_SHIFT is larger (in magnitude) than any prev_year, and, being divisible by 400, + // distributes correctly over the calculation on the next line. + const YEAR_SHIFT: i64 = (-(i32::MIN as i64 - 1) / 400 + 1) * 400; + fixed += (prev_year + YEAR_SHIFT) / 4 - (prev_year + YEAR_SHIFT) / 100 + + (prev_year + YEAR_SHIFT) / 400 + - const { YEAR_SHIFT / 4 - YEAR_SHIFT / 100 + YEAR_SHIFT / 400 }; + RataDie::new(fixed) +} + +/// Calculates the month/day from the 1-based day of the year +pub fn year_day(year: i32, day_of_year: u16) -> (u8, u8) { + // Calculates the prior days of the year, then applies a correction based on leap year conditions for the correct ISO date conversion. + let correction = if day_of_year < 31 + 28 + is_leap_year(year) as u16 { + -1 + } else { + (!is_leap_year(year)) as i32 + }; + let month = ((12 * (day_of_year as i32 + correction) + 373) / 367) as u8; // in 1..12 < u8::MAX + let day = (day_of_year - days_before_month(year, month)) as u8; // <= days_in_month < u8::MAX + (month, day) +} + +/// Lisp code reference: +pub fn gregorian_from_fixed(date: RataDie) -> Result<(i32, u8, u8), I32CastError> { + let year = year_from_fixed(date)?; + let day_of_year = date - day_before_year(year); + let (month, day) = year_day(year, day_of_year as u16); + Ok((year, month, day)) +} + +/// Calculates the date of Easter in the given year +pub fn easter(year: i32) -> RataDie { + let century = (year / 100) + 1; + let shifted_epact = + (14 + 11 * year.rem_euclid(19) - century * 3 / 4 + (5 + 8 * century) / 25).rem_euclid(30); + let adjusted_epact = shifted_epact + + (shifted_epact == 0 || (shifted_epact == 1 && 10 < year.rem_euclid(19))) as i32; + let paschal_moon = fixed_from_gregorian(year, 4, 19) - adjusted_epact as i64; + + k_day_after(0, paschal_moon) +} + +#[test] +fn test_easter() { + // https://en.wikipedia.org/wiki/List_of_dates_for_Easter + for (y, m, d) in [ + (2021, 4, 4), + (2022, 4, 17), + (2023, 4, 9), + (2024, 3, 31), + (2025, 4, 20), + (2026, 4, 5), + (2027, 3, 28), + (2028, 4, 16), + (2029, 4, 1), + ] { + assert_eq!(easter(y), fixed_from_gregorian(y, m, d)); + } +} diff --git a/deps/crates/vendor/calendrical_calculations/src/hebrew.rs b/deps/crates/vendor/calendrical_calculations/src/hebrew.rs new file mode 100644 index 00000000000000..7eb1560a169f6b --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/src/hebrew.rs @@ -0,0 +1,707 @@ +// This file is part of ICU4X. +// +// The contents of this file implement algorithms from Calendrical Calculations +// by Reingold & Dershowitz, Cambridge University Press, 4th edition (2018), +// which have been released as Lisp code at +// under the Apache-2.0 license. Accordingly, this file is released under +// the Apache License, Version 2.0 which can be found at the calendrical_calculations +// package root or at http://www.apache.org/licenses/LICENSE-2.0. + +use crate::helpers::{final_func, i64_to_i32, next_u8}; +use crate::rata_die::{Moment, RataDie}; +#[allow(unused_imports)] +use core_maths::*; + +/// Lisp code reference: +pub(crate) const FIXED_HEBREW_EPOCH: RataDie = + crate::julian::fixed_from_julian_book_version(-3761, 10, 7); + +/// Biblical Hebrew dates. The months are reckoned a bit strangely, with the new year occurring on +/// Tishri (as in the civil calendar) but the months being numbered in a different order +#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq, PartialOrd, Ord)] +#[allow(clippy::exhaustive_structs)] +pub struct BookHebrew { + /// The year + pub year: i32, + /// The month + pub month: u8, + /// The day + pub day: u8, +} + +// The BookHebrew Months +/// The biblical month number used for the month of Nisan +pub const NISAN: u8 = 1; +/// The biblical month number used for the month of Iyyar +pub const IYYAR: u8 = 2; +/// The biblical month number used for the month of Sivan +pub const SIVAN: u8 = 3; +/// The biblical month number used for the month of Tammuz +pub const TAMMUZ: u8 = 4; +/// The biblical month number used for the month of Av +pub const AV: u8 = 5; +/// The biblical month number used for the month of Elul +pub const ELUL: u8 = 6; +/// The biblical month number used for the month of Tishri +pub const TISHRI: u8 = 7; +/// The biblical month number used for the month of Marheshvan +pub const MARHESHVAN: u8 = 8; +/// The biblical month number used for the month of Kislev +pub const KISLEV: u8 = 9; +/// The biblical month number used for the month of Tevet +pub const TEVET: u8 = 10; +/// The biblical month number used for the month of Shevat +pub const SHEVAT: u8 = 11; +/// The biblical month number used for the month of Adar (and Adar I) +pub const ADAR: u8 = 12; +/// The biblical month number used for the month of Adar II +pub const ADARII: u8 = 13; + +// BIBLICAL HEBREW CALENDAR FUNCTIONS + +impl BookHebrew { + /// The civil calendar has the same year and day numbering as the book one, but the months are numbered + /// differently + pub fn to_civil_date(self) -> (i32, u8, u8) { + let biblical_month = self.month; + let biblical_year = self.year; + let mut civil_month; + civil_month = (biblical_month + 6) % 12; + + if civil_month == 0 { + civil_month = 12; + } + + if Self::is_hebrew_leap_year(biblical_year) && biblical_month < TISHRI { + civil_month += 1; + } + (biblical_year, civil_month, self.day) + } + + /// The civil calendar has the same year and day numbering as the book one, but the months are numbered + /// differently + pub fn from_civil_date(civil_year: i32, civil_month: u8, civil_day: u8) -> Self { + let mut biblical_month; + + if civil_month <= 6 { + biblical_month = civil_month + 6; // months 1-6 correspond to biblical months 7-12 + } else { + biblical_month = civil_month - 6; // months 7-12 correspond to biblical months 1-6 + if Self::is_hebrew_leap_year(civil_year) { + biblical_month -= 1 + } + if biblical_month == 0 { + // Special case for Adar II in a leap year + biblical_month = 13; + } + } + + BookHebrew { + year: civil_year, + month: biblical_month, + day: civil_day, + } + } + // Moment of mean conjunction (New Moon) of h_month in BookHebrew + /// Lisp code reference: + #[allow(dead_code)] + pub(crate) fn molad(book_year: i32, book_month: u8) -> Moment { + let y = if book_month < TISHRI { + book_year + 1 + } else { + book_year + }; // Treat Nisan as start of year + + let months_elapsed = (book_month as f64 - TISHRI as f64) // Months this year + + ((235.0 * y as f64 - 234.0) / 19.0).floor(); // Months until New Year. + + Moment::new( + FIXED_HEBREW_EPOCH.to_f64_date() - (876.0 / 25920.0) + + months_elapsed * (29.0 + (1.0 / 2.0) + (793.0 / 25920.0)), + ) + } + + // ADAR = 12, ADARII = 13 + /// Lisp code reference: + #[allow(dead_code)] + fn last_month_of_book_hebrew_year(book_year: i32) -> u8 { + if Self::is_hebrew_leap_year(book_year) { + ADARII + } else { + ADAR + } + } + + // Number of days elapsed from the (Sunday) noon prior to the epoch of the BookHebrew Calendar to the molad of Tishri of BookHebrew year (h_year) or one day later + /// Lisp code reference: + fn book_hebrew_calendar_elapsed_days(book_year: i32) -> i32 { + let months_elapsed = ((235.0 * book_year as f64 - 234.0) / 19.0).floor() as i64; + let parts_elapsed = 12084 + 13753 * months_elapsed; + let days = 29 * months_elapsed + (parts_elapsed as f64 / 25920.0).floor() as i64; + + if (3 * (days + 1)).rem_euclid(7) < 3 { + days as i32 + 1 + } else { + days as i32 + } + } + + // Delays to start of BookHebrew year to keep ordinary year in range 353-356 and leap year in range 383-386 + /// Lisp code reference: + fn book_hebrew_year_length_correction(book_year: i32) -> u8 { + let ny0 = Self::book_hebrew_calendar_elapsed_days(book_year - 1); + let ny1 = Self::book_hebrew_calendar_elapsed_days(book_year); + let ny2 = Self::book_hebrew_calendar_elapsed_days(book_year + 1); + + if (ny2 - ny1) == 356 { + 2 + } else if (ny1 - ny0) == 382 { + 1 + } else { + 0 + } + } + + // Fixed date of BookHebrew new year + /// Lisp code reference: + pub fn book_hebrew_new_year(book_year: i32) -> RataDie { + RataDie::new( + FIXED_HEBREW_EPOCH.to_i64_date() + + Self::book_hebrew_calendar_elapsed_days(book_year) as i64 + + Self::book_hebrew_year_length_correction(book_year) as i64, + ) + } + + /// Lisp code reference: + pub fn days_in_book_hebrew_year(book_year: i32) -> u16 { + (Self::book_hebrew_new_year(1 + book_year) - Self::book_hebrew_new_year(book_year)) as u16 + } + + /// Lisp code reference: + pub fn is_hebrew_leap_year(book_year: i32) -> bool { + (7 * book_year + 1).rem_euclid(19) < 7 + } + + // True if the month Marheshvan is going to be long in given BookHebrew year + /// Lisp code reference: + #[allow(dead_code)] + fn is_long_marheshvan(book_year: i32) -> bool { + let long_marheshavan_year_lengths = [355, 385]; + long_marheshavan_year_lengths.contains(&Self::days_in_book_hebrew_year(book_year)) + } + + // True if the month Kislve is going to be short in given BookHebrew year + /// Lisp code reference: + #[allow(dead_code)] + fn is_short_kislev(book_year: i32) -> bool { + let short_kislev_year_lengths = [353, 383]; + short_kislev_year_lengths.contains(&Self::days_in_book_hebrew_year(book_year)) + } + + // Last day of month (h_month) in BookHebrew year (book_year) + /// Lisp code reference: + pub fn last_day_of_book_hebrew_month(book_year: i32, book_month: u8) -> u8 { + match book_month { + IYYAR | TAMMUZ | ELUL | TEVET | ADARII => 29, + ADAR => { + if !Self::is_hebrew_leap_year(book_year) { + 29 + } else { + 30 + } + } + MARHESHVAN => { + if !Self::is_long_marheshvan(book_year) { + 29 + } else { + 30 + } + } + KISLEV => { + if Self::is_short_kislev(book_year) { + 29 + } else { + 30 + } + } + _ => 30, + } + } + + /// Lisp code reference: + pub fn fixed_from_book_hebrew(date: BookHebrew) -> RataDie { + let book_year = date.year; + let book_month = date.month; + let book_day = date.day; + + let mut total_days = Self::book_hebrew_new_year(book_year) + book_day.into() - 1; // (day - 1) Days so far this month. + + if book_month < TISHRI { + // Then add days in prior months this year before + for m in + (TISHRI..=Self::last_month_of_book_hebrew_year(book_year)).chain(NISAN..book_month) + { + total_days += Self::last_day_of_book_hebrew_month(book_year, m).into(); + } + } else { + // Else add days in prior months this year + for m in TISHRI..book_month { + total_days += Self::last_day_of_book_hebrew_month(book_year, m).into(); + } + } + + total_days + } + + /// Lisp code reference: + pub fn book_hebrew_from_fixed(date: RataDie) -> BookHebrew { + let approx = i64_to_i32( + 1 + ((date - FIXED_HEBREW_EPOCH) as f64).div_euclid(35975351.0 / 98496.0) as i64, // The value 35975351/98496, the average length of a BookHebrew year, can be approximated by 365.25 + ) + .unwrap_or_else(|e| e.saturate()); + + // Search forward for the year + let year_condition = |year: i32| Self::book_hebrew_new_year(year) <= date; + let year = final_func(approx - 1, year_condition); + + // Starting month for search for month. + let start = if date + < Self::fixed_from_book_hebrew(BookHebrew { + year, + month: NISAN, + day: 1, + }) { + TISHRI + } else { + NISAN + }; + + let month_condition = |m: u8| { + date <= Self::fixed_from_book_hebrew(BookHebrew { + year, + month: m, + day: Self::last_day_of_book_hebrew_month(year, m), + }) + }; + // Search forward from either Tishri or Nisan. + let month = next_u8(start, month_condition); + + // Calculate the day by subtraction. + let day = (date + - Self::fixed_from_book_hebrew(BookHebrew { + year, + month, + day: 1, + })) + + 1; + + BookHebrew { + year, + month, + day: day as u8, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Debug)] + struct DateCase { + year: i32, + month: u8, + day: u8, + } + + static TEST_FIXED_DATE: [i64; 33] = [ + -214193, -61387, 25469, 49217, 171307, 210155, 253427, 369740, 400085, 434355, 452605, + 470160, 473837, 507850, 524156, 544676, 567118, 569477, 601716, 613424, 626596, 645554, + 664224, 671401, 694799, 704424, 708842, 709409, 709580, 727274, 728714, 744313, 764652, + ]; + + static HEBREW_DATES: [DateCase; 33] = [ + DateCase { + year: 3174, + month: 5, + day: 10, + }, + DateCase { + year: 3593, + month: 9, + day: 25, + }, + DateCase { + year: 3831, + month: 7, + day: 3, + }, + DateCase { + year: 3896, + month: 7, + day: 9, + }, + DateCase { + year: 4230, + month: 10, + day: 18, + }, + DateCase { + year: 4336, + month: 3, + day: 4, + }, + DateCase { + year: 4455, + month: 8, + day: 13, + }, + DateCase { + year: 4773, + month: 2, + day: 6, + }, + DateCase { + year: 4856, + month: 2, + day: 23, + }, + DateCase { + year: 4950, + month: 1, + day: 7, + }, + DateCase { + year: 5000, + month: 13, + day: 8, + }, + DateCase { + year: 5048, + month: 1, + day: 21, + }, + DateCase { + year: 5058, + month: 2, + day: 7, + }, + DateCase { + year: 5151, + month: 4, + day: 1, + }, + DateCase { + year: 5196, + month: 11, + day: 7, + }, + DateCase { + year: 5252, + month: 1, + day: 3, + }, + DateCase { + year: 5314, + month: 7, + day: 1, + }, + DateCase { + year: 5320, + month: 12, + day: 27, + }, + DateCase { + year: 5408, + month: 3, + day: 20, + }, + DateCase { + year: 5440, + month: 4, + day: 3, + }, + DateCase { + year: 5476, + month: 5, + day: 5, + }, + DateCase { + year: 5528, + month: 4, + day: 4, + }, + DateCase { + year: 5579, + month: 5, + day: 11, + }, + DateCase { + year: 5599, + month: 1, + day: 12, + }, + DateCase { + year: 5663, + month: 1, + day: 22, + }, + DateCase { + year: 5689, + month: 5, + day: 19, + }, + DateCase { + year: 5702, + month: 7, + day: 8, + }, + DateCase { + year: 5703, + month: 1, + day: 14, + }, + DateCase { + year: 5704, + month: 7, + day: 8, + }, + DateCase { + year: 5752, + month: 13, + day: 12, + }, + DateCase { + year: 5756, + month: 12, + day: 5, + }, + DateCase { + year: 5799, + month: 8, + day: 12, + }, + DateCase { + year: 5854, + month: 5, + day: 5, + }, + ]; + + static EXPECTED_MOLAD_DATES: [f64; 33] = [ + -1850718767f64 / 8640f64, + -1591805959f64 / 25920f64, + 660097927f64 / 25920f64, + 1275506059f64 / 25920f64, + 4439806081f64 / 25920f64, + 605235101f64 / 2880f64, + 3284237627f64 / 12960f64, + 9583515841f64 / 25920f64, + 2592403883f64 / 6480f64, + 2251656649f64 / 5184f64, + 11731320839f64 / 25920f64, + 12185988041f64 / 25920f64, + 6140833583f64 / 12960f64, + 6581722991f64 / 12960f64, + 6792982499f64 / 12960f64, + 4705980311f64 / 8640f64, + 14699670013f64 / 25920f64, + 738006961f64 / 1296f64, + 1949499007f64 / 3240f64, + 5299956319f64 / 8640f64, + 3248250415f64 / 5184f64, + 16732660061f64 / 25920f64, + 17216413717f64 / 25920f64, + 1087650871f64 / 1620f64, + 2251079609f64 / 3240f64, + 608605601f64 / 864f64, + 306216383f64 / 432f64, + 18387526207f64 / 25920f64, + 3678423761f64 / 5184f64, + 1570884431f64 / 2160f64, + 18888119389f64 / 25920f64, + 19292268013f64 / 25920f64, + 660655045f64 / 864f64, + ]; + + static EXPECTED_LAST_HEBREW_MONTH: [u8; 33] = [ + 12, 12, 12, 12, 12, 12, 12, 12, 13, 12, 13, 12, 12, 12, 12, 13, 12, 13, 12, 13, 12, 12, 12, + 12, 12, 13, 12, 13, 12, 13, 12, 12, 12, + ]; + + static EXPECTED_HEBREW_ELASPED_CALENDAR_DAYS: [i32; 33] = [ + 1158928, 1311957, 1398894, 1422636, 1544627, 1583342, 1626812, 1742956, 1773254, 1807597, + 1825848, 1843388, 1847051, 1881010, 1897460, 1917895, 1940545, 1942729, 1974889, 1986554, + 1999723, 2018712, 2037346, 2044640, 2068027, 2077507, 2082262, 2082617, 2083000, 2100511, + 2101988, 2117699, 2137779, + ]; + + static EXPECTED_FIXED_HEBREW_NEW_YEAR: [i64; 33] = [ + -214497, -61470, 25467, 49209, 171200, 209915, 253385, 369529, 399827, 434172, 452421, + 469963, 473624, 507583, 524033, 544468, 567118, 569302, 601462, 613127, 626296, 645285, + 663919, 671213, 694600, 704080, 708835, 709190, 709573, 727084, 728561, 744272, 764352, + ]; + + static EXPECTED_DAYS_IN_HEBREW_YEAR: [u16; 33] = [ + 354, 354, 355, 355, 355, 355, 355, 353, 383, 354, 383, 354, 354, 355, 353, 383, 353, 385, + 353, 383, 355, 354, 354, 354, 355, 385, 355, 383, 354, 385, 355, 354, 355, + ]; + + static EXPECTED_MARHESHVAN_VALUES: [bool; 33] = [ + false, false, true, true, true, true, true, false, false, false, false, false, false, true, + false, false, false, true, false, false, true, false, false, false, true, true, true, + false, false, true, true, false, true, + ]; + + static EXPECTED_KISLEV_VALUES: [bool; 33] = [ + false, false, false, false, false, false, false, true, true, false, true, false, false, + false, true, true, true, false, true, true, false, false, false, false, false, false, + false, true, false, false, false, false, false, + ]; + + static EXPECTED_DAY_IN_MONTH: [u8; 33] = [ + 30, 30, 30, 30, 29, 30, 30, 29, 29, 30, 29, 30, 29, 29, 30, 30, 30, 30, 30, 29, 30, 29, 30, + 30, 30, 30, 30, 30, 30, 29, 29, 29, 30, + ]; + + #[allow(dead_code)] + static CIVIL_EXPECTED_DAY_IN_MONTH: [u8; 33] = [ + 30, 30, 30, 30, 29, 30, 29, 29, 29, 30, 30, 30, 29, 29, 30, 29, 30, 29, 29, 30, 30, 29, 30, + 30, 30, 30, 30, 29, 30, 30, 29, 29, 30, + ]; + + #[test] + fn test_hebrew_epoch() { + // page 119 of the Calendrical Calculations book + assert_eq!(FIXED_HEBREW_EPOCH, RataDie::new(-1373427)); + } + + #[test] + fn test_hebrew_molad() { + let precision = 1_00000f64; + for (case, expected) in HEBREW_DATES.iter().zip(EXPECTED_MOLAD_DATES.iter()) { + let molad = + (BookHebrew::molad(case.year, case.month).inner() * precision).round() / precision; + let final_expected = (expected * precision).round() / precision; + assert_eq!(molad, final_expected, "{case:?}"); + } + } + + #[test] + fn test_last_book_hebrew_month() { + for (case, expected) in HEBREW_DATES.iter().zip(EXPECTED_LAST_HEBREW_MONTH.iter()) { + let last_month = BookHebrew::last_month_of_book_hebrew_year(case.year); + assert_eq!(last_month, *expected); + } + } + + #[test] + fn test_book_hebrew_calendar_elapsed_days() { + for (case, expected) in HEBREW_DATES + .iter() + .zip(EXPECTED_HEBREW_ELASPED_CALENDAR_DAYS.iter()) + { + let elapsed_days = BookHebrew::book_hebrew_calendar_elapsed_days(case.year); + assert_eq!(elapsed_days, *expected); + } + } + + #[test] + fn test_book_hebrew_year_length_correction() { + let year_length_correction: [u8; 33] = [ + 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + ]; + for (case, expected) in HEBREW_DATES.iter().zip(year_length_correction.iter()) { + let correction = BookHebrew::book_hebrew_year_length_correction(case.year); + assert_eq!(correction, *expected); + } + } + + #[test] + fn test_book_hebrew_new_year() { + for (case, expected) in HEBREW_DATES + .iter() + .zip(EXPECTED_FIXED_HEBREW_NEW_YEAR.iter()) + { + let f_date = BookHebrew::book_hebrew_new_year(case.year); + assert_eq!(f_date.to_i64_date(), *expected); + } + } + + #[test] + fn test_days_in_book_hebrew_year() { + for (case, expected) in HEBREW_DATES.iter().zip(EXPECTED_DAYS_IN_HEBREW_YEAR.iter()) { + let days_in_year = BookHebrew::days_in_book_hebrew_year(case.year); + assert_eq!(days_in_year, *expected); + } + } + + #[test] + fn test_long_marheshvan() { + for (case, expected) in HEBREW_DATES.iter().zip(EXPECTED_MARHESHVAN_VALUES.iter()) { + let marsheshvan = BookHebrew::is_long_marheshvan(case.year); + assert_eq!(marsheshvan, *expected); + } + } + + #[test] + fn test_short_kislev() { + for (case, expected) in HEBREW_DATES.iter().zip(EXPECTED_KISLEV_VALUES.iter()) { + let kislev = BookHebrew::is_short_kislev(case.year); + assert_eq!(kislev, *expected); + } + } + + #[test] + fn test_last_day_in_book_hebrew_month() { + for (case, expected) in HEBREW_DATES.iter().zip(EXPECTED_DAY_IN_MONTH.iter()) { + let days_in_month = BookHebrew::last_day_of_book_hebrew_month(case.year, case.month); + assert_eq!(days_in_month, *expected); + } + } + + #[test] + fn test_fixed_from_book_hebrew() { + for (case, f_date) in HEBREW_DATES.iter().zip(TEST_FIXED_DATE.iter()) { + assert_eq!( + BookHebrew::fixed_from_book_hebrew(BookHebrew { + year: case.year, + month: case.month, + day: case.day + }), + RataDie::new(*f_date), + "{case:?}" + ); + } + } + + #[test] + fn test_book_hebrew_from_fixed() { + for (case, f_date) in HEBREW_DATES.iter().zip(TEST_FIXED_DATE.iter()) { + assert_eq!( + BookHebrew::book_hebrew_from_fixed(RataDie::new(*f_date)), + BookHebrew { + year: case.year, + month: case.month, + day: case.day + }, + "{case:?}" + ); + } + } + + #[test] + fn test_civil_to_book_conversion() { + for (f_date, case) in TEST_FIXED_DATE.iter().zip(HEBREW_DATES.iter()) { + let book_hebrew = BookHebrew::book_hebrew_from_fixed(RataDie::new(*f_date)); + let (y, m, d) = book_hebrew.to_civil_date(); + let book_hebrew = BookHebrew::from_civil_date(y, m, d); + + assert_eq!( + (case.year, case.month), + (book_hebrew.year, book_hebrew.month) + ) + } + } +} diff --git a/deps/crates/vendor/calendrical_calculations/src/hebrew_keviyah.rs b/deps/crates/vendor/calendrical_calculations/src/hebrew_keviyah.rs new file mode 100644 index 00000000000000..b36a39c157b382 --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/src/hebrew_keviyah.rs @@ -0,0 +1,1067 @@ +// This file is part of ICU4X. +// +// The contents of this file implement algorithms from Calendrical Calculations +// by Reingold & Dershowitz, Cambridge University Press, 4th edition (2018), +// which have been released as Lisp code at +// under the Apache-2.0 license. Accordingly, this file is released under +// the Apache License, Version 2.0 which can be found at the calendrical_calculations +// package root or at http://www.apache.org/licenses/LICENSE-2.0. + +// The algorithms in this file are rather well-published in multiple places, +// though the resource that was primarily used was +// J Jean Adler's _A Short History of the Jewish Fixed Calendar_, found +// at , with more detailed appendices +// at . +// Most of the math can be found on Wikipedia as well, +// at + +//! Alternate, more efficient structures for working with the Hebrew Calendar +//! using the keviyah and Four Gates system +//! +//! The main entry point for this code is [`YearInfo::compute_for()`] and [`YearInfo::year_containing_rd()`], +//! which will efficiently calculate certain information about a Hebrew year, given the Hebrew year +//! or a date that falls within it, and produce it as a [`YearInfo`]. +//! +//! From there, you can compute additional information via [`YearInfo::new_year()`] and by accessing +//! the methods on [`YearInfo::keviyah`]. +//! +//! +//! # How this code works: +//! +//! ## How the Hebrew Calendar works +//! +//! The Hebrew calendar is a lunisolar calendar following a Metonic cycle: every 19 years, the pattern of +//! leap years repeats. However, the precise month lengths vary from cycle to cycle: There are a handful of +//! corrections performed to ensure that: +//! +//! - The lunar conjunction happens on or before the first day of the month +//! - Yom Kippur is not before or after the Sabbath +//! - Hoshana Rabbah is not on the Sabbath +//! +//! These corrections can be done using systematic calculations, which this code attempts to efficiently perform. +//! +//! ## Molad +//! +//! A molad is the time of a conjunction, the moment when the new moon occurs. The "Molad Tishrei" is +//! the conjunction corresponding to the month Tishrei, the first month, so it is the molad that starts the new year. +//! In this file we'll typically use "molad" to refer to the molad Tishrei of a year. +//! +//! The Hebrew calendar does not always start on the day of the molad Tishrei: it may be postponed one or two days. +//! However, the time in the week that the molad occurs is sufficient to know when it gets postponed to. +//! +//! ## Keviyah +//! +//! See also: the [`Keviyah`] type. +//! +//! This is the core concept being used here. Everything you need to know about the characteristics +//! of a hebrew year can be boiled down to a notion called the "keviyah" of a year. This +//! encapsulates three bits of information: +//! +//! - What day of the week the year starts on +//! - What the month lengths are +//! - What day of the week Passover starts on. +//! +//! While this seems like many possible combinations, only fourteen of them are possible. +//! +//! Knowing the Keviyah of the year you can understand exactly what the lengths of each month are. +//! Furthermore, if you know the week the year falls in, you can additionally understand what +//! the precise day of the new year is. +//! +//! [`YearInfo`] encapsulates these two pieces of information: the [`Keviyah`] and the number of weeks +//! since the epoch of the Hebrew calendar. +//! +//! ## The Four Gates table +//! +//! This is an efficient lookup based way of calculating the [`Keviyah`] for a year. In the Metonic cycle, +//! there are four broad types of year: leap years, years preceding leap years, years succeeding leap years, +//! and years sandwiched between leap years. For each of these year types, there is a partitioning +//! of the week into seven segments, and the [`Keviyah`] of that year depends on which segment the molad falls +//! in. +//! +//! So to calculate the [`Keviyah`] of a year, we can calculate its molad, pick the right partitioning based on the +//! year type, and see where the molad falls in that table. + +use crate::helpers::i64_to_i32; +use crate::rata_die::RataDie; +use core::cmp::Ordering; + +// A note on time notation +// +// Hebrew timekeeping has some differences from standard timekeeping. A Hebrew day is split into 24 +// hours, each split into 1080 ḥalakim ("parts", abbreviated "ḥal" or "p"). Furthermore, the Hebrew +// day for calendrical purposes canonically starts at 6PM the previous evening, e.g. Hebrew Monday +// starts on Sunday 6PM. (For non-calendrical observational purposes this varies and is based on +// the sunset, but that is not too relevant for the algorithms here.) +// +// In this file an unqualified day of the week will refer to a standard weekday, and Hebrew weekdays +// will be referred to as "Hebrew Sunday" etc. Sometimes the term "regular" or "standard" will be used +// to refer to a standard weekday when we particularly wish to avoid ambiguity. +// +// Hebrew weeks start on Sunday. A common notation for times of the week looks like 2-5-204, which +// means "second Hebrew Day of the week, 5h 204 ḥal", which is 5h 204 ḥal after the start of Hebrew +// Monday (which is 23h:204ḥal on standard Sunday). +// +// Some resources will use ḥalakim notation when talking about time during a standard day. This +// document will use standard `:` notation for this, as used above with 23h:204ḥal being equal to +// 5h 204ḥal. In other words, if a time is notated using dashes or spaces, it is relative to the +// hebrew start of day, whereas if it is notated using a colon, it is relative to midnight. +// +// Finally, Adjler, the resource we are using, uses both inclusive and exclusive time notation. It +// is typical across resources using the 2-5-204 notation for the 2 to be "second day" as opposed +// to "two full days have passed" (i.e., on the first day). However *in the context of +// calculations* Adjler will use 1-5-204 to refer to stuff happening on Hebrew Monday, and clarify +// it as (2)-5-204. This is because zero-indexing works better in calculations. +// +// Comparing these algorithms with the source in Adjler should be careful about this. All other +// resources seem to universally 1-index in the dashes notation. This file will only use +// zero-indexed notation when explicitly disambiguated, usually when talking about intervals. + +/// Calculate the number of months preceding the molad Tishrei for a given hebrew year (Tishrei is the first month) +#[inline] +fn months_preceding_molad(h_year: i32) -> i64 { + // Ft = INT((235N + 1 / 19)) + // Where N = h_year - 1 (number of elapsed years since epoch) + // This math essentially comes from the Metonic cycle of 19 years containing + // 235 months: 12 months per year, plus an extra month for each of the 7 leap years. + + (235 * (i64::from(h_year) - 1) + 1).div_euclid(19) +} + +/// Conveniently create a constant for a ḥalakim (by default in 1-indexed notation). Produces a constant +/// that tracks the number of ḥalakim since the beginning of the week +macro_rules! ḥal { + ($d:literal-$h:literal-$p:literal) => {{ + const CONSTANT: i32 = (($d - 1) * 24 + $h) * 1080 + $p; + CONSTANT + }}; + (0-indexed $d:literal-$h:literal-$p:literal) => {{ + const CONSTANT: i32 = ($d * 24 + $h) * 1080 + $p; + CONSTANT + }}; +} + +/// The molad Beherad is the first molad, i.e. the molad of the epoch year. +/// It occurred on Oct 6, 3761 BC, 23h:204ḥal (Jerusalem Time, Julian Calendar) +/// +/// Which is the second Hebrew day of the week (Hebrew Monday), 5h 204ḥal, 2-5-204. +/// ("Beharad" בהרד is just a way of writing 2-5-204, ב-ה-רד using Hebrew numerals) +/// +/// This is 31524ḥal after the start of the week (Saturday 6PM) +/// +/// From Adjler Appendix A +const MOLAD_BEHERAD_OFFSET: i32 = ḥal!(2 - 5 - 204); + +/// The amount of time a Hebrew lunation takes (in ḥalakim). This is not exactly the amount of time +/// taken by one revolution of the moon (the real world seldom has events that are perfect integer +/// multiples of 1080ths of an hour), but it is what the Hebrew calendar uses. This does mean that +/// there will be drift over time with the actual state of the celestial sphere, however that is +/// irrelevant since the actual state of the celestial sphere is not what is used for the Hebrew +/// calendar. +/// +/// This is 29-12-793 in zero-indexed notation. It is equal to 765433ḥal. +/// From Adjler Appendix A +const HEBREW_LUNATION_TIME: i32 = ḥal!(0-indexed 29-12-793); + +/// From Reingold (ch 8.2, in implementation for fixed-from-hebrew) +const HEBREW_APPROX_YEAR_LENGTH: f64 = 35975351.0 / 98496.0; + +/// The number of ḥalakim in a week +/// +/// (This is 181440) +const ḤALAKIM_IN_WEEK: i64 = 1080 * 24 * 7; + +/// The Hebrew calendar epoch. It did not need to be postponed, so it occurs on Hebrew Monday, Oct 7, 3761 BCE (Julian), +/// the same as the Molad Beherad. +/// +/// (note that the molad Beherad occurs on standard Sunday, but because it happens after 6PM it is still Hebrew Monday) +const HEBREW_CALENDAR_EPOCH: RataDie = crate::julian::fixed_from_julian_book_version(-3761, 10, 7); + +/// The minumum hebrew year supported by this code (this is the minimum value for i32) +pub const HEBREW_MIN_YEAR: i32 = i32::MIN; +/// The minumum R.D. supported by this code (this code will clamp outside of it) +// (this constant is verified by tests) +pub const HEBREW_MIN_RD: RataDie = RataDie::new(-784362951979); +/// The maximum hebrew year supported by this code (this is the maximum alue for i32) +// (this constant is verified by tests) +pub const HEBREW_MAX_YEAR: i32 = i32::MAX; +/// The maximum R.D. supported by this code (this is the last day in [`HEBREW_MAX_YEAR`]) +// (this constant is verified by tests) +pub const HEBREW_MAX_RD: RataDie = RataDie::new(784360204356); + +/// Given a Hebrew Year, returns its molad specified as: +/// +/// - The number of weeks since the week of Beharad (Oct 6, 3761 BCE Julian) +/// - The number of ḥalakim since the start of the week (Hebrew Sunday, starting on Saturday at 18:00) +#[inline] +fn molad_details(h_year: i32) -> (i64, i32) { + let months_preceding = months_preceding_molad(h_year); + + // The molad tishri expressed in parts since the beginning of the week containing Molad of Beharad + // Formula from Adjler Appendix A + let molad = MOLAD_BEHERAD_OFFSET as i64 + months_preceding * HEBREW_LUNATION_TIME as i64; + + // Split into quotient and remainder + let weeks_since_beharad = molad.div_euclid(ḤALAKIM_IN_WEEK); + let in_week = molad.rem_euclid(ḤALAKIM_IN_WEEK); + + let in_week = i32::try_from(in_week); + debug_assert!(in_week.is_ok(), "ḤALAKIM_IN_WEEK should fit in an i32"); + + (weeks_since_beharad, in_week.unwrap_or(0)) +} + +/// Everything about a given year. Can be conveniently packed down into an i64 if needed. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +#[allow(clippy::exhaustive_structs)] // This may change but we're fine breaking this crate +pub struct YearInfo { + /// The Keviyah of the year + pub keviyah: Keviyah, + /// How many full weeks have passed since the week of Beharad + pub weeks_since_beharad: i64, +} + +impl YearInfo { + /// Compute the YearInfo for a given year + #[inline] + pub fn compute_for(h_year: i32) -> Self { + let (mut weeks_since_beharad, ḥalakim) = molad_details(h_year); + + let cycle_type = MetonicCycleType::for_h_year(h_year); + + let keviyah = keviyah_for(cycle_type, ḥalakim); + + // The last six hours of Hebrew Saturday (i.e. after noon on Regular Saturday) + // get unconditionally postponed to Monday according to the Four Gates table. This + // puts us in a new week! + if ḥalakim >= ḥal!(7 - 18 - 0) { + weeks_since_beharad += 1; + } + + Self { + keviyah, + weeks_since_beharad, + } + } + + /// Returns the YearInfo and h_year for the year containing `date` + /// + /// This will clamp the R.D. such that the hebrew year is within range for i32 + #[inline] + pub fn year_containing_rd(date: RataDie) -> (Self, i32) { + #[allow(unused_imports)] + use core_maths::*; + + let date = date.clamp(HEBREW_MIN_RD, HEBREW_MAX_RD); + + let days_since_epoch = (date - HEBREW_CALENDAR_EPOCH) as f64; + let maybe_approx = + i64_to_i32(1 + days_since_epoch.div_euclid(HEBREW_APPROX_YEAR_LENGTH) as i64); + let approx = maybe_approx.unwrap_or_else(|e| e.saturate()); + + let yi = Self::compute_for(approx); + + // compute if yi ⩼ rd + let cmp = yi.compare(date); + + let (yi, h_year) = match cmp { + // The approx year is a year greater. Go one year down + Ordering::Greater => { + let prev = approx.saturating_sub(1); + (Self::compute_for(prev), prev) + } + // Bullseye + Ordering::Equal => (yi, approx), + // The approx year is a year lower. Go one year up. + Ordering::Less => { + let next = approx.saturating_add(1); + (Self::compute_for(next), next) + } + }; + + debug_assert!(yi.compare(date).is_eq(), + "Date {date:?} calculated approximately to Hebrew Year {approx} (comparison: {cmp:?}), \ + should be contained in adjacent year {h_year} but that year is still {:?} it", yi.compare(date)); + + (yi, h_year) + } + + /// Compare this year against a date. Returns Ordering::Greater + /// when this year is after the given date + /// + /// i.e. this is computing self ⩼ rd + fn compare(self, rd: RataDie) -> Ordering { + let ny = self.new_year(); + let len = self.keviyah.year_length(); + + if rd < ny { + Ordering::Greater + } else if rd >= ny + len.into() { + Ordering::Less + } else { + Ordering::Equal + } + } + + /// Compute the date of New Year's Day + #[inline] + pub fn new_year(self) -> RataDie { + // Beharad started on Monday + const BEHARAD_START_OF_YEAR: StartOfYear = StartOfYear::Monday; + let days_since_beharad = (self.weeks_since_beharad * 7) + + self.keviyah.start_of_year() as i64 + - BEHARAD_START_OF_YEAR as i64; + HEBREW_CALENDAR_EPOCH + days_since_beharad + } +} + +/// The Keviyah (קביעה) of a year. +/// +/// A year may be one of fourteen types, categorized by the day of +/// week of the new year (the first number, 1 = Sunday), the type of year (Deficient, Regular, +/// Complete), and the day of week of the first day of Passover. The last segment disambiguates +/// between cases that have the same first two but differ on whether they are leap years (since +/// Passover happens in Nisan, after the leap month Adar). +/// +/// The discriminant values of these entries are according to +/// the positions these keviyot appear in the Four Gates table, +/// with the leap year ones being offset by 7. We don't directly rely on this +/// property but it is useful for potential bitpacking, and we use it as a way +/// to double-check that the four gates code is set up correctly. We do directly +/// rely on the leap-keviyot being after the regular ones (and starting with בחה) in is_leap. +/// +/// For people unsure if their editor supports bidirectional text, +/// the first Keviyah (2D3) is Bet (ב), Ḥet (ח), Gimel (ג). +/// +/// (The Hebrew values are used in code for two reasons: firstly, Rust identifiers +/// can't start with a number, and secondly, sources differ on the Latin alphanumeric notation +/// but use identical Hebrew notation) +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] +#[allow(clippy::exhaustive_enums)] // There are only 14 keviyot (and always have been) +pub enum Keviyah { + // Regular years + /// 2D3 + בחג = 0, + /// 2C5 + בשה = 1, + /// 3R5 + גכה = 2, + /// 5R7 + הכז = 3, + /// 5C1 + השא = 4, + /// 7D1 + זחא = 5, + /// 7C3 + זשג = 6, + + // Leap years + /// 2D5 + בחה = 7, + /// 2C7 + בשז = 8, + /// 3R7 + גכז = 9, + /// 5D1 + החא = 10, + /// 5C3 + השג = 11, + /// 7D3 + זחג = 12, + /// 7C5 + זשה = 13, +} + +/// The type of year it is +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] +#[allow(clippy::exhaustive_enums)] // This is intrinsic to the calendar +pub enum YearType { + /// חסרה: both Ḥeshvan and Kislev have 29 days + Deficient = -1, + /// כסדרה: Ḥeshvan has 29, Kislev has 30 + Regular = 0, + /// שלמה: both Ḥeshvan and Kislev have 30 days + Complete = 1, +} + +impl YearType { + /// The length correction from a regular year (354/385) + fn length_correction(self) -> i8 { + self as i8 + } + + /// The length of Ḥeshvan + fn ḥeshvan_length(self) -> u8 { + if self == Self::Complete { + ḤESHVAN_DEFAULT_LEN + 1 + } else { + ḤESHVAN_DEFAULT_LEN + } + } + + /// The length correction of Kislev + fn kislev_length(self) -> u8 { + if self == Self::Deficient { + KISLEV_DEFAULT_LEN - 1 + } else { + KISLEV_DEFAULT_LEN + } + } +} +/// The day of the new year. Only these four days are permitted. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] +#[allow(clippy::exhaustive_enums)] // This is intrinsic to the calendar +pub enum StartOfYear { + // Compiler forced me to document these, + /// Monday (everyone knows what Monday is) + Monday = 2, + /// Tuesday (everyone knows what Tuesday is) + Tuesday = 3, + /// Thursday (everyone knows what Thursday is) + Thursday = 5, + /// Saturday (everyone knows what Saturday is) + Saturday = 7, +} + +// Given a constant expression of the type FOO + BAR + BAZ convert +// every element into a u16 and return +macro_rules! u16_cvt( + // the $first / $rest pattern is needed since + // macros cannot use `+` as a separator in repetition + ($first:ident $(+ $rest:ident)*) => { + { + // make sure it is constant + // we use as here because it works in consts and in this context + // overflow will panic anyway + const COMPUTED: u16 = $first as u16 $(+ $rest as u16)*; + COMPUTED + } + }; +); + +// Month lengths (ref: https://en.wikipedia.org/wiki/Hebrew_calendar#Months) +const TISHREI_LEN: u8 = 30; +// except in Complete years +const ḤESHVAN_DEFAULT_LEN: u8 = 29; +// Except in Deficient years +const KISLEV_DEFAULT_LEN: u8 = 30; +const TEVET_LEN: u8 = 29; +const SHEVAT_LEN: u8 = 30; +const ADARI_LEN: u8 = 30; +const ADAR_LEN: u8 = 29; +const NISAN_LEN: u8 = 30; +const IYYAR_LEN: u8 = 29; +const SIVAN_LEN: u8 = 30; +const TAMMUZ_LEN: u8 = 29; +const AV_LEN: u8 = 30; +const ELUL_LEN: u8 = 29; + +/// Normalized month constant for Tishrei +/// +/// These are not ordinal months, rather these are the month number in a regular year +/// Adar, Adar I and Adar II all normalize to 6 +pub const TISHREI: u8 = 1; +/// Normalized month constant (see [`TISHREI`]) +pub const ḤESHVAN: u8 = 2; +/// Normalized month constant (see [`TISHREI`]) +pub const KISLEV: u8 = 3; +/// Normalized month constant (see [`TISHREI`]) +pub const TEVET: u8 = 4; +/// Normalized month constant (see [`TISHREI`]) +pub const SHEVAT: u8 = 5; +/// Normalized month constant (see [`TISHREI`]) +pub const ADAR: u8 = 6; +/// Normalized month constant (see [`TISHREI`]) +pub const NISAN: u8 = 7; +/// Normalized month constant (see [`TISHREI`]) +pub const IYYAR: u8 = 8; +/// Normalized month constant (see [`TISHREI`]) +pub const SIVAN: u8 = 9; +/// Normalized month constant (see [`TISHREI`]) +pub const TAMMUZ: u8 = 10; +/// Normalized month constant (see [`TISHREI`]) +pub const AV: u8 = 11; +/// Normalized month constant (see [`TISHREI`]) +pub const ELUL: u8 = 12; + +impl Keviyah { + /// Get the type of year for this Keviyah. + /// + /// Comes from the second letter in this Keviyah: + /// ח = D, כ = R, ש = C + #[inline] + pub fn year_type(self) -> YearType { + match self { + Self::בחג => YearType::Deficient, + Self::בשה => YearType::Complete, + Self::גכה => YearType::Regular, + Self::הכז => YearType::Regular, + Self::השא => YearType::Complete, + Self::זחא => YearType::Deficient, + Self::זשג => YearType::Complete, + Self::בחה => YearType::Deficient, + Self::בשז => YearType::Complete, + Self::גכז => YearType::Regular, + Self::החא => YearType::Deficient, + Self::השג => YearType::Complete, + Self::זחג => YearType::Deficient, + Self::זשה => YearType::Complete, + } + } + /// Get the day of the new year for this Keviyah + /// + /// Comes from the first letter in this Keviyah: + /// ב = 2 = Monday, ג = 3 = Tuesday, ה = 5 = Thursday, ז = 7 = Saturday + #[inline] + pub fn start_of_year(self) -> StartOfYear { + match self { + Self::בחג => StartOfYear::Monday, + Self::בשה => StartOfYear::Monday, + Self::גכה => StartOfYear::Tuesday, + Self::הכז => StartOfYear::Thursday, + Self::השא => StartOfYear::Thursday, + Self::זחא => StartOfYear::Saturday, + Self::זשג => StartOfYear::Saturday, + Self::בחה => StartOfYear::Monday, + Self::בשז => StartOfYear::Monday, + Self::גכז => StartOfYear::Tuesday, + Self::החא => StartOfYear::Thursday, + Self::השג => StartOfYear::Thursday, + Self::זחג => StartOfYear::Saturday, + Self::זשה => StartOfYear::Saturday, + } + } + + /// Normalize the ordinal month to the "month number" in the year (ignoring + /// leap months), i.e. Adar and Adar II are both represented by 6. + /// + /// Returns None if given the index of Adar I (6 in a leap year) + #[inline] + fn normalized_ordinal_month(self, ordinal_month: u8) -> Option { + if self.is_leap() { + match ordinal_month.cmp(&6) { + // Adar I + Ordering::Equal => None, + Ordering::Less => Some(ordinal_month), + Ordering::Greater => Some(ordinal_month - 1), + } + } else { + Some(ordinal_month) + } + } + + /// Given an ordinal, civil month (1-indexed month starting at Tishrei) + /// return its length + #[inline] + pub fn month_len(self, ordinal_month: u8) -> u8 { + // Normalize it to the month number + let Some(normalized_ordinal_month) = self.normalized_ordinal_month(ordinal_month) else { + return ADARI_LEN; + }; + debug_assert!(normalized_ordinal_month <= 12 && normalized_ordinal_month > 0); + match normalized_ordinal_month { + TISHREI => TISHREI_LEN, + ḤESHVAN => self.year_type().ḥeshvan_length(), + KISLEV => self.year_type().kislev_length(), + TEVET => TEVET_LEN, + SHEVAT => SHEVAT_LEN, + ADAR => ADAR_LEN, + NISAN => NISAN_LEN, + IYYAR => IYYAR_LEN, + SIVAN => SIVAN_LEN, + TAMMUZ => TAMMUZ_LEN, + AV => AV_LEN, + ELUL => ELUL_LEN, + _ => { + debug_assert!(false, "Got unknown month index {ordinal_month}"); + 30 + } + } + } + + /// Get the number of days preceding this month + #[inline] + pub fn days_preceding(self, ordinal_month: u8) -> u16 { + // convenience constant to keep the additions smallish + // Number of days before (any) Adar in a regular year + const BEFORE_ADAR_DEFAULT_LEN: u16 = u16_cvt!( + TISHREI_LEN + ḤESHVAN_DEFAULT_LEN + KISLEV_DEFAULT_LEN + TEVET_LEN + SHEVAT_LEN + ); + + let Some(normalized_ordinal_month) = self.normalized_ordinal_month(ordinal_month) else { + // Get Adar I out of the way + let corrected = + BEFORE_ADAR_DEFAULT_LEN as i16 + i16::from(self.year_type().length_correction()); + return corrected as u16; + }; + debug_assert!(normalized_ordinal_month <= ELUL && normalized_ordinal_month > 0); + + let year_type = self.year_type(); + + let mut days = match normalized_ordinal_month { + TISHREI => 0, + ḤESHVAN => u16_cvt!(TISHREI_LEN), + KISLEV => u16_cvt!(TISHREI_LEN) + u16::from(year_type.ḥeshvan_length()), + // Use default lengths after this, we'll apply the correction later + // (This helps optimize this into a simple jump table) + TEVET => u16_cvt!(TISHREI_LEN + ḤESHVAN_DEFAULT_LEN + KISLEV_DEFAULT_LEN), + SHEVAT => u16_cvt!(TISHREI_LEN + ḤESHVAN_DEFAULT_LEN + KISLEV_DEFAULT_LEN + TEVET_LEN), + ADAR => BEFORE_ADAR_DEFAULT_LEN, + NISAN => u16_cvt!(BEFORE_ADAR_DEFAULT_LEN + ADAR_LEN), + IYYAR => u16_cvt!(BEFORE_ADAR_DEFAULT_LEN + ADAR_LEN + NISAN_LEN), + SIVAN => u16_cvt!(BEFORE_ADAR_DEFAULT_LEN + ADAR_LEN + NISAN_LEN + IYYAR_LEN), + TAMMUZ => { + u16_cvt!(BEFORE_ADAR_DEFAULT_LEN + ADAR_LEN + NISAN_LEN + IYYAR_LEN + SIVAN_LEN) + } + #[rustfmt::skip] + AV => u16_cvt!(BEFORE_ADAR_DEFAULT_LEN + ADAR_LEN + NISAN_LEN + IYYAR_LEN + SIVAN_LEN + TAMMUZ_LEN), + #[rustfmt::skip] + _ => u16_cvt!(BEFORE_ADAR_DEFAULT_LEN + ADAR_LEN + NISAN_LEN + IYYAR_LEN + SIVAN_LEN + TAMMUZ_LEN + AV_LEN), + }; + + // If it is after Kislev and Ḥeshvan, we should add the year correction + if normalized_ordinal_month > KISLEV { + // Ensure the casts are fine + debug_assert!(days > 1 && year_type.length_correction().abs() <= 1); + days = (days as i16 + year_type.length_correction() as i16) as u16; + } + + // In a leap year, after Adar (and including Adar II), we should add + // the length of Adar 1 + if normalized_ordinal_month >= ADAR && self.is_leap() { + days += u16::from(ADARI_LEN); + } + + days + } + + /// Given a day of the year, return the ordinal month and day as (month, day). + pub fn month_day_for(self, mut day: u16) -> (u8, u8) { + for month in 1..14 { + let month_len = self.month_len(month); + if let Ok(day) = u8::try_from(day) { + if day <= month_len { + return (month, day); + } + } + day -= u16::from(month_len); + } + debug_assert!(false, "Attempted to get Hebrew date for {day:?}, in keviyah {self:?}, didn't have enough days in the year"); + self.last_month_day_in_year() + } + + /// Return the last ordinal month and day in this year as (month, day) + #[inline] + pub fn last_month_day_in_year(self) -> (u8, u8) { + // Elul is always the last month of the year + if self.is_leap() { + (13, ELUL_LEN) + } else { + (12, ELUL_LEN) + } + } + + /// Whether this year is a leap year + #[inline] + pub fn is_leap(self) -> bool { + debug_assert_eq!(Self::בחה as u8, 7, "Representation of keviyot changed!"); + // Because we have arranged our keviyot such that all leap keviyot come after + // the regular ones, this just a comparison + self >= Self::בחה + } + + /// Given the hebrew year for this Keviyah, calculate the YearInfo + #[inline] + pub fn year_info(self, h_year: i32) -> YearInfo { + let (mut weeks_since_beharad, ḥalakim) = molad_details(h_year); + + // The last six hours of Hebrew Saturday (i.e. after noon on Regular Saturday) + // get unconditionally postponed to Monday according to the Four Gates table. This + // puts us in a new week! + if ḥalakim >= ḥal!(7 - 18 - 0) { + weeks_since_beharad += 1; + } + + YearInfo { + keviyah: self, + weeks_since_beharad, + } + } + + /// How many days are in this year + #[inline] + pub fn year_length(self) -> u16 { + let base_year_length = if self.is_leap() { 384 } else { 354 }; + + (base_year_length + i16::from(self.year_type().length_correction())) as u16 + } + /// Construct this from an integer between 0 and 13 + /// + /// Potentially useful for bitpacking + #[inline] + pub fn from_integer(integer: u8) -> Self { + debug_assert!( + integer < 14, + "Keviyah::from_integer() takes in a number between 0 and 13 inclusive" + ); + match integer { + 0 => Self::בחג, + 1 => Self::בשה, + 2 => Self::גכה, + 3 => Self::הכז, + 4 => Self::השא, + 5 => Self::זחא, + 6 => Self::זשג, + 7 => Self::בחה, + 8 => Self::בשז, + 9 => Self::גכז, + 10 => Self::החא, + 11 => Self::השג, + 12 => Self::זחג, + _ => Self::זשה, + } + } +} + +// Four Gates Table +// ====================== +// +// The Four Gates table is a table that takes the time of week of the molad +// and produces a Keviyah for the year +/// "Metonic cycle" in general refers to any 19-year repeating pattern used by lunisolar +/// calendars. The Hebrew calendar uses one where years 3, 6, 8, 11, 14, 17, 19 +/// are leap years. +/// +/// The Hebrew calendar further categorizes regular years as whether they come before/after/or +/// between leap years, and this is used when performing lookups. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +enum MetonicCycleType { + /// Before a leap year (2, 5, 10, 13, 16) + LMinusOne, + /// After a leap year (1, 4, 9, 12, 15) + LPlusOne, + /// Between leap years (7. 18) + LPlusMinusOne, + /// Leap year (3, 6, 8, 11, 14, 17, 19) + Leap, +} + +impl MetonicCycleType { + fn for_h_year(h_year: i32) -> Self { + // h_year is 1-indexed, and our metonic cycle year numberings + // are 1-indexed, so we really need to do `(h_year - 1) % 19 + 1` + // + // However, that is equivalent to `h_year % 19` provided you handle the + // fact that that operation will produce 0 instead of 19. + // Both numbers end up in our wildcard leap year arm so that's fine. + let remainder = h_year.rem_euclid(19); + match remainder { + // These numbers are 1-indexed + 2 | 5 | 10 | 13 | 16 => Self::LMinusOne, + 1 | 4 | 9 | 12 | 15 => Self::LPlusOne, + 7 | 18 => Self::LPlusMinusOne, + _ => { + debug_assert!(matches!(remainder, 3 | 6 | 8 | 11 | 14 | 17 | 0 | 19)); + Self::Leap + } + } + } +} + +// The actual Four Gates tables. +// +// Each entry is a range (ending at the next entry), and it corresponds to the equivalent discriminant value of the Keviyah type. +// Leap and regular years map to different Keviyah values, however regular years all map to the same set of +// seven values, with differing ḥalakim bounds for each. The first entry in the Four Gates table straddles the end of the previous week +// and the beginning of this one. +// +// The regular-year tables only differ by their third and last entries (We may be able to write this as more compact code) +// +// You can reference these tables from https://en.wikipedia.org/wiki/Hebrew_calendar#The_four_gates +// or from Adjler (Appendix 4). Be sure to look at the Adjler table referring the "modern calendar", older tables +// use slightly different numbers. +const FOUR_GATES_LMINUSONE: [i32; 7] = [ + ḥal!(7 - 18 - 0), + ḥal!(1 - 9 - 204), + ḥal!(2 - 18 - 0), + ḥal!(3 - 9 - 204), + ḥal!(5 - 9 - 204), + ḥal!(5 - 18 - 0), + ḥal!(6 - 9 - 204), +]; +const FOUR_GATES_LPLUSONE: [i32; 7] = [ + ḥal!(7 - 18 - 0), + ḥal!(1 - 9 - 204), + ḥal!(2 - 15 - 589), + ḥal!(3 - 9 - 204), + ḥal!(5 - 9 - 204), + ḥal!(5 - 18 - 0), + ḥal!(6 - 0 - 408), +]; + +const FOUR_GATES_LPLUSMINUSONE: [i32; 7] = [ + ḥal!(7 - 18 - 0), + ḥal!(1 - 9 - 204), + ḥal!(2 - 15 - 589), + ḥal!(3 - 9 - 204), + ḥal!(5 - 9 - 204), + ḥal!(5 - 18 - 0), + ḥal!(6 - 9 - 204), +]; + +const FOUR_GATES_LEAP: [i32; 7] = [ + ḥal!(7 - 18 - 0), + ḥal!(1 - 20 - 491), + ḥal!(2 - 18 - 0), + ḥal!(3 - 18 - 0), + ḥal!(4 - 11 - 695), + ḥal!(5 - 18 - 0), + ḥal!(6 - 20 - 491), +]; + +/// Perform the four gates calculation, giving you the Keviyah for a given year type and +/// the ḥalakim-since-beginning-of-week of its molad Tishri +#[inline] +fn keviyah_for(year_type: MetonicCycleType, ḥalakim: i32) -> Keviyah { + let gate = match year_type { + MetonicCycleType::LMinusOne => FOUR_GATES_LMINUSONE, + MetonicCycleType::LPlusOne => FOUR_GATES_LPLUSONE, + MetonicCycleType::LPlusMinusOne => FOUR_GATES_LPLUSMINUSONE, + MetonicCycleType::Leap => FOUR_GATES_LEAP, + }; + + // Calculate the non-leap and leap keviyot for this year + // This could potentially be made more efficient by just finding + // the right window on `gate` and transmuting, but this unrolled loop should be fine too. + let keviyot = if ḥalakim >= gate[0] || ḥalakim < gate[1] { + (Keviyah::בחג, Keviyah::בחה) + } else if ḥalakim < gate[2] { + (Keviyah::בשה, Keviyah::בשז) + } else if ḥalakim < gate[3] { + (Keviyah::גכה, Keviyah::גכז) + } else if ḥalakim < gate[4] { + (Keviyah::הכז, Keviyah::החא) + } else if ḥalakim < gate[5] { + (Keviyah::השא, Keviyah::השג) + } else if ḥalakim < gate[6] { + (Keviyah::זחא, Keviyah::זחג) + } else { + (Keviyah::זשג, Keviyah::זשה) + }; + + // We have conveniently set the discriminant value of Keviyah to match the four gates index + // Let's just assert to make sure the table above is correct. + debug_assert!( + keviyot.0 as u8 + 7 == keviyot.1 as u8, + "The table above should produce matching-indexed keviyot for the leap/non-leap year" + ); + #[cfg(debug_assertions)] + #[expect(clippy::indexing_slicing)] // debug_assertion code + if keviyot.0 as u8 == 0 { + // The first entry in the gates table straddles the ends of the week + debug_assert!( + ḥalakim >= gate[keviyot.0 as usize] || ḥalakim < gate[(keviyot.0 as usize + 1) % 7], + "The table above should produce the right indexed keviyah, instead found {keviyot:?} for time {ḥalakim} (year type {year_type:?})" + ); + } else { + // Other entries must properly bound the ḥalakim + debug_assert!( + ḥalakim >= gate[keviyot.0 as usize] && ḥalakim < gate[(keviyot.0 as usize + 1) % 7], + "The table above should produce the right indexed keviyah, instead found {keviyot:?} for time {ḥalakim} (year type {year_type:?})" + ); + } + + if year_type == MetonicCycleType::Leap { + keviyot.1 + } else { + keviyot.0 + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::hebrew::{self, BookHebrew}; + + #[test] + fn test_consts() { + assert_eq!(MOLAD_BEHERAD_OFFSET, 31524); + assert_eq!(ḤALAKIM_IN_WEEK, 181440); + // Adjler's printed value for this constant is incorrect (as confirmed by Adjler over email). + // Adjler is correct about the value being ḥal!(0-indexed 29-12-793). + // which matches the math used in `crate::hebrew::molad()` from Calendrical Calculations. + // + // The correct constant is seen in + assert_eq!(HEBREW_LUNATION_TIME, 765433); + + // Nicer to have the code be self-contained, but always worth asserting + assert_eq!(HEBREW_CALENDAR_EPOCH, hebrew::FIXED_HEBREW_EPOCH); + } + + #[test] + fn test_roundtrip_days() { + for h_year in (1..10).chain(5775..5795).chain(10000..10010) { + let year_info = YearInfo::compute_for(h_year); + let ny = year_info.new_year(); + for day in 1..=year_info.keviyah.year_length() { + let offset_date = ny + i64::from(day) - 1; + let (offset_yearinfo, offset_h_year) = YearInfo::year_containing_rd(offset_date); + + assert_eq!( + offset_h_year, h_year, + "Backcomputed h_year should be same for day {day} in Hebrew Year {h_year}" + ); + assert_eq!( + offset_yearinfo, year_info, + "Backcomputed YearInfo should be same for day {day} in Hebrew Year {h_year}" + ); + + let (month, day2) = year_info.keviyah.month_day_for(day); + + let days_preceding = year_info.keviyah.days_preceding(month); + + assert_eq!( + days_preceding + u16::from(day2), + day, + "{h_year}-{month}-{day2} should round trip for day-of-year {day}" + ) + } + } + } + #[test] + fn test_book_parity() { + let mut last_year = None; + for h_year in (1..100).chain(5600..5900).chain(10000..10100) { + let book_date = BookHebrew::from_civil_date(h_year, 1, 1); + let book_ny = BookHebrew::fixed_from_book_hebrew(book_date); + let kv_yearinfo = YearInfo::compute_for(h_year); + let kv_ny = kv_yearinfo.new_year(); + assert_eq!( + book_ny, + kv_ny, + "Book and Keviyah-based years should match for Hebrew Year {h_year}. Got YearInfo {kv_yearinfo:?}" + ); + let book_is_leap = BookHebrew::is_hebrew_leap_year(h_year); + assert_eq!( + book_is_leap, + kv_yearinfo.keviyah.is_leap(), + "Book and Keviyah-based years should match for Hebrew Year {h_year}. Got YearInfo {kv_yearinfo:?}" + ); + + let book_year_len = BookHebrew::days_in_book_hebrew_year(h_year); + let book_year_type = match book_year_len { + 355 | 385 => YearType::Complete, + 354 | 384 => YearType::Regular, + 353 | 383 => YearType::Deficient, + _ => unreachable!("Found unexpected book year len {book_year_len}"), + }; + assert_eq!( + book_year_type, + kv_yearinfo.keviyah.year_type(), + "Book and Keviyah-based years should match for Hebrew Year {h_year}. Got YearInfo {kv_yearinfo:?}" + ); + + let kv_recomputed_yearinfo = kv_yearinfo.keviyah.year_info(h_year); + assert_eq!( + kv_recomputed_yearinfo, + kv_yearinfo, + "Recomputed YearInfo should match for Hebrew Year {h_year}. Got YearInfo {kv_yearinfo:?}" + ); + + let year_len = kv_yearinfo.keviyah.year_length(); + + let month_range = if kv_yearinfo.keviyah.is_leap() { + 1..14 + } else { + 1..13 + }; + + let mut days_preceding = 0; + + for month in month_range { + let kv_month_len = kv_yearinfo.keviyah.month_len(month); + let book_date = BookHebrew::from_civil_date(h_year, month, 1); + let book_month_len = + BookHebrew::last_day_of_book_hebrew_month(book_date.year, book_date.month); + assert_eq!(kv_month_len, book_month_len, "Month lengths should be same for ordinal hebrew month {month} in year {h_year}. Got YearInfo {kv_yearinfo:?}"); + + assert_eq!(days_preceding, kv_yearinfo.keviyah.days_preceding(month), "Days preceding should be the sum of preceding days for ordinal hebrew month {month} in year {h_year}. Got YearInfo {kv_yearinfo:?}"); + days_preceding += u16::from(kv_month_len); + } + + for offset in [0, 1, 100, year_len - 100, year_len - 2, year_len - 1] { + let offset_date = kv_ny + offset.into(); + let (offset_yearinfo, offset_h_year) = YearInfo::year_containing_rd(offset_date); + + assert_eq!(offset_h_year, h_year, "Backcomputed h_year should be same for date {offset_date:?} in Hebrew Year {h_year} (offset from ny {offset})"); + assert_eq!(offset_yearinfo, kv_yearinfo, "Backcomputed YearInfo should be same for date {offset_date:?} in Hebrew Year {h_year} (offset from ny {offset})"); + } + + if let Some((last_h_year, predicted_ny)) = last_year { + if last_h_year + 1 == h_year { + assert_eq!(predicted_ny, kv_ny, "{last_h_year}'s YearInfo predicts New Year {predicted_ny:?}, which does not match current new year. Got YearInfo {kv_yearinfo:?}"); + } + } + + last_year = Some((h_year, kv_ny + year_len.into())) + } + } + #[test] + fn test_minmax() { + let min = YearInfo::compute_for(HEBREW_MIN_YEAR); + let min_ny = min.new_year(); + assert_eq!(min_ny, HEBREW_MIN_RD); + + let (recomputed_yi, recomputed_y) = YearInfo::year_containing_rd(min_ny); + assert_eq!(recomputed_y, HEBREW_MIN_YEAR); + assert_eq!(recomputed_yi, min); + + let max = YearInfo::compute_for(HEBREW_MAX_YEAR); + let max_ny = max.new_year(); + // -1 since max_ny is also a part of the year + let max_last = max_ny + i64::from(max.keviyah.year_length()) - 1; + assert_eq!(max_last, HEBREW_MAX_RD); + + let (recomputed_yi, recomputed_y) = YearInfo::year_containing_rd(max_last); + assert_eq!(recomputed_y, HEBREW_MAX_YEAR); + assert_eq!(recomputed_yi, max); + } + + #[test] + fn test_leap_agreement() { + for year0 in -1000..1000 { + let year1 = year0 + 1; + let info0 = YearInfo::compute_for(year0); + let info1 = YearInfo::compute_for(year1); + let num_months = (info1.new_year() - info0.new_year()) / 29; + if info0.keviyah.is_leap() { + assert_eq!(num_months, 13, "{year0}"); + } else { + assert_eq!(num_months, 12, "{year0}"); + } + } + } + #[test] + fn test_issue_6262() { + // These are years where the molad ḥalakim is *exactly* ḥal!(7 - 18 - 0), we need + // to ensure the Saturday wraparound logic works correctly + + let rds = [ + // 72036-07-10 + (26310435, 75795), + // 189394-12-06 + (69174713, 193152), + ]; + + for (rd, expected_year) in rds { + let rd = RataDie::new(rd); + let (yi, year) = YearInfo::year_containing_rd(rd); + assert_eq!(year, expected_year); + + let yi_recomputed = yi.keviyah.year_info(year); + assert_eq!(yi, yi_recomputed); + // Double check that these testcases are on the boundary + let (_weeks, ḥalakim) = molad_details(year); + assert_eq!(ḥalakim, ḥal!(7 - 18 - 0)); + } + } +} diff --git a/deps/crates/vendor/calendrical_calculations/src/helpers.rs b/deps/crates/vendor/calendrical_calculations/src/helpers.rs new file mode 100644 index 00000000000000..b19160b6f96e95 --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/src/helpers.rs @@ -0,0 +1,347 @@ +// This file is part of ICU4X. +// +// The contents of this file implement algorithms from Calendrical Calculations +// by Reingold & Dershowitz, Cambridge University Press, 4th edition (2018), +// which have been released as Lisp code at +// under the Apache-2.0 license. Accordingly, this file is released under +// the Apache License, Version 2.0 which can be found at the calendrical_calculations +// package root or at http://www.apache.org/licenses/LICENSE-2.0. + +use crate::astronomy::Location; +use crate::rata_die::{Moment, RataDie}; +#[allow(unused_imports)] +use core_maths::*; + +pub(crate) trait IntegerRoundings { + fn div_ceil(self, rhs: Self) -> Self; +} + +impl IntegerRoundings for i64 { + // copied from std + fn div_ceil(self, rhs: Self) -> Self { + let d = self / rhs; + let r = self % rhs; + if (r > 0 && rhs > 0) || (r < 0 && rhs < 0) { + d + 1 + } else { + d + } + } +} + +#[test] +fn test_div_ceil() { + assert_eq!(IntegerRoundings::div_ceil(i64::MIN, 1), i64::MIN); + assert_eq!( + IntegerRoundings::div_ceil(i64::MIN, 2), + -4611686018427387904 + ); + assert_eq!( + IntegerRoundings::div_ceil(i64::MIN, 3), + -3074457345618258602 + ); + + assert_eq!(IntegerRoundings::div_ceil(-10, 1), -10); + assert_eq!(IntegerRoundings::div_ceil(-10, 2), -5); + assert_eq!(IntegerRoundings::div_ceil(-10, 3), -3); + + assert_eq!(IntegerRoundings::div_ceil(-9, 1), -9); + assert_eq!(IntegerRoundings::div_ceil(-9, 2), -4); + assert_eq!(IntegerRoundings::div_ceil(-9, 3), -3); + + assert_eq!(IntegerRoundings::div_ceil(-8, 1), -8); + assert_eq!(IntegerRoundings::div_ceil(-8, 2), -4); + assert_eq!(IntegerRoundings::div_ceil(-8, 3), -2); + + assert_eq!(IntegerRoundings::div_ceil(-2, 1), -2); + assert_eq!(IntegerRoundings::div_ceil(-2, 2), -1); + assert_eq!(IntegerRoundings::div_ceil(-2, 3), 0); + + assert_eq!(IntegerRoundings::div_ceil(-1, 1), -1); + assert_eq!(IntegerRoundings::div_ceil(-1, 2), 0); + assert_eq!(IntegerRoundings::div_ceil(-1, 3), 0); + + assert_eq!(IntegerRoundings::div_ceil(0, 1), 0); + assert_eq!(IntegerRoundings::div_ceil(0, 2), 0); + assert_eq!(IntegerRoundings::div_ceil(0, 3), 0); + + assert_eq!(IntegerRoundings::div_ceil(1, 1), 1); + assert_eq!(IntegerRoundings::div_ceil(1, 2), 1); + assert_eq!(IntegerRoundings::div_ceil(1, 3), 1); + + assert_eq!(IntegerRoundings::div_ceil(2, 1), 2); + assert_eq!(IntegerRoundings::div_ceil(2, 2), 1); + assert_eq!(IntegerRoundings::div_ceil(2, 3), 1); + + assert_eq!(IntegerRoundings::div_ceil(8, 1), 8); + assert_eq!(IntegerRoundings::div_ceil(8, 2), 4); + assert_eq!(IntegerRoundings::div_ceil(8, 3), 3); + + assert_eq!(IntegerRoundings::div_ceil(9, 1), 9); + assert_eq!(IntegerRoundings::div_ceil(9, 2), 5); + assert_eq!(IntegerRoundings::div_ceil(9, 3), 3); + + assert_eq!(IntegerRoundings::div_ceil(10, 1), 10); + assert_eq!(IntegerRoundings::div_ceil(10, 2), 5); + assert_eq!(IntegerRoundings::div_ceil(10, 3), 4); + + assert_eq!(IntegerRoundings::div_ceil(i64::MAX, 1), 9223372036854775807); + assert_eq!(IntegerRoundings::div_ceil(i64::MAX, 2), 4611686018427387904); + assert_eq!(IntegerRoundings::div_ceil(i64::MAX, 3), 3074457345618258603); + + for n in -100..100 { + for d in 1..5 { + let x1 = IntegerRoundings::div_ceil(n, d); + let x2 = (n as f64 / d as f64).ceil(); + assert_eq!(x1, x2 as i64); + } + } +} + +// Highest power is *last* +pub(crate) fn poly(x: f64, coeffs: &[f64]) -> f64 { + coeffs.iter().rev().fold(0.0, |a, c| a * x + c) +} + +// A generic function that finds a value within an interval +// where a certain condition is satisfied. +pub(crate) fn binary_search( + mut l: f64, + mut h: f64, + test: impl Fn(f64) -> bool, + epsilon: f64, +) -> f64 { + debug_assert!(l < h); + + loop { + let mid = l + (h - l) / 2.0; + + // Determine which direction to go. `test` returns true if we need to go left. + (l, h) = if test(mid) { (l, mid) } else { (mid, h) }; + + // When the interval width reaches `epsilon`, return the current midpoint. + if (h - l) < epsilon { + return mid; + } + } +} + +pub(crate) fn next_moment(mut index: Moment, location: Location, condition: F) -> RataDie +where + F: Fn(Moment, Location) -> bool, +{ + loop { + if condition(index, location) { + return index.as_rata_die(); + } + index += 1.0; + } +} + +pub(crate) fn next(mut index: RataDie, condition: F) -> RataDie +where + F: Fn(RataDie) -> bool, +{ + loop { + if condition(index) { + return index; + } + index += 1; + } +} + +pub(crate) fn next_u8(mut index: u8, condition: F) -> u8 +where + F: Fn(u8) -> bool, +{ + loop { + if condition(index) { + return index; + } + index += 1; + } +} + +// "Final" is a reserved keyword in rust, which explains the naming convention here. +pub(crate) fn final_func(mut index: i32, condition: F) -> i32 +where + F: Fn(i32) -> bool, +{ + while condition(index) { + index += 1; + } + index - 1 +} + +#[test] +fn test_binary_search() { + struct TestCase { + test_fn: fn(f64) -> bool, + range: (f64, f64), + expected: f64, + } + + let test_cases = [ + TestCase { + test_fn: |x: f64| x >= 4.0, + range: (0.0, 10.0), + expected: 4.0, + }, + TestCase { + test_fn: |x: f64| x * x >= 2.0, + range: (0.0, 2.0), + expected: 2.0f64.sqrt(), + }, + TestCase { + test_fn: |x: f64| x >= -4.0, + range: (-10.0, 0.0), + expected: -4.0, + }, + TestCase { + test_fn: |x: f64| x >= 0.0, + range: (0.0, 10.0), + expected: 0.0, + }, + TestCase { + test_fn: |x: f64| x > 10.0, + range: (0.0, 10.0), + expected: 10.0, + }, + ]; + + for case in test_cases { + let result = binary_search(case.range.0, case.range.1, case.test_fn, 1e-4); + assert!((result - case.expected).abs() < 0.0001); + } +} + +pub(crate) fn invert_angular f64>(f: F, y: f64, r: (f64, f64)) -> f64 { + binary_search(r.0, r.1, |x| (f(x) - y).rem_euclid(360.0) < 180.0, 1e-5) +} + +#[test] +fn test_invert_angular() { + struct TestCase { + f: fn(f64) -> f64, + y: f64, + r: (f64, f64), + expected: f64, + } + + fn f1(x: f64) -> f64 { + (2.0 * x).rem_euclid(360.0) + } + + fn f2(x: f64) -> f64 { + (3.0 * x).rem_euclid(360.0) + } + + fn f3(x: f64) -> f64 { + (x).rem_euclid(360.0) + } + // tolerance for comparing floating points. + let tolerance = 1e-5; + + let test_cases = [ + TestCase { + f: f1, + y: 4.0, + r: (0.0, 10.0), + expected: 4.0, + }, + TestCase { + f: f2, + y: 6.0, + r: (0.0, 20.0), + expected: 6.0, + }, + TestCase { + f: f3, + y: 400.0, + r: (0.0, 10.0), + expected: 10.0, + }, + TestCase { + f: f3, + y: 0.0, + r: (0.0, 10.0), + expected: 0.0, + }, + TestCase { + f: f3, + y: 10.0, + r: (0.0, 10.0), + expected: 10.0, + }, + ]; + + for case in test_cases { + let x = invert_angular(case.f, case.y, case.r); + assert!((((case.f)(x)).rem_euclid(360.0) - case.expected).abs() < tolerance); + } +} + +/// Error returned when casting from an i32 +#[derive(Copy, Clone, Debug, displaydoc::Display)] +#[allow(clippy::exhaustive_enums)] // enum is specific to function and has a closed set of possible values +pub enum I32CastError { + /// Less than i32::MIN + BelowMin, + /// Greater than i32::MAX + AboveMax, +} + +impl core::error::Error for I32CastError {} + +impl I32CastError { + /// Recovers the value saturated to `i32:::MIN..=i32::MAX`. + pub const fn saturate(self) -> i32 { + match self { + I32CastError::BelowMin => i32::MIN, + I32CastError::AboveMax => i32::MAX, + } + } +} + +/// Convert an i64 to i32 and with information on which way it was out of bounds if so +#[inline] +pub const fn i64_to_i32(input: i64) -> Result { + if input < i32::MIN as i64 { + Err(I32CastError::BelowMin) + } else if input > i32::MAX as i64 { + Err(I32CastError::AboveMax) + } else { + Ok(input as i32) + } +} + +/// Convert an i64 to i32 but saturate at th ebounds +#[inline] +pub(crate) fn i64_to_saturated_i32(input: i64) -> i32 { + i64_to_i32(input).unwrap_or_else(|i| i.saturate()) +} + +#[test] +fn test_i64_to_saturated_i32() { + assert_eq!(i64_to_saturated_i32(i64::MIN), i32::MIN); + assert_eq!(i64_to_saturated_i32(-2147483649), -2147483648); + assert_eq!(i64_to_saturated_i32(-2147483648), -2147483648); + assert_eq!(i64_to_saturated_i32(-2147483647), -2147483647); + assert_eq!(i64_to_saturated_i32(-2147483646), -2147483646); + assert_eq!(i64_to_saturated_i32(-100), -100); + assert_eq!(i64_to_saturated_i32(0), 0); + assert_eq!(i64_to_saturated_i32(100), 100); + assert_eq!(i64_to_saturated_i32(2147483646), 2147483646); + assert_eq!(i64_to_saturated_i32(2147483647), 2147483647); + assert_eq!(i64_to_saturated_i32(2147483648), 2147483647); + assert_eq!(i64_to_saturated_i32(2147483649), 2147483647); + assert_eq!(i64_to_saturated_i32(i64::MAX), i32::MAX); +} + +/// returns the weekday (0-6) after (strictly) the fixed date +pub(crate) const fn k_day_after(weekday: i64, fixed: RataDie) -> RataDie { + let day_of_week = fixed.to_i64_date().rem_euclid(7); + let beginning_of_week = fixed.to_i64_date() - day_of_week; + let day = beginning_of_week + weekday; + RataDie::new(day + if weekday <= day_of_week { 7 } else { 0 }) +} diff --git a/deps/crates/vendor/calendrical_calculations/src/islamic.rs b/deps/crates/vendor/calendrical_calculations/src/islamic.rs new file mode 100644 index 00000000000000..a1d9b1324fba04 --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/src/islamic.rs @@ -0,0 +1,262 @@ +use crate::astronomy::*; +use crate::helpers::{i64_to_saturated_i32, next}; +use crate::rata_die::{Moment, RataDie}; +#[allow(unused_imports)] +use core_maths::*; + +pub use crate::astronomy::Location; + +/// The average length of an Islamic year, equal to 12 moon cycles +pub const MEAN_YEAR_LENGTH: f64 = MEAN_SYNODIC_MONTH * 12.; + +/// Different islamic calendars use different epochs (Thursday vs Friday) due to disagreement on the exact date of Mohammed's migration to Mecca. +/// Lisp code reference: +pub const ISLAMIC_EPOCH_FRIDAY: RataDie = crate::julian::fixed_from_julian(622, 7, 16); + +/// Different islamic calendars use different epochs (Thursday vs Friday) due to disagreement on the exact date of Mohammed's migration to Mecca. +/// Lisp code reference: +pub const ISLAMIC_EPOCH_THURSDAY: RataDie = crate::julian::fixed_from_julian(622, 7, 15); + +// Inline to copy over docs. This can be made into a separate value as per need. +#[doc(inline)] +pub use crate::chinese_based::WELL_BEHAVED_ASTRONOMICAL_RANGE; + +/// Lisp code reference: +pub const CAIRO: Location = Location { + latitude: 30.1, + longitude: 31.3, + elevation: 200.0, + utc_offset: (1_f64 / 12_f64), +}; + +/// The location of Mecca; used for Islamic calendar calculations. +pub const MECCA: Location = Location { + latitude: 6427.0 / 300.0, + longitude: 11947.0 / 300.0, + elevation: 298.0, + utc_offset: (1_f64 / 8_f64), +}; + +/// Lisp code reference: +pub fn fixed_from_observational_islamic( + year: i32, + month: u8, + day: u8, + location: Location, +) -> RataDie { + let year = i64::from(year); + let month = i64::from(month); + let day = i64::from(day); + let midmonth = ISLAMIC_EPOCH_FRIDAY.to_f64_date() + + (((year - 1) as f64) * 12.0 + month as f64 - 0.5) * MEAN_SYNODIC_MONTH; + let lunar_phase = Astronomical::calculate_new_moon_at_or_before(RataDie::new(midmonth as i64)); + Astronomical::phasis_on_or_before(RataDie::new(midmonth as i64), location, Some(lunar_phase)) + + day + - 1 +} + +/// Lisp code reference: +pub fn observational_islamic_from_fixed(date: RataDie, location: Location) -> (i32, u8, u8) { + let lunar_phase = Astronomical::calculate_new_moon_at_or_before(date); + let crescent = Astronomical::phasis_on_or_before(date, location, Some(lunar_phase)); + let elapsed_months = + ((crescent - ISLAMIC_EPOCH_FRIDAY) as f64 / MEAN_SYNODIC_MONTH).round() as i32; + let year = elapsed_months.div_euclid(12) + 1; + let month = elapsed_months.rem_euclid(12) + 1; + let day = (date - crescent + 1) as u8; + + (year, month as u8, day) +} + +// Saudi visibility criterion on eve of fixed date in Mecca. +// The start of the new month only happens if both of these criteria are met: The moon is a waxing crescent at sunset of the previous day +// and the moon sets after the sun on that same evening. +/// Lisp code reference: +fn saudi_criterion(date: RataDie) -> Option { + let sunset = Astronomical::sunset((date - 1).as_moment(), MECCA)?; + let tee = Location::universal_from_standard(sunset, MECCA); + let phase = Astronomical::lunar_phase(tee, Astronomical::julian_centuries(tee)); + let moonlag = Astronomical::moonlag((date - 1).as_moment(), MECCA)?; + + Some(phase > 0.0 && phase < 90.0 && moonlag > 0.0) +} + +fn adjusted_saudi_criterion(date: RataDie) -> bool { + saudi_criterion(date).unwrap_or_default() +} + +// Closest fixed date on or before date when Saudi visibility criterion is held. +/// Lisp code reference: +pub fn saudi_new_month_on_or_before(date: RataDie) -> RataDie { + let last_new_moon = (Astronomical::lunar_phase_at_or_before(0.0, date.as_moment())) + .inner() + .floor(); // Gets the R.D Date of the prior new moon + let age = date.to_f64_date() - last_new_moon; + // Explanation of why the value 3.0 is chosen: https://github.com/unicode-org/icu4x/pull/3673/files#r1267460916 + let tau = if age <= 3.0 && !adjusted_saudi_criterion(date) { + // Checks if the criterion is not yet visible on the evening of date + last_new_moon - 30.0 // Goes back a month + } else { + last_new_moon + }; + + next(RataDie::new(tau as i64), adjusted_saudi_criterion) // Loop that increments the day and checks if the criterion is now visible +} + +/// Lisp code reference: +pub fn saudi_islamic_from_fixed(date: RataDie) -> (i32, u8, u8) { + let crescent = saudi_new_month_on_or_before(date); + let elapsed_months = + ((crescent - ISLAMIC_EPOCH_FRIDAY) as f64 / MEAN_SYNODIC_MONTH).round() as i64; + let year = i64_to_saturated_i32(elapsed_months.div_euclid(12) + 1); + let month = (elapsed_months.rem_euclid(12) + 1) as u8; + let day = ((date - crescent) + 1) as u8; + + (year, month, day) +} + +/// Lisp code reference: +pub fn fixed_from_saudi_islamic(year: i32, month: u8, day: u8) -> RataDie { + let midmonth = RataDie::new( + ISLAMIC_EPOCH_FRIDAY.to_i64_date() + + (((year as f64 - 1.0) * 12.0 + month as f64 - 0.5) * MEAN_SYNODIC_MONTH).floor() + as i64, + ); + let first_day_of_month = saudi_new_month_on_or_before(midmonth).to_i64_date(); + + RataDie::new(first_day_of_month + day as i64 - 1) +} + +/// Lisp code reference: +pub fn fixed_from_tabular_islamic(year: i32, month: u8, day: u8, epoch: RataDie) -> RataDie { + let year = i64::from(year); + let month = i64::from(month); + let day = i64::from(day); + + RataDie::new( + (epoch.to_i64_date() - 1) + + (year - 1) * 354 + + (3 + year * 11).div_euclid(30) + + 29 * (month - 1) + + month.div_euclid(2) + + day, + ) +} +/// Lisp code reference: +pub fn tabular_islamic_from_fixed(date: RataDie, epoch: RataDie) -> (i32, u8, u8) { + let year = i64_to_saturated_i32(((date - epoch) * 30 + 10646).div_euclid(10631)); + let prior_days = + date.to_f64_date() - fixed_from_tabular_islamic(year, 1, 1, epoch).to_f64_date(); + debug_assert!(prior_days >= 0.0); + debug_assert!(prior_days <= 354.); + let month = (((prior_days * 11.0) + 330.0) / 325.0) as u8; // Prior days is maximum 354 (when year length is 355), making the value always less than 12 + debug_assert!(month <= 12); + let day = (date.to_f64_date() - fixed_from_tabular_islamic(year, month, 1, epoch).to_f64_date() + + 1.0) as u8; // The value will always be number between 1-30 because of the difference between the date and lunar ordinals function. + + (year, month, day) +} + +/// The number of days in a month for the observational islamic calendar +pub fn observational_islamic_month_days(year: i32, month: u8, location: Location) -> u8 { + let midmonth = ISLAMIC_EPOCH_FRIDAY.to_f64_date() + + (((year - 1) as f64) * 12.0 + month as f64 - 0.5) * MEAN_SYNODIC_MONTH; + + let lunar_phase: f64 = + Astronomical::calculate_new_moon_at_or_before(RataDie::new(midmonth as i64)); + let f_date = Astronomical::phasis_on_or_before( + RataDie::new(midmonth as i64), + location, + Some(lunar_phase), + ); + + Astronomical::month_length(f_date, location) +} + +/// The number of days in a month for the Saudi (Umm Al-Qura) calendar +pub fn saudi_islamic_month_days(year: i32, month: u8) -> u8 { + // We cannot use month_days from the book here, that is for the observational calendar + // + // Instead we subtract the two new months calculated using the saudi criterion + let midmonth = Moment::new( + ISLAMIC_EPOCH_FRIDAY.to_f64_date() + + (((year - 1) as f64) * 12.0 + month as f64 - 0.5) * MEAN_SYNODIC_MONTH, + ); + let midmonth_next = midmonth + MEAN_SYNODIC_MONTH; + + let month_start = saudi_new_month_on_or_before(midmonth.as_rata_die()); + let next_month_start = saudi_new_month_on_or_before(midmonth_next.as_rata_die()); + + let diff = next_month_start - month_start; + debug_assert!( + diff <= 30 || !WELL_BEHAVED_ASTRONOMICAL_RANGE.contains(&month_start), + "umm-al-qura months must not be more than 30 days" + ); + u8::try_from(diff).unwrap_or(30) +} + +#[cfg(test)] +mod tests { + use super::*; + + static TEST_FIXED_DATE: [i64; 33] = [ + -214193, -61387, 25469, 49217, 171307, 210155, 253427, 369740, 400085, 434355, 452605, + 470160, 473837, 507850, 524156, 544676, 567118, 569477, 601716, 613424, 626596, 645554, + 664224, 671401, 694799, 704424, 708842, 709409, 709580, 727274, 728714, 744313, 764652, + ]; + // Removed: 601716 and 727274 fixed dates + static TEST_FIXED_DATE_UMMALQURA: [i64; 31] = [ + -214193, -61387, 25469, 49217, 171307, 210155, 253427, 369740, 400085, 434355, 452605, + 470160, 473837, 507850, 524156, 544676, 567118, 569477, 613424, 626596, 645554, 664224, + 671401, 694799, 704424, 708842, 709409, 709580, 728714, 744313, 764652, + ]; + // Values from lisp code + static SAUDI_CRITERION_EXPECTED: [bool; 33] = [ + false, false, true, false, false, true, false, true, false, false, true, false, false, + true, true, true, true, false, false, true, true, true, false, false, false, false, false, + false, true, false, true, false, true, + ]; + // Values from lisp code, removed two expected months. + static SAUDI_NEW_MONTH_OR_BEFORE_EXPECTED: [f64; 31] = [ + -214203.0, -61412.0, 25467.0, 49210.0, 171290.0, 210152.0, 253414.0, 369735.0, 400063.0, + 434348.0, 452598.0, 470139.0, 473830.0, 507850.0, 524150.0, 544674.0, 567118.0, 569450.0, + 613421.0, 626592.0, 645551.0, 664214.0, 671391.0, 694779.0, 704405.0, 708835.0, 709396.0, + 709573.0, 728709.0, 744301.0, 764647.0, + ]; + #[test] + fn test_islamic_epoch_friday() { + let epoch = ISLAMIC_EPOCH_FRIDAY.to_i64_date(); + // Proleptic Gregorian year of Islamic Epoch + let epoch_year_from_fixed = crate::gregorian::year_from_fixed(RataDie::new(epoch)).unwrap(); + // 622 is the correct proleptic Gregorian year for the Islamic Epoch + assert_eq!(epoch_year_from_fixed, 622); + } + + #[test] + fn test_islamic_epoch_thursday() { + let epoch = ISLAMIC_EPOCH_THURSDAY.to_i64_date(); + // Proleptic Gregorian year of Islamic Epoch + let epoch_year_from_fixed = crate::gregorian::year_from_fixed(RataDie::new(epoch)).unwrap(); + // 622 is the correct proleptic Gregorian year for the Islamic Epoch + assert_eq!(epoch_year_from_fixed, 622); + } + + #[test] + fn test_saudi_criterion() { + for (boolean, f_date) in SAUDI_CRITERION_EXPECTED.iter().zip(TEST_FIXED_DATE.iter()) { + let bool_result = saudi_criterion(RataDie::new(*f_date)).unwrap(); + assert_eq!(*boolean, bool_result, "{f_date:?}"); + } + } + + #[test] + fn test_saudi_new_month_or_before() { + for (date, f_date) in SAUDI_NEW_MONTH_OR_BEFORE_EXPECTED + .iter() + .zip(TEST_FIXED_DATE_UMMALQURA.iter()) + { + let date_result = saudi_new_month_on_or_before(RataDie::new(*f_date)).to_f64_date(); + assert_eq!(*date, date_result, "{f_date:?}"); + } + } +} diff --git a/deps/crates/vendor/calendrical_calculations/src/julian.rs b/deps/crates/vendor/calendrical_calculations/src/julian.rs new file mode 100644 index 00000000000000..fc1be1279a361f --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/src/julian.rs @@ -0,0 +1,141 @@ +// This file is part of ICU4X. +// +// The contents of this file implement algorithms from Calendrical Calculations +// by Reingold & Dershowitz, Cambridge University Press, 4th edition (2018), +// which have been released as Lisp code at +// under the Apache-2.0 license. Accordingly, this file is released under +// the Apache License, Version 2.0 which can be found at the calendrical_calculations +// package root or at http://www.apache.org/licenses/LICENSE-2.0. + +use crate::helpers::{i64_to_i32, k_day_after, I32CastError}; +use crate::rata_die::RataDie; + +// 1st Jan of 1st year proleptic Julian is equivalent to December 30th of 0th year proleptic Gregorian +const JULIAN_EPOCH: RataDie = crate::gregorian::fixed_from_gregorian(0, 12, 30); + +/// Lisp code reference: +#[inline(always)] +pub const fn is_leap_year(year: i32) -> bool { + year % 4 == 0 +} + +/// Lisp code reference: +pub const fn fixed_from_julian(year: i32, month: u8, day: u8) -> RataDie { + let mut fixed = + JULIAN_EPOCH.to_i64_date() - 1 + 365 * (year as i64 - 1) + (year as i64 - 1).div_euclid(4); + debug_assert!(month > 0 && month < 13, "Month should be in range 1..=12."); + fixed += match month { + 1 => 0, + 2 => 31, + 3 => 59, + 4 => 90, + 5 => 120, + 6 => 151, + 7 => 181, + 8 => 212, + 9 => 243, + 10 => 273, + 11 => 304, + 12 => 334, + _ => -1, + }; + // Only add one if the month is after February (month > 2), since leap days are added to the end of February + if month > 2 && is_leap_year(year) { + fixed += 1; + } + RataDie::new(fixed + (day as i64)) +} + +/// Lisp code reference: +pub fn julian_from_fixed(date: RataDie) -> Result<(i32, u8, u8), I32CastError> { + let approx = (4 * date.to_i64_date() + 1464).div_euclid(1461); + let year = i64_to_i32(approx)?; + let prior_days = date + - fixed_from_julian(year, 1, 1) + - if is_leap_year(year) && date > fixed_from_julian(year, 2, 28) { + 1 + } else { + 0 + }; + let adjusted_year = if prior_days >= 365 { + year.saturating_add(1) + } else { + year + }; + let adjusted_prior_days = prior_days.rem_euclid(365); + debug_assert!((0..365).contains(&adjusted_prior_days)); + let month = if adjusted_prior_days < 31 { + 1 + } else if adjusted_prior_days < 59 { + 2 + } else if adjusted_prior_days < 90 { + 3 + } else if adjusted_prior_days < 120 { + 4 + } else if adjusted_prior_days < 151 { + 5 + } else if adjusted_prior_days < 181 { + 6 + } else if adjusted_prior_days < 212 { + 7 + } else if adjusted_prior_days < 243 { + 8 + } else if adjusted_prior_days < 273 { + 9 + } else if adjusted_prior_days < 304 { + 10 + } else if adjusted_prior_days < 334 { + 11 + } else { + 12 + }; + let day = (date - fixed_from_julian(adjusted_year, month, 1) + 1) as u8; // as days_in_month is < u8::MAX + debug_assert!(day <= 31, "Day assertion failed; date: {date:?}, adjusted_year: {adjusted_year}, prior_days: {prior_days}, month: {month}, day: {day}"); + + Ok((adjusted_year, month, day)) +} + +/// Get a fixed date from the ymd of a Julian date. +/// +/// Years are counted as in _Calendrical Calculations_ by Reingold & Dershowitz, +/// meaning there is no year 0. For instance, near the epoch date, years are counted: -3, -2, -1, 1, 2, 3 instead of -2, -1, 0, 1, 2, 3. +/// +/// Primarily useful for use with code constructing epochs specified in the bookg +pub const fn fixed_from_julian_book_version(book_year: i32, month: u8, day: u8) -> RataDie { + debug_assert!(book_year != 0); + // TODO: Should we check the bounds here? + fixed_from_julian( + if book_year < 0 { + book_year + 1 + } else { + book_year + }, + month, + day, + ) +} + +/// Calculates the date of Easter in the given year +pub fn easter(year: i32) -> RataDie { + let shifted_epact = (14 + 11 * year.rem_euclid(19)) % 30; + let paschal_moon = fixed_from_julian(year, 4, 19) - shifted_epact as i64; + k_day_after(0, paschal_moon) +} + +#[test] +fn test_easter() { + // https://en.wikipedia.org/wiki/List_of_dates_for_Easter, dates in Gregorian + for (y, m, d) in [ + (2021, 5, 2), + (2022, 4, 24), + (2023, 4, 16), + (2024, 5, 5), + (2025, 4, 20), + (2026, 4, 12), + (2027, 5, 2), + (2028, 4, 16), + (2029, 4, 8), + ] { + assert_eq!(easter(y), crate::gregorian::fixed_from_gregorian(y, m, d)); + } +} diff --git a/deps/crates/vendor/calendrical_calculations/src/lib.rs b/deps/crates/vendor/calendrical_calculations/src/lib.rs new file mode 100644 index 00000000000000..f1d2f9adb376d9 --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/src/lib.rs @@ -0,0 +1,77 @@ +// This file is part of ICU4X. +// +// The contents of this file implement algorithms from Calendrical Calculations +// by Reingold & Dershowitz, Cambridge University Press, 4th edition (2018), +// which have been released as Lisp code at +// under the Apache-2.0 license. Accordingly, this file is released under +// the Apache License, Version 2.0 which can be found at the calendrical_calculations +// package root or at http://www.apache.org/licenses/LICENSE-2.0. + +//! Calendrical calculations +//! +//! This crate implements algorithms from +//! Calendrical Calculations by Reingold & Dershowitz, Cambridge University Press, 4th edition (2018) +//! as needed by [ICU4X](https://github.com/unicode-org/icu4x). +//! +//! Most of these algorithms can be found as lisp code in the book or +//! [on GithHub](https://github.com/EdReingold/calendar-code2/blob/main/calendar.l). +//! +//! The primary purpose of this crate is use by ICU4X, however if non-ICU4X users need this we are happy +//! to add more structure to this crate as needed. +// https://github.com/unicode-org/icu4x/blob/main/documents/process/boilerplate.md#library-annotations +#![cfg_attr(not(any(test, doc)), no_std)] +#![cfg_attr( + not(test), + deny( + clippy::indexing_slicing, + clippy::unwrap_used, + clippy::expect_used, + clippy::panic, + clippy::exhaustive_structs, + clippy::exhaustive_enums, + clippy::trivially_copy_pass_by_ref, + missing_debug_implementations, + ) +)] +#![warn(missing_docs)] + +mod astronomy; +/// Chinese-like lunar calendars (Chinese, Dangi) +pub mod chinese_based; +/// The Coptic calendar +pub mod coptic; +/// Error handling +mod error; +/// The Ethiopian calendar +pub mod ethiopian; +/// The Gregorian calendar +pub mod gregorian; +/// The Hebrew calendar +pub mod hebrew; +pub mod hebrew_keviyah; +/// Additional math helpers +pub mod helpers; +/// Various islamic lunar calendars +pub mod islamic; +/// Aliases for the Gregorian calendar. +/// +/// This is *not* the ISO week calendar as described in the book. +#[deprecated(since = "0.2.3", note = "use `gregorian`")] +pub mod iso { + pub use crate::gregorian::day_before_year; + pub use crate::gregorian::days_before_month; + pub use crate::gregorian::easter; + pub use crate::gregorian::fixed_from_gregorian as const_fixed_from_iso; + pub use crate::gregorian::fixed_from_gregorian as fixed_from_iso; + pub use crate::gregorian::gregorian_from_fixed as iso_from_fixed; + pub use crate::gregorian::is_leap_year; + pub use crate::gregorian::year_day; + pub use crate::gregorian::year_from_fixed as iso_year_from_fixed; +} +/// The Julian calendar +pub mod julian; +/// The Persian calendar +pub mod persian; +/// Representation of Rata Die (R.D.) dates, which are +/// represented as the number of days since ISO date 0001-01-01. +pub mod rata_die; diff --git a/deps/crates/vendor/calendrical_calculations/src/persian.rs b/deps/crates/vendor/calendrical_calculations/src/persian.rs new file mode 100644 index 00000000000000..32fe743fb3cbba --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/src/persian.rs @@ -0,0 +1,216 @@ +// This file is part of ICU4X. +// +// The contents of this file implement algorithms from Calendrical Calculations +// by Reingold & Dershowitz, Cambridge University Press, 4th edition (2018), +// which have been released as Lisp code at +// under the Apache-2.0 license. Accordingly, this file is released under +// the Apache License, Version 2.0 which can be found at the calendrical_calculations +// package root or at http://www.apache.org/licenses/LICENSE-2.0. + +use crate::helpers::{i64_to_i32, I32CastError, IntegerRoundings}; +use crate::rata_die::RataDie; + +/// Lisp code reference: +// Book states that the Persian epoch is the date: 3/19/622 and since the Persian Calendar has no year 0, the best choice was to use the Julian function. +const FIXED_PERSIAN_EPOCH: RataDie = crate::julian::fixed_from_julian(622, 3, 19); + +// All these years are not leap, while they are considered leap by the 33-year +// rule. The year following each of them is leap, but it's considered non-leap +// by the 33-year rule. This table has been tested to match the modified +// astronomical algorithm based on the 52.5 degrees east meridian from 1178 AP +// (an arbitrary date before the Persian calendar was adopted in 1304 AP) to +// 3000 AP (an arbitrary date far into the future). +const NON_LEAP_CORRECTION: [i32; 78] = [ + 1502, 1601, 1634, 1667, 1700, 1733, 1766, 1799, 1832, 1865, 1898, 1931, 1964, 1997, 2030, 2059, + 2063, 2096, 2129, 2158, 2162, 2191, 2195, 2224, 2228, 2257, 2261, 2290, 2294, 2323, 2327, 2356, + 2360, 2389, 2393, 2422, 2426, 2455, 2459, 2488, 2492, 2521, 2525, 2554, 2558, 2587, 2591, 2620, + 2624, 2653, 2657, 2686, 2690, 2719, 2723, 2748, 2752, 2756, 2781, 2785, 2789, 2818, 2822, 2847, + 2851, 2855, 2880, 2884, 2888, 2913, 2917, 2921, 2946, 2950, 2954, 2979, 2983, 2987, +]; + +const MIN_NON_LEAP_CORRECTION: i32 = NON_LEAP_CORRECTION[0]; + +/// Lisp code reference: +/// Not used, but kept for comparative purposes +pub fn fixed_from_arithmetic_persian(year: i32, month: u8, day: u8) -> RataDie { + let p_year = i64::from(year); + let month = i64::from(month); + let day = i64::from(day); + let y = if p_year > 0 { + p_year - 474 + } else { + p_year - 473 + }; + let year = y.rem_euclid(2820) + 474; + + RataDie::new( + FIXED_PERSIAN_EPOCH.to_i64_date() - 1 + + 1029983 * y.div_euclid(2820) + + 365 * (year - 1) + + (31 * year - 5).div_euclid(128) + + if month <= 7 { + 31 * (month - 1) + } else { + 30 * (month - 1) + 6 + } + + day, + ) +} + +/// fixed_from_arithmetic_persian, modified to use the more correct 33-year rule +pub fn fixed_from_fast_persian(year: i32, month: u8, day: u8) -> RataDie { + let p_year = i64::from(year); + let month = i64::from(month); + let day = i64::from(day); + let mut new_year = FIXED_PERSIAN_EPOCH.to_i64_date() - 1 + + 365 * (p_year - 1) + + (8 * p_year + 21).div_euclid(33); + if year > MIN_NON_LEAP_CORRECTION && NON_LEAP_CORRECTION.binary_search(&(year - 1)).is_ok() { + new_year -= 1; + } + RataDie::new( + new_year - 1 + + if month <= 7 { + 31 * (month - 1) + } else { + 30 * (month - 1) + 6 + } + + day, + ) +} + +/// Lisp code reference: +/// Not used, but kept for comparative purposes +pub fn arithmetic_persian_from_fixed(date: RataDie) -> Result<(i32, u8, u8), I32CastError> { + let year = arithmetic_persian_year_from_fixed(date); + let year = i64_to_i32(year)?; + let day_of_year = 1_i64 + (date - fixed_from_arithmetic_persian(year, 1, 1)); + #[allow(unstable_name_collisions)] // div_ceil is unstable and polyfilled + let month = if day_of_year <= 186 { + day_of_year.div_ceil(31) as u8 + } else { + (day_of_year - 6).div_ceil(30) as u8 + }; + let day = (date - fixed_from_arithmetic_persian(year, month, 1) + 1) as u8; + Ok((year, month, day)) +} + +/// arithmetic_persian_from_fixed, modified to use the 33-year rule method +pub fn fast_persian_from_fixed(date: RataDie) -> Result<(i32, u8, u8), I32CastError> { + let year = fast_persian_year_from_fixed(date); + let mut year = i64_to_i32(year)?; + let mut day_of_year = 1_i64 + (date - fixed_from_fast_persian(year, 1, 1)); + if day_of_year == 366 + && year >= MIN_NON_LEAP_CORRECTION + && NON_LEAP_CORRECTION.binary_search(&year).is_ok() + { + year += 1; + day_of_year = 1; + } + #[allow(unstable_name_collisions)] // div_ceil is unstable and polyfilled + let month = if day_of_year <= 186 { + day_of_year.div_ceil(31) as u8 + } else { + (day_of_year - 6).div_ceil(30) as u8 + }; + let day = (date - fixed_from_fast_persian(year, month, 1) + 1) as u8; + Ok((year, month, day)) +} + +/// Lisp code reference: +/// Not used, but kept for comparative purposes +fn arithmetic_persian_year_from_fixed(date: RataDie) -> i64 { + let d0 = date - fixed_from_arithmetic_persian(475, 1, 1); + let n2820 = d0.div_euclid(1029983); + let d1 = d0.rem_euclid(1029983); + let y2820 = if d1 == 1029982 { + 2820 + } else { + (128 * d1 + 46878).div_euclid(46751) + }; + let year = 474 + n2820 * 2820 + y2820; + if year > 0 { + year + } else { + year - 1 + } +} + +/// arithmetic_persian_year_from_fixed modified for the 33-year rule +fn fast_persian_year_from_fixed(date: RataDie) -> i64 { + let days_since_epoch = date - FIXED_PERSIAN_EPOCH + 1; + 1 + (33 * days_since_epoch + 3).div_euclid(12053) +} + +/// Lisp code reference: https://github.com/EdReingold/calendar-code2/blob/main/calendar.l#L4789 +/// Not used, but kept for comparative purposes +#[allow(dead_code)] +fn is_arithmetic_leap_year(p_year: i32) -> bool { + let mut p_year = p_year as i64; + if 0 < p_year { + p_year -= 474; + } else { + p_year -= 473; + }; + let year = p_year.rem_euclid(2820) + 474; + + ((year + 38) * 31).rem_euclid(128) < 31 +} + +/// Calculated using the 33-year rule +pub fn is_leap_year(p_year: i32) -> bool { + if p_year >= MIN_NON_LEAP_CORRECTION && NON_LEAP_CORRECTION.binary_search(&p_year).is_ok() { + false + } else if p_year > MIN_NON_LEAP_CORRECTION + && NON_LEAP_CORRECTION.binary_search(&(p_year - 1)).is_ok() + { + true + } else { + let p_year = p_year as i64; + (25 * p_year + 11).rem_euclid(33) < 8 + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_persian_epoch() { + let epoch = FIXED_PERSIAN_EPOCH.to_i64_date(); + // Proleptic Gregorian year of Persian Epoch + let epoch_year_from_fixed = crate::gregorian::year_from_fixed(RataDie::new(epoch)).unwrap(); + // 622 is the correct proleptic Gregorian year for the Persian Epoch + assert_eq!(epoch_year_from_fixed, 622); + } + + // Persian New Year occurring in March of proleptic Gregorian year (g_year) to fixed date + fn nowruz(g_year: i32) -> RataDie { + let (y, _m, _d) = crate::gregorian::gregorian_from_fixed(FIXED_PERSIAN_EPOCH).unwrap(); + let persian_year = g_year - y + 1; + let year = if persian_year <= 0 { + persian_year - 1 + } else { + persian_year + }; + fixed_from_fast_persian(year, 1, 1) + } + + #[test] + fn test_nowruz() { + // These values are used as test data in appendix C of the "Calendrical Calculations" book + let nowruz_test_year_start = 2000; + let nowruz_test_year_end = 2103; + + for year in nowruz_test_year_start..=nowruz_test_year_end { + let two_thousand_eight_to_fixed = nowruz(year).to_i64_date(); + let gregorian_date = crate::gregorian::fixed_from_gregorian(year, 3, 21); + let (persian_year, _m, _d) = fast_persian_from_fixed(gregorian_date).unwrap(); + assert_eq!( + fast_persian_from_fixed(RataDie::new(two_thousand_eight_to_fixed)) + .unwrap() + .0, + persian_year + ); + } + } +} diff --git a/deps/crates/vendor/calendrical_calculations/src/rata_die.rs b/deps/crates/vendor/calendrical_calculations/src/rata_die.rs new file mode 100644 index 00000000000000..f4de6f4ce11bc0 --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/src/rata_die.rs @@ -0,0 +1,231 @@ +// This file is part of ICU4X. +// +// The contents of this file implement algorithms from Calendrical Calculations +// by Reingold & Dershowitz, Cambridge University Press, 4th edition (2018), +// which have been released as Lisp code at +// under the Apache-2.0 license. Accordingly, this file is released under +// the Apache License, Version 2.0 which can be found at the calendrical_calculations +// package root or at http://www.apache.org/licenses/LICENSE-2.0. + +use core::fmt; +use core::ops::{Add, AddAssign, Sub, SubAssign}; +#[allow(unused_imports)] +use core_maths::*; + +/// The *Rata Die*, or *R.D.*: number of days since January 1, 1 CE. +/// +/// **The primary definition of this type is in the [`calendrical_calculations`](https://docs.rs/calendrical_calculations) crate.** +/// +/// See: +/// +/// Typically, one should obtain RataDies from other calendrical code, rather than constructing them from integers. +/// The valid range for direct construction is deliberately not documented as it may change. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct RataDie(i64); + +impl RataDie { + /// Create a `RataDie` + /// + /// Typically, one should obtain `RataDie`s from other calendrical code, rather than + /// constructing them from integers. The valid range for direct construction is + /// deliberately not documented as it may change. + pub const fn new(fixed_date: i64) -> Self { + let result = Self(fixed_date); + #[cfg(debug_assertions)] + result.check(); + result + } + + /// Check that it is in range + #[cfg(debug_assertions)] + const fn check(self) { + if self.0 > i64::MAX / 256 { + debug_assert!( + false, + "RataDie is not designed to store values near to the overflow boundary" + ); + } + if self.0 < i64::MIN / 256 { + debug_assert!( + false, + "RataDie is not designed to store values near to the overflow boundary" + ); + } + } + + /// A valid `RataDie` that is intended to be below all dates representable in calendars + #[doc(hidden)] // for testing only + pub const fn big_negative() -> Self { + Self::new(i64::MIN / 256 / 256) + } + + /// Convert this to an `i64` value representing the `RataDie` + pub const fn to_i64_date(self) -> i64 { + self.0 + } + + /// Convert this to an `f64` value representing the `RataDie` + pub(crate) const fn to_f64_date(self) -> f64 { + self.0 as f64 + } + + /// Calculate the number of days between two `RataDie` in a const-friendly way + /// + /// ``` + /// use calendrical_calculations::julian::fixed_from_julian; + /// + /// assert_eq!( + /// fixed_from_julian(1930, 2, 2).since(fixed_from_julian(1930, 1, 1)), + /// 32 + /// ); + /// ``` + pub const fn since(self, rhs: Self) -> i64 { + self.0 - rhs.0 + } + + /// Calculate the number of days between two `RataDie` in a const-friendly way + /// + /// ``` + /// use calendrical_calculations::julian::fixed_from_julian; + /// + /// assert_eq!( + /// fixed_from_julian(1930, 1, 1).until(fixed_from_julian(1930, 2, 2)), + /// 32 + /// ); + /// ``` + pub const fn until(self, rhs: Self) -> i64 { + rhs.0 - self.0 + } + + /// Adds a number of days to this `RataDie` in a const-friendly way + pub const fn add(self, rhs: i64) -> Self { + let result = Self(self.0 + rhs); + #[cfg(debug_assertions)] + result.check(); + result + } + + /// Convert this to a [`Moment`] + pub(crate) const fn as_moment(self) -> Moment { + Moment::new(self.0 as f64) + } +} + +impl fmt::Debug for RataDie { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let rd = self.0; + if let Ok((y, m, d)) = crate::gregorian::gregorian_from_fixed(*self) { + write!(f, "{rd} R.D. ({y}-{m:02}-{d:02})") + } else { + write!(f, "{rd} R.D. (out of bounds)") + } + } +} + +/// Shift a RataDie N days into the future +impl Add for RataDie { + type Output = Self; + fn add(self, rhs: i64) -> Self::Output { + self.add(rhs) + } +} + +impl AddAssign for RataDie { + fn add_assign(&mut self, rhs: i64) { + self.0 += rhs; + } +} + +/// Shift a RataDie N days into the past +impl Sub for RataDie { + type Output = Self; + fn sub(self, rhs: i64) -> Self::Output { + let result = Self(self.0 - rhs); + #[cfg(debug_assertions)] + result.check(); + result + } +} + +impl SubAssign for RataDie { + fn sub_assign(&mut self, rhs: i64) { + self.0 -= rhs; + } +} + +/// Calculate the number of days between two RataDie +impl Sub for RataDie { + type Output = i64; + fn sub(self, rhs: Self) -> Self::Output { + self.since(rhs) + } +} + +/// A moment is a RataDie with a fractional part giving the time of day. +/// +/// NOTE: This should not cause overflow errors for most cases, but consider +/// alternative implementations if necessary. +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] +pub(crate) struct Moment(f64); + +/// Add a number of days to a Moment +impl Add for Moment { + type Output = Self; + fn add(self, rhs: f64) -> Self::Output { + Self(self.0 + rhs) + } +} + +impl AddAssign for Moment { + fn add_assign(&mut self, rhs: f64) { + self.0 += rhs; + } +} + +/// Subtract a number of days from a Moment +impl Sub for Moment { + type Output = Self; + fn sub(self, rhs: f64) -> Self::Output { + Self(self.0 - rhs) + } +} + +impl SubAssign for Moment { + fn sub_assign(&mut self, rhs: f64) { + self.0 -= rhs; + } +} + +/// Calculate the number of days between two moments +impl Sub for Moment { + type Output = f64; + fn sub(self, rhs: Self) -> Self::Output { + self.0 - rhs.0 + } +} + +impl Moment { + /// Create a new moment + pub const fn new(value: f64) -> Moment { + Moment(value) + } + + /// Get the inner field of a Moment + pub const fn inner(self) -> f64 { + self.0 + } + + /// Get the RataDie of a Moment + pub fn as_rata_die(self) -> RataDie { + RataDie::new(self.0.floor() as i64) + } +} + +#[test] +fn test_moment_to_rata_die_conversion() { + for i in -1000..=1000 { + let moment = Moment::new(i as f64); + let rata_die = moment.as_rata_die(); + assert_eq!(rata_die.to_i64_date(), i); + } +} diff --git a/deps/crates/vendor/core_maths/.cargo-checksum.json b/deps/crates/vendor/core_maths/.cargo-checksum.json new file mode 100644 index 00000000000000..8bfd3119e348f4 --- /dev/null +++ b/deps/crates/vendor/core_maths/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"1564fee10504e497a68aad04f7a6ebacb467956f4a50a85415227eaafa55b96e","LICENSE":"9ebf8c4cc0b735ca13a766451f7b8097db3185975ceb2ba94b5abf439156a91f","README.md":"cf4421c888471876bf715ce49aabe59ace32d165b1cd9878fa8d8f5ecd005fc1","src/lib.rs":"3ccbc7d11f612c33b8e5beb966ebda4aee777132ac1568c6a9f77a3d5fe08fda"},"package":"77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30"} \ No newline at end of file diff --git a/deps/crates/vendor/core_maths/Cargo.toml b/deps/crates/vendor/core_maths/Cargo.toml new file mode 100644 index 00000000000000..9fc6e034531741 --- /dev/null +++ b/deps/crates/vendor/core_maths/Cargo.toml @@ -0,0 +1,37 @@ +# 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] +name = "core_maths" +version = "0.1.1" +authors = ["Robert Bastian + +Extension trait for full float functionality in `#[no_std]` backed by [`libm`]. + +Method signatures, implementation, and documentation are copied from as `std` 1.72, +with calls to instrinsics replaced by their `libm` equivalents. + +# Usage +```rust +#[allow(unused_imports)] // will be unused on std targets +use core_maths::*; + +3.9.floor(); +``` + + diff --git a/deps/crates/vendor/core_maths/src/lib.rs b/deps/crates/vendor/core_maths/src/lib.rs new file mode 100644 index 00000000000000..810287b273dce0 --- /dev/null +++ b/deps/crates/vendor/core_maths/src/lib.rs @@ -0,0 +1,1221 @@ +//! Extension trait for full float functionality in `#[no_std]` backed by [`libm`]. +//! +//! Method signatures, implementation, and documentation are copied from as `std` 1.72, +//! with calls to instrinsics replaced by their `libm` equivalents. +//! +//! # Usage +//! ```rust +//! #[allow(unused_imports)] // will be unused on std targets +//! use core_maths::*; +//! +//! 3.9.floor(); +//! ``` + +#![no_std] +#![warn(missing_docs)] + +/// See [`crate`]. +pub trait CoreFloat: Sized + Copy { + /// Returns the largest integer less than or equal to `self`. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let f = 3.7_f64; + /// let g = 3.0_f64; + /// let h = -3.7_f64; + /// + /// assert_eq!(CoreFloat::floor(f), 3.0); + /// assert_eq!(CoreFloat::floor(g), 3.0); + /// assert_eq!(CoreFloat::floor(h), -4.0); + /// ``` + fn floor(self) -> Self; + + /// Returns the smallest integer greater than or equal to `self`. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let f = 3.01_f64; + /// let g = 4.0_f64; + /// + /// assert_eq!(CoreFloat::ceil(f), 4.0); + /// assert_eq!(CoreFloat::ceil(g), 4.0); + /// ``` + fn ceil(self) -> Self; + + /// Returns the nearest integer to `self`. If a value is half-way between two + /// integers, round away from `0.0`. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let f = 3.3_f64; + /// let g = -3.3_f64; + /// let h = -3.7_f64; + /// let i = 3.5_f64; + /// let j = 4.5_f64; + /// + /// assert_eq!(CoreFloat::round(f), 3.0); + /// assert_eq!(CoreFloat::round(g), -3.0); + /// assert_eq!(CoreFloat::round(h), -4.0); + /// assert_eq!(CoreFloat::round(i), 4.0); + /// assert_eq!(CoreFloat::round(j), 5.0); + /// ``` + fn round(self) -> Self; + + /// Returns the integer part of `self`. + /// This means that non-integer numbers are always truncated towards zero. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let f = 3.7_f64; + /// let g = 3.0_f64; + /// let h = -3.7_f64; + /// + /// assert_eq!(CoreFloat::trunc(f), 3.0); + /// assert_eq!(CoreFloat::trunc(g), 3.0); + /// assert_eq!(CoreFloat::trunc(h), -3.0); + /// ``` + fn trunc(self) -> Self; + + /// Returns the fractional part of `self`. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let x = 3.6_f64; + /// let y = -3.6_f64; + /// let abs_difference_x = (CoreFloat::fract(x) - CoreFloat::abs(0.6)); + /// let abs_difference_y = (CoreFloat::fract(y) - CoreFloat::abs(-0.6)); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + fn fract(self) -> Self; + + /// Computes the absolute value of `self`. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let x = 3.5_f64; + /// let y = -3.5_f64; + /// + /// let abs_difference_x = (CoreFloat::abs(x) - CoreFloat::abs(x)); + /// let abs_difference_y = (CoreFloat::abs(y) - (CoreFloat::abs(-y))); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// + /// assert!(f64::NAN.abs().is_nan()); + /// ``` + fn abs(self) -> Self; + + /// Returns a number that represents the sign of `self`. + /// + /// - `1.0` if the number is positive, `+0.0` or `INFINITY` + /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` + /// - NaN if the number is NaN + /// + /// This method does not use an intrinsic in `std`, so its code is copied. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let f = 3.5_f64; + /// + /// assert_eq!(CoreFloat::signum(f), 1.0); + /// assert_eq!(CoreFloat::signum(f64::NEG_INFINITY), -1.0); + /// + /// assert!(CoreFloat::signum(f64::NAN).is_nan()); + /// ``` + fn signum(self) -> Self; + + /// Returns a number composed of the magnitude of `self` and the sign of + /// `sign`. + /// + /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise + /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of + /// `sign` is returned. Note, however, that conserving the sign bit on NaN + /// across arithmetical operations is not generally guaranteed. + /// See [explanation of NaN as a special value](primitive@f32) for more info. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let f = 3.5_f64; + /// + /// assert_eq!(CoreFloat::copysign(f, 0.42), 3.5_f64); + /// assert_eq!(CoreFloat::copysign(f, -0.42), -3.5_f64); + /// assert_eq!(CoreFloat::copysign(-f, 0.42), 3.5_f64); + /// assert_eq!(CoreFloat::copysign(-f, -0.42), -3.5_f64); + /// + /// assert!(CoreFloat::copysign(f64::NAN, 1.0).is_nan()); + /// ``` + fn copysign(self, sign: Self) -> Self; + + /// Fused multiply-add. Computes `(self * a) + b` with only one rounding + /// error, yielding a more accurate result than an unfused multiply-add. + /// + /// Using `mul_add` *may* be more performant than an unfused multiply-add if + /// the target architecture has a dedicated `fma` CPU instruction. However, + /// this is not always true, and will be heavily dependant on designing + /// algorithms with specific target hardware in mind. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let m = 10.0_f64; + /// let x = 4.0_f64; + /// let b = 60.0_f64; + /// + /// // 100.0 + /// let abs_difference = (CoreFloat::mul_add(m, x, b) - ((m * x) + b)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn mul_add(self, a: Self, b: Self) -> Self; + + /// Calculates Euclidean division, the matching method for `rem_euclid`. + /// + /// This computes the integer `n` such that + /// `self = n * rhs + self.rem_euclid(rhs)`. + /// In other words, the result is `self / rhs` rounded to the integer `n` + /// such that `self >= n * rhs`. + /// + /// This method does not use an intrinsic in `std`, so its code is copied. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let a: f64 = 7.0; + /// let b = 4.0; + /// assert_eq!(CoreFloat::div_euclid(a, b), 1.0); // 7.0 > 4.0 * 1.0 + /// assert_eq!(CoreFloat::div_euclid(-a, b), -2.0); // -7.0 >= 4.0 * -2.0 + /// assert_eq!(CoreFloat::div_euclid(a, -b), -1.0); // 7.0 >= -4.0 * -1.0 + /// assert_eq!(CoreFloat::div_euclid(-a, -b), 2.0); // -7.0 >= -4.0 * 2.0 + /// ``` + fn div_euclid(self, rhs: Self) -> Self; + + /// Calculates the least nonnegative remainder of `self (mod rhs)`. + /// + /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in + /// most cases. However, due to a floating point round-off error it can + /// result in `r == rhs.abs()`, violating the mathematical definition, if + /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`. + /// This result is not an element of the function's codomain, but it is the + /// closest floating point number in the real numbers and thus fulfills the + /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)` + /// approximately. + /// + /// This method does not use an intrinsic in `std`, so its code is copied. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let a: f64 = 7.0; + /// let b = 4.0; + /// assert_eq!(CoreFloat::rem_euclid(a, b), 3.0); + /// assert_eq!(CoreFloat::rem_euclid(-a, b), 1.0); + /// assert_eq!(CoreFloat::rem_euclid(a, -b), 3.0); + /// assert_eq!(CoreFloat::rem_euclid(-a, -b), 1.0); + /// // limitation due to round-off error + /// assert!(CoreFloat::rem_euclid(-f64::EPSILON, 3.0) != 0.0); + /// ``` + fn rem_euclid(self, rhs: Self) -> Self; + + /// Raises a number to an integer power. + /// + /// Using this function is generally faster than using `powf`. + /// It might have a different sequence of rounding operations than `powf`, + /// so the results are not guaranteed to agree. + /// + /// This method is not available in `libm`, so it uses a custom implementation. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let x = 2.0_f64; + /// let abs_difference = (CoreFloat::powi(x, 2) - (x * x)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn powi(self, n: i32) -> Self; + + /// Raises a number to a floating point power. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let x = 2.0_f64; + /// let abs_difference = (CoreFloat::powf(x, 2.0) - (x * x)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn powf(self, n: Self) -> Self; + + /// Returns the square root of a number. + /// + /// Returns NaN if `self` is a negative number other than `-0.0`. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let positive = 4.0_f64; + /// let negative = -4.0_f64; + /// let negative_zero = -0.0_f64; + /// + /// let abs_difference = (CoreFloat::sqrt(positive) - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// assert!(CoreFloat::sqrt(negative).is_nan()); + /// assert!(CoreFloat::sqrt(negative_zero) == negative_zero); + /// ``` + fn sqrt(self) -> Self; + + /// Returns `e^(self)`, (the exponential function). + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let one = 1.0_f64; + /// // e^1 + /// let e = CoreFloat::exp(one); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn exp(self) -> Self; + + /// Returns `2^(self)`. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let f = 2.0_f64; + /// + /// // 2^2 - 4 == 0 + /// let abs_difference = (CoreFloat::exp2(f) - 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn exp2(self) -> Self; + + /// Returns the natural logarithm of the number. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let one = 1.0_f64; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (CoreFloat::ln(e) - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn ln(self) -> Self; + + /// Returns the logarithm of the number with respect to an arbitrary base. + /// + /// The result might not be correctly rounded owing to implementation details; + /// `self.log2()` can produce more accurate results for base 2, and + /// `self.log10()` can produce more accurate results for base 10. + /// + /// This method does not use an intrinsic in `std`, so its code is copied. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let twenty_five = 25.0_f64; + /// + /// // log5(25) - 2 == 0 + /// let abs_difference = (CoreFloat::log(twenty_five, 5.0) - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn log(self, base: Self) -> Self; + + /// Returns the base 2 logarithm of the number. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let four = 4.0_f64; + /// + /// // log2(4) - 2 == 0 + /// let abs_difference = (CoreFloat::log2(four) - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn log2(self) -> Self; + + /// Returns the base 10 logarithm of the number. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let hundred = 100.0_f64; + /// + /// // log10(100) - 2 == 0 + /// let abs_difference = (CoreFloat::log10(hundred) - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn log10(self) -> Self; + + /// Returns the cube root of a number. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let x = 8.0_f64; + /// + /// // x^(1/3) - 2 == 0 + /// let abs_difference = (CoreFloat::cbrt(x) - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn cbrt(self) -> Self; + + /// Compute the distance between the origin and a point (`x`, `y`) on the + /// Euclidean plane. Equivalently, compute the length of the hypotenuse of a + /// right-angle triangle with other sides having length `x.abs()` and + /// `y.abs()`. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let x = 2.0_f64; + /// let y = 3.0_f64; + /// + /// // sqrt(x^2 + y^2) + /// let abs_difference = (CoreFloat::hypot(x, y) - (x.powi(2) + y.powi(2)).sqrt()).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn hypot(self, other: Self) -> Self; + + /// Computes the sine of a number (in radians). + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let x = std::f64::consts::FRAC_PI_2; + /// + /// let abs_difference = (CoreFloat::sin(x) - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn sin(self) -> Self; + + /// Computes the cosine of a number (in radians). + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let x = 2.0 * std::f64::consts::PI; + /// + /// let abs_difference = (CoreFloat::cos(x) - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn cos(self) -> Self; + + /// Computes the tangent of a number (in radians). + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let x = std::f64::consts::FRAC_PI_4; + /// + /// let abs_difference = (CoreFloat::tan(x) - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-14); + /// ``` + fn tan(self) -> Self; + + /// Computes the arcsine of a number. Return value is in radians in + /// the range [-pi/2, pi/2] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let f = std::f64::consts::FRAC_PI_2; + /// + /// // asin(sin(pi/2)) + /// let abs_difference = (CoreFloat::asin(f.sin()) - std::f64::consts::FRAC_PI_2).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn asin(self) -> Self; + + /// Computes the arccosine of a number. Return value is in radians in + /// the range [0, pi] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let f = std::f64::consts::FRAC_PI_4; + /// + /// // acos(cos(pi/4)) + /// let abs_difference = (CoreFloat::acos(f.cos()) - std::f64::consts::FRAC_PI_4).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn acos(self) -> Self; + + /// Computes the arctangent of a number. Return value is in radians in the + /// range [-pi/2, pi/2]; + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let f = 1.0_f64; + /// + /// // atan(tan(1)) + /// let abs_difference = (CoreFloat::atan(f.tan()) - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn atan(self) -> Self; + + /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. + /// + /// * `x = 0`, `y = 0`: `0` + /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` + /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` + /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// // Positive angles measured counter-clockwise + /// // from positive x axis + /// // -pi/4 radians (45 deg clockwise) + /// let x1 = 3.0_f64; + /// let y1 = -3.0_f64; + /// + /// // 3pi/4 radians (135 deg counter-clockwise) + /// let x2 = -3.0_f64; + /// let y2 = 3.0_f64; + /// + /// let abs_difference_1 = (CoreFloat::atan2(y1, x1) - (-std::f64::consts::FRAC_PI_4)).abs(); + /// let abs_difference_2 = (CoreFloat::atan2(y2, x2) - (3.0 * std::f64::consts::FRAC_PI_4)).abs(); + /// + /// assert!(abs_difference_1 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + fn atan2(self, other: Self) -> Self; + + /// Simultaneously computes the sine and cosine of the number, `x`. Returns + /// `(sin(x), cos(x))`. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let x = std::f64::consts::FRAC_PI_4; + /// let f = CoreFloat::sin_cos(x); + /// + /// let abs_difference_0 = (f.0 - x.sin()).abs(); + /// let abs_difference_1 = (f.1 - x.cos()).abs(); + /// + /// assert!(abs_difference_0 < 1e-10); + /// assert!(abs_difference_1 < 1e-10); + /// ``` + fn sin_cos(self) -> (Self, Self) { + (self.sin(), self.cos()) + } + + /// Returns `e^(self) - 1` in a way that is accurate even if the + /// number is close to zero. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let x = 1e-16_f64; + /// + /// // for very small x, e^x is approximately 1 + x + x^2 / 2 + /// let approx = x + x * x / 2.0; + /// let abs_difference = (CoreFloat::exp_m1(x) - approx).abs(); + /// + /// assert!(abs_difference < 1e-20); + /// ``` + fn exp_m1(self) -> Self; + + /// Returns `ln(1+n)` (natural logarithm) more accurately than if + /// the operations were performed separately. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let x = 1e-16_f64; + /// + /// // for very small x, ln(1 + x) is approximately x - x^2 / 2 + /// let approx = x - x * x / 2.0; + /// let abs_difference = (CoreFloat::ln_1p(x) - approx).abs(); + /// + /// assert!(abs_difference < 1e-20); + /// ``` + fn ln_1p(self) -> Self; + + /// Hyperbolic sine function. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let e = std::f64::consts::E; + /// let x = 1.0_f64; + /// + /// let f = CoreFloat::sinh(x); + /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` + /// let g = ((e * e) - 1.0) / (2.0 * e); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + fn sinh(self) -> Self; + + /// Hyperbolic cosine function. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let e = std::f64::consts::E; + /// let x = 1.0_f64; + /// let f = CoreFloat::cosh(x); + /// // Solving cosh() at 1 gives this result + /// let g = ((e * e) + 1.0) / (2.0 * e); + /// let abs_difference = (f - g).abs(); + /// + /// // Same result + /// assert!(abs_difference < 1.0e-10); + /// ``` + fn cosh(self) -> Self; + + /// Hyperbolic tangent function. + /// + /// This implementation uses `libm` instead of the Rust intrinsic. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let e = std::f64::consts::E; + /// let x = 1.0_f64; + /// + /// let f = CoreFloat::tanh(x); + /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` + /// let g = (1.0 - e.powi(-2)) / (1.0 + e.powi(-2)); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + fn tanh(self) -> Self; + + /// Inverse hyperbolic sine function. + /// + /// This method does not use an intrinsic in `std`, so its code is copied. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let x = 1.0_f64; + /// let f = CoreFloat::asinh(x.sinh()); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + fn asinh(self) -> Self; + + /// Inverse hyperbolic cosine function. + /// + /// This method does not use an intrinsic in `std`, so its code is copied. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let x = 1.0_f64; + /// let f = CoreFloat::acosh(x.cosh()); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + fn acosh(self) -> Self; + + /// Inverse hyperbolic tangent function. + /// + /// This method does not use an intrinsic in `std`, so its code is copied. + /// + /// # Examples + /// + /// ``` + /// use core_maths::*; + /// let e = std::f64::consts::E; + /// let f = CoreFloat::atanh(e.tanh()); + /// + /// let abs_difference = (f - e).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + fn atanh(self) -> Self; +} + +impl CoreFloat for f32 { + #[inline] + fn floor(self) -> Self { + libm::floorf(self) + } + + #[inline] + fn ceil(self) -> Self { + libm::ceilf(self) + } + + #[inline] + fn round(self) -> Self { + libm::roundf(self) + } + + #[inline] + fn trunc(self) -> Self { + libm::truncf(self) + } + + #[inline] + fn fract(self) -> Self { + self - self.trunc() + } + + #[inline] + fn abs(self) -> Self { + libm::fabsf(self) + } + + #[inline] + fn signum(self) -> Self { + if self.is_nan() { + Self::NAN + } else { + 1.0_f32.copysign(self) + } + } + + #[inline] + fn copysign(self, sign: Self) -> Self { + libm::copysignf(self, sign) + } + + #[inline] + fn mul_add(self, a: Self, b: Self) -> Self { + libm::fmaf(self, a, b) + } + + #[inline] + fn div_euclid(self, rhs: Self) -> Self { + let q = (self / rhs).trunc(); + if self % rhs < 0.0 { + return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }; + } + q + } + + #[inline] + fn rem_euclid(self, rhs: Self) -> Self { + let r = self % rhs; + if r < 0.0 { + r + rhs.abs() + } else { + r + } + } + + #[inline] + fn powi(self, exp: i32) -> Self { + if exp == 0 { + return 1.0; + } + + let mut base = if exp < 0 { self.recip() } else { self }; + let mut exp = exp.unsigned_abs(); + let mut acc = 1.0; + + while exp > 1 { + if (exp & 1) == 1 { + acc *= base; + } + exp /= 2; + base = base * base; + } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc * base + } + + #[inline] + fn powf(self, n: Self) -> Self { + libm::powf(self, n) + } + + #[inline] + fn sqrt(self) -> Self { + libm::sqrtf(self) + } + + #[inline] + fn exp(self) -> Self { + libm::expf(self) + } + + #[inline] + fn exp2(self) -> Self { + libm::exp2f(self) + } + + #[inline] + fn ln(self) -> Self { + libm::logf(self) + } + + #[inline] + fn log(self, base: Self) -> Self { + self.ln() / base.ln() + } + + #[inline] + fn log2(self) -> Self { + libm::log2f(self) + } + + #[inline] + fn log10(self) -> Self { + libm::log10f(self) + } + + #[inline] + fn cbrt(self) -> Self { + libm::cbrtf(self) + } + + #[inline] + fn hypot(self, other: Self) -> Self { + libm::hypotf(self, other) + } + + #[inline] + fn sin(self) -> Self { + libm::sinf(self) + } + + #[inline] + fn cos(self) -> Self { + libm::cosf(self) + } + + #[inline] + fn tan(self) -> Self { + libm::tanf(self) + } + + #[inline] + fn asin(self) -> Self { + libm::asinf(self) + } + + #[inline] + fn acos(self) -> Self { + libm::acosf(self) + } + + #[inline] + fn atan(self) -> Self { + libm::atanf(self) + } + + #[inline] + fn atan2(self, other: Self) -> Self { + libm::atan2f(self, other) + } + + #[inline] + fn exp_m1(self) -> Self { + libm::expm1f(self) + } + + #[inline] + fn ln_1p(self) -> Self { + libm::log1pf(self) + } + + #[inline] + fn sinh(self) -> Self { + libm::sinhf(self) + } + + #[inline] + fn cosh(self) -> Self { + libm::coshf(self) + } + + #[inline] + fn tanh(self) -> Self { + libm::tanhf(self) + } + + #[inline] + fn asinh(self) -> Self { + let ax = self.abs(); + let ix = 1.0 / ax; + (ax + (ax / (Self::hypot(1.0, ix) + ix))) + .ln_1p() + .copysign(self) + } + + #[inline] + fn acosh(self) -> Self { + if self < 1.0 { + Self::NAN + } else { + (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln() + } + } + + #[inline] + fn atanh(self) -> Self { + 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() + } +} + +impl CoreFloat for f64 { + #[inline] + fn floor(self) -> Self { + libm::floor(self) + } + + #[inline] + fn ceil(self) -> Self { + libm::ceil(self) + } + + #[inline] + fn round(self) -> Self { + libm::round(self) + } + + #[inline] + fn trunc(self) -> Self { + libm::trunc(self) + } + + #[inline] + fn fract(self) -> Self { + self - self.trunc() + } + + #[inline] + fn abs(self) -> Self { + libm::fabs(self) + } + + #[inline] + fn signum(self) -> Self { + if self.is_nan() { + Self::NAN + } else { + 1.0_f64.copysign(self) + } + } + + #[inline] + fn copysign(self, sign: Self) -> Self { + libm::copysign(self, sign) + } + + #[inline] + fn mul_add(self, a: Self, b: Self) -> Self { + libm::fma(self, a, b) + } + + #[inline] + fn div_euclid(self, rhs: Self) -> Self { + let q = (self / rhs).trunc(); + if self % rhs < 0.0 { + return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }; + } + q + } + + #[inline] + fn rem_euclid(self, rhs: Self) -> Self { + let r = self % rhs; + if r < 0.0 { + r + rhs.abs() + } else { + r + } + } + + #[inline] + fn powi(self, exp: i32) -> Self { + if exp == 0 { + return 1.0; + } + + let mut base = if exp < 0 { self.recip() } else { self }; + let mut exp = exp.unsigned_abs(); + let mut acc = 1.0; + + while exp > 1 { + if (exp & 1) == 1 { + acc *= base; + } + exp /= 2; + base = base * base; + } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc * base + } + + #[inline] + fn powf(self, n: Self) -> Self { + libm::pow(self, n) + } + + #[inline] + fn sqrt(self) -> Self { + libm::sqrt(self) + } + + #[inline] + fn exp(self) -> Self { + libm::exp(self) + } + + #[inline] + fn exp2(self) -> Self { + libm::exp2(self) + } + + #[inline] + fn ln(self) -> Self { + libm::log(self) + } + + #[inline] + fn log(self, base: Self) -> Self { + self.ln() / base.ln() + } + + #[inline] + fn log2(self) -> Self { + libm::log2(self) + } + + #[inline] + fn log10(self) -> Self { + libm::log10(self) + } + + #[inline] + fn cbrt(self) -> Self { + libm::cbrt(self) + } + + #[inline] + fn hypot(self, other: Self) -> Self { + libm::hypot(self, other) + } + + #[inline] + fn sin(self) -> Self { + libm::sin(self) + } + + #[inline] + fn cos(self) -> Self { + libm::cos(self) + } + + #[inline] + fn tan(self) -> Self { + libm::tan(self) + } + + #[inline] + fn asin(self) -> Self { + libm::asin(self) + } + + #[inline] + fn acos(self) -> Self { + libm::acos(self) + } + + #[inline] + fn atan(self) -> Self { + libm::atan(self) + } + + #[inline] + fn atan2(self, other: Self) -> Self { + libm::atan2(self, other) + } + + #[inline] + fn exp_m1(self) -> Self { + libm::expm1(self) + } + + #[inline] + fn ln_1p(self) -> Self { + libm::log1p(self) + } + + #[inline] + fn sinh(self) -> Self { + libm::sinh(self) + } + + #[inline] + fn cosh(self) -> Self { + libm::cosh(self) + } + + #[inline] + fn tanh(self) -> Self { + libm::tanh(self) + } + + #[inline] + fn asinh(self) -> Self { + let ax = self.abs(); + let ix = 1.0 / ax; + (ax + (ax / (Self::hypot(1.0, ix) + ix))) + .ln_1p() + .copysign(self) + } + + #[inline] + fn acosh(self) -> Self { + if self < 1.0 { + Self::NAN + } else { + (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln() + } + } + + #[inline] + fn atanh(self) -> Self { + 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() + } +} diff --git a/deps/crates/vendor/diplomat-runtime/.cargo-checksum.json b/deps/crates/vendor/diplomat-runtime/.cargo-checksum.json new file mode 100644 index 00000000000000..9cd84d5f584890 --- /dev/null +++ b/deps/crates/vendor/diplomat-runtime/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"e8bec462a1cbed1f6f350f9d51d214ed1062b6fedda209c73ae0a47866ea5e1f","LICENSE-APACHE":"639c20c7f14fb122750d5ad1a6cfb116d9bf8d103e709ee40949e5a12a731666","LICENSE-MIT":"3337fe6e4a3830ad87c23cb9d6d750f9a1e5c45efc08de9c76c1a207fc6966c4","README.md":"9b721778a162ec713582e022ee8e497739d9bc1afba35227f845d3de570e6d95","src/callback.rs":"1783da7e20dd4cad0b44f721bc1db07f426caad05ac4385c09e15cc933118c27","src/lib.rs":"43fcf30a684e88070f121ef90ca07a92ad33161d902767e75756cdb2cf9c797c","src/result.rs":"937bbc231ae7be5cc59251b9857e3a7dd86bb5d148a6b011d03d5bcf437dbf40","src/rust_interop.rs":"76cf89f9a1e6d01627aa04200a0095b1faf7c8caad0a1f9ffe0f4ad4ce99a1c2","src/slices.rs":"62a4ef83221d158ae999f18ee1e3cad936f824c57106c5df607ba4aee12161a4","src/wasm_glue.rs":"f861965c188005b6bee339f702b95b7b860bfe073fd185275593c6c9fe8ace3c","src/write.rs":"a6e77b2d6b0a35983d5803f1d2c6d8f7fbf35c03f398a2785bcdd4f11b75808c"},"package":"c270cf75c6ba9d974a7a670d96c7bf8007cd0d03e1fbe128d62bd47d9fe25aef"} \ No newline at end of file diff --git a/deps/crates/vendor/diplomat-runtime/Cargo.toml b/deps/crates/vendor/diplomat-runtime/Cargo.toml new file mode 100644 index 00000000000000..4eb4ec5abebd04 --- /dev/null +++ b/deps/crates/vendor/diplomat-runtime/Cargo.toml @@ -0,0 +1,55 @@ +# 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.81" +name = "diplomat-runtime" +version = "0.13.1" +authors = [ + "Shadaj Laddad ", + "Manish Goregaokar ", + "Quinn Okabayashi ", +] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Common runtime utilities used by diplomat codegen" +readme = "README.md" +keywords = [ + "ffi", + "codegen", +] +categories = [ + "development-tools", + "compilers", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-diplomat/diplomat" + +[features] +jvm-callback-support = ["dep:jni"] +log = ["dep:log"] + +[lib] +name = "diplomat_runtime" +path = "src/lib.rs" + +[dependencies.jni] +version = "0.21" +optional = true + +[dependencies.log] +version = "0.4" +optional = true diff --git a/deps/crates/vendor/diplomat-runtime/LICENSE-APACHE b/deps/crates/vendor/diplomat-runtime/LICENSE-APACHE new file mode 100644 index 00000000000000..05fcffa855c462 --- /dev/null +++ b/deps/crates/vendor/diplomat-runtime/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2022 The Diplomat Developers + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/deps/crates/vendor/diplomat-runtime/LICENSE-MIT b/deps/crates/vendor/diplomat-runtime/LICENSE-MIT new file mode 100644 index 00000000000000..cf62c31bc7531d --- /dev/null +++ b/deps/crates/vendor/diplomat-runtime/LICENSE-MIT @@ -0,0 +1,27 @@ +MIT License + +Copyright (c) 2022 The Diplomat Developers + +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/deps/crates/vendor/diplomat-runtime/README.md b/deps/crates/vendor/diplomat-runtime/README.md new file mode 100644 index 00000000000000..438a9400703af2 --- /dev/null +++ b/deps/crates/vendor/diplomat-runtime/README.md @@ -0,0 +1,42 @@ +# Diplomat +Diplomat is an experimental Rust tool for generating FFI definitions allowing many other languages to call Rust code. With Diplomat, you can simply define Rust APIs to be exposed over FFI and get high-level C, C++, and JavaScript bindings automatically! + +Diplomat supports generating bindings from Rust to: +- C +- C++ +- Dart +- Javascript/Typescript +- Kotlin (using JNA) +- Python (using [nanobind](https://nanobind.readthedocs.io/en/latest/index.html)) + +Diplomat supports languages through a plugin interface that makes it easy to add support for your favourite language. See [the book to get started](https://rust-diplomat.github.io/diplomat/developer.html), and `tool/src/{c, cpp, js}` for examples of existing language plugins. + +## Installation +First, install the CLI tool for generating bindings: +```bash +$ cargo install diplomat-tool +``` + +Then, add the Diplomat macro and runtime as dependencies to your project: +```toml +diplomat = "0.10.0" +diplomat-runtime = "0.10.0" +``` + +## Getting Started + +Documentation on how to use Diplomat can be found [in the book](https://rust-diplomat.github.io/diplomat/). + +### Architecture +See the [design doc](docs/design_doc.md) for more details. + +### Building and Testing +Simply run `cargo build` to build all the libraries and compile an example. To run unit tests, run `cargo test`. + +Diplomat makes use of snapshot tests to check macro and code generation logic. When code generation logic changes and the snapshots need to be updated, run `cargo insta review` (run `cargo install cargo-insta` to get the tool) to view the changes and update the snapshots. + +#### Javascript bindings for `wasm32-unknown-unknown` +The Javascript backend assumes that you are building WebAssembly on the C Spec ABI. This is not currently default for the `wasm32-unknown-unknown` target in the latest version of Rust, and so until the [new WASM ABI](https://blog.rust-lang.org/2025/04/04/c-abi-changes-for-wasm32-unknown-unknown/) is made stable, you have two options: + +1. Build using nightly Rust and enable the [`-Zwasm-c-abi=spec`](https://doc.rust-lang.org/stable/unstable-book/compiler-flags/wasm-c-abi.html) flag. +1. Configure the JS backend to use legacy bindings. There is a [WASM ABI config option](https://github.com/rust-diplomat/diplomat/blob/main/tool/src/js/mod.rs) for this, please read [the guide on configuration in the book](https://rust-diplomat.github.io/diplomat/config) for more on how to configure. \ No newline at end of file diff --git a/deps/crates/vendor/diplomat-runtime/src/callback.rs b/deps/crates/vendor/diplomat-runtime/src/callback.rs new file mode 100644 index 00000000000000..a571e656176460 --- /dev/null +++ b/deps/crates/vendor/diplomat-runtime/src/callback.rs @@ -0,0 +1,62 @@ +#[cfg(feature = "jvm-callback-support")] +use alloc::boxed::Box; +use core::ffi::c_void; +#[cfg(feature = "jvm-callback-support")] +use jni::{ + objects::{GlobalRef, JObject}, + sys::jlong, + JNIEnv, +}; + +/// Struct representing a callback from Rust into a foreign language +/// +/// This is largely used internally by the Diplomat macro, and should not need to be constructed +/// manually outside of that context +#[repr(C)] +pub struct DiplomatCallback { + /// Any data required to run the callback; e.g. a pointer to the + /// callback wrapper object in the foreign runtime + the runtime itself + pub data: *mut c_void, + /// Function to actually run the callback. Note the first param is mutable, but depending + /// on if this is passed to a Fn or FnMut may not actually need to be. + /// FFI-Callers of said functions should cast to mutable. + /// + /// Takes in `self.data` and any number of additional arguments. + pub run_callback: unsafe extern "C" fn(*mut c_void, ...) -> ReturnType, + /// Function to destroy this callback struct. + /// + /// Takes in `self.data` + pub destructor: Option, +} + +impl Drop for DiplomatCallback { + fn drop(&mut self) { + if let Some(destructor) = self.destructor { + unsafe { + (destructor)(self.data); + } + } + } +} + +// return a pointer to a JNI GlobalRef, which is a JVM GC root to the object provided. +// this can then be stored as a field in a struct, so that the struct +// is not deallocated until the JVM calls a destructor that unwraps +// the GlobalRef so it can be dropped. +#[cfg(feature = "jvm-callback-support")] +#[no_mangle] +extern "system" fn create_rust_jvm_cookie<'local>( + env: JNIEnv<'local>, + obj_to_ref: JObject<'local>, +) -> jlong { + let global_ref = env.new_global_ref(obj_to_ref).unwrap(); + Box::into_raw(Box::new(global_ref)) as jlong +} + +#[cfg(feature = "jvm-callback-support")] +#[no_mangle] +extern "system" fn destroy_rust_jvm_cookie(global_ref_boxed: jlong) { + unsafe { + drop(Box::from_raw(global_ref_boxed as *mut GlobalRef)); + } +} diff --git a/deps/crates/vendor/diplomat-runtime/src/lib.rs b/deps/crates/vendor/diplomat-runtime/src/lib.rs new file mode 100644 index 00000000000000..95dd78b4a38dad --- /dev/null +++ b/deps/crates/vendor/diplomat-runtime/src/lib.rs @@ -0,0 +1,104 @@ +#![cfg_attr(not(any(target_arch = "wasm32")), no_std)] + +//! The [Diplomat](https://rust-diplomat.github.io/diplomat/) runtime crate. +//! +//! This crate provides Diplomat-specific types for crates writing `#[diplomat::bridge]` modules. +//! Include this in any crate that also depends on `diplomat`, since `#[diplomat::bridge]` +//! will generate code that relies on types from here. +//! +//! This crate contains a fair number of `DiplomatFoo` types. Some, like +//! [`DiplomatOption`], are FFI-safe versions of Rust types that can be put in +//! a struct and passed safely over FFI. Others, like [`DiplomatChar`], are simple +//! type aliases that signal to the Diplomat tool that particular semantics are desired +//! on the C++ side. +//! +//! # Features +//! +//! The `log` feature enables logging support, currently enabled via the wasm-only `diplomat_init()`. +//! +//! The `jvm-callback-support` feature should be enabled if building Diplomat for use in the JVM, for +//! a Diplomat-based library that uses callbacks. +extern crate alloc; + +use alloc::alloc::Layout; + +#[cfg(all(target_arch = "wasm32", target_os = "unknown"))] +mod wasm_glue; + +mod write; +pub use write::DiplomatWrite; +pub use write::{diplomat_buffer_write_create, diplomat_buffer_write_destroy}; +mod slices; +pub use slices::{ + DiplomatOwnedSlice, DiplomatOwnedStr16Slice, DiplomatOwnedStrSlice, DiplomatOwnedUTF8StrSlice, + DiplomatSlice, DiplomatSliceMut, DiplomatStr16Slice, DiplomatStrSlice, DiplomatUtf8StrSlice, +}; + +mod callback; +pub use callback::DiplomatCallback; + +mod result; +pub use result::{DiplomatOption, DiplomatResult}; + +pub mod rust_interop; + +/// Like [`char`], but unvalidated. +/// +/// This type will usually map to some character type in the target language, and +/// you will not need to worry about the safety of mismatched string invariants. +pub type DiplomatChar = u32; + +/// Like [`str`], but unvalidated. +/// +/// This is a dynamically sized type, it should be used behind an `&` or a `Box` +/// +/// This type will usually map to some string type in the target language, and +/// you will not need to worry about the safety of mismatched string invariants. +pub type DiplomatStr = [u8]; + +/// Like `Wstr`, but unvalidated. +/// +/// This is a dynamically sized type, it should be used behind an `&` or a `Box` +/// +/// This type will usually map to some string type in the target language, and +/// you will not need to worry about the safety of mismatched string invariants. +pub type DiplomatStr16 = [u16]; + +/// Like [`u8`], but interpreted explicitly as a raw byte as opposed to a numerical value. +/// +/// This matters for languages like JavaScript or Dart, where there's only a single numeric +/// type, but special types for byte buffers. +pub type DiplomatByte = u8; + +/// Allocates a buffer of a given size in Rust's memory. +/// +/// Primarily to be called by generated FFI bindings, not Rust code, but is available if needed. +/// +/// # Safety +/// - The allocated buffer must be freed with [`diplomat_free()`]. +#[no_mangle] +pub unsafe extern "C" fn diplomat_alloc(size: usize, align: usize) -> *mut u8 { + alloc::alloc::alloc(Layout::from_size_align(size, align).unwrap()) +} + +/// Frees a buffer that was allocated in Rust's memory. +/// +/// Primarily to be called by generated FFI bindings, not Rust code, but is available if needed. +/// +/// # Safety +/// - `ptr` must be a pointer to a valid buffer allocated by [`diplomat_alloc()`]. +#[no_mangle] +pub unsafe extern "C" fn diplomat_free(ptr: *mut u8, size: usize, align: usize) { + alloc::alloc::dealloc(ptr, Layout::from_size_align(size, align).unwrap()) +} + +/// Whether a `&[u8]` is a `&str`. +/// +/// Primarily to be called by generated FFI bindings, not Rust code, but is available if needed. +/// +/// # Safety +/// - `ptr` and `size` must be a valid `&[u8]` +#[no_mangle] +pub unsafe extern "C" fn diplomat_is_str(ptr: *const u8, size: usize) -> bool { + core::str::from_utf8(core::slice::from_raw_parts(ptr, size)).is_ok() +} diff --git a/deps/crates/vendor/diplomat-runtime/src/result.rs b/deps/crates/vendor/diplomat-runtime/src/result.rs new file mode 100644 index 00000000000000..a553dcdae81160 --- /dev/null +++ b/deps/crates/vendor/diplomat-runtime/src/result.rs @@ -0,0 +1,124 @@ +use core::fmt; +use core::mem::ManuallyDrop; + +#[repr(C)] +union DiplomatResultValue { + ok: ManuallyDrop, + err: ManuallyDrop, +} + +/// A [`Result`]-like type that can be passed across the FFI boundary +/// as a value. Used internally to return [`Result`]s and [`Option`]s +/// from functions. +#[repr(C)] +pub struct DiplomatResult { + value: DiplomatResultValue, + pub is_ok: bool, +} + +/// A type to represent Option over FFI. +/// +/// Used internally to handle `Option` arguments and return types, and needs to be +/// used explicitly for optional struct fields. +pub type DiplomatOption = DiplomatResult; + +impl DiplomatResult { + pub fn as_ref(&self) -> Result<&T, &E> { + // Safety: we're only accessing the union variants when the flag is correct + unsafe { + if self.is_ok { + Ok(&self.value.ok) + } else { + Err(&self.value.err) + } + } + } +} + +impl DiplomatOption { + /// Helper for converting into an Option to avoid trait ambiguity errors with Into + #[inline] + pub fn into_option(self) -> Option { + self.into() + } + + /// Helper for converting into an Option with the inner type converted + #[inline] + pub fn into_converted_option>(self) -> Option { + self.into_option().map(Into::into) + } +} + +impl Clone for DiplomatResult { + fn clone(&self) -> Self { + unsafe { + if self.is_ok { + Ok((*self.value.ok).clone()).into() + } else { + Err((*self.value.err).clone()).into() + } + } + } +} + +impl Drop for DiplomatResult { + fn drop(&mut self) { + unsafe { + if self.is_ok { + let _ = ManuallyDrop::take(&mut self.value.ok); + } else { + let _ = ManuallyDrop::take(&mut self.value.err); + } + } + } +} + +impl From> for DiplomatResult { + fn from(result: Result) -> Self { + match result { + Result::Ok(ok) => DiplomatResult { + value: DiplomatResultValue { + ok: ManuallyDrop::new(ok), + }, + is_ok: true, + }, + + Result::Err(err) => DiplomatResult { + value: DiplomatResultValue { + err: ManuallyDrop::new(err), + }, + is_ok: false, + }, + } + } +} + +impl From> for DiplomatOption { + fn from(option: Option) -> Self { + option.ok_or(()).into() + } +} + +impl From> for Option { + fn from(result: DiplomatOption) -> Self { + Result::::from(result).ok() + } +} + +impl From> for Result { + fn from(mut result: DiplomatResult) -> Result { + unsafe { + if result.is_ok { + Ok(ManuallyDrop::take(&mut result.value.ok)) + } else { + Err(ManuallyDrop::take(&mut result.value.err)) + } + } + } +} + +impl fmt::Debug for DiplomatResult { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.as_ref().fmt(f) + } +} diff --git a/deps/crates/vendor/diplomat-runtime/src/rust_interop.rs b/deps/crates/vendor/diplomat-runtime/src/rust_interop.rs new file mode 100644 index 00000000000000..d1b20122e9211a --- /dev/null +++ b/deps/crates/vendor/diplomat-runtime/src/rust_interop.rs @@ -0,0 +1,79 @@ +//! Types for interfacing with Diplomat FFI APIs from Rust. +//! +//! By and large, Diplomat helps you produce a Rust-written library that can be called from other +//! languages. You write the library in Rust, but interact with the Diplomat-wrapped library +//! in a non-Rust language. +//! +//! However, either for debugging purposes, or for extending the library in custom ways, you may find +//! yourself wanting to work with the Diplomat-wrapped library from Rust. This module contains +//! utilities for doing that. + +use crate::diplomat_buffer_write_create; +use crate::diplomat_buffer_write_destroy; +use crate::DiplomatWrite; +use core::borrow::Borrow; + +/// A [`DiplomatWrite`] backed by a `Vec`, for convenient use in Rust. +pub struct RustWriteVec { + /// Safety Invariant: must have been created by diplomat_buffer_write_create() + ptr: *mut DiplomatWrite, +} + +impl RustWriteVec { + /// Creates a new [`RustWriteVec`] with the given initial buffer capacity. + pub fn with_capacity(cap: usize) -> Self { + Self { + ptr: diplomat_buffer_write_create(cap), + } + } + + /// Borrows the underlying [`DiplomatWrite`]. + #[allow(clippy::should_implement_trait)] // the trait is also implemented + pub fn borrow(&self) -> &DiplomatWrite { + // Safety: the pointer is valid because the Drop impl hasn't been called yet. + unsafe { &*self.ptr } + } + + /// Mutably borrows the underlying [`DiplomatWrite`]. + /// + /// # Safety + /// The contents of the returned pointer MUST NOT be swapped with another instance + /// of [`DiplomatWrite`] that may have been created from a different source. This + /// requirement is satisfied if this is the only instance of [`DiplomatWrite`] + /// in scope. + /// + /// For more information, see [`DiplomatWrite`]. + pub unsafe fn borrow_mut(&mut self) -> &mut DiplomatWrite { + // Safety: the pointer is valid because the Drop impl hasn't been called yet. + unsafe { &mut *self.ptr } + } +} + +impl Borrow for RustWriteVec { + fn borrow(&self) -> &DiplomatWrite { + self.borrow() + } +} + +impl Drop for RustWriteVec { + fn drop(&mut self) { + // Safety: by invariant, ptr was created by diplomat_buffer_write_create() + unsafe { diplomat_buffer_write_destroy(self.ptr) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use core::fmt::Write; + + #[test] + fn test_rust_write() { + let mut buffer = RustWriteVec::with_capacity(5); + // Safety: this is the only instance of `DiplomatWrite` in scope. + unsafe { buffer.borrow_mut() } + .write_str("Hello World") + .unwrap(); + assert_eq!(buffer.borrow().as_bytes(), b"Hello World"); + } +} diff --git a/deps/crates/vendor/diplomat-runtime/src/slices.rs b/deps/crates/vendor/diplomat-runtime/src/slices.rs new file mode 100644 index 00000000000000..1c7638aa0d746c --- /dev/null +++ b/deps/crates/vendor/diplomat-runtime/src/slices.rs @@ -0,0 +1,291 @@ +use alloc::boxed::Box; +use core::marker::PhantomData; +use core::mem::ManuallyDrop; +use core::ops::{Deref, DerefMut}; +use core::ptr::NonNull; + +/// This is equivalent to `&[T]`, except it has a stable `repr(C)` layout +#[repr(C)] +pub struct DiplomatSlice<'a, T> { + // Invariant: ptr is a valid ptr to the beginning of an &[T] allocation. It may be null if len is null + ptr: *const T, + // Invariant: the allocation contains at least `len` elements + len: usize, + phantom: PhantomData<&'a [T]>, +} + +impl Clone for DiplomatSlice<'_, T> { + fn clone(&self) -> Self { + *self + } +} +impl Copy for DiplomatSlice<'_, T> {} + +impl<'a, T> From<&'a [T]> for DiplomatSlice<'a, T> { + fn from(x: &'a [T]) -> Self { + // Safe to construct since we're constructing it from a slice + DiplomatSlice { + ptr: x.as_ptr(), + len: x.len(), + phantom: PhantomData, + } + } +} + +impl<'a, T> From> for &'a [T] { + fn from(x: DiplomatSlice<'a, T>) -> Self { + unsafe { + // It's common in C-land to represent empty slices with NULL, which is not the case in Rust + // We normalize this + if x.ptr.is_null() { + debug_assert!(x.len == 0); + return &[]; + } + // Safety: carrying over safety variants from DiplomatSlice, and we null-checked + core::slice::from_raw_parts(x.ptr, x.len) + } + } +} + +impl Deref for DiplomatSlice<'_, T> { + type Target = [T]; + fn deref(&self) -> &[T] { + (*self).into() + } +} + +/// This is equivalent to `&mut [T]`, except it has a stable repr(C) layout +#[repr(C)] +pub struct DiplomatSliceMut<'a, T> { + // Invariant: ptr is a valid ptr to the beginning of an &[T] allocation. It may be null if len is null + ptr: *mut T, + // Invariant: the allocation contains at least `len` elements + len: usize, + phantom: PhantomData<&'a mut [T]>, +} + +impl<'a, T> From<&'a mut [T]> for DiplomatSliceMut<'a, T> { + fn from(x: &'a mut [T]) -> Self { + // Safe to construct since we're constructing it from a slice + DiplomatSliceMut { + ptr: x.as_mut_ptr(), + len: x.len(), + phantom: PhantomData, + } + } +} + +impl<'a, T> From> for &'a mut [T] { + fn from(x: DiplomatSliceMut<'a, T>) -> Self { + unsafe { + if x.ptr.is_null() { + debug_assert!(x.len == 0); + return &mut []; + } + // Safety: carrying over safety variants from DiplomatSliceMut + core::slice::from_raw_parts_mut(x.ptr, x.len) + } + } +} + +impl Deref for DiplomatSliceMut<'_, T> { + type Target = [T]; + fn deref(&self) -> &[T] { + if self.ptr.is_null() { + debug_assert!(self.len == 0); + return &[]; + } + unsafe { + // Safety: carrying over safety variants from DiplomatSliceMut + + core::slice::from_raw_parts(self.ptr, self.len) + } + } +} + +impl DerefMut for DiplomatSliceMut<'_, T> { + fn deref_mut(&mut self) -> &mut [T] { + if self.ptr.is_null() { + debug_assert!(self.len == 0); + return &mut []; + } + unsafe { + // Safety: carrying over safety variants from DiplomatSliceMut + + core::slice::from_raw_parts_mut(self.ptr, self.len) + } + } +} + +/// This is equivalent to `Box<[T]>`. +/// +/// By and large, this is useful when a backend like JS or Dart needs to allocate +/// a new slice in Rust memory to pass data around *anyway*, so we can avoid wasting +/// allocations by reusing them in Rust. +#[repr(C)] +pub struct DiplomatOwnedSlice { + // Invariant: ptr is a valid ptr to the beginning of an owned Box<[T]> allocation. It may be null if len is null + ptr: *mut T, + // Invariant: the allocation contains `len` elements + len: usize, + phantom: PhantomData>, +} + +impl Drop for DiplomatOwnedSlice { + fn drop(&mut self) { + if !self.ptr.is_null() { + unsafe { + // Safety: This is equivalent to a valid Box + drop(Box::from_raw(core::ptr::slice_from_raw_parts_mut( + self.ptr, self.len, + ))); + } + } + } +} + +impl From> for DiplomatOwnedSlice { + fn from(x: Box<[T]>) -> Self { + // Safe to construct since we're constructing it from a valid Box<[T]> + let len = x.len(); + DiplomatOwnedSlice { + ptr: Box::into_raw(x) as *mut T, + len, + phantom: PhantomData, + } + } +} + +impl From> for Box<[T]> { + fn from(x: DiplomatOwnedSlice) -> Self { + let x = ManuallyDrop::new(x); + unsafe { + if x.ptr.is_null() { + debug_assert!(x.len == 0); + let dangling = core::ptr::NonNull::dangling().as_ptr(); + return Box::from_raw(core::ptr::slice_from_raw_parts_mut(dangling, x.len)); + } + // Safety: carrying over safety variants from DiplomatOwnedSlice + Box::from_raw(core::ptr::slice_from_raw_parts_mut(x.ptr, x.len)) + } + } +} + +impl Deref for DiplomatOwnedSlice { + type Target = [T]; + fn deref(&self) -> &[T] { + if self.ptr.is_null() { + debug_assert!(self.len == 0); + return &[]; + } + // Safety: The type invariants allow us to treat is as a valid Box<[T]> + unsafe { core::slice::from_raw_parts(self.ptr, self.len) } + } +} + +impl DerefMut for DiplomatOwnedSlice { + fn deref_mut(&mut self) -> &mut [T] { + if self.ptr.is_null() { + debug_assert!(self.len == 0); + return &mut []; + } + // Safety: The type invariants allow us to treat is as a valid Box<[T]> + unsafe { core::slice::from_raw_parts_mut(self.ptr, self.len) } + } +} + +/// This is equivalent to `&str`, except it has a stable `repr(C)` layout +// Safety invariant: contained slice must be valid UTF-8 +#[repr(transparent)] +#[derive(Copy, Clone)] +pub struct DiplomatUtf8StrSlice<'a>(DiplomatSlice<'a, u8>); + +impl<'a> From<&'a str> for DiplomatUtf8StrSlice<'a> { + fn from(x: &'a str) -> Self { + // Safety: invariant upheld; obtained from `str` + Self(x.as_bytes().into()) + } +} + +impl<'a> From> for &'a str { + fn from(x: DiplomatUtf8StrSlice<'a>) -> Self { + unsafe { + // We can assume this because of the invariant on DiplomatUtf8StrSlice + core::str::from_utf8_unchecked(<&[u8]>::from(x.0)) + } + } +} + +impl Deref for DiplomatUtf8StrSlice<'_> { + type Target = str; + fn deref(&self) -> &str { + (*self).into() + } +} + +/// This is equivalent to `Box`, except it has a stable `repr(C)` layout +// Safety invariant: contained slice must be valid UTF-8 +#[repr(transparent)] +pub struct DiplomatOwnedUTF8StrSlice(DiplomatOwnedSlice); + +impl From> for DiplomatOwnedUTF8StrSlice { + fn from(x: Box) -> Self { + // Safety: invariant upheld; obtained from `str` + Self(Box::<[u8]>::from(x).into()) + } +} + +impl From for Box { + fn from(x: DiplomatOwnedUTF8StrSlice) -> Self { + let buf = Box::<[u8]>::from(x.0); + let len = buf.len(); + let raw = Box::into_raw(buf); + let raw = if raw.is_null() { + debug_assert!(len == 0); + NonNull::::dangling().as_ptr() + } else { + raw as *mut u8 + }; + unsafe { + // We deconstructed the Box already so we don't have to worry about provenance + // We're technically making an &mut [u8] here, because there isn't an easy route to construct + // string types that are owned + let slice = core::slice::from_raw_parts_mut(raw, len); + // We can assume this because of the invariant on DiplomatOwnedUTF8StrSlice + let strslice = core::str::from_utf8_unchecked_mut(slice); + Box::from_raw(strslice as *mut str) + } + } +} + +impl Deref for DiplomatOwnedUTF8StrSlice { + type Target = str; + fn deref(&self) -> &str { + let slice = &self.0; + unsafe { + // We can assume this because of the invariant on DiplomatOwnedUTF8StrSlice + core::str::from_utf8_unchecked(slice) + } + } +} + +/// This like `&str`, but unvalidated and safe to use over FFI +/// +/// This type will usually map to some string type in the target language, and +/// you will not need to worry about the safety of mismatched string invariants. +pub type DiplomatStrSlice<'a> = DiplomatSlice<'a, u8>; +/// This like `Box`, but unvalidated and safe to use over FFI +/// +/// This type will usually map to some string type in the target language, and +/// you will not need to worry about the safety of mismatched string invariants. +pub type DiplomatOwnedStrSlice = DiplomatOwnedSlice; +/// An unvalidated UTF-16 string that is safe to use over FFI +/// +/// This type will usually map to some string type in the target language, and +/// you will not need to worry about the safety of mismatched string invariants. +pub type DiplomatStr16Slice<'a> = DiplomatSlice<'a, u16>; +/// An unvalidated, owned UTF-16 string that is safe to use over FFI +/// +/// This type will usually map to some string type in the target language, and +/// you will not need to worry about the safety of mismatched string invariants. +pub type DiplomatOwnedStr16Slice<'a> = DiplomatOwnedSlice; diff --git a/deps/crates/vendor/diplomat-runtime/src/wasm_glue.rs b/deps/crates/vendor/diplomat-runtime/src/wasm_glue.rs new file mode 100644 index 00000000000000..eba51f973be8af --- /dev/null +++ b/deps/crates/vendor/diplomat-runtime/src/wasm_glue.rs @@ -0,0 +1,98 @@ +//! Wasm-specific glue code +//! +//! This is a private module +use alloc::format; + +/// In theory, this function may be useful for other backends eventually, but +/// currently it is only useful in WASM so it is in this module. +#[no_mangle] +unsafe extern "C" fn diplomat_init() { + #[cfg(debug_assertions)] + std::panic::set_hook(Box::new(panic_handler)); + #[cfg(feature = "log")] + log::set_logger(&ConsoleLogger) + .map(|()| log::set_max_level(log::LevelFilter::Debug)) + .unwrap(); +} + +fn panic_handler(info: &std::panic::PanicHookInfo) { + let msg = match info.payload().downcast_ref::<&'static str>() { + Some(&s) => s, + None => match info.payload().downcast_ref::() { + Some(s) => s.as_str(), + None => "Box", + }, + }; + + let msg = match info.location() { + Some(l) => format!( + "wasm panicked at {}:{}:{}:\n{msg}", + l.file(), + l.line(), + l.column(), + ), + None => format!("wasm panicked at :\n{msg}"), + }; + + extern "C" { + fn diplomat_throw_error_js(ptr: *const u8, len: usize); + } + + unsafe { diplomat_throw_error_js(msg.as_ptr(), msg.len()) } +} + +#[cfg(feature = "log")] +struct ConsoleLogger; + +#[cfg(feature = "log")] +impl log::Log for ConsoleLogger { + #[inline] + fn enabled(&self, metadata: &log::Metadata) -> bool { + metadata.level() <= log::max_level() + } + + fn log(&self, record: &log::Record) { + if !self.enabled(record.metadata()) { + return; + } + + let out = match record.level() { + log::Level::Error => { + extern "C" { + fn diplomat_console_error_js(ptr: *const u8, len: usize); + } + diplomat_console_error_js + } + log::Level::Warn => { + extern "C" { + fn diplomat_console_warn_js(ptr: *const u8, len: usize); + } + diplomat_console_warn_js + } + log::Level::Info => { + extern "C" { + fn diplomat_console_info_js(ptr: *const u8, len: usize); + } + diplomat_console_info_js + } + log::Level::Debug => { + extern "C" { + fn diplomat_console_log_js(ptr: *const u8, len: usize); + } + diplomat_console_log_js + } + log::Level::Trace => { + extern "C" { + fn diplomat_console_debug_js(ptr: *const u8, len: usize); + } + diplomat_console_debug_js + } + }; + + let msg = alloc::format!("{}", record.args()); + + unsafe { out(msg.as_ptr(), msg.len()) }; + } + + fn flush(&self) {} +} diff --git a/deps/crates/vendor/diplomat-runtime/src/write.rs b/deps/crates/vendor/diplomat-runtime/src/write.rs new file mode 100644 index 00000000000000..1d6400680d2e22 --- /dev/null +++ b/deps/crates/vendor/diplomat-runtime/src/write.rs @@ -0,0 +1,270 @@ +use alloc::boxed::Box; +use alloc::vec::Vec; +use core::ffi::c_void; +use core::{fmt, ptr}; + +/// An object that can one can write UTF-8 strings to +/// +/// This allows the C API to write to arbitrary kinds of objects, for example a +/// C++ std::string or a char buffer. +/// +/// The way to use this object is to fill out the `buf`, `len`, `cap` fields with +/// appropriate values for the buffer, its current length, and its current capacity, +/// and `flush` and `grow` with appropriate callbacks (using `context` to reference any +/// state they need). This object will be passed by mutable reference to the Rust side, +/// and Rust will write to it, calling `grow()` as necessary. Once done, it will call `flush()` +/// to update any state on `context` (e.g. adding a null terminator, updating the length). +/// The object on the foreign side will be directly usable after this, the foreign side +/// need not perform additional state updates after passing an [`DiplomatWrite`] to +/// a function. +/// +/// May be extended in the future to support further invariants +/// +/// DiplomatWrite will not perform any cleanup on `context` or `buf`, these are logically +/// "borrows" from the FFI side. +/// +/// # DiplomatWrite is Polymorphic +/// +/// Instances of [`DiplomatWrite`] can be created from multiple different sources. +/// There are two constructors available in `diplomat_runtime`: +/// +/// 1. [`diplomat_simple_write()`] to write to a fixed-size buffer. +/// 2. [`diplomat_buffer_write_create()`] to write to a Vec allocated by Rust. +/// A wrapper is provided: [`RustWriteVec`](rust_interop::RustWriteVec). +/// +/// Backends may have additional constructors for writing to various shapes of buffer. +/// +/// ⚠️ Because [`DiplomatWrite`] is polymorphic, the destructor must know how the instance +/// was constructed. It is therefore unsound to use functions such as [`core::mem::swap`] +/// on instances of [`DiplomatWrite`] with potentially different sources. For example, +/// the following code is not safe: +/// +/// ```no_run +/// use diplomat_runtime::DiplomatWrite; +/// fn bad(write: &mut DiplomatWrite) { +/// let mut some_other_write: DiplomatWrite = unimplemented!(); +/// // Not safe! The two `DiplomatWrite`s have different invariants +/// core::mem::swap(write, &mut some_other_write); +/// } +/// ``` +/// +/// As a result, any function that returns an owned `DiplomatWrite` or a `&mut DiplomatWrite` +/// must be `unsafe`. For an example, see [`RustWriteVec::borrow_mut`]. +/// +/// Diplomat backends guarantee they will only ever hand the same type of `DiplomatWrite` object to Rust +/// code; this is only something you need to worry about if using [`RustWriteVec`](rust_interop::RustWriteVec), +/// or `DiplomatWrite` objects manually created in Rust via APIs like `diplomat_simple_write`. +/// +/// # Safety invariants: +/// - `flush()` and `grow()` will be passed `self` including `context` and it should always be safe to do so. +/// `context` may be null, however `flush()` and `grow()` must then be ready to receive it as such. +/// - `buf` must be a valid pointer to `cap` bytes of memory +/// - `buf` must point to `len` consecutive properly initialized bytes +/// - `cap` must be less than or equal to isize::MAX +/// - `grow()` must either return false or update `buf` and `cap` for a valid buffer +/// of at least the requested buffer size. +/// - If grow_failed is true all safety invariants on buf/cap/len MUST still hold. +/// - `DiplomatWrite::flush()` will be automatically called by Diplomat. `flush()` might also be called +/// (erroneously) on the Rust side (it's a public method), so it must be idempotent. +#[repr(C)] +pub struct DiplomatWrite { + /// Context pointer for additional data needed by `grow()` and `flush()`. May be `null`. + /// + /// The pointer may reference structured data on the foreign side, + /// such as C++ std::string, used to reallocate buf. + context: *mut c_void, + /// The raw string buffer, which will be mutated on the Rust side. + buf: *mut u8, + /// The current filled size of the buffer + len: usize, + /// The current capacity of the buffer + cap: usize, + /// Set to true if `grow` ever fails. + grow_failed: bool, + /// Called by Rust to indicate that there is no more data to write. + /// + /// May be called multiple times. + /// + /// Arguments: + /// - `self` (`*mut DiplomatWrite`): This `DiplomatWrite` + flush: extern "C" fn(*mut DiplomatWrite), + /// Called by Rust to request more capacity in the buffer. The implementation should allocate a new + /// buffer and copy the contents of the old buffer into the new buffer, updating `self.buf` and `self.cap` + /// + /// Arguments: + /// - `self` (`*mut DiplomatWrite`): This `DiplomatWrite` + /// - `capacity` (`usize`): The requested capacity. + /// + /// Returns: `true` if the allocation succeeded. Should not update any state if it failed. + grow: extern "C" fn(*mut DiplomatWrite, usize) -> bool, +} + +impl DiplomatWrite { + /// Call this function before releasing the buffer to C + pub fn flush(&mut self) { + (self.flush)(self); + } + + /// Returns a pointer to the buffer's bytes. + /// + /// If growth has failed, this returns what has been written so far. + pub fn as_bytes(&self) -> &[u8] { + if self.buf.is_null() { + return &[]; + } + debug_assert!(self.len <= self.cap); + // Safety checklist, assuming this struct's safety invariants: + // 1. `buf` is a valid pointer and not null + // 2. `buf` points to `len` consecutive properly initialized bytes + // 3. `buf` won't be mutated because it is only directly accessible via + // `diplomat_buffer_write_get_bytes`, whose safety invariant states + // that the bytes cannot be mutated while borrowed + // can only be dereferenced using unsafe code + // 4. `buf`'s total size is no larger than isize::MAX + unsafe { core::slice::from_raw_parts(self.buf, self.len) } + } +} +impl fmt::Write for DiplomatWrite { + fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { + if self.grow_failed { + return Ok(()); + } + let needed_len = self.len + s.len(); + if needed_len > self.cap { + let success = (self.grow)(self, needed_len); + if !success { + self.grow_failed = true; + return Ok(()); + } + } + debug_assert!(needed_len <= self.cap); + unsafe { + ptr::copy_nonoverlapping(s.as_bytes().as_ptr(), self.buf.add(self.len), s.len()); + } + self.len = needed_len; + Ok(()) + } +} + +/// Create an `DiplomatWrite` that can write to a fixed-length stack allocated `u8` buffer. +/// +/// Once done, this will append a null terminator to the written string. +/// +/// This is largely used internally by Diplomat-generated FFI code, and should not need to be constructed +/// manually outside of that context. See [`RustWriteVec`](rust_interop::RustWriteVec) if you need this in Rust. +/// +/// # Safety +/// +/// - `buf` must be a valid pointer to a region of memory that can hold at `buf_size` bytes +#[no_mangle] +pub unsafe extern "C" fn diplomat_simple_write(buf: *mut u8, buf_size: usize) -> DiplomatWrite { + extern "C" fn grow(_this: *mut DiplomatWrite, _cap: usize) -> bool { + false + } + extern "C" fn flush(this: *mut DiplomatWrite) { + unsafe { + debug_assert!((*this).len <= (*this).cap); + let buf = (*this).buf; + ptr::write(buf.add((*this).len), 0) + } + } + DiplomatWrite { + context: ptr::null_mut(), + buf, + len: 0, + grow_failed: false, + // keep an extra byte in our pocket for the null terminator + cap: buf_size - 1, + flush, + grow, + } +} + +/// Create an [`DiplomatWrite`] that can write to a dynamically allocated buffer managed by Rust. +/// +/// Use [`diplomat_buffer_write_destroy()`] to free the writable and its underlying buffer. +/// The pointer is valid until that function is called. +/// +/// This is largely used internally by Diplomat-generated FFI code, and should not need to be constructed +/// manually outside of that context. See [`RustWriteVec`](rust_interop::RustWriteVec) if you need this in Rust. +/// +/// The grow impl never sets `grow_failed`, although it is possible for it to panic. +#[no_mangle] +pub extern "C" fn diplomat_buffer_write_create(cap: usize) -> *mut DiplomatWrite { + extern "C" fn grow(this: *mut DiplomatWrite, new_cap: usize) -> bool { + unsafe { + let this = this.as_mut().unwrap(); + let mut vec = Vec::from_raw_parts(this.buf, 0, this.cap); + vec.reserve(new_cap); + this.cap = vec.capacity(); + this.buf = vec.as_mut_ptr(); + core::mem::forget(vec); + } + true + } + + extern "C" fn flush(_: *mut DiplomatWrite) {} + + let mut vec = Vec::::with_capacity(cap); + let ret = DiplomatWrite { + context: ptr::null_mut(), + buf: vec.as_mut_ptr(), + len: 0, + grow_failed: false, + cap, + flush, + grow, + }; + + core::mem::forget(vec); + Box::into_raw(Box::new(ret)) +} + +/// Grabs a pointer to the underlying buffer of a writable. +/// +/// Returns null if there was an allocation error during the write construction. +/// +/// # Safety +/// - The returned pointer is valid until the passed writable is destroyed. +/// - The returned pointer is valid for both reads and writes, however Rust code +/// may not write to it if `this` is being accessed by other methods simultaneously. +/// - `this` must be a pointer to a valid [`DiplomatWrite`] constructed by +/// [`diplomat_buffer_write_create()`]. +#[no_mangle] +pub extern "C" fn diplomat_buffer_write_get_bytes(this: *mut DiplomatWrite) -> *mut u8 { + let this = unsafe { &*this }; + if this.grow_failed { + core::ptr::null_mut() + } else { + this.buf + } +} + +/// Gets the length in bytes of the content written to the writable. +/// +/// Returns 0 if there was an allocation error during the write construction. +/// +/// # Safety +/// - `this` must be a pointer to a valid [`DiplomatWrite`] constructed by +/// [`diplomat_buffer_write_create()`]. +#[no_mangle] +pub extern "C" fn diplomat_buffer_write_len(this: &DiplomatWrite) -> usize { + if this.grow_failed { + 0 + } else { + this.len + } +} + +/// Destructor for Rust-memory backed writables. +/// +/// # Safety +/// - `this` must be a pointer to a valid [`DiplomatWrite`] constructed by +/// [`diplomat_buffer_write_create()`]. +#[no_mangle] +pub unsafe extern "C" fn diplomat_buffer_write_destroy(this: *mut DiplomatWrite) { + let this = Box::from_raw(this); + let vec = Vec::from_raw_parts(this.buf, 0, this.cap); + drop(vec); + drop(this); +} diff --git a/deps/crates/vendor/diplomat/.cargo-checksum.json b/deps/crates/vendor/diplomat/.cargo-checksum.json new file mode 100644 index 00000000000000..07aba30c344a18 --- /dev/null +++ b/deps/crates/vendor/diplomat/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"cfa16e7d8bbf1e6193a3291dc8dcdeacef3b792cbe0590c0e9ee027ba69a7dd7","LICENSE-APACHE":"639c20c7f14fb122750d5ad1a6cfb116d9bf8d103e709ee40949e5a12a731666","LICENSE-MIT":"3337fe6e4a3830ad87c23cb9d6d750f9a1e5c45efc08de9c76c1a207fc6966c4","README.md":"9b721778a162ec713582e022ee8e497739d9bc1afba35227f845d3de570e6d95","src/enum_convert.rs":"0b6d4d9f2e0705086a48865247749660ddd75c4895c64245adcdbc16e89c57e1","src/lib.rs":"c083cdce00eca20c9f8225cd5c4fb39e6caf35f9db662100e30ac25421f7d69f","src/snapshots/diplomat__tests__both_kinds_of_option.snap":"160716e090b88c83c26feb324ec0be858572f7bb9abb0fd170814990858ca2fb","src/snapshots/diplomat__tests__callback_arguments.snap":"dee4df7c4f9707799e07b9d60b10b2f28bf6f591e165ee8686c5a2bf5fb98dea","src/snapshots/diplomat__tests__cfgd_struct.snap":"a795ac7fd3632f33e53d5ed776cc7a8f1492f819e35dc61ea786fecfb1a1da36","src/snapshots/diplomat__tests__cfged_method-2.snap":"ffaeb4c9cc4218edb08462cd6e3b1411cc0ed7383d4d5c3f06224ec4ee268601","src/snapshots/diplomat__tests__cfged_method.snap":"5b64993a0dc085628000f4ff076a45dc37f56068f778aa2cc752566e4df63899","src/snapshots/diplomat__tests__method_taking_mutable_slice.snap":"2d27211feadd4e1dafdf082c87d601c7b1c7fb168f29b04e74872713410f967e","src/snapshots/diplomat__tests__method_taking_mutable_str.snap":"e4c65337861a78b3c9762545fcdbccc1169bab9183ff750fc467a5367dba9c56","src/snapshots/diplomat__tests__method_taking_owned_slice.snap":"19ff5e72210a9eeb1fe7157398fd233d8fd2f8adf6cdea1aac2f383e2dd3d265","src/snapshots/diplomat__tests__method_taking_owned_str.snap":"9d19ab348150ca408eb618c1338f17fafecb61a6ac4db9dcd88435f19152f2cd","src/snapshots/diplomat__tests__method_taking_slice.snap":"5388b177a221877e093366fc268732307a9c774e1d673d39b5b1040a05304a80","src/snapshots/diplomat__tests__method_taking_str.snap":"dcf6ed76f55522af95666fdec05fc51d4009c0955ceb623e43c7df3456cbbbb5","src/snapshots/diplomat__tests__mod_with_enum.snap":"628c64bc63da18e14011622fb0c45e9822cdca61b33e3aebae00cacc49f859c9","src/snapshots/diplomat__tests__mod_with_rust_result.snap":"2d4c3fb61d479da8ade2c2c70ee6a0611bbd00436b38c056d8ae4f06787cfc09","src/snapshots/diplomat__tests__mod_with_write_result.snap":"9cc947c2eea7331a1bfa2b3b1a0f67576b5196f2a213f4a1d3f1d890f8d8f2aa","src/snapshots/diplomat__tests__multilevel_borrows.snap":"a5aa1bbde0f0426713a34524fc65cd4a86718820624d9b82589174c3467c86d3","src/snapshots/diplomat__tests__self_params.snap":"dc5e7fb5008a3c6034a4d0baa072d1c48790aedc45445b23388c8d5220924829","src/snapshots/diplomat__tests__slices.snap":"2d1680a836cd7e673838a0995c08d286493b8d1bc9e87d6a9596c09404fc9a04","src/snapshots/diplomat__tests__traits.snap":"9725784d9be393ebf81c3cd4576dbc13aeecdf6b6cfec71f1178aeb8d42700bc","src/transparent_convert.rs":"cc3ccca2745182dd0232facd350764845e9fbaf0481d2f2b68dce03c8edb8599"},"package":"ece782ffeb426ef0d3074c5623e8f6552cc912e4bbeecfda9583cb01b02b8ba1"} \ No newline at end of file diff --git a/deps/crates/vendor/diplomat/Cargo.toml b/deps/crates/vendor/diplomat/Cargo.toml new file mode 100644 index 00000000000000..c0ea234e8ec99a --- /dev/null +++ b/deps/crates/vendor/diplomat/Cargo.toml @@ -0,0 +1,70 @@ +# 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.81" +name = "diplomat" +version = "0.13.0" +authors = [ + "Shadaj Laddad ", + "Manish Goregaokar ", + "Quinn Okabayashi ", +] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "The diplomat FFI generation macro" +readme = "README.md" +keywords = [ + "ffi", + "codegen", +] +categories = [ + "development-tools", + "compilers", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-diplomat/diplomat" + +[lib] +name = "diplomat" +path = "src/lib.rs" +proc-macro = true + +[dependencies.diplomat_core] +version = "0.13.0" +default-features = false + +[dependencies.proc-macro2] +version = "1.0.27" + +[dependencies.quote] +version = "1.0" + +[dependencies.syn] +version = "2.0" +features = [ + "full", + "extra-traits", +] + +[dev-dependencies.insta] +version = "1.7.1" + +[dev-dependencies.prettyplease] +version = "0.2.30" + +[dev-dependencies.tempfile] +version = "3.2.0" diff --git a/deps/crates/vendor/diplomat/LICENSE-APACHE b/deps/crates/vendor/diplomat/LICENSE-APACHE new file mode 100644 index 00000000000000..05fcffa855c462 --- /dev/null +++ b/deps/crates/vendor/diplomat/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2022 The Diplomat Developers + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/deps/crates/vendor/diplomat/LICENSE-MIT b/deps/crates/vendor/diplomat/LICENSE-MIT new file mode 100644 index 00000000000000..cf62c31bc7531d --- /dev/null +++ b/deps/crates/vendor/diplomat/LICENSE-MIT @@ -0,0 +1,27 @@ +MIT License + +Copyright (c) 2022 The Diplomat Developers + +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/deps/crates/vendor/diplomat/README.md b/deps/crates/vendor/diplomat/README.md new file mode 100644 index 00000000000000..438a9400703af2 --- /dev/null +++ b/deps/crates/vendor/diplomat/README.md @@ -0,0 +1,42 @@ +# Diplomat +Diplomat is an experimental Rust tool for generating FFI definitions allowing many other languages to call Rust code. With Diplomat, you can simply define Rust APIs to be exposed over FFI and get high-level C, C++, and JavaScript bindings automatically! + +Diplomat supports generating bindings from Rust to: +- C +- C++ +- Dart +- Javascript/Typescript +- Kotlin (using JNA) +- Python (using [nanobind](https://nanobind.readthedocs.io/en/latest/index.html)) + +Diplomat supports languages through a plugin interface that makes it easy to add support for your favourite language. See [the book to get started](https://rust-diplomat.github.io/diplomat/developer.html), and `tool/src/{c, cpp, js}` for examples of existing language plugins. + +## Installation +First, install the CLI tool for generating bindings: +```bash +$ cargo install diplomat-tool +``` + +Then, add the Diplomat macro and runtime as dependencies to your project: +```toml +diplomat = "0.10.0" +diplomat-runtime = "0.10.0" +``` + +## Getting Started + +Documentation on how to use Diplomat can be found [in the book](https://rust-diplomat.github.io/diplomat/). + +### Architecture +See the [design doc](docs/design_doc.md) for more details. + +### Building and Testing +Simply run `cargo build` to build all the libraries and compile an example. To run unit tests, run `cargo test`. + +Diplomat makes use of snapshot tests to check macro and code generation logic. When code generation logic changes and the snapshots need to be updated, run `cargo insta review` (run `cargo install cargo-insta` to get the tool) to view the changes and update the snapshots. + +#### Javascript bindings for `wasm32-unknown-unknown` +The Javascript backend assumes that you are building WebAssembly on the C Spec ABI. This is not currently default for the `wasm32-unknown-unknown` target in the latest version of Rust, and so until the [new WASM ABI](https://blog.rust-lang.org/2025/04/04/c-abi-changes-for-wasm32-unknown-unknown/) is made stable, you have two options: + +1. Build using nightly Rust and enable the [`-Zwasm-c-abi=spec`](https://doc.rust-lang.org/stable/unstable-book/compiler-flags/wasm-c-abi.html) flag. +1. Configure the JS backend to use legacy bindings. There is a [WASM ABI config option](https://github.com/rust-diplomat/diplomat/blob/main/tool/src/js/mod.rs) for this, please read [the guide on configuration in the book](https://rust-diplomat.github.io/diplomat/config) for more on how to configure. \ No newline at end of file diff --git a/deps/crates/vendor/diplomat/src/enum_convert.rs b/deps/crates/vendor/diplomat/src/enum_convert.rs new file mode 100644 index 00000000000000..0dbdad9c2f5905 --- /dev/null +++ b/deps/crates/vendor/diplomat/src/enum_convert.rs @@ -0,0 +1,87 @@ +use quote::{quote, ToTokens}; +use syn::parse::{Parse, ParseStream}; +use syn::*; + +// An attribute that is a list of idents +pub struct EnumConvertAttribute { + path: Path, + + needs_wildcard: bool, +} + +impl Parse for EnumConvertAttribute { + fn parse(input: ParseStream) -> Result { + let paths = input.parse_terminated(Path::parse, Token![,])?; + if paths.is_empty() { + return Err(input.error("#[diplomat::enum_convert] needs a path argument")); + } + let needs_wildcard = if paths.len() == 2 { + if let Some(ident) = paths[1].get_ident() { + if ident == "needs_wildcard" { + true + } else { + return Err(input.error( + "#[diplomat::enum_convert] only recognizes needs_wildcard keyword", + )); + } + } else { + return Err( + input.error("#[diplomat::enum_convert] only recognizes needs_wildcard keyword") + ); + } + } else if paths.len() > 1 { + return Err(input.error("#[diplomat::enum_convert] only supports up to two arguments")); + } else { + // no needs_wildcard marker + false + }; + Ok(EnumConvertAttribute { + path: paths[0].clone(), + needs_wildcard, + }) + } +} + +pub fn gen_enum_convert(attr: EnumConvertAttribute, input: ItemEnum) -> proc_macro2::TokenStream { + let mut from_arms = vec![]; + let mut into_arms = vec![]; + + let this_name = &input.ident; + let other_name = &attr.path; + for variant in &input.variants { + if variant.fields != Fields::Unit { + return Error::new(variant.ident.span(), "variant may not have fields") + .to_compile_error(); + } + + let variant_name = &variant.ident; + from_arms.push(quote!(#other_name::#variant_name => Self::#variant_name)); + into_arms.push(quote!(#this_name::#variant_name => Self::#variant_name)); + } + + if attr.needs_wildcard { + let error = format!( + "Encountered unknown field for {}", + other_name.to_token_stream() + ); + from_arms.push(quote!(_ => unreachable!(#error))) + } + quote! { + #[allow(deprecated)] + impl From<#other_name> for #this_name { + fn from(other: #other_name) -> Self { + match other { + #(#from_arms,)* + } + } + } + #[allow(deprecated)] + impl From<#this_name> for #other_name { + fn from(this: #this_name) -> Self { + match this { + #(#into_arms,)* + } + } + } + } +} diff --git a/deps/crates/vendor/diplomat/src/lib.rs b/deps/crates/vendor/diplomat/src/lib.rs new file mode 100644 index 00000000000000..eff4168d8b5e8a --- /dev/null +++ b/deps/crates/vendor/diplomat/src/lib.rs @@ -0,0 +1,1248 @@ +//! The [Diplomat](https://rust-diplomat.github.io/diplomat/) macro crate. +//! +//! This crate provides the `#[diplomat::bridge]` proc macro, which can be used to +//! generate FFI hooks for use with bindings generated by the `diplomat-tool` library. +//! +//! Be sure to also include the [`diplomat_runtime`](https://docs.rs/diplomat_runtime) crate +//! when using the `#[diplomat::bridge]` macro. + +use proc_macro2::{Span, TokenStream}; +use quote::{quote, ToTokens}; +use syn::*; + +use diplomat_core::ast::{self, StdlibOrDiplomat}; + +mod enum_convert; +mod transparent_convert; + +fn cfgs_to_stream(attrs: &[Attribute]) -> proc_macro2::TokenStream { + attrs + .iter() + .fold(quote!(), |prev, attr| quote!(#prev #attr)) +} + +fn param_ty(param_ty: &ast::TypeName) -> syn::Type { + match ¶m_ty { + ast::TypeName::StrReference(lt @ Some(_lt), encoding, _) => { + // At the param boundary we MUST use FFI-safe diplomat slice types, + // not Rust stdlib types (which are not FFI-safe and must be converted) + encoding.get_diplomat_slice_type(lt) + } + ast::TypeName::StrReference(None, encoding, _) => encoding.get_diplomat_slice_type(&None), + ast::TypeName::StrSlice(encoding, _) => { + // At the param boundary we MUST use FFI-safe diplomat slice types, + // not Rust stdlib types (which are not FFI-safe and must be converted) + let inner = encoding.get_diplomat_slice_type(&Some(ast::Lifetime::Anonymous)); + syn::parse_quote_spanned!(Span::call_site() => diplomat_runtime::DiplomatSlice<#inner>) + } + ast::TypeName::PrimitiveSlice(ltmt, prim, _) => { + // At the param boundary we MUST use FFI-safe diplomat slice types, + // not Rust stdlib types (which are not FFI-safe and must be converted) + prim.get_diplomat_slice_type(ltmt) + } + ast::TypeName::Option(..) if !param_ty.is_ffi_safe() => { + param_ty.ffi_safe_version().to_syn() + } + _ => param_ty.to_syn(), + } +} + +fn param_conversion( + name: &ast::Ident, + param_type: &ast::TypeName, + cast_to: Option<&syn::Type>, +) -> Option { + match ¶m_type { + // conversion only needed for slices that are specified as Rust types rather than diplomat_runtime types + ast::TypeName::StrReference(.., StdlibOrDiplomat::Stdlib) + | ast::TypeName::StrSlice(.., StdlibOrDiplomat::Stdlib) + | ast::TypeName::PrimitiveSlice(.., StdlibOrDiplomat::Stdlib) + | ast::TypeName::Result(..) => Some(if let Some(cast_to) = cast_to { + quote!(let #name: #cast_to = #name.into();) + } else { + quote!(let #name = #name.into();) + }), + // Convert Option and DiplomatOption + // simplify the check by just checking is_ffi_safe() + ast::TypeName::Option(inner, _stdlib) => { + let mut tokens = TokenStream::new(); + + if !param_type.is_ffi_safe() { + let inner_ty = inner.ffi_safe_version().to_syn(); + tokens.extend(quote!(let #name : Option<#inner_ty> = #name.into();)); + } + if !inner.is_ffi_safe() { + tokens.extend(quote!(let #name = #name.map(|v| v.into());)); + } + + if !tokens.is_empty() { + Some(tokens) + } else { + None + } + } + ast::TypeName::Function(in_types, out_type, mutability) => { + let cb_wrap_ident = &name; + let mut cb_param_list = vec![]; + let mut cb_params_and_types_list = vec![]; + let mut cb_arg_type_list = vec![]; + let mut all_params_conversion = vec![]; + for (index, in_ty) in in_types.iter().enumerate() { + let param_ident_str = format!("arg{index}"); + let orig_type = in_ty.to_syn(); + let param_converted_type = param_ty(in_ty); + if let Some(conversion) = param_conversion( + &ast::Ident::from(param_ident_str.clone()), + in_ty, + Some(¶m_converted_type), + ) { + all_params_conversion.push(conversion); + } + let param_ident = Ident::new(¶m_ident_str, Span::call_site()); + cb_arg_type_list.push(param_converted_type); + cb_params_and_types_list.push(quote!(#param_ident: #orig_type)); + cb_param_list.push(param_ident); + } + + let (ret_type, conversion) = if !out_type.is_ffi_safe() { + (out_type.ffi_safe_version(), quote! { .into() }) + } else { + (*out_type.clone(), TokenStream::new()) + }; + + let cb_ret_type = ret_type.to_syn(); + + let mutability = match mutability { + ast::Mutability::Immutable => quote!(const), + ast::Mutability::Mutable => quote!(mut), + }; + let tokens = quote! { + let #cb_wrap_ident = move | #(#cb_params_and_types_list,)* | unsafe { + #(#all_params_conversion)* + let _ = &#cb_wrap_ident; // Force the lambda to capture the full object, see https://doc.rust-lang.org/edition-guide/rust-2021/disjoint-capture-in-closures.html + std::mem::transmute:: #cb_ret_type, unsafe extern "C" fn (*#mutability c_void, #(#cb_arg_type_list,)*) -> #cb_ret_type> + (#cb_wrap_ident.run_callback)(#cb_wrap_ident.data, #(#cb_param_list,)*) #conversion + }; + }; + Some(parse2(tokens).unwrap()) + } + _ => None, + } +} + +fn gen_custom_vtable(custom_trait: &ast::Trait, custom_trait_vtable_type: &Ident) -> Item { + let mut method_sigs: Vec = vec![]; + method_sigs.push(quote!( + pub destructor: Option, + pub size: usize, + pub alignment: usize, + )); + for m in &custom_trait.methods { + // TODO check that this is the right conversion, it might be the wrong direction + let mut param_types: Vec = m.params.iter().map(|p| param_ty(&p.ty)).collect(); + let method_name = Ident::new(&format!("run_{}_callback", m.name), Span::call_site()); + let return_tokens = match &m.output_type { + Some(ret_ty) => { + let conv_ret_ty = ret_ty.to_syn(); + quote!( -> #conv_ret_ty) + } + None => { + quote! {} + } + }; + param_types.insert(0, syn::parse_quote!(*const c_void)); + method_sigs.push(quote!( + pub #method_name: unsafe extern "C" fn (#(#param_types),*) #return_tokens, + + )); + } + syn::parse_quote!( + #[repr(C)] + #[allow(deprecated)] + pub struct #custom_trait_vtable_type { + #(#method_sigs)* + } + ) +} + +fn gen_custom_trait_impl(custom_trait: &ast::Trait, custom_trait_struct_name: &Ident) -> Item { + let mut methods: Vec = vec![]; + for m in &custom_trait.methods { + let param_names: Vec = m + .params + .iter() + .map(|p| { + let p_name = &p.name; + quote! {, #p_name} + }) + .collect(); + let mut all_params_conversion = vec![]; + let mut param_names_and_types: Vec = m + .params + .iter() + .map(|p| { + let orig_type = p.ty.to_syn(); + let p_ty = param_ty(&p.ty); + if let Some(conversion) = param_conversion(&p.name.clone(), &p.ty, Some(&p_ty)) { + all_params_conversion.push(conversion); + } + let p_name = &p.name; + quote!(#p_name : #orig_type) + }) + .collect(); + let method_name = &m.name; + let (return_tokens, end_token) = match &m.output_type { + Some(ret_ty) => { + let conv_ret_ty = ret_ty.to_syn(); + (quote!( -> #conv_ret_ty), quote! {}) + } + None => (quote! {}, quote! {;}), + }; + if let Some(self_param) = &m.self_param { + let mut self_modifier = quote! {}; + if let Some((lifetime, mutability)) = &self_param.reference { + let lifetime_mod = if *lifetime == ast::Lifetime::Anonymous { + quote! { & } + } else { + let prime = "'".to_string(); + let lifetime = lifetime.to_syn(); + quote! { & #prime #lifetime } + }; + let mutability_mod = if *mutability == ast::Mutability::Mutable { + quote! {mut} + } else { + quote! {} + }; + self_modifier = quote! { #lifetime_mod #mutability_mod } + } + param_names_and_types.insert(0, quote!(#self_modifier self)); + } + + let lifetimes = { + let lifetime_env = &m.lifetimes; + if lifetime_env.is_empty() { + quote! {} + } else { + quote! { <#lifetime_env> } + } + }; + let runner_method_name = + Ident::new(&format!("run_{method_name}_callback"), Span::call_site()); + methods.push(syn::Item::Fn(syn::parse_quote!( + fn #method_name #lifetimes (#(#param_names_and_types),*) #return_tokens { + unsafe { + #(#all_params_conversion)* + ((self.vtable).#runner_method_name)(self.data #(#param_names)*)#end_token + } + } + + ))); + } + let trait_name = &custom_trait.name; + syn::parse_quote!( + impl #trait_name for #custom_trait_struct_name { + #(#methods)* + } + ) +} + +fn gen_custom_type_method(strct: &ast::CustomType, m: &ast::Method) -> Item { + let self_ident = Ident::new(strct.name().as_str(), Span::call_site()); + let method_ident = Ident::new(m.name.as_str(), Span::call_site()); + let extern_ident = Ident::new(m.abi_name.as_str(), Span::call_site()); + gen_custom_function(FuncGen { + self_ident: Some(self_ident), + func_ident: method_ident, + extern_ident, + self_param: m.self_param.as_ref(), + params: &m.params, + return_type: m.return_type.as_ref(), + lifetime_env: &m.lifetime_env, + attrs: &m.attrs, + }) +} + +struct FuncGen<'a> { + self_ident: Option, + func_ident: Ident, + extern_ident: Ident, + self_param: Option<&'a crate::ast::SelfParam>, + params: &'a [crate::ast::Param], + return_type: Option<&'a crate::ast::TypeName>, + lifetime_env: &'a crate::ast::LifetimeEnv, + attrs: &'a crate::ast::Attrs, +} + +fn gen_custom_function(func_info: FuncGen) -> Item { + let mut all_params = vec![]; + + let mut all_params_conversion = vec![]; + let mut all_params_names = vec![]; + func_info.params.iter().for_each(|p| { + let ty = param_ty(&p.ty); + let name = &p.name; + all_params_names.push(name); + all_params.push(syn::parse_quote!(#name: #ty)); + if let Some(conversion) = param_conversion(&p.name, &p.ty, None) { + all_params_conversion.push(conversion); + } + }); + + let this_ident = Pat::Ident(PatIdent { + attrs: vec![], + by_ref: None, + mutability: None, + ident: Ident::new("this", Span::call_site()), + subpat: None, + }); + + if let Some(self_param) = func_info.self_param { + all_params.insert( + 0, + FnArg::Typed(PatType { + attrs: vec![], + pat: Box::new(this_ident.clone()), + colon_token: syn::token::Colon(Span::call_site()), + ty: Box::new(self_param.to_typename().to_syn()), + }), + ); + } + + let lifetimes = { + let lifetime_env = func_info.lifetime_env; + if lifetime_env.is_empty() { + quote! {} + } else { + quote! { <#lifetime_env> } + } + }; + + let func_ident = func_info.func_ident; + + let method_invocation = if func_info.self_param.is_some() { + quote! { #this_ident.#func_ident } + } else if let Some(self_ident) = func_info.self_ident { + quote! { #self_ident::#func_ident } + } else { + quote! { #func_ident } + }; + + let (return_tokens, maybe_into) = if let Some(return_type) = func_info.return_type { + if let ast::TypeName::Result(ok, err, StdlibOrDiplomat::Stdlib) = return_type { + let ok = ok.to_syn(); + let err = err.to_syn(); + ( + quote! { -> diplomat_runtime::DiplomatResult<#ok, #err> }, + quote! { .into() }, + ) + } else if let ast::TypeName::StrReference(_, _, StdlibOrDiplomat::Stdlib) + | ast::TypeName::StrSlice(.., StdlibOrDiplomat::Stdlib) + | ast::TypeName::PrimitiveSlice(_, _, StdlibOrDiplomat::Stdlib) = return_type + { + let return_type_syn = return_type.ffi_safe_version().to_syn(); + (quote! { -> #return_type_syn }, quote! { .into() }) + } else if let ast::TypeName::Ordering = return_type { + let return_type_syn = return_type.to_syn(); + (quote! { -> #return_type_syn }, quote! { as i8 }) + } else if let ast::TypeName::Option(ty, is_std_option) = return_type { + match ty.as_ref() { + // pass by reference, Option becomes null + ast::TypeName::Box(..) | ast::TypeName::Reference(..) => { + let return_type_syn = return_type.to_syn(); + let conversion = if *is_std_option == StdlibOrDiplomat::Stdlib { + quote! {} + } else { + quote! {.into()} + }; + (quote! { -> #return_type_syn }, conversion) + } + // anything else goes through DiplomatResult + _ => { + let ty = ty.to_syn(); + let conversion = if *is_std_option == StdlibOrDiplomat::Stdlib { + quote! { .ok_or(()).into() } + } else { + quote! {} + }; + ( + quote! { -> diplomat_runtime::DiplomatResult<#ty, ()> }, + conversion, + ) + } + } + } else { + let return_type_syn = return_type.to_syn(); + (quote! { -> #return_type_syn }, quote! {}) + } + } else { + (quote! {}, quote! {}) + }; + + let write_flushes = func_info + .params + .iter() + .filter(|p| p.is_write()) + .map(|p| { + let p = &p.name; + quote! { #p.flush(); } + }) + .collect::>(); + + let extern_ident = func_info.extern_ident; + + let cfg = cfgs_to_stream(&func_info.attrs.cfg); + if write_flushes.is_empty() { + Item::Fn(syn::parse_quote! { + #[no_mangle] + #cfg + #[allow(deprecated)] + extern "C" fn #extern_ident #lifetimes(#(#all_params),*) #return_tokens { + #(#all_params_conversion)* + #method_invocation(#(#all_params_names),*) #maybe_into + } + }) + } else { + Item::Fn(syn::parse_quote! { + #[no_mangle] + #cfg + #[allow(deprecated)] + extern "C" fn #extern_ident #lifetimes(#(#all_params),*) #return_tokens { + #(#all_params_conversion)* + let ret = #method_invocation(#(#all_params_names),*); + #(#write_flushes)* + ret #maybe_into + } + }) + } +} + +struct AttributeInfo { + repr: bool, + opaque: bool, + #[allow(unused)] + is_out: bool, +} + +impl AttributeInfo { + fn extract(attrs: &mut Vec) -> Self { + let mut repr = false; + let mut opaque = false; + let mut is_out = false; + attrs.retain(|attr| { + let ident = &attr.path().segments.iter().next().unwrap().ident; + if ident == "repr" { + repr = true; + // don't actually extract repr attrs, just detect them + return true; + } else if ident == "diplomat" { + if attr.path().segments.len() == 2 { + let seg = &attr.path().segments.iter().nth(1).unwrap().ident; + if seg == "opaque" { + opaque = true; + return false; + } else if seg == "out" { + is_out = true; + return false; + } else if seg == "rust_link" + || seg == "out" + || seg == "attr" + || seg == "abi_rename" + || seg == "demo" + { + // diplomat-tool reads these, not diplomat::bridge. + // throw them away so rustc doesn't complain about unknown attributes + return false; + } else if seg == "enum_convert" || seg == "transparent_convert" { + // diplomat::bridge doesn't read this, but it's handled separately + // as an attribute + return true; + } else if seg == "config" { + panic!("#[diplomat::config] is restricted to top level types in lib.rs."); + } else { + panic!("Only #[diplomat::opaque] and #[diplomat::rust_link] are supported: {seg:?}") + } + } else { + panic!("#[diplomat::foo] attrs have a single-segment path name") + } + } + true + }); + + Self { + repr, + opaque, + is_out, + } + } +} + +fn gen_bridge(mut input: ItemMod) -> ItemMod { + let module = ast::Module::from_syn(&input, true); + // Clean out any diplomat attributes so Rust doesn't get mad + let _attrs = AttributeInfo::extract(&mut input.attrs); + let (brace, mut new_contents) = input.content.unwrap(); + + new_contents.push(parse2(quote! { use diplomat_runtime::*; }).unwrap()); + new_contents.push(parse2(quote! { use core::ffi::c_void; }).unwrap()); + + new_contents.iter_mut().for_each(|c| match c { + Item::Struct(s) => { + let info = AttributeInfo::extract(&mut s.attrs); + + if !info.opaque { + // This is validated by HIR, but it's also nice to validate it in the macro so that there + // are early error messages + for field in s.fields.iter_mut() { + let _attrs = AttributeInfo::extract(&mut field.attrs); + let ty = ast::TypeName::from_syn(&field.ty, None); + if !ty.is_ffi_safe() { + let ffisafe = ty.ffi_safe_version(); + panic!("Found non-FFI safe type inside struct: {ty}, try {ffisafe}"); + } + } + } + + // Normal opaque types don't need repr(transparent) because the inner type is + // never referenced. #[diplomat::transparent_convert] handles adding repr(transparent) + // on its own + if !info.opaque { + let repr = if !info.repr { + quote!(#[repr(C)]) + } else { + quote!() + }; + + *s = syn::parse_quote! { + #repr + #s + } + } + } + + Item::Enum(e) => { + let info = AttributeInfo::extract(&mut e.attrs); + + for v in &mut e.variants { + let info = AttributeInfo::extract(&mut v.attrs); + if info.opaque { + panic!("#[diplomat::opaque] not allowed on enum variants"); + } + } + + // Normal opaque types don't need repr(transparent) because the inner type is + // never referenced. + if !info.opaque { + *e = syn::parse_quote! { + #[repr(C)] + #[derive(Clone, Copy)] + #e + }; + } + } + + Item::Impl(i) => { + for item in &mut i.items { + if let syn::ImplItem::Fn(ref mut m) = *item { + let info = AttributeInfo::extract(&mut m.attrs); + if info.opaque { + panic!("#[diplomat::opaque] not allowed on methods") + } + for i in m.sig.inputs.iter_mut() { + let _attrs = match i { + syn::FnArg::Receiver(s) => AttributeInfo::extract(&mut s.attrs), + syn::FnArg::Typed(t) => AttributeInfo::extract(&mut t.attrs), + }; + } + } + } + } + _ => (), + }); + + for custom_type in module.declared_types.values() { + custom_type.methods().iter().for_each(|m| { + let gen_m = gen_custom_type_method(custom_type, m); + new_contents.push(gen_m); + }); + + if let ast::CustomType::Opaque(opaque) = custom_type { + let destroy_ident = Ident::new(opaque.dtor_abi_name.as_str(), Span::call_site()); + + let type_ident = custom_type.name().to_syn(); + + let (lifetime_defs, lifetimes) = if let Some(lifetime_env) = custom_type.lifetimes() { + ( + quote! { <#lifetime_env> }, + lifetime_env.lifetimes_to_tokens(), + ) + } else { + (quote! {}, quote! {}) + }; + + let cfg = cfgs_to_stream(&custom_type.attrs().cfg); + + // for now, body is empty since all we need to do is drop the box + // TODO(#13): change to take a `*mut` and handle DST boxes appropriately + new_contents.push(Item::Fn(syn::parse_quote! { + #[no_mangle] + #cfg + #[allow(deprecated)] + extern "C" fn #destroy_ident #lifetime_defs(this: Box<#type_ident #lifetimes>) {} + })); + } + } + + for custom_trait in module.declared_traits.values() { + let custom_trait_name = Ident::new( + &format!("DiplomatTraitStruct_{}", custom_trait.name), + Span::call_site(), + ); + let custom_trait_vtable_type = + Ident::new(&format!("{}_VTable", custom_trait.name), Span::call_site()); + + // vtable + new_contents.push(gen_custom_vtable(custom_trait, &custom_trait_vtable_type)); + + // trait struct + new_contents.push(syn::parse_quote! { + #[repr(C)] + pub struct #custom_trait_name { + data: *const c_void, + pub vtable: #custom_trait_vtable_type, + } + }); + if custom_trait.is_send { + new_contents.push(syn::parse_quote! { + unsafe impl std::marker::Send for #custom_trait_name {} + }); + } + if custom_trait.is_sync { + new_contents.push(syn::parse_quote! { + unsafe impl std::marker::Sync for #custom_trait_name {} + }); + } + + // trait struct wrapper for all methods + new_contents.push(gen_custom_trait_impl(custom_trait, &custom_trait_name)); + + // destructor + new_contents.push(syn::parse_quote! { + impl Drop for #custom_trait_name { + fn drop(&mut self) { + if let Some(destructor) = self.vtable.destructor { + unsafe { + (destructor)(self.data); + } + } + } + } + }) + } + + for func in module.declared_functions.values() { + let func_ident = Ident::new(func.name.as_str(), Span::call_site()); + let extern_ident = Ident::new(func.abi_name.as_str(), Span::call_site()); + new_contents.push(gen_custom_function(FuncGen { + self_ident: None, + func_ident, + extern_ident, + self_param: None, + params: &func.params, + return_type: func.output_type.as_ref(), + lifetime_env: &func.lifetimes, + attrs: &func.attrs, + })) + } + + ItemMod { + attrs: input.attrs, + vis: input.vis, + mod_token: input.mod_token, + ident: input.ident, + content: Some((brace, new_contents)), + semi: input.semi, + unsafety: None, + } +} + +/// Mark a module to be exposed through Diplomat-generated FFI. +#[proc_macro_attribute] +pub fn bridge( + _attr: proc_macro::TokenStream, + input: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + let expanded = gen_bridge(parse_macro_input!(input)); + proc_macro::TokenStream::from(expanded.to_token_stream()) +} + +// Config is done in [`diplomat_tool::gen`], so we just set things to be ignored here. +#[proc_macro_attribute] +pub fn config( + _attr: proc_macro::TokenStream, + _input: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + "".parse().unwrap() +} + +/// Generate From and Into implementations for a Diplomat enum +/// +/// This is invoked as `#[diplomat::enum_convert(OtherEnumName)]` +/// on a Diplomat enum. It will assume the other enum has exactly the same variants +/// and generate From and Into implementations using those. In case that enum is `#[non_exhaustive]`, +/// you may use `#[diplomat::enum_convert(OtherEnumName, needs_wildcard)]` to generate a panicky wildcard +/// branch. It is up to the library author to ensure the enums are kept in sync. You may use the `#[non_exhaustive_omitted_patterns]` +/// lint to enforce this. +#[proc_macro_attribute] +pub fn enum_convert( + attr: proc_macro::TokenStream, + input: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + // proc macros handle compile errors by using special error tokens. + // In case of an error, we don't want the original code to go away too + // (otherwise that will cause more errors) so we hold on to it and we tack it in + // with no modifications below + let input_cached: proc_macro2::TokenStream = input.clone().into(); + let expanded = + enum_convert::gen_enum_convert(parse_macro_input!(attr), parse_macro_input!(input)); + + let full = quote! { + #expanded + #input_cached + }; + proc_macro::TokenStream::from(full.to_token_stream()) +} + +/// Generate conversions from inner types for opaque Diplomat types with a single field +/// +/// This is invoked as `#[diplomat::transparent_convert]` +/// on an opaque Diplomat type. It will add `#[repr(transparent)]` and implement `pub(crate) fn transparent_convert()` +/// which allows constructing an `&Self` from a reference to the inner field. +#[proc_macro_attribute] +pub fn transparent_convert( + _attr: proc_macro::TokenStream, + input: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + // proc macros handle compile errors by using special error tokens. + // In case of an error, we don't want the original code to go away too + // (otherwise that will cause more errors) so we hold on to it and we tack it in + // with no modifications below + let input_cached: proc_macro2::TokenStream = input.clone().into(); + let expanded = transparent_convert::gen_transparent_convert(parse_macro_input!(input)); + + let full = quote! { + #expanded + #[repr(transparent)] + #input_cached + }; + proc_macro::TokenStream::from(full.to_token_stream()) +} + +#[proc_macro_attribute] +pub fn macro_rules( + _attr: proc_macro::TokenStream, + input: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + // proc macros handle compile errors by using special error tokens. + // In case of an error, we don't want the original code to go away too + // (otherwise that will cause more errors) so we hold on to it and we tack it in + // with no modifications below + let input_cached: proc_macro2::TokenStream = input.clone().into(); + let expanded = diplomat_core::ast::MacroDef::validate(parse_macro_input!(input)); + let full = quote! { + #expanded + #input_cached + }; + proc_macro::TokenStream::from(full.to_token_stream()) +} + +// Expose attributes for macro_rules to parse: +macro_rules! expose_attrs { + ($($attr_name:ident),+) => { + $( + #[proc_macro_attribute] + pub fn $attr_name( + _attr: proc_macro::TokenStream, + input: proc_macro::TokenStream, + ) -> proc_macro::TokenStream { + input + } + )* + } +} + +expose_attrs! {opaque, attr, demo} + +#[cfg(test)] +mod tests { + + use proc_macro2::TokenStream; + use quote::ToTokens; + use syn::parse_quote; + + use super::gen_bridge; + + fn pretty_print_code(tokens: TokenStream) -> String { + let item = syn::parse2(tokens).unwrap(); + let file = syn::File { + attrs: vec![], + items: vec![item], + shebang: None, + }; + + prettyplease::unparse(&file) + } + + #[test] + fn method_taking_str() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + struct Foo {} + + impl Foo { + pub fn from_str(s: &DiplomatStr) { + unimplemented!() + } + } + } + }) + .to_token_stream() + )); + } + + #[test] + fn slices() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + use diplomat_runtime::{DiplomatStr, DiplomatStr16, DiplomatByte, DiplomatOwnedSlice, + DiplomatOwnedStr16Slice, DiplomatOwnedStrSlice, DiplomatOwnedUTF8StrSlice, + DiplomatSlice, DiplomatSliceMut, DiplomatStr16Slice, DiplomatStrSlice, DiplomatUtf8StrSlice}; + struct Foo<'a> { + a: DiplomatSlice<'a, u8>, + b: DiplomatSlice<'a, u16>, + c: DiplomatUtf8StrSlice<'a>, + d: DiplomatStrSlice<'a>, + e: DiplomatStr16Slice<'a>, + f: DiplomatSlice<'a, DiplomatByte>, + } + + impl Foo { + pub fn make(a: &'a [u8], b: &'a [u16], c: &'a str, d: &'a DiplomatStr, e: &'a DiplomatStr16, f: &'a [DiplomatByte]) -> Self { + Foo { + a, b, c, d, e, f, + } + } + pub fn make_runtime_types(a: DiplomatSlice<'a, u8>, b: DiplomatSlice<'a, u16>, c: DiplomatUtf8StrSlice<'a>, d: DiplomatStrSlice<'a>, e: DiplomatStr16Slice<'a>, f: DiplomatSlice<'a, DiplomatByte>) -> Self { + Foo { + a: a.into(), + b: b.into(), + c: c.into(), + d: d.into(), + e: e.into(), + f: f.into(), + } + } + pub fn boxes(a: Box<[u8]>, b: Box<[u16]>, c: Box, d: Box, e: Box, f: Box<[DiplomatByte]>) -> Self { + unimplemented!() + } + pub fn boxes_runtime_types(a: DiplomatOwnedSlice, b: DiplomatOwnedSlice, c: DiplomatOwnedUTF8StrSlice, d: DiplomatOwnedStrSlice, e: DiplomatOwnedStr16Slice, f: DiplomatOwnedSlice) -> Self { + unimplemented!() + } + pub fn a(self) -> &[u8] { + self.a + } + pub fn b(self) -> &[u16] { + self.b + } + pub fn c(self) -> &str { + self.c + } + pub fn d(self) -> &DiplomatStr { + self.d + } + pub fn e(self) -> &DiplomatStr16 { + self.e + } + pub fn f(self) -> &[DiplomatByte] { + self.f + } + } + } + }) + .to_token_stream() + )); + } + + #[test] + fn method_taking_slice() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + struct Foo {} + + impl Foo { + pub fn from_slice(s: &[f64]) { + unimplemented!() + } + } + } + }) + .to_token_stream() + )); + } + + #[test] + fn method_taking_mutable_slice() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + struct Foo {} + + impl Foo { + pub fn fill_slice(s: &mut [f64]) { + unimplemented!() + } + } + } + }) + .to_token_stream() + )); + } + + #[test] + fn method_taking_owned_slice() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + struct Foo {} + + impl Foo { + pub fn fill_slice(s: Box<[u16]>) { + unimplemented!() + } + } + } + }) + .to_token_stream() + )); + } + + #[test] + fn method_taking_owned_str() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + struct Foo {} + + impl Foo { + pub fn something_with_str(s: Box) { + unimplemented!() + } + } + } + }) + .to_token_stream() + )); + } + + #[test] + fn mod_with_enum() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + enum Abc { + A, + B = 123, + } + + impl Abc { + pub fn do_something(&self) { + unimplemented!() + } + } + } + }) + .to_token_stream() + )); + } + + #[test] + fn mod_with_write_result() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + struct Foo {} + + impl Foo { + pub fn to_string(&self, to: &mut DiplomatWrite) -> Result<(), ()> { + unimplemented!() + } + } + } + }) + .to_token_stream() + )); + } + + #[test] + fn mod_with_rust_result() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + struct Foo {} + + impl Foo { + pub fn bar(&self) -> Result<(), ()> { + unimplemented!() + } + } + } + }) + .to_token_stream() + )); + } + + #[test] + fn multilevel_borrows() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + #[diplomat::opaque] + struct Foo<'a>(&'a str); + + #[diplomat::opaque] + struct Bar<'b, 'a: 'b>(&'b Foo<'a>); + + struct Baz<'x, 'y> { + foo: &'y Foo<'x>, + } + + impl<'a> Foo<'a> { + pub fn new(x: &'a str) -> Box> { + unimplemented!() + } + + pub fn get_bar<'b>(&'b self) -> Box> { + unimplemented!() + } + + pub fn get_baz<'b>(&'b self) -> Baz<'b, 'a> { + Bax { foo: self } + } + } + } + }) + .to_token_stream() + )); + } + + #[test] + fn self_params() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + #[diplomat::opaque] + struct RefList<'a> { + data: &'a i32, + next: Option>, + } + + impl<'b> RefList<'b> { + pub fn extend(&mut self, other: &Self) -> Self { + unimplemented!() + } + } + } + }) + .to_token_stream() + )); + } + + #[test] + fn cfged_method() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + struct Foo {} + + impl Foo { + #[cfg(feature = "foo")] + pub fn bar(s: u8) { + unimplemented!() + } + } + } + }) + .to_token_stream() + )); + + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + struct Foo {} + + #[cfg(feature = "bar")] + impl Foo { + #[cfg(feature = "foo")] + pub fn bar(s: u8) { + unimplemented!() + } + } + } + }) + .to_token_stream() + )); + } + + #[test] + fn cfgd_struct() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + #[diplomat::opaque] + #[cfg(feature = "foo")] + struct Foo {} + #[cfg(feature = "foo")] + impl Foo { + pub fn bar(s: u8) { + unimplemented!() + } + } + } + }) + .to_token_stream() + )); + } + + #[test] + fn callback_arguments() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + pub struct Wrapper { + cant_be_empty: bool, + } + pub struct TestingStruct { + x: i32, + y: i32, + } + impl Wrapper { + pub fn test_multi_arg_callback(f: impl Fn(i32) -> i32, x: i32) -> i32 { + f(10 + x) + } + pub fn test_multiarg_void_callback(f: impl Fn(i32, &str)) { + f(-10, "hello it's a string\0"); + } + pub fn test_mod_array(g: impl Fn(&[u8])) { + let bytes: Vec = vec![0x11, 0x22]; + g(bytes.as_slice().into()); + } + pub fn test_no_args(h: impl Fn()) -> i32 { + h(); + -5 + } + pub fn test_cb_with_struct(f: impl Fn(TestingStruct) -> i32) -> i32 { + let arg = TestingStruct { + x: 1, + y: 5, + }; + f(arg) + } + pub fn test_multiple_cb_args(f: impl Fn() -> i32, g: impl Fn(i32) -> i32) -> i32 { + f() + g(5) + } + } + } + }) + .to_token_stream() + )); + } + + #[test] + fn traits() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + pub struct TestingStruct { + x: i32, + y: i32, + } + + pub trait TesterTrait: std::marker::Send { + fn test_trait_fn(&self, x: i32) -> i32; + fn test_void_trait_fn(&self); + fn test_struct_trait_fn(&self, s: TestingStruct) -> i32; + fn test_slice_trait_fn(&self, s: &[u8]) -> i32; + } + + pub struct Wrapper { + cant_be_empty: bool, + } + + impl Wrapper { + pub fn test_with_trait(t: impl TesterTrait, x: i32) -> i32 { + t.test_void_trait_fn(); + t.test_trait_fn(x) + } + + pub fn test_trait_with_struct(t: impl TesterTrait) -> i32 { + let arg = TestingStruct { + x: 1, + y: 5, + }; + t.test_struct_trait_fn(arg) + } + } + + } + }) + .to_token_stream() + )); + } + + #[test] + fn both_kinds_of_option() { + insta::assert_snapshot!(pretty_print_code( + gen_bridge(parse_quote! { + mod ffi { + use diplomat_runtime::DiplomatOption; + #[diplomat::opaque] + struct Foo {} + struct CustomStruct { + num: u8, + b: bool, + diplo_option: DiplomatOption, + } + impl Foo { + pub fn diplo_option_u8(x: DiplomatOption) -> DiplomatOption { + x + } + pub fn diplo_option_ref(x: DiplomatOption<&Foo>) -> DiplomatOption<&Foo> { + x + } + pub fn diplo_option_box() -> DiplomatOption> { + x + } + pub fn diplo_option_struct(x: DiplomatOption) -> DiplomatOption { + x + } + pub fn option_u8(x: Option) -> Option { + x + } + pub fn option_ref(x: Option<&Foo>) -> Option<&Foo> { + x + } + pub fn option_box() -> Option> { + x + } + pub fn option_struct(x: Option) -> Option { + x + } + } + } + }) + .to_token_stream() + )); + } +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__both_kinds_of_option.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__both_kinds_of_option.snap new file mode 100644 index 00000000000000..215155c34d67ce --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__both_kinds_of_option.snap @@ -0,0 +1,100 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n use diplomat_runtime::DiplomatOption; #[diplomat::opaque] struct Foo\n {} struct CustomStruct\n { num: u8, b: bool, diplo_option: DiplomatOption, } impl Foo\n {\n pub fn diplo_option_u8(x: DiplomatOption) ->\n DiplomatOption { x } pub fn\n diplo_option_ref(x: DiplomatOption<&Foo>) -> DiplomatOption<&Foo>\n { x } pub fn diplo_option_box() -> DiplomatOption> { x }\n pub fn diplo_option_struct(x: DiplomatOption) ->\n DiplomatOption { x } pub fn option_u8(x: Option)\n -> Option { x } pub fn option_ref(x: Option<&Foo>) ->\n Option<&Foo> { x } pub fn option_box() -> Option> { x }\n pub fn option_struct(x: Option) ->\n Option { x }\n }\n }\n}).to_token_stream())" +--- +mod ffi { + use diplomat_runtime::DiplomatOption; + struct Foo {} + #[repr(C)] + struct CustomStruct { + num: u8, + b: bool, + diplo_option: DiplomatOption, + } + impl Foo { + pub fn diplo_option_u8(x: DiplomatOption) -> DiplomatOption { + x + } + pub fn diplo_option_ref(x: DiplomatOption<&Foo>) -> DiplomatOption<&Foo> { + x + } + pub fn diplo_option_box() -> DiplomatOption> { + x + } + pub fn diplo_option_struct( + x: DiplomatOption, + ) -> DiplomatOption { + x + } + pub fn option_u8(x: Option) -> Option { + x + } + pub fn option_ref(x: Option<&Foo>) -> Option<&Foo> { + x + } + pub fn option_box() -> Option> { + x + } + pub fn option_struct(x: Option) -> Option { + x + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_diplo_option_u8( + x: diplomat_runtime::DiplomatOption, + ) -> diplomat_runtime::DiplomatResult { + Foo::diplo_option_u8(x) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_diplo_option_ref( + x: Option<&Foo>, + ) -> diplomat_runtime::DiplomatOption<&Foo> { + let x: Option<&Foo> = x.into(); + Foo::diplo_option_ref(x).into() + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_diplo_option_box() -> diplomat_runtime::DiplomatOption> { + Foo::diplo_option_box().into() + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_diplo_option_struct( + x: diplomat_runtime::DiplomatOption, + ) -> diplomat_runtime::DiplomatResult { + Foo::diplo_option_struct(x) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_option_u8( + x: diplomat_runtime::DiplomatOption, + ) -> diplomat_runtime::DiplomatResult { + let x: Option = x.into(); + Foo::option_u8(x).ok_or(()).into() + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_option_ref(x: Option<&Foo>) -> Option<&Foo> { + Foo::option_ref(x) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_option_box() -> Option> { + Foo::option_box() + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_option_struct( + x: diplomat_runtime::DiplomatOption, + ) -> diplomat_runtime::DiplomatResult { + let x: Option = x.into(); + Foo::option_struct(x).ok_or(()).into() + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_destroy(this: Box) {} +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__callback_arguments.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__callback_arguments.snap new file mode 100644 index 00000000000000..ea07dc78e14794 --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__callback_arguments.snap @@ -0,0 +1,140 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n pub struct Wrapper { cant_be_empty: bool, } pub struct TestingStruct\n { x: i32, y: i32, } impl Wrapper\n {\n pub fn test_multi_arg_callback(f: impl Fn(i32) -> i32, x: i32) ->\n i32 { f(10 + x) } pub fn\n test_multiarg_void_callback(f: impl Fn(i32, &str))\n { f(-10, \"hello it's a string\\0\"); } pub fn\n test_mod_array(g: impl Fn(&[u8]))\n {\n let bytes: Vec = vec![0x11, 0x22];\n g(bytes.as_slice().into());\n } pub fn test_no_args(h: impl Fn()) -> i32 { h(); -5 } pub fn\n test_cb_with_struct(f: impl Fn(TestingStruct) -> i32) -> i32\n { let arg = TestingStruct { x: 1, y: 5, }; f(arg) } pub fn\n test_multiple_cb_args(f: impl Fn() -> i32, g: impl Fn(i32) -> i32)\n -> i32 { f() + g(5) }\n }\n }\n}).to_token_stream())" +--- +mod ffi { + #[repr(C)] + pub struct Wrapper { + cant_be_empty: bool, + } + #[repr(C)] + pub struct TestingStruct { + x: i32, + y: i32, + } + impl Wrapper { + pub fn test_multi_arg_callback(f: impl Fn(i32) -> i32, x: i32) -> i32 { + f(10 + x) + } + pub fn test_multiarg_void_callback(f: impl Fn(i32, &str)) { + f(-10, "hello it's a string\0"); + } + pub fn test_mod_array(g: impl Fn(&[u8])) { + let bytes: Vec = vec![0x11, 0x22]; + g(bytes.as_slice().into()); + } + pub fn test_no_args(h: impl Fn()) -> i32 { + h(); + -5 + } + pub fn test_cb_with_struct(f: impl Fn(TestingStruct) -> i32) -> i32 { + let arg = TestingStruct { x: 1, y: 5 }; + f(arg) + } + pub fn test_multiple_cb_args( + f: impl Fn() -> i32, + g: impl Fn(i32) -> i32, + ) -> i32 { + f() + g(5) + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Wrapper_test_multi_arg_callback( + f: DiplomatCallback, + x: i32, + ) -> i32 { + let f = move |arg0: i32| unsafe { + let _ = &f; + std::mem::transmute::< + unsafe extern "C" fn(*mut c_void, ...) -> i32, + unsafe extern "C" fn(*const c_void, i32) -> i32, + >(f.run_callback)(f.data, arg0) + }; + Wrapper::test_multi_arg_callback(f, x) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Wrapper_test_multiarg_void_callback(f: DiplomatCallback<()>) { + let f = move |arg0: i32, arg1: &str| unsafe { + let arg1: diplomat_runtime::DiplomatUtf8StrSlice = arg1.into(); + let _ = &f; + std::mem::transmute::< + unsafe extern "C" fn(*mut c_void, ...) -> (), + unsafe extern "C" fn( + *const c_void, + i32, + diplomat_runtime::DiplomatUtf8StrSlice, + ) -> (), + >(f.run_callback)(f.data, arg0, arg1) + .into() + }; + Wrapper::test_multiarg_void_callback(f) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Wrapper_test_mod_array(g: DiplomatCallback<()>) { + let g = move |arg0: &[u8]| unsafe { + let arg0: diplomat_runtime::DiplomatSlice = arg0.into(); + let _ = &g; + std::mem::transmute::< + unsafe extern "C" fn(*mut c_void, ...) -> (), + unsafe extern "C" fn( + *const c_void, + diplomat_runtime::DiplomatSlice, + ) -> (), + >(g.run_callback)(g.data, arg0) + .into() + }; + Wrapper::test_mod_array(g) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Wrapper_test_no_args(h: DiplomatCallback<()>) -> i32 { + let h = move || unsafe { + let _ = &h; + std::mem::transmute::< + unsafe extern "C" fn(*mut c_void, ...) -> (), + unsafe extern "C" fn(*const c_void) -> (), + >(h.run_callback)(h.data) + .into() + }; + Wrapper::test_no_args(h) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Wrapper_test_cb_with_struct(f: DiplomatCallback) -> i32 { + let f = move |arg0: TestingStruct| unsafe { + let _ = &f; + std::mem::transmute::< + unsafe extern "C" fn(*mut c_void, ...) -> i32, + unsafe extern "C" fn(*const c_void, TestingStruct) -> i32, + >(f.run_callback)(f.data, arg0) + }; + Wrapper::test_cb_with_struct(f) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Wrapper_test_multiple_cb_args( + f: DiplomatCallback, + g: DiplomatCallback, + ) -> i32 { + let f = move || unsafe { + let _ = &f; + std::mem::transmute::< + unsafe extern "C" fn(*mut c_void, ...) -> i32, + unsafe extern "C" fn(*const c_void) -> i32, + >(f.run_callback)(f.data) + }; + let g = move |arg0: i32| unsafe { + let _ = &g; + std::mem::transmute::< + unsafe extern "C" fn(*mut c_void, ...) -> i32, + unsafe extern "C" fn(*const c_void, i32) -> i32, + >(g.run_callback)(g.data, arg0) + }; + Wrapper::test_multiple_cb_args(f, g) + } +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__cfgd_struct.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__cfgd_struct.snap new file mode 100644 index 00000000000000..a0a59a81c58181 --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__cfgd_struct.snap @@ -0,0 +1,26 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n #[diplomat::opaque] #[cfg(feature = \"foo\")] struct Foo {}\n #[cfg(feature = \"foo\")] impl Foo\n { pub fn bar(s: u8) { unimplemented!() } }\n }\n}).to_token_stream())" +--- +mod ffi { + #[cfg(feature = "foo")] + struct Foo {} + #[cfg(feature = "foo")] + impl Foo { + pub fn bar(s: u8) { + unimplemented!() + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[cfg(feature = "foo")] + #[allow(deprecated)] + extern "C" fn Foo_bar(s: u8) { + Foo::bar(s) + } + #[no_mangle] + #[cfg(feature = "foo")] + #[allow(deprecated)] + extern "C" fn Foo_destroy(this: Box) {} +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__cfged_method-2.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__cfged_method-2.snap new file mode 100644 index 00000000000000..d03505624d3857 --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__cfged_method-2.snap @@ -0,0 +1,24 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n struct Foo {} #[cfg(feature = \"bar\")] impl Foo\n { #[cfg(feature = \"foo\")] pub fn bar(s: u8) { unimplemented!() } }\n }\n}).to_token_stream())" +--- +mod ffi { + #[repr(C)] + struct Foo {} + #[cfg(feature = "bar")] + impl Foo { + #[cfg(feature = "foo")] + pub fn bar(s: u8) { + unimplemented!() + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[cfg(feature = "bar")] + #[cfg(feature = "foo")] + #[allow(deprecated)] + extern "C" fn Foo_bar(s: u8) { + Foo::bar(s) + } +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__cfged_method.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__cfged_method.snap new file mode 100644 index 00000000000000..0fd6b5b670afe1 --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__cfged_method.snap @@ -0,0 +1,22 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n struct Foo {} impl Foo\n { #[cfg(feature = \"foo\")] pub fn bar(s: u8) { unimplemented!() } }\n }\n}).to_token_stream())" +--- +mod ffi { + #[repr(C)] + struct Foo {} + impl Foo { + #[cfg(feature = "foo")] + pub fn bar(s: u8) { + unimplemented!() + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[cfg(feature = "foo")] + #[allow(deprecated)] + extern "C" fn Foo_bar(s: u8) { + Foo::bar(s) + } +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_mutable_slice.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_mutable_slice.snap new file mode 100644 index 00000000000000..3822c42e90e48e --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_mutable_slice.snap @@ -0,0 +1,21 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n struct Foo {} impl Foo\n { pub fn fill_slice(s: &mut [f64]) { unimplemented!() } }\n }\n}).to_token_stream())" +--- +mod ffi { + #[repr(C)] + struct Foo {} + impl Foo { + pub fn fill_slice(s: &mut [f64]) { + unimplemented!() + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_fill_slice(s: diplomat_runtime::DiplomatSliceMut) { + let s = s.into(); + Foo::fill_slice(s) + } +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_mutable_str.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_mutable_str.snap new file mode 100644 index 00000000000000..bebbcf845518cc --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_mutable_str.snap @@ -0,0 +1,26 @@ +--- +source: macro/src/lib.rs +expression: "rustfmt_code(&gen_bridge(parse_quote! {\n mod ffi\n {\n struct Foo {} impl Foo\n {\n pub fn make_uppercase(s : & mut str) { unimplemented! () }\n }\n }\n }).to_token_stream().to_string())" +--- +mod ffi { + #[repr(C)] + struct Foo {} + impl Foo { + pub fn make_uppercase(s: &mut str) { + unimplemented!() + } + } + #[no_mangle] + extern "C" fn Foo_make_uppercase(s_diplomat_data: *mut u8, s_diplomat_len: usize) { + Foo::make_uppercase(unsafe { + core::str::from_utf8_mut(core::slice::from_raw_parts_mut( + s_diplomat_data, + s_diplomat_len, + )) + .unwrap() + }) + } + #[no_mangle] + extern "C" fn Foo_destroy(this: Box) {} +} + diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_owned_slice.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_owned_slice.snap new file mode 100644 index 00000000000000..ea168fba062eea --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_owned_slice.snap @@ -0,0 +1,21 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n struct Foo {} impl Foo\n { pub fn fill_slice(s: Box<[u16]>) { unimplemented!() } }\n }\n}).to_token_stream())" +--- +mod ffi { + #[repr(C)] + struct Foo {} + impl Foo { + pub fn fill_slice(s: Box<[u16]>) { + unimplemented!() + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_fill_slice(s: diplomat_runtime::DiplomatOwnedSlice) { + let s = s.into(); + Foo::fill_slice(s) + } +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_owned_str.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_owned_str.snap new file mode 100644 index 00000000000000..06ab16eaddcced --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_owned_str.snap @@ -0,0 +1,23 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n struct Foo {} impl Foo\n { pub fn something_with_str(s: Box) { unimplemented!() } }\n }\n}).to_token_stream())" +--- +mod ffi { + #[repr(C)] + struct Foo {} + impl Foo { + pub fn something_with_str(s: Box) { + unimplemented!() + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_something_with_str( + s: diplomat_runtime::DiplomatOwnedUTF8StrSlice, + ) { + let s = s.into(); + Foo::something_with_str(s) + } +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_slice.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_slice.snap new file mode 100644 index 00000000000000..d7e8b4b01b226f --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_slice.snap @@ -0,0 +1,21 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n struct Foo {} impl Foo\n { pub fn from_slice(s: &[f64]) { unimplemented!() } }\n }\n}).to_token_stream())" +--- +mod ffi { + #[repr(C)] + struct Foo {} + impl Foo { + pub fn from_slice(s: &[f64]) { + unimplemented!() + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_from_slice(s: diplomat_runtime::DiplomatSlice) { + let s = s.into(); + Foo::from_slice(s) + } +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_str.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_str.snap new file mode 100644 index 00000000000000..53fa3d94b0265b --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__method_taking_str.snap @@ -0,0 +1,21 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n struct Foo {} impl Foo\n { pub fn from_str(s: &DiplomatStr) { unimplemented!() } }\n }\n}).to_token_stream())" +--- +mod ffi { + #[repr(C)] + struct Foo {} + impl Foo { + pub fn from_str(s: &DiplomatStr) { + unimplemented!() + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_from_str(s: diplomat_runtime::DiplomatStrSlice) { + let s = s.into(); + Foo::from_str(s) + } +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__mod_with_enum.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__mod_with_enum.snap new file mode 100644 index 00000000000000..c9ce129da25165 --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__mod_with_enum.snap @@ -0,0 +1,24 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n enum Abc { A, B = 123, } impl Abc\n { pub fn do_something(&self) { unimplemented!() } }\n }\n}).to_token_stream())" +--- +mod ffi { + #[repr(C)] + #[derive(Clone, Copy)] + enum Abc { + A, + B = 123, + } + impl Abc { + pub fn do_something(&self) { + unimplemented!() + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Abc_do_something(this: &Abc) { + this.do_something() + } +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__mod_with_rust_result.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__mod_with_rust_result.snap new file mode 100644 index 00000000000000..54d1b4978491bb --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__mod_with_rust_result.snap @@ -0,0 +1,20 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n struct Foo {} impl Foo\n { pub fn bar(&self) -> Result<(), ()> { unimplemented!() } }\n }\n}).to_token_stream())" +--- +mod ffi { + #[repr(C)] + struct Foo {} + impl Foo { + pub fn bar(&self) -> Result<(), ()> { + unimplemented!() + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_bar(this: &Foo) -> diplomat_runtime::DiplomatResult<(), ()> { + this.bar().into() + } +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__mod_with_write_result.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__mod_with_write_result.snap new file mode 100644 index 00000000000000..b813366fba7429 --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__mod_with_write_result.snap @@ -0,0 +1,25 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n struct Foo {} impl Foo\n {\n pub fn to_string(&self, to: &mut DiplomatWrite) -> Result<(), ()>\n { unimplemented!() }\n }\n }\n}).to_token_stream())" +--- +mod ffi { + #[repr(C)] + struct Foo {} + impl Foo { + pub fn to_string(&self, to: &mut DiplomatWrite) -> Result<(), ()> { + unimplemented!() + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_to_string( + this: &Foo, + to: &mut diplomat_runtime::DiplomatWrite, + ) -> diplomat_runtime::DiplomatResult<(), ()> { + let ret = this.to_string(to); + to.flush(); + ret.into() + } +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__multilevel_borrows.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__multilevel_borrows.snap new file mode 100644 index 00000000000000..d72eb0ec7349a2 --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__multilevel_borrows.snap @@ -0,0 +1,49 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n #[diplomat::opaque] struct Foo<'a>(&'a str); #[diplomat::opaque]\n struct Bar<'b, 'a: 'b>(&'b Foo<'a>); struct Baz<'x, 'y>\n { foo: &'y Foo<'x>, } impl<'a> Foo<'a>\n {\n pub fn new(x: &'a str) -> Box> { unimplemented!() } pub fn\n get_bar<'b>(&'b self) -> Box> { unimplemented!() } pub\n fn get_baz<'b>(&'b self) -> Baz<'b, 'a> { Bax { foo: self } }\n }\n }\n}).to_token_stream())" +--- +mod ffi { + struct Foo<'a>(&'a str); + struct Bar<'b, 'a: 'b>(&'b Foo<'a>); + #[repr(C)] + struct Baz<'x, 'y> { + foo: &'y Foo<'x>, + } + impl<'a> Foo<'a> { + pub fn new(x: &'a str) -> Box> { + unimplemented!() + } + pub fn get_bar<'b>(&'b self) -> Box> { + unimplemented!() + } + pub fn get_baz<'b>(&'b self) -> Baz<'b, 'a> { + Bax { foo: self } + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Bar_destroy<'b, 'a: 'b>(this: Box>) {} + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_new<'a>( + x: diplomat_runtime::DiplomatUtf8StrSlice<'a>, + ) -> Box> { + let x = x.into(); + Foo::new(x) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_get_bar<'a: 'b, 'b>(this: &'b Foo<'a>) -> Box> { + this.get_bar() + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_get_baz<'a: 'b, 'b>(this: &'b Foo<'a>) -> Baz<'b, 'a> { + this.get_baz() + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_destroy<'a>(this: Box>) {} +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__self_params.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__self_params.snap new file mode 100644 index 00000000000000..488ed47796e2c3 --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__self_params.snap @@ -0,0 +1,28 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n #[diplomat::opaque] struct RefList<'a>\n { data: &'a i32, next: Option>, } impl<'b> RefList<'b>\n {\n pub fn extend(&mut self, other: &Self) -> Self\n { unimplemented!() }\n }\n }\n}).to_token_stream())" +--- +mod ffi { + struct RefList<'a> { + data: &'a i32, + next: Option>, + } + impl<'b> RefList<'b> { + pub fn extend(&mut self, other: &Self) -> Self { + unimplemented!() + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[allow(deprecated)] + extern "C" fn RefList_extend<'b>( + this: &mut RefList<'b>, + other: &RefList<'b>, + ) -> RefList<'b> { + this.extend(other) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn RefList_destroy<'a>(this: Box>) {} +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__slices.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__slices.snap new file mode 100644 index 00000000000000..6cc94055042be4 --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__slices.snap @@ -0,0 +1,180 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n use\n diplomat_runtime::{DiplomatStr, DiplomatStr16, DiplomatByte,\n DiplomatOwnedSlice, DiplomatOwnedStr16Slice,\n DiplomatOwnedStrSlice, DiplomatOwnedUTF8StrSlice, DiplomatSlice,\n DiplomatSliceMut, DiplomatStr16Slice, DiplomatStrSlice,\n DiplomatUtf8StrSlice}; struct Foo<'a>\n {\n a: DiplomatSlice<'a, u8>, b: DiplomatSlice<'a, u16>, c:\n DiplomatUtf8StrSlice<'a>, d: DiplomatStrSlice<'a>, e:\n DiplomatStr16Slice<'a>, f: DiplomatSlice<'a, DiplomatByte>,\n } impl Foo\n {\n pub fn\n make(a: &'a [u8], b: &'a [u16], c: &'a str, d: &'a DiplomatStr, e:\n &'a DiplomatStr16, f: &'a [DiplomatByte]) -> Self\n { Foo { a, b, c, d, e, f, } } pub fn\n make_runtime_types(a: DiplomatSlice<'a, u8>, b: DiplomatSlice<'a,\n u16>, c: DiplomatUtf8StrSlice<'a>, d: DiplomatStrSlice<'a>, e:\n DiplomatStr16Slice<'a>, f: DiplomatSlice<'a, DiplomatByte>) ->\n Self\n {\n Foo\n {\n a: a.into(), b: b.into(), c: c.into(), d: d.into(), e:\n e.into(), f: f.into(),\n }\n } pub fn\n boxes(a: Box<[u8]>, b: Box<[u16]>, c: Box, d:\n Box, e: Box, f: Box<[DiplomatByte]>)\n -> Self { unimplemented!() } pub fn\n boxes_runtime_types(a: DiplomatOwnedSlice, b:\n DiplomatOwnedSlice, c: DiplomatOwnedUTF8StrSlice, d:\n DiplomatOwnedStrSlice, e: DiplomatOwnedStr16Slice, f:\n DiplomatOwnedSlice) -> Self { unimplemented!() } pub\n fn a(self) -> &[u8] { self.a } pub fn b(self) -> &[u16] { self.b }\n pub fn c(self) -> &str { self.c } pub fn d(self) -> &DiplomatStr\n { self.d } pub fn e(self) -> &DiplomatStr16 { self.e } pub fn\n f(self) -> &[DiplomatByte] { self.f }\n }\n }\n}).to_token_stream())" +--- +mod ffi { + use diplomat_runtime::{ + DiplomatStr, DiplomatStr16, DiplomatByte, DiplomatOwnedSlice, + DiplomatOwnedStr16Slice, DiplomatOwnedStrSlice, DiplomatOwnedUTF8StrSlice, + DiplomatSlice, DiplomatSliceMut, DiplomatStr16Slice, DiplomatStrSlice, + DiplomatUtf8StrSlice, + }; + #[repr(C)] + struct Foo<'a> { + a: DiplomatSlice<'a, u8>, + b: DiplomatSlice<'a, u16>, + c: DiplomatUtf8StrSlice<'a>, + d: DiplomatStrSlice<'a>, + e: DiplomatStr16Slice<'a>, + f: DiplomatSlice<'a, DiplomatByte>, + } + impl Foo { + pub fn make( + a: &'a [u8], + b: &'a [u16], + c: &'a str, + d: &'a DiplomatStr, + e: &'a DiplomatStr16, + f: &'a [DiplomatByte], + ) -> Self { + Foo { a, b, c, d, e, f } + } + pub fn make_runtime_types( + a: DiplomatSlice<'a, u8>, + b: DiplomatSlice<'a, u16>, + c: DiplomatUtf8StrSlice<'a>, + d: DiplomatStrSlice<'a>, + e: DiplomatStr16Slice<'a>, + f: DiplomatSlice<'a, DiplomatByte>, + ) -> Self { + Foo { + a: a.into(), + b: b.into(), + c: c.into(), + d: d.into(), + e: e.into(), + f: f.into(), + } + } + pub fn boxes( + a: Box<[u8]>, + b: Box<[u16]>, + c: Box, + d: Box, + e: Box, + f: Box<[DiplomatByte]>, + ) -> Self { + unimplemented!() + } + pub fn boxes_runtime_types( + a: DiplomatOwnedSlice, + b: DiplomatOwnedSlice, + c: DiplomatOwnedUTF8StrSlice, + d: DiplomatOwnedStrSlice, + e: DiplomatOwnedStr16Slice, + f: DiplomatOwnedSlice, + ) -> Self { + unimplemented!() + } + pub fn a(self) -> &[u8] { + self.a + } + pub fn b(self) -> &[u16] { + self.b + } + pub fn c(self) -> &str { + self.c + } + pub fn d(self) -> &DiplomatStr { + self.d + } + pub fn e(self) -> &DiplomatStr16 { + self.e + } + pub fn f(self) -> &[DiplomatByte] { + self.f + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_make( + a: diplomat_runtime::DiplomatSlice<'a, u8>, + b: diplomat_runtime::DiplomatSlice<'a, u16>, + c: diplomat_runtime::DiplomatUtf8StrSlice<'a>, + d: diplomat_runtime::DiplomatStrSlice<'a>, + e: diplomat_runtime::DiplomatStr16Slice<'a>, + f: diplomat_runtime::DiplomatSlice<'a, DiplomatByte>, + ) -> Foo { + let a = a.into(); + let b = b.into(); + let c = c.into(); + let d = d.into(); + let e = e.into(); + let f = f.into(); + Foo::make(a, b, c, d, e, f) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_make_runtime_types( + a: diplomat_runtime::DiplomatSlice<'a, u8>, + b: diplomat_runtime::DiplomatSlice<'a, u16>, + c: diplomat_runtime::DiplomatUtf8StrSlice<'a>, + d: diplomat_runtime::DiplomatStrSlice<'a>, + e: diplomat_runtime::DiplomatStr16Slice<'a>, + f: diplomat_runtime::DiplomatSlice<'a, DiplomatByte>, + ) -> Foo { + Foo::make_runtime_types(a, b, c, d, e, f) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_boxes( + a: diplomat_runtime::DiplomatOwnedSlice, + b: diplomat_runtime::DiplomatOwnedSlice, + c: diplomat_runtime::DiplomatOwnedUTF8StrSlice, + d: diplomat_runtime::DiplomatOwnedStrSlice, + e: diplomat_runtime::DiplomatOwnedStr16Slice, + f: diplomat_runtime::DiplomatOwnedSlice, + ) -> Foo { + let a = a.into(); + let b = b.into(); + let c = c.into(); + let d = d.into(); + let e = e.into(); + let f = f.into(); + Foo::boxes(a, b, c, d, e, f) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_boxes_runtime_types( + a: diplomat_runtime::DiplomatOwnedSlice, + b: diplomat_runtime::DiplomatOwnedSlice, + c: diplomat_runtime::DiplomatOwnedUTF8StrSlice, + d: diplomat_runtime::DiplomatOwnedStrSlice, + e: diplomat_runtime::DiplomatOwnedStr16Slice, + f: diplomat_runtime::DiplomatOwnedSlice, + ) -> Foo { + Foo::boxes_runtime_types(a, b, c, d, e, f) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_a(this: Foo) -> diplomat_runtime::DiplomatSlice { + this.a().into() + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_b(this: Foo) -> diplomat_runtime::DiplomatSlice { + this.b().into() + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_c(this: Foo) -> diplomat_runtime::DiplomatUtf8StrSlice { + this.c().into() + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_d(this: Foo) -> diplomat_runtime::DiplomatStrSlice { + this.d().into() + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_e(this: Foo) -> diplomat_runtime::DiplomatStr16Slice { + this.e().into() + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Foo_f(this: Foo) -> diplomat_runtime::DiplomatSlice { + this.f().into() + } +} diff --git a/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__traits.snap b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__traits.snap new file mode 100644 index 00000000000000..48824b239d20f6 --- /dev/null +++ b/deps/crates/vendor/diplomat/src/snapshots/diplomat__tests__traits.snap @@ -0,0 +1,99 @@ +--- +source: macro/src/lib.rs +expression: "pretty_print_code(gen_bridge(parse_quote!\n{\n mod ffi\n {\n pub struct TestingStruct { x: i32, y: i32, } pub trait TesterTrait:\n std::marker::Send\n {\n fn test_trait_fn(&self, x: i32) -> i32; fn\n test_void_trait_fn(&self); fn\n test_struct_trait_fn(&self, s: TestingStruct) -> i32; fn\n test_slice_trait_fn(&self, s: &[u8]) -> i32;\n } pub struct Wrapper { cant_be_empty: bool, } impl Wrapper\n {\n pub fn test_with_trait(t: impl TesterTrait, x: i32) -> i32\n { t.test_void_trait_fn(); t.test_trait_fn(x) } pub fn\n test_trait_with_struct(t: impl TesterTrait) -> i32\n {\n let arg = TestingStruct { x: 1, y: 5, };\n t.test_struct_trait_fn(arg)\n }\n }\n }\n}).to_token_stream())" +--- +mod ffi { + #[repr(C)] + pub struct TestingStruct { + x: i32, + y: i32, + } + pub trait TesterTrait: std::marker::Send { + fn test_trait_fn(&self, x: i32) -> i32; + fn test_void_trait_fn(&self); + fn test_struct_trait_fn(&self, s: TestingStruct) -> i32; + fn test_slice_trait_fn(&self, s: &[u8]) -> i32; + } + #[repr(C)] + pub struct Wrapper { + cant_be_empty: bool, + } + impl Wrapper { + pub fn test_with_trait(t: impl TesterTrait, x: i32) -> i32 { + t.test_void_trait_fn(); + t.test_trait_fn(x) + } + pub fn test_trait_with_struct(t: impl TesterTrait) -> i32 { + let arg = TestingStruct { x: 1, y: 5 }; + t.test_struct_trait_fn(arg) + } + } + use diplomat_runtime::*; + use core::ffi::c_void; + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Wrapper_test_with_trait( + t: DiplomatTraitStruct_TesterTrait, + x: i32, + ) -> i32 { + Wrapper::test_with_trait(t, x) + } + #[no_mangle] + #[allow(deprecated)] + extern "C" fn Wrapper_test_trait_with_struct( + t: DiplomatTraitStruct_TesterTrait, + ) -> i32 { + Wrapper::test_trait_with_struct(t) + } + #[repr(C)] + #[allow(deprecated)] + pub struct TesterTrait_VTable { + pub destructor: Option, + pub size: usize, + pub alignment: usize, + pub run_test_trait_fn_callback: unsafe extern "C" fn(*const c_void, i32) -> i32, + pub run_test_void_trait_fn_callback: unsafe extern "C" fn(*const c_void), + pub run_test_struct_trait_fn_callback: unsafe extern "C" fn( + *const c_void, + TestingStruct, + ) -> i32, + pub run_test_slice_trait_fn_callback: unsafe extern "C" fn( + *const c_void, + diplomat_runtime::DiplomatSlice, + ) -> i32, + } + #[repr(C)] + pub struct DiplomatTraitStruct_TesterTrait { + data: *const c_void, + pub vtable: TesterTrait_VTable, + } + unsafe impl std::marker::Send for DiplomatTraitStruct_TesterTrait {} + impl TesterTrait for DiplomatTraitStruct_TesterTrait { + fn test_trait_fn(&self, x: i32) -> i32 { + unsafe { ((self.vtable).run_test_trait_fn_callback)(self.data, x) } + } + fn test_void_trait_fn(&self) { + unsafe { + ((self.vtable).run_test_void_trait_fn_callback)(self.data); + } + } + fn test_struct_trait_fn(&self, s: TestingStruct) -> i32 { + unsafe { ((self.vtable).run_test_struct_trait_fn_callback)(self.data, s) } + } + fn test_slice_trait_fn(&self, s: &[u8]) -> i32 { + unsafe { + let s: diplomat_runtime::DiplomatSlice = s.into(); + ((self.vtable).run_test_slice_trait_fn_callback)(self.data, s) + } + } + } + impl Drop for DiplomatTraitStruct_TesterTrait { + fn drop(&mut self) { + if let Some(destructor) = self.vtable.destructor { + unsafe { + (destructor)(self.data); + } + } + } + } +} diff --git a/deps/crates/vendor/diplomat/src/transparent_convert.rs b/deps/crates/vendor/diplomat/src/transparent_convert.rs new file mode 100644 index 00000000000000..43f7b0b4248c89 --- /dev/null +++ b/deps/crates/vendor/diplomat/src/transparent_convert.rs @@ -0,0 +1,32 @@ +use quote::quote; +use syn::*; + +pub fn gen_transparent_convert(s: ItemStruct) -> proc_macro2::TokenStream { + let mut fields = s.fields.iter(); + let field1 = if let Some(field1) = fields.next() { + &field1.ty + } else { + panic!("#[diplomat::transparent_convert] only allowed on structs with a single field") + }; + + if fields.next().is_some() { + panic!("#[diplomat::transparent_convert] only allowed on structs with a single field") + } + let struct_name = &s.ident; + let (impl_generics, ty_generics, _) = s.generics.split_for_impl(); + let mut impl_generics: Generics = parse_quote!(#impl_generics); + let custom_lifetime: GenericParam = parse_quote!('transparent_convert_outer); + impl_generics.params.push(custom_lifetime); + quote! { + impl #impl_generics #struct_name #ty_generics { + // can potentially add transparent_convert_owned, _mut later + pub(crate) fn transparent_convert(from: &'transparent_convert_outer #field1) -> &'transparent_convert_outer Self { + // Safety: This is safe because the caller of gen_transparent_convert + // adds a repr(transparent) to the struct. + unsafe { + &*(from as *const #field1 as *const Self) + } + } + } + } +} diff --git a/deps/crates/vendor/diplomat_core/.cargo-checksum.json b/deps/crates/vendor/diplomat_core/.cargo-checksum.json new file mode 100644 index 00000000000000..2f3b0004aa0213 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"f887962a7b2222c64220947d25479877f9fbc27b9c3403c33497471c164b2c3e","LICENSE-APACHE":"639c20c7f14fb122750d5ad1a6cfb116d9bf8d103e709ee40949e5a12a731666","LICENSE-MIT":"3337fe6e4a3830ad87c23cb9d6d750f9a1e5c45efc08de9c76c1a207fc6966c4","README.md":"9b721778a162ec713582e022ee8e497739d9bc1afba35227f845d3de570e6d95","src/ast/attrs.rs":"3ed0967bba303956c302dba9996d99f6bc87eed7d681fcad2f103560bc28fd7b","src/ast/docs.rs":"6ec9e08c762d11d03f8aca993b3b9d74b930d60ee2d2d3cad548f5bb19aa8c22","src/ast/enums.rs":"ca2d018a3cf3cb6d0b075d2c8f19015e870a050cd5d1f0ae730738e9b0e4b138","src/ast/functions.rs":"914260a2dac7147c8287a0d7cd7c8b25c958d4b217f8bff57c7b3bbb2fad4640","src/ast/idents.rs":"05c7245ce6cb0d46b070f92a4996247545e1699da66d546bfd039a1e3a1a717d","src/ast/lifetimes.rs":"724548fc5a8da4565e36b26acb6018ecd3fc077776746dcd74dee08e3a393186","src/ast/macros.rs":"d853b0f645aaac811d98b0afd5c59955e68870e18172fa8a7082d7c181f42370","src/ast/methods.rs":"73a0bcfa9384dd5d6d73e41c5ade01556a2e0d2d1c6ee350a14ba5ebe8abb95b","src/ast/mod.rs":"03ef2c1e5664fed612a1f5ee6a871f7ec960e3af605478719cbd9b11e6a42dcf","src/ast/modules.rs":"bc8a87b7ee6966a2118870d8134365a25a21514530d90fd624eeb65ed943a639","src/ast/opaque.rs":"799e767d9be72d6cb383758d093be754b4b7e3f3f0f6a3176dee9f3db7e74907","src/ast/paths.rs":"480bef69cb395eb931a7e086ccde7b49f508ace10e61367002c4b072b9dd4b44","src/ast/snapshots/diplomat_core__ast__attrs__tests__attr.snap":"a67d1d88995e5140fae1b85175885c79e833a6c09d30df164bb800cf70bb9725","src/ast/snapshots/diplomat_core__ast__attrs__tests__cfg_attr.snap":"581caacd95ddb7aba9ea1d01318571a98dd5099646f7f9307064593f47edefac","src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-2.snap":"1fbb268bb55cad81803555e0552948bfa9ee1edc161f76b0e26bb5c16ac8389b","src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-3.snap":"ed4ba8423cb7605fd7a5e3faf35baafa58ce6758b50da2c98ccc0cd60792bfff","src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-4.snap":"ed4ba8423cb7605fd7a5e3faf35baafa58ce6758b50da2c98ccc0cd60792bfff","src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-5.snap":"2cbfa3d75adb944b19a4e0abdfa5cf7f9a4f82cdcd4d4b0efdbf1c857dc12aaf","src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs.snap":"0f42d7d22c82d1950aea7a59ead36701d6d572efe0d0969608afa58d8780e052","src/ast/snapshots/diplomat_core__ast__attrs__tests__rename-2.snap":"e790b3af120d71bb30b89b3a9b803cb42c58cf2f77101517cc3aa718497aa65c","src/ast/snapshots/diplomat_core__ast__attrs__tests__rename.snap":"e790b3af120d71bb30b89b3a9b803cb42c58cf2f77101517cc3aa718497aa65c","src/ast/snapshots/diplomat_core__ast__enums__tests__enum_with_discr.snap":"b89a5ec4a27f4b37a9579e177bede43fa6d453dd613ba4bc36e8e8e85ec92e7e","src/ast/snapshots/diplomat_core__ast__enums__tests__simple_enum.snap":"ff5ff54221eb87d980ed7bc1d1377b335b918dcea53caa3f4b9345b2e4b105f4","src/ast/snapshots/diplomat_core__ast__functions__tests__free_function.snap":"1941401785df2ae5fce2539e5b0514a4e7046c6440ae2c29519aedf164d21c9e","src/ast/snapshots/diplomat_core__ast__functions__tests__free_function_lifetimes.snap":"b6aef464478f240718e50ae0b55cf2ff1d0cc174c44d52bd29cd5099928b5491","src/ast/snapshots/diplomat_core__ast__functions__tests__free_function_output.snap":"210621d72626ff57d5414171997bdd1f889a586f39300e3cb3dc44bc75e6f0dd","src/ast/snapshots/diplomat_core__ast__methods__tests__cfged_method.snap":"c40532110650d39deec501fdff4fe69d9513adb40a787eff60391926918f2b04","src/ast/snapshots/diplomat_core__ast__methods__tests__nonstatic_methods-2.snap":"af48687633e88c1de24495b7dc8d6cbdf2972e9316e0d3f83fbe1f6686595634","src/ast/snapshots/diplomat_core__ast__methods__tests__nonstatic_methods.snap":"1ad9b01794280d738c76fc4dc2bd561f7177eb93855ff37d6ddc40d3e587c48e","src/ast/snapshots/diplomat_core__ast__methods__tests__static_methods-2.snap":"8af6ba37c419c4d9dc4e61a33f87585d25b0ef51716c216e0372f8c1952cf053","src/ast/snapshots/diplomat_core__ast__methods__tests__static_methods.snap":"c9ea1881533ce39fa7d9dc9ccc0949db2040f1828d260a1bacac870dc3b84863","src/ast/snapshots/diplomat_core__ast__modules__tests__import_in_non_diplomat_not_analyzed.snap":"87b9c79c33daa988b82786780dd757aeed0c65e2f60c48ee590599f984d2440b","src/ast/snapshots/diplomat_core__ast__modules__tests__method_visibility.snap":"7db85121648ca3a38c7d02a2cdede97e4d1f1973447ab935515048f65b5ddc93","src/ast/snapshots/diplomat_core__ast__modules__tests__simple_mod.snap":"78ced742540c867327833f69fa2ef6267cca21946ed0f8dee7ae8f0c1af8c6e8","src/ast/snapshots/diplomat_core__ast__structs__tests__simple_struct.snap":"f0b5e2a7da2fe0e50d1b123b2b746891b35cbd79d6de1394217007d90cc2fa0d","src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-10.snap":"b2b17cecb20e8c406f73becb508a7cddff1918cf0d080a45dcbb35317028b159","src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-11.snap":"8e068c9df2797c552421a267bbc6c1af45f7ecf1bfbb9434a64ae9bb95af184a","src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-12.snap":"413911d9b60a1541d9ac51f69b4a9552b7c5fee2a3e62defc327432f85101104","src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-2.snap":"75c377161d51dc0c4d7d91b59b04c1de62b5dffaa1a2c9cac7841ce359f82d9d","src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-3.snap":"418ff306adad93373b277f1a2fa02d1c9e66c54534d2f675288e05dcdec9696f","src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-4.snap":"f7bad0025bf2c64a18e8dd7d4a5c43f2b5ccbd4ff88e9bd2f78c226fb3f22540","src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-5.snap":"9a7b7dde9399f300bfcd739506ded5113021880629d75291b962984ec1e8fe8c","src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-6.snap":"ff1e3b2867786c467ef1148d2837da441a23e4b32d7a284a438ff5c317bafc81","src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-7.snap":"291a10613d0128d3b4cf9ef4eeea0ca43d5266c539f9a8ff130addef140bacac","src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-8.snap":"05969fe0bae4857e1893c681ab890d515a6d497da04a02f865cb520770af1164","src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-9.snap":"761d8a0f4511eed5cf3f8b7544972ba4518939147c303bb7654ba60ced8741b8","src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes.snap":"6306fae6bc6fbaf5eb679bf3313877259f9ccc09232da568fd98fe8e20eab284","src/ast/snapshots/diplomat_core__ast__types__tests__typename_boxes-2.snap":"97946b1e3118aec7ac7490f0bf38ba45013bb63c5d6bac12e3dd20fc7103348f","src/ast/snapshots/diplomat_core__ast__types__tests__typename_boxes.snap":"e3a1a07e2bfa0869918c973983b658a8e4123203f86a54a743dc6aff6a984f65","src/ast/snapshots/diplomat_core__ast__types__tests__typename_named.snap":"30b58ef9e59641eea9dfba9b965256d7a5d8667e241b7a209eb7d09208d75f7e","src/ast/snapshots/diplomat_core__ast__types__tests__typename_option-2.snap":"c90606884d4100b2d1c13822452743df2d771eec673c181eaf52808b0ba438e6","src/ast/snapshots/diplomat_core__ast__types__tests__typename_option.snap":"b60052fe5d5d553e8c9ed9995ffefbb8d0a414c567c8a58675c3cc5394392d73","src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives-2.snap":"506dcd6ea86644d4043229804bf615c8bc34cd20feef2204cd755674bf3cd00f","src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives-3.snap":"b92cd7f7cb2877c83ed8fac16d27b670e0e9d501cd6b3f70db84b322b686405f","src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives.snap":"c086765d65faac19f529a03f50ca0566cfe4e9a10b32f608ae4b9c3ad27ffdad","src/ast/snapshots/diplomat_core__ast__types__tests__typename_references-2.snap":"3ced7f6c3e2078d9534dff84e5e4a200efa84bf94435fde478c9e02b4a2b2053","src/ast/snapshots/diplomat_core__ast__types__tests__typename_references.snap":"77d5bcd560adff2216e349e0c87cff988501aef22848fbf1906b6b622ffe47cf","src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-2.snap":"aafb55a23e6be26ea03ece0595e0fa0c451bdba51f606ecaa2cddea7b21cd642","src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-3.snap":"5cc176444520a4ebf76c184d4c33643d83a87f18a4856b2565d41de79798e831","src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-4.snap":"64addbbcc9efce4ff6b98856154ce695271dc9dd74e9d921b35c2b0cf55e4bbe","src/ast/snapshots/diplomat_core__ast__types__tests__typename_result.snap":"d67d6adbd0d814503f4bcde00d65ee3e7dd353a4a6cf96b4206f145e46fbcddb","src/ast/snapshots/diplomat_core__ast__validity__tests__lifetime_in_return.snap":"aa05830ac368b2d10bc9403aaa2c8afc2345a2e21ff86e2089a0e664fde16254","src/ast/structs.rs":"2c60c74192b643268fa333276bc24deaa7f36db36fae430e2e0e95a7507b0c63","src/ast/traits.rs":"dc81b27e1c0407fab3e9266964e1a71ae7bbb6987a6a4156095299e12d83ac1d","src/ast/types.rs":"b277e7ba1687f64a2cf8b69139a31e8a48dc3ce196a8540fa22ff55b58cb31d4","src/environment.rs":"85005a4afabd0b1c22ca17d7ba12ef71783e9c001359037c714e13788f3e39a4","src/hir/attrs.rs":"927c1182e3c19c87e01d794f35d20e12da43c4f3fac3ca8529af2705dbdd9ea3","src/hir/defs.rs":"e69c37ecba56d8aa3dd73659132fd568cd37786f671bd3519aa4395cb490772c","src/hir/elision.rs":"e8c2116b52c9914887470ee30ae7b008980c2ca0630932c180556cadb4c826d9","src/hir/lifetimes.rs":"44d21b066b1ca7471a6a4c0e6cd5f674d985083962431de6fa7f543368e612f4","src/hir/lowering.rs":"23b49d7ff7ee3c5bd55055374f3902c2a2df8955f3df2a6620ca3805039d2631","src/hir/methods.rs":"40dc71e2045b1009d6a7593e3d355f51b1bbf8b3d183034f3da1ed368e3d7394","src/hir/methods/borrowing_field.rs":"4a6e75d17b702149e560c66f3ed47b35f93f50d741ab92547b4547fe9b650117","src/hir/methods/borrowing_param.rs":"51bff763a6db4a504d6f3f92d54492a4db3b05f2810f2baaa41962b01570cd2f","src/hir/mod.rs":"a9f126cac4196ebafa21fb7e38990c5ccb80129206fbcfa474db5576df98d1e3","src/hir/paths.rs":"f908e23f4b69d782fac365784f96a99c7f09dc5c599b55bd77d838ce7082264c","src/hir/primitives.rs":"88bb0d2c12843bd2a807af4edb29c383759bc8773be3c7db5e3df323775173a7","src/hir/snapshots/diplomat_core__hir__attrs__tests__auto.snap":"6259200be6bc4910ff01724ff85bc71790399a021c080f567e91af5925204e26","src/hir/snapshots/diplomat_core__hir__attrs__tests__comparator.snap":"e8e96961fae140828d6efc445ab717aad1b18f99ef8b7963b6e15555a25d9208","src/hir/snapshots/diplomat_core__hir__attrs__tests__iterator.snap":"0b744965baadb830f80c6e31494fb9c5d74e891fe7851f62e945c8a600d2d24c","src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_non_opaque_type.snap":"cc33a9372727df0547c9eb0b060c18e0c53aadadc228f18ee231f1184893a1ee","src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_opaque_type.snap":"325d0f372174390f6ed104609021a780e4d09080fda257628d20a6100a2f1f84","src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_unsupported_backend.snap":"d2286a9d382a106b6f3fbdd1303eecceffd723e875629e92c3cd181838b11705","src/hir/snapshots/diplomat_core__hir__attrs__tests__primitive_struct_slices.snap":"325d0f372174390f6ed104609021a780e4d09080fda257628d20a6100a2f1f84","src/hir/snapshots/diplomat_core__hir__attrs__tests__primitive_struct_slices_for_unsupported_backend.snap":"b85c827327134ca9860a00271fb9d80a009ede63c8533223cfe516f5385a9052","src/hir/snapshots/diplomat_core__hir__attrs__tests__struct_ref_for_unsupported_backend.snap":"2d51284344c1e13640d2fc43bc8a1dd4d8bb17d541fcae23e0a03a3df37d3f22","src/hir/snapshots/diplomat_core__hir__attrs__tests__unsupported_features.snap":"35dc32635b7b55cb877d4c3158e56352ef54de6ccb95ebe03d915c2c8bc71df4","src/hir/snapshots/diplomat_core__hir__elision__tests__borrowing_fields.snap":"6c2a9c1135f6259df281ed47760469849f21858be7c02caa4d47bcd77fc51f9a","src/hir/snapshots/diplomat_core__hir__elision__tests__elision_in_struct.snap":"7ba370040523d555971018c576b2bcb23840f308b5786dd727b74b501155c635","src/hir/snapshots/diplomat_core__hir__elision__tests__simple_mod.snap":"19bbdfee8be7cee3532c55f8f525b6ce4a24a69a762daf2be4a26a9b3c1ec91d","src/hir/snapshots/diplomat_core__hir__type_context__tests__basic_lowering.snap":"5b39ac0c01561014dc4a5f9d9f8bcdd319cce1665943c1f560cc7ab615c50b9f","src/hir/snapshots/diplomat_core__hir__type_context__tests__callback_borrowing_fails.snap":"eb7a33a0106ee09c871f5388988f45f3d82a39efdb9c936be1faf0832e02632e","src/hir/snapshots/diplomat_core__hir__type_context__tests__callback_borrowing_fails_with_unsafe_borrows.snap":"af43ceee856fac7fc8a698a39f8fe63ee5f7c91a81e9036465578b9509da2697","src/hir/snapshots/diplomat_core__hir__type_context__tests__lifetime_in_return.snap":"d6cf25b5676bad7f07c1c742e452dd4fda928b65869c95df0f8db91e56351cf7","src/hir/snapshots/diplomat_core__hir__type_context__tests__mut_struct.snap":"fe3fcbe5da79471e11209bf4f1f0aab82c87eb06feafc965ee81bbd5fd6f0622","src/hir/snapshots/diplomat_core__hir__type_context__tests__mut_struct_fails.snap":"1b1fbf420596fe33510f499cff44128cd23c36c04c6f31919b312b3f1cb8b6d7","src/hir/snapshots/diplomat_core__hir__type_context__tests__non_opaque_move.snap":"eef91b4cbd82f89441741f7bbe1d20d195c2876c2d4966eecbd55183f29d1151","src/hir/snapshots/diplomat_core__hir__type_context__tests__non_primitive_struct_slices_fails.snap":"7efa8f4e8a2e970add2269b2efbc06566623ee1d3a3db9908ca949cc0789c97b","src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_checks_with_error.snap":"1c9a5bffce9ccf66732caf6b379a6523eff53e533ebf4adbecfb169b2a384d60","src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_checks_with_safe_use.snap":"c3dee2afc274a8b70bf686ad9970826d5b59b798eecabb70a4b7bdb272816bab","src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_ffi.snap":"f17967b801a984433ab58a17acf39fd528b21c15b822745841bb366045c50840","src/hir/snapshots/diplomat_core__hir__type_context__tests__option.snap":"6b0c9d95c5761aadf62c5822eb587966240b950012e55ae39c4d53b921e2ced8","src/hir/snapshots/diplomat_core__hir__type_context__tests__option_invalid.snap":"8b7bf64e7d5a3a58ae5161966eaa2b31d5364ab3a869451f17095985d8e2d753","src/hir/snapshots/diplomat_core__hir__type_context__tests__option_valid.snap":"d29eabf19445e75454532259015011b06ec37d9cc9209476360d75bd75c61bfb","src/hir/snapshots/diplomat_core__hir__type_context__tests__required_implied_bounds.snap":"67bb19010f4db7eeb8261c7a6d31f59107340507d525f2a993a0485aff06519b","src/hir/snapshots/diplomat_core__hir__type_context__tests__return_struct_slice.snap":"b6d4c090b3c7c0f15aac40f3c8218a8b260fe64ef021ccdf11c0b121e7b218c8","src/hir/snapshots/diplomat_core__hir__type_context__tests__struct_forbidden.snap":"36852df51a118656dbd474858d6466ab803c0ac2a17b80e77c52a319b791298c","src/hir/snapshots/diplomat_core__hir__type_context__tests__struct_ref_fails.snap":"f22e76488acea33ec25130607b9af7ffcf971fec1a6d6ae81a61457777b8dfd8","src/hir/snapshots/diplomat_core__hir__type_context__tests__zst_non_opaque.snap":"e78ca15abab15a89da23c6f8f08bd6534331e7ca37e599061150615b1c674fbf","src/hir/ty_position.rs":"b3a29026a1f376b3bcaf6981c15d915b2711ee443cf9a3b322fd817d44c50ed3","src/hir/type_context.rs":"4d8028b4e109c43805f4e4a01bf57932139dc0fd69732a18968be8fb674a9b16","src/hir/types.rs":"0e3c0edf7745cf9215c1d0d79cf54d350a73e2249e2222254e22383c1d399806","src/lib.rs":"6bca84ef449b737270c0da7e8ae9dc82cfbd57e83c078b20c9894050274ed7e7"},"package":"eb0f9322e2c506400ac3f374abfcaf9fd841fcdb729bbf008a135b600f99ede7"} \ No newline at end of file diff --git a/deps/crates/vendor/diplomat_core/Cargo.toml b/deps/crates/vendor/diplomat_core/Cargo.toml new file mode 100644 index 00000000000000..ae8dab9318d3e3 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/Cargo.toml @@ -0,0 +1,90 @@ +# 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.81" +name = "diplomat_core" +version = "0.13.0" +authors = [ + "Shadaj Laddad ", + "Manish Goregaokar ", + "Quinn Okabayashi ", +] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Shared utilities between Diplomat macros and code generation" +readme = "README.md" +keywords = [ + "ffi", + "codegen", +] +categories = [ + "development-tools", + "compilers", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-diplomat/diplomat" + +[package.metadata.docs.rs] +all-features = true + +[features] +hir = ["either"] + +[lib] +name = "diplomat_core" +path = "src/lib.rs" + +[dependencies.displaydoc] +version = "0.2" +optional = true + +[dependencies.either] +version = "1.9.0" +optional = true +default-features = false + +[dependencies.proc-macro2] +version = "1.0.27" + +[dependencies.quote] +version = "1.0" + +[dependencies.serde] +version = "1.0" +features = [ + "derive", + "alloc", +] +default-features = false + +[dependencies.smallvec] +version = "1.9.0" + +[dependencies.strck] +version = "1.0" +features = ["ident"] + +[dependencies.syn] +version = "2" +features = [ + "full", + "extra-traits", +] + +[dev-dependencies.insta] +version = "1.7.1" +features = ["yaml"] diff --git a/deps/crates/vendor/diplomat_core/LICENSE-APACHE b/deps/crates/vendor/diplomat_core/LICENSE-APACHE new file mode 100644 index 00000000000000..05fcffa855c462 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2022 The Diplomat Developers + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/deps/crates/vendor/diplomat_core/LICENSE-MIT b/deps/crates/vendor/diplomat_core/LICENSE-MIT new file mode 100644 index 00000000000000..cf62c31bc7531d --- /dev/null +++ b/deps/crates/vendor/diplomat_core/LICENSE-MIT @@ -0,0 +1,27 @@ +MIT License + +Copyright (c) 2022 The Diplomat Developers + +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/deps/crates/vendor/diplomat_core/README.md b/deps/crates/vendor/diplomat_core/README.md new file mode 100644 index 00000000000000..438a9400703af2 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/README.md @@ -0,0 +1,42 @@ +# Diplomat +Diplomat is an experimental Rust tool for generating FFI definitions allowing many other languages to call Rust code. With Diplomat, you can simply define Rust APIs to be exposed over FFI and get high-level C, C++, and JavaScript bindings automatically! + +Diplomat supports generating bindings from Rust to: +- C +- C++ +- Dart +- Javascript/Typescript +- Kotlin (using JNA) +- Python (using [nanobind](https://nanobind.readthedocs.io/en/latest/index.html)) + +Diplomat supports languages through a plugin interface that makes it easy to add support for your favourite language. See [the book to get started](https://rust-diplomat.github.io/diplomat/developer.html), and `tool/src/{c, cpp, js}` for examples of existing language plugins. + +## Installation +First, install the CLI tool for generating bindings: +```bash +$ cargo install diplomat-tool +``` + +Then, add the Diplomat macro and runtime as dependencies to your project: +```toml +diplomat = "0.10.0" +diplomat-runtime = "0.10.0" +``` + +## Getting Started + +Documentation on how to use Diplomat can be found [in the book](https://rust-diplomat.github.io/diplomat/). + +### Architecture +See the [design doc](docs/design_doc.md) for more details. + +### Building and Testing +Simply run `cargo build` to build all the libraries and compile an example. To run unit tests, run `cargo test`. + +Diplomat makes use of snapshot tests to check macro and code generation logic. When code generation logic changes and the snapshots need to be updated, run `cargo insta review` (run `cargo install cargo-insta` to get the tool) to view the changes and update the snapshots. + +#### Javascript bindings for `wasm32-unknown-unknown` +The Javascript backend assumes that you are building WebAssembly on the C Spec ABI. This is not currently default for the `wasm32-unknown-unknown` target in the latest version of Rust, and so until the [new WASM ABI](https://blog.rust-lang.org/2025/04/04/c-abi-changes-for-wasm32-unknown-unknown/) is made stable, you have two options: + +1. Build using nightly Rust and enable the [`-Zwasm-c-abi=spec`](https://doc.rust-lang.org/stable/unstable-book/compiler-flags/wasm-c-abi.html) flag. +1. Configure the JS backend to use legacy bindings. There is a [WASM ABI config option](https://github.com/rust-diplomat/diplomat/blob/main/tool/src/js/mod.rs) for this, please read [the guide on configuration in the book](https://rust-diplomat.github.io/diplomat/config) for more on how to configure. \ No newline at end of file diff --git a/deps/crates/vendor/diplomat_core/src/ast/attrs.rs b/deps/crates/vendor/diplomat_core/src/ast/attrs.rs new file mode 100644 index 00000000000000..c44912962aa3e8 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/attrs.rs @@ -0,0 +1,519 @@ +//! This module contains utilities for dealing with Rust attributes + +use serde::ser::{SerializeStruct, Serializer}; +use serde::Serialize; +use std::borrow::Cow; +use std::convert::Infallible; +use std::str::FromStr; +use syn::parse::{Error as ParseError, Parse, ParseStream}; +use syn::{Attribute, Expr, Ident, Lit, LitStr, Meta, MetaList, MetaNameValue, Token}; + +/// The list of attributes on a type. All attributes except `attrs` (HIR attrs) are +/// potentially read by the diplomat macro and the AST backends, anything that is not should +/// be added as an HIR attribute ([`crate::hir::Attrs`]). +/// +/// # Inheritance +/// +/// Attributes are typically "inherited": the attributes on a module +/// apply to all types and methods with it, the attributes on an impl apply to all +/// methods in it, and the attributes on an enum apply to all variants within it. +/// This allows the user to specify a single attribute to affect multiple fields. +/// +/// However, the details of inheritance are not always the same for each attribute. For example, rename attributes +/// on a module only apply to the types within it (others methods would get doubly renamed). +/// +/// Each attribute here documents its inheritance behavior. Note that the HIR attributes do not get inherited +/// during AST construction, since at that time it's unclear which of those attributes are actually available. +#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)] +#[non_exhaustive] +pub struct Attrs { + /// The regular #[cfg()] attributes. Inherited, though the inheritance onto methods is the + /// only relevant one here. + pub cfg: Vec, + + /// The #[deprecated(note = 'foo')] attribute. + pub deprecated: Option, + + /// HIR backend attributes. + /// + /// Inherited, but only during lowering. See [`crate::hir::Attrs`] for details on which HIR attributes are inherited. + /// + /// During AST attribute inheritance, HIR backend attributes are copied over from impls to their methods since the HIR does + /// not see the impl blocks. + pub attrs: Vec, + + /// Renames to apply to the underlying C symbol. Can be found on methods, impls, and bridge modules, and is inherited. + /// + /// Affects method names when inherited onto methods. + /// + /// Affects destructor names when inherited onto types. + /// + /// Inherited. + pub abi_rename: RenameAttr, + + /// For use by [`crate::hir::Attrs::demo_attrs`] + pub demo_attrs: Vec, +} + +impl Attrs { + fn add_attr(&mut self, attr: Attr) { + match attr { + Attr::Cfg(attr) => self.cfg.push(attr), + Attr::DiplomatBackend(attr) => self.attrs.push(attr), + Attr::CRename(rename) => self.abi_rename.extend(&rename), + Attr::DemoBackend(attr) => self.demo_attrs.push(attr), + Attr::Deprecated(msg) => self.deprecated = Some(msg), + } + } + + /// Get a copy of these attributes for use in inheritance, masking out things + /// that should not be inherited + pub(crate) fn attrs_for_inheritance(&self, context: AttrInheritContext) -> Self { + // These attributes are inherited during lowering (since that's when they're parsed) + // + // Except for impls: lowering has no concept of impls so these get inherited early. This + // is fine since impls have no inherent behavior and all attributes on impls are necessarily + // only there for inheritance + let attrs = if context == AttrInheritContext::MethodFromImpl { + self.attrs.clone() + } else { + Vec::new() + }; + + let demo_attrs = if context == AttrInheritContext::MethodFromImpl { + self.demo_attrs.clone() + } else { + Vec::new() + }; + + let abi_rename = self.abi_rename.attrs_for_inheritance(context, true); + Self { + cfg: self.cfg.clone(), + + deprecated: None, + + attrs, + abi_rename, + demo_attrs, + } + } + + pub(crate) fn add_attrs(&mut self, attrs: &[Attribute]) { + for attr in syn_attr_to_ast_attr(attrs) { + self.add_attr(attr) + } + } + pub(crate) fn from_attrs(attrs: &[Attribute]) -> Self { + let mut this = Self::default(); + this.add_attrs(attrs); + this + } +} + +impl From<&[Attribute]> for Attrs { + fn from(other: &[Attribute]) -> Self { + Self::from_attrs(other) + } +} + +enum Attr { + Cfg(Attribute), + DiplomatBackend(DiplomatBackendAttr), + CRename(RenameAttr), + DemoBackend(DemoBackendAttr), + Deprecated(String), + // More goes here +} + +fn syn_attr_to_ast_attr(attrs: &[Attribute]) -> impl Iterator + '_ { + let cfg_path: syn::Path = syn::parse_str("cfg").unwrap(); + let dattr_path: syn::Path = syn::parse_str("diplomat::attr").unwrap(); + let crename_attr: syn::Path = syn::parse_str("diplomat::abi_rename").unwrap(); + let demo_path: syn::Path = syn::parse_str("diplomat::demo").unwrap(); + let deprecated: syn::Path = syn::parse_str("deprecated").unwrap(); + attrs.iter().filter_map(move |a| { + if a.path() == &cfg_path { + Some(Attr::Cfg(a.clone())) + } else if a.path() == &dattr_path { + Some(Attr::DiplomatBackend( + a.parse_args() + .expect("Failed to parse malformed diplomat::attr"), + )) + } else if a.path() == &crename_attr { + Some(Attr::CRename(RenameAttr::from_meta(&a.meta).unwrap())) + } else if a.path() == &demo_path { + Some(Attr::DemoBackend( + a.parse_args() + .expect("Failed to parse malformed diplomat::demo"), + )) + } else if a.path() == &deprecated { + if let Some(Meta::NameValue(MetaNameValue { + value: + syn::Expr::Lit(syn::ExprLit { + lit: Lit::Str(s), .. + }), + .. + })) = a + .meta + .require_list() + .ok() + .and_then(|m| syn::parse2::(m.tokens.clone()).ok()) + { + Some(Attr::Deprecated(s.value())) + } else { + Some(Attr::Deprecated("deprecated".into())) + } + } else { + None + } + }) +} + +impl Serialize for Attrs { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // 1 is the number of fields in the struct. + let mut state = serializer.serialize_struct("Attrs", 1)?; + if !self.cfg.is_empty() { + let cfg: Vec<_> = self + .cfg + .iter() + .map(|a| quote::quote!(#a).to_string()) + .collect(); + state.serialize_field("cfg", &cfg)?; + } + if !self.attrs.is_empty() { + state.serialize_field("attrs", &self.attrs)?; + } + if !self.abi_rename.is_empty() { + state.serialize_field("abi_rename", &self.abi_rename)?; + } + state.end() + } +} + +/// A `#[diplomat::attr(...)]` attribute +/// +/// Its contents must start with single element that is a CFG-expression +/// (so it may contain `foo = bar`, `foo = "bar"`, `ident`, `*` atoms, +/// and `all()`, `not()`, and `any()` combiners), and then be followed by one +/// or more backend-specific attributes, which can be any valid meta-item +#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize)] +#[non_exhaustive] +pub struct DiplomatBackendAttr { + pub cfg: DiplomatBackendAttrCfg, + #[serde(serialize_with = "serialize_meta")] + pub meta: Meta, +} + +fn serialize_meta(m: &Meta, s: S) -> Result +where + S: Serializer, +{ + quote::quote!(#m).to_string().serialize(s) +} + +#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize)] +#[non_exhaustive] +pub enum DiplomatBackendAttrCfg { + Not(Box), + Any(Vec), + All(Vec), + Star, + // "auto", smartly figure out based on the attribute used + Auto, + BackendName(String), + NameValue(String, String), +} + +impl Parse for DiplomatBackendAttrCfg { + fn parse(input: ParseStream<'_>) -> syn::Result { + let lookahead = input.lookahead1(); + if lookahead.peek(Ident) { + let name: Ident = input.parse()?; + if name == "auto" { + Ok(DiplomatBackendAttrCfg::Auto) + } else if name == "not" { + let content; + let _paren = syn::parenthesized!(content in input); + Ok(DiplomatBackendAttrCfg::Not(Box::new(content.parse()?))) + } else if name == "any" || name == "all" { + let content; + let _paren = syn::parenthesized!(content in input); + let list = content.parse_terminated(Self::parse, Token![,])?; + let vec = list.into_iter().collect(); + if name == "any" { + Ok(DiplomatBackendAttrCfg::Any(vec)) + } else { + Ok(DiplomatBackendAttrCfg::All(vec)) + } + } else if input.peek(Token![=]) { + let _t: Token![=] = input.parse()?; + if input.peek(Ident) { + let value: Ident = input.parse()?; + Ok(DiplomatBackendAttrCfg::NameValue( + name.to_string(), + value.to_string(), + )) + } else { + let value: LitStr = input.parse()?; + Ok(DiplomatBackendAttrCfg::NameValue( + name.to_string(), + value.value(), + )) + } + } else { + Ok(DiplomatBackendAttrCfg::BackendName(name.to_string())) + } + } else if lookahead.peek(Token![*]) { + let _t: Token![*] = input.parse()?; + Ok(DiplomatBackendAttrCfg::Star) + } else { + Err(ParseError::new( + input.span(), + "CFG portion of #[diplomat::attr] fails to parse", + )) + } + } +} + +/// Meant to be used with Attribute::parse_args() +impl Parse for DiplomatBackendAttr { + fn parse(input: ParseStream<'_>) -> syn::Result { + let cfg = input.parse()?; + let _comma: Token![,] = input.parse()?; + let meta = input.parse()?; + Ok(Self { cfg, meta }) + } +} + +// #region demo_gen specific attributes +/// A `#[diplomat::demo(...)]` attribute +#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize)] +#[non_exhaustive] +pub struct DemoBackendAttr { + #[serde(serialize_with = "serialize_meta")] + pub meta: Meta, +} + +/// Meant to be used with Attribute::parse_args() +impl Parse for DemoBackendAttr { + fn parse(input: ParseStream<'_>) -> syn::Result { + let meta = input.parse()?; + Ok(Self { meta }) + } +} + +// #endregion + +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] +pub(crate) enum AttrInheritContext { + Variant, + Type, + /// When a method or an impl is inheriting from a module + MethodOrImplFromModule, + /// When a method is inheriting from an impl + /// + /// This distinction is made because HIR attributes are pre-inherited from the impl to the + /// method, so the boundary of "method inheriting from module" is different + MethodFromImpl, + // Currently there's no way to feed an attribute to a Module, but such inheritance will + // likely apply during lowering for config defaults. + #[allow(unused)] + Module, +} + +/// A pattern for use in rename attributes, like `#[diplomat::abi_rename]` +/// +/// This can be parsed from a string, typically something like `icu4x_{0}`. +/// It can have up to one {0} for replacement. +/// +/// In the future this may support transformations like to_camel_case, etc, +/// probably specified as a list like `#[diplomat::abi_rename("foo{0}", to_camel_case)]` +#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize)] +pub struct RenameAttr { + pattern: Option, +} + +impl RenameAttr { + /// Apply all renames to a given string + pub fn apply<'a>(&'a self, name: Cow<'a, str>) -> Cow<'a, str> { + if let Some(ref pattern) = self.pattern { + let replacement = &pattern.replacement; + if let Some(index) = pattern.insertion_index { + format!("{}{name}{}", &replacement[..index], &replacement[index..]).into() + } else { + replacement.into() + } + } else { + name + } + } + + /// Whether this rename is empty and will perform no changes + pub(crate) fn is_empty(&self) -> bool { + self.pattern.is_none() + } + + pub(crate) fn extend(&mut self, other: &Self) { + if other.pattern.is_some() { + self.pattern.clone_from(&other.pattern); + } + + // In the future if we support things like to_lower_case they may inherit separately + // from patterns. + } + + /// Get a copy of these attributes for use in inheritance, masking out things + /// that should not be inherited + pub(crate) fn attrs_for_inheritance( + &self, + context: AttrInheritContext, + is_abi_rename: bool, + ) -> Self { + let pattern = match context { + // No inheritance from modules to method-likes for the rename attribute + AttrInheritContext::MethodOrImplFromModule if !is_abi_rename => Default::default(), + // No effect on variants + AttrInheritContext::Variant => Default::default(), + _ => self.pattern.clone(), + }; + // In the future if we support things like to_lower_case they may inherit separately + // from patterns. + Self { pattern } + } + + /// From a replacement pattern, like "icu4x_{0}". Can have up to one {0} in it for substitution. + fn from_pattern(s: &str) -> Self { + Self { + pattern: Some(s.parse().unwrap()), + } + } + + pub(crate) fn from_meta(meta: &Meta) -> Result { + let attr = StandardAttribute::from_meta(meta) + .map_err(|_| "#[diplomat::abi_rename] must be given a string value")?; + + match attr { + StandardAttribute::String(s) => Ok(RenameAttr::from_pattern(&s)), + StandardAttribute::List(_) => { + Err("Failed to parse malformed #[diplomat::abi_rename(...)]: found list") + } + StandardAttribute::Empty => { + Err("Failed to parse malformed #[diplomat::abi_rename(...)]: found no parameters") + } + } + } +} + +impl FromStr for RenamePattern { + type Err = Infallible; + fn from_str(s: &str) -> Result { + if let Some(index) = s.find("{0}") { + let replacement = format!("{}{}", &s[..index], &s[index + 3..]); + Ok(Self { + replacement, + insertion_index: Some(index), + }) + } else { + Ok(Self { + replacement: s.into(), + insertion_index: None, + }) + } + } +} + +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize)] +struct RenamePattern { + /// The string to replace with + replacement: String, + /// The index in `replacement` in which to insert the original string. If None, + /// this is a pure rename + insertion_index: Option, +} + +/// Helper type for parsing standard attributes. A standard attribute typically will accept the forms: +/// +/// - `#[attr = "foo"]` and `#[attr("foo")]` for a simple string +/// - `#[attr(....)]` for a more complicated context +/// - `#[attr]` for a "defaulting" context +/// +/// This allows attributes to parse simple string values without caring too much about the NameValue vs List representation +/// and then attributes can choose to handle more complicated lists if they so desire. +pub(crate) enum StandardAttribute<'a> { + String(String), + List(#[allow(dead_code)] &'a MetaList), + Empty, +} + +impl<'a> StandardAttribute<'a> { + /// Parse from a Meta. Returns an error when no string value is specified in the path/namevalue forms. + pub(crate) fn from_meta(meta: &'a Meta) -> Result { + match meta { + Meta::Path(..) => Ok(Self::Empty), + Meta::NameValue(ref nv) => { + // Support a shortcut `abi_rename = "..."` + let Expr::Lit(ref lit) = nv.value else { + return Err(()); + }; + let Lit::Str(ref lit) = lit.lit else { + return Err(()); + }; + Ok(Self::String(lit.value())) + } + // The full syntax to which we'll add more things in the future, `abi_rename("")` + Meta::List(list) => { + if let Ok(lit) = list.parse_args::() { + Ok(Self::String(lit.value())) + } else { + Ok(Self::List(list)) + } + } + } + } +} + +#[cfg(test)] +mod tests { + use insta; + + use syn; + + use super::{DiplomatBackendAttr, DiplomatBackendAttrCfg, RenameAttr}; + + #[test] + fn test_cfgs() { + let attr_cfg: DiplomatBackendAttrCfg = syn::parse_quote!(*); + insta::assert_yaml_snapshot!(attr_cfg); + let attr_cfg: DiplomatBackendAttrCfg = syn::parse_quote!(cpp); + insta::assert_yaml_snapshot!(attr_cfg); + let attr_cfg: DiplomatBackendAttrCfg = syn::parse_quote!(has = overloading); + insta::assert_yaml_snapshot!(attr_cfg); + let attr_cfg: DiplomatBackendAttrCfg = syn::parse_quote!(has = "overloading"); + insta::assert_yaml_snapshot!(attr_cfg); + let attr_cfg: DiplomatBackendAttrCfg = + syn::parse_quote!(any(all(*, cpp, has="overloading"), not(js))); + insta::assert_yaml_snapshot!(attr_cfg); + } + + #[test] + fn test_attr() { + let attr: syn::Attribute = + syn::parse_quote!(#[diplomat::attr(any(cpp, has = "overloading"), namespacing)]); + let attr: DiplomatBackendAttr = attr.parse_args().unwrap(); + insta::assert_yaml_snapshot!(attr); + } + + #[test] + fn test_rename() { + let attr: syn::Attribute = syn::parse_quote!(#[diplomat::abi_rename = "foobar_{0}"]); + let attr = RenameAttr::from_meta(&attr.meta).unwrap(); + insta::assert_yaml_snapshot!(attr); + let attr: syn::Attribute = syn::parse_quote!(#[diplomat::abi_rename("foobar_{0}")]); + let attr = RenameAttr::from_meta(&attr.meta).unwrap(); + insta::assert_yaml_snapshot!(attr); + } +} diff --git a/deps/crates/vendor/diplomat_core/src/ast/docs.rs b/deps/crates/vendor/diplomat_core/src/ast/docs.rs new file mode 100644 index 00000000000000..4b612c36d95271 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/docs.rs @@ -0,0 +1,440 @@ +use super::Path; +use core::fmt; +use quote::ToTokens; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use syn::parse::{self, Parse, ParseStream}; +use syn::{Attribute, Ident, Meta, Token}; + +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Debug, Default)] +pub struct Docs(String, Vec); + +#[non_exhaustive] +pub enum TypeReferenceSyntax { + SquareBrackets, + AtLink, +} + +impl Docs { + pub fn from_attrs(attrs: &[Attribute]) -> Self { + Self(Self::get_doc_lines(attrs), Self::get_rust_link(attrs)) + } + + fn get_doc_lines(attrs: &[Attribute]) -> String { + let mut lines: String = String::new(); + + attrs.iter().for_each(|attr| { + if let Meta::NameValue(ref nv) = attr.meta { + if nv.path.is_ident("doc") { + let node: syn::LitStr = syn::parse2(nv.value.to_token_stream()).unwrap(); + let line = node.value().trim().to_string(); + + if !lines.is_empty() { + lines.push('\n'); + } + + lines.push_str(&line); + } + } + }); + + lines + } + + fn get_rust_link(attrs: &[Attribute]) -> Vec { + attrs + .iter() + .filter(|i| i.path().to_token_stream().to_string() == "diplomat :: rust_link") + .map(|i| i.parse_args().expect("Malformed attribute")) + .collect() + } + + pub fn is_empty(&self) -> bool { + self.0.is_empty() && self.1.is_empty() + } + + /// Convert to markdown + pub fn to_markdown( + &self, + ref_syntax: TypeReferenceSyntax, + docs_url_gen: &DocsUrlGenerator, + ) -> String { + use std::fmt::Write; + let mut lines = match ref_syntax { + TypeReferenceSyntax::SquareBrackets => self.0.replace("[`", "[").replace("`]", "]"), + TypeReferenceSyntax::AtLink => self.0.replace("[`", "{@link ").replace("`]", "}"), + }; + + let mut has_compact = false; + for rust_link in &self.1 { + if rust_link.display == RustLinkDisplay::Compact { + has_compact = true; + } else if rust_link.display == RustLinkDisplay::Normal { + if !lines.is_empty() { + write!(lines, "\n\n").unwrap(); + } + write!( + lines, + "See the [Rust documentation for `{name}`]({link}) for more information.", + name = rust_link.path.elements.last().unwrap(), + link = docs_url_gen.gen_for_rust_link(rust_link) + ) + .unwrap(); + } + } + if has_compact { + if !lines.is_empty() { + write!(lines, "\n\n").unwrap(); + } + write!(lines, "Additional information: ").unwrap(); + for (i, rust_link) in self + .1 + .iter() + .filter(|r| r.display == RustLinkDisplay::Compact) + .enumerate() + { + if i != 0 { + write!(lines, ", ").unwrap(); + } + write!( + lines, + "[{}]({})", + i + 1, + docs_url_gen.gen_for_rust_link(rust_link) + ) + .unwrap(); + } + } + lines + } + + pub fn rust_links(&self) -> &[RustLink] { + &self.1 + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] +#[non_exhaustive] +pub enum RustLinkDisplay { + /// A nice expanded representation that includes the type name + /// + /// e.g. "See the \[link to Rust documentation\] for more details" + Normal, + /// A compact representation that will fit multiple rust_link entries in one line + /// + /// E.g. "For further information, see: 1, 2, 3, 4" (all links) + Compact, + /// Hidden. Useful for programmatically annotating an API as related without showing a link to the user + Hidden, +} + +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Debug, PartialOrd, Ord)] +#[non_exhaustive] +pub struct RustLink { + pub path: Path, + pub typ: DocType, + pub display: RustLinkDisplay, +} + +impl Parse for RustLink { + fn parse(input: ParseStream<'_>) -> parse::Result { + let path = input.parse()?; + let path = Path::from_syn(&path); + let _comma: Token![,] = input.parse()?; + let ty_ident: Ident = input.parse()?; + let typ = match &*ty_ident.to_string() { + "Struct" => DocType::Struct, + "StructField" => DocType::StructField, + "Enum" => DocType::Enum, + "EnumVariant" => DocType::EnumVariant, + "EnumVariantField" => DocType::EnumVariantField, + "Trait" => DocType::Trait, + "FnInStruct" => DocType::FnInStruct, + "FnInTypedef" => DocType::FnInTypedef, + "FnInEnum" => DocType::FnInEnum, + "FnInTrait" => DocType::FnInTrait, + "DefaultFnInTrait" => DocType::DefaultFnInTrait, + "Fn" => DocType::Fn, + "Mod" => DocType::Mod, + "Constant" => DocType::Constant, + "AssociatedConstantInEnum" => DocType::AssociatedConstantInEnum, + "AssociatedConstantInTrait" => DocType::AssociatedConstantInTrait, + "AssociatedConstantInStruct" => DocType::AssociatedConstantInStruct, + "Macro" => DocType::Macro, + "AssociatedTypeInEnum" => DocType::AssociatedTypeInEnum, + "AssociatedTypeInTrait" => DocType::AssociatedTypeInTrait, + "AssociatedTypeInStruct" => DocType::AssociatedTypeInStruct, + "Typedef" => DocType::Typedef, + t => { + return Err(parse::Error::new( + ty_ident.span(), + format!("Unknown rust_link doc type {t:?}"), + )) + } + }; + let lookahead = input.lookahead1(); + let display = if lookahead.peek(Token![,]) { + let _comma: Token![,] = input.parse()?; + let display_ident: Ident = input.parse()?; + match &*display_ident.to_string() { + "normal" => RustLinkDisplay::Normal, + "compact" => RustLinkDisplay::Compact, + "hidden" => RustLinkDisplay::Hidden, + _ => return Err(parse::Error::new(display_ident.span(), "Unknown rust_link display style: Must be must be `normal`, `compact`, or `hidden`.")), + } + } else { + RustLinkDisplay::Normal + }; + Ok(RustLink { path, typ, display }) + } +} +impl fmt::Display for RustLink { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}#{:?}", self.path, self.typ) + } +} + +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Debug, PartialOrd, Ord)] +#[non_exhaustive] +pub enum DocType { + Struct, + StructField, + Enum, + EnumVariant, + EnumVariantField, + Trait, + FnInStruct, + FnInTypedef, + FnInEnum, + FnInTrait, + DefaultFnInTrait, + Fn, + Mod, + Constant, + AssociatedConstantInEnum, + AssociatedConstantInTrait, + AssociatedConstantInStruct, + Macro, + AssociatedTypeInEnum, + AssociatedTypeInTrait, + AssociatedTypeInStruct, + Typedef, +} + +#[derive(Default)] +pub struct DocsUrlGenerator { + default_url: Option, + base_urls: HashMap, +} + +impl DocsUrlGenerator { + pub fn with_base_urls(default_url: Option, base_urls: HashMap) -> Self { + Self { + default_url, + base_urls, + } + } + + fn gen_for_rust_link(&self, rust_link: &RustLink) -> String { + use DocType::*; + + let mut r = String::new(); + + let base = self + .base_urls + .get(rust_link.path.elements[0].as_str()) + .map(String::as_str) + .or(self.default_url.as_deref()) + .unwrap_or("https://docs.rs/"); + + r.push_str(base); + if !base.ends_with('/') { + r.push('/'); + } + if r == "https://docs.rs/" { + r.push_str(rust_link.path.elements[0].as_str()); + r.push_str("/latest/"); + } + + let mut elements = rust_link.path.elements.iter().peekable(); + + let module_depth = rust_link.path.elements.len() + - match rust_link.typ { + Mod => 0, + Struct | Enum | Trait | Fn | Macro | Constant | Typedef => 1, + FnInEnum + | FnInStruct + | FnInTypedef + | FnInTrait + | DefaultFnInTrait + | EnumVariant + | StructField + | AssociatedTypeInEnum + | AssociatedTypeInStruct + | AssociatedTypeInTrait + | AssociatedConstantInEnum + | AssociatedConstantInStruct + | AssociatedConstantInTrait => 2, + EnumVariantField => 3, + }; + + for _ in 0..module_depth { + r.push_str(elements.next().unwrap().as_str()); + r.push('/'); + } + + if elements.peek().is_none() { + r.push_str("index.html"); + return r; + } + + r.push_str(match rust_link.typ { + Typedef | FnInTypedef => "type.", + Struct + | StructField + | FnInStruct + | AssociatedTypeInStruct + | AssociatedConstantInStruct => "struct.", + Enum + | EnumVariant + | EnumVariantField + | FnInEnum + | AssociatedTypeInEnum + | AssociatedConstantInEnum => "enum.", + Trait + | FnInTrait + | DefaultFnInTrait + | AssociatedTypeInTrait + | AssociatedConstantInTrait => "trait.", + Fn => "fn.", + Constant => "constant.", + Macro => "macro.", + Mod => unreachable!(), + }); + + r.push_str(elements.next().unwrap().as_str()); + + r.push_str(".html"); + + match rust_link.typ { + FnInStruct | FnInEnum | DefaultFnInTrait | FnInTypedef => { + r.push_str("#method."); + r.push_str(elements.next().unwrap().as_str()); + } + AssociatedTypeInStruct | AssociatedTypeInEnum | AssociatedTypeInTrait => { + r.push_str("#associatedtype."); + r.push_str(elements.next().unwrap().as_str()); + } + AssociatedConstantInStruct | AssociatedConstantInEnum | AssociatedConstantInTrait => { + r.push_str("#associatedconstant."); + r.push_str(elements.next().unwrap().as_str()); + } + FnInTrait => { + r.push_str("#tymethod."); + r.push_str(elements.next().unwrap().as_str()); + } + EnumVariant => { + r.push_str("#variant."); + r.push_str(elements.next().unwrap().as_str()); + } + StructField => { + r.push_str("#structfield."); + r.push_str(elements.next().unwrap().as_str()); + } + EnumVariantField => { + r.push_str("#variant."); + r.push_str(elements.next().unwrap().as_str()); + r.push_str(".field."); + r.push_str(elements.next().unwrap().as_str()); + } + Struct | Enum | Trait | Fn | Mod | Constant | Macro | Typedef => {} + } + r + } +} + +#[test] +fn test_docs_url_generator() { + let test_cases = [ + ( + syn::parse_quote! { #[diplomat::rust_link(std::foo::bar::batz, Struct)] }, + "https://docs.rs/std/latest/std/foo/bar/struct.batz.html", + ), + ( + syn::parse_quote! { #[diplomat::rust_link(std::foo::bar::batz, StructField)] }, + "https://docs.rs/std/latest/std/foo/struct.bar.html#structfield.batz", + ), + ( + syn::parse_quote! { #[diplomat::rust_link(std::foo::bar::batz, Enum)] }, + "https://docs.rs/std/latest/std/foo/bar/enum.batz.html", + ), + ( + syn::parse_quote! { #[diplomat::rust_link(std::foo::bar::batz, EnumVariant)] }, + "https://docs.rs/std/latest/std/foo/enum.bar.html#variant.batz", + ), + ( + syn::parse_quote! { #[diplomat::rust_link(std::foo::bar::batz, EnumVariantField)] }, + "https://docs.rs/std/latest/std/enum.foo.html#variant.bar.field.batz", + ), + ( + syn::parse_quote! { #[diplomat::rust_link(std::foo::bar::batz, Trait)] }, + "https://docs.rs/std/latest/std/foo/bar/trait.batz.html", + ), + ( + syn::parse_quote! { #[diplomat::rust_link(std::foo::bar::batz, FnInStruct)] }, + "https://docs.rs/std/latest/std/foo/struct.bar.html#method.batz", + ), + ( + syn::parse_quote! { #[diplomat::rust_link(std::foo::bar::batz, FnInEnum)] }, + "https://docs.rs/std/latest/std/foo/enum.bar.html#method.batz", + ), + ( + syn::parse_quote! { #[diplomat::rust_link(std::foo::bar::batz, FnInTrait)] }, + "https://docs.rs/std/latest/std/foo/trait.bar.html#tymethod.batz", + ), + ( + syn::parse_quote! { #[diplomat::rust_link(std::foo::bar::batz, DefaultFnInTrait)] }, + "https://docs.rs/std/latest/std/foo/trait.bar.html#method.batz", + ), + ( + syn::parse_quote! { #[diplomat::rust_link(std::foo::bar::batz, Fn)] }, + "https://docs.rs/std/latest/std/foo/bar/fn.batz.html", + ), + ( + syn::parse_quote! { #[diplomat::rust_link(std::foo::bar::batz, Mod)] }, + "https://docs.rs/std/latest/std/foo/bar/batz/index.html", + ), + ( + syn::parse_quote! { #[diplomat::rust_link(std::foo::bar::batz, Constant)] }, + "https://docs.rs/std/latest/std/foo/bar/constant.batz.html", + ), + ( + syn::parse_quote! { #[diplomat::rust_link(std::foo::bar::batz, Macro)] }, + "https://docs.rs/std/latest/std/foo/bar/macro.batz.html", + ), + ]; + + for (attr, expected) in test_cases.clone() { + assert_eq!( + DocsUrlGenerator::default().gen_for_rust_link(&Docs::from_attrs(&[attr]).1[0]), + expected + ); + } + + assert_eq!( + DocsUrlGenerator::with_base_urls( + None, + [("std".to_string(), "http://std-docs.biz/".to_string())] + .into_iter() + .collect() + ) + .gen_for_rust_link(&Docs::from_attrs(&[test_cases[0].0.clone()]).1[0]), + "http://std-docs.biz/std/foo/bar/struct.batz.html" + ); + + assert_eq!( + DocsUrlGenerator::with_base_urls(Some("http://std-docs.biz/".to_string()), HashMap::new()) + .gen_for_rust_link(&Docs::from_attrs(&[test_cases[0].0.clone()]).1[0]), + "http://std-docs.biz/std/foo/bar/struct.batz.html" + ); +} diff --git a/deps/crates/vendor/diplomat_core/src/ast/enums.rs b/deps/crates/vendor/diplomat_core/src/ast/enums.rs new file mode 100644 index 00000000000000..3169b6331a5b6d --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/enums.rs @@ -0,0 +1,127 @@ +use serde::Serialize; + +use super::docs::Docs; +use super::{AttrInheritContext, Attrs, Ident, Method}; +use quote::ToTokens; + +/// A fieldless enum declaration in an FFI module. +#[derive(Clone, Serialize, Debug, Hash, PartialEq, Eq)] +#[non_exhaustive] +pub struct Enum { + pub name: Ident, + pub docs: Docs, + /// A list of variants of the enum. (name, discriminant, docs, attrs) + pub variants: Vec<(Ident, isize, Docs, Attrs)>, + pub methods: Vec, + pub attrs: Attrs, +} + +impl Enum { + /// Extract an [`Enum`] metadata value from an AST node. + pub fn new(enm: &syn::ItemEnum, parent_attrs: &Attrs) -> Enum { + let mut last_discriminant = -1; + if !enm.generics.params.is_empty() { + // Generic types are not allowed. + // Assuming all enums cannot have lifetimes? We don't even have a + // `lifetimes` field. If we change our minds we can adjust this later + // and update the `CustomType::lifetimes` API accordingly. + panic!("Enums cannot have generic parameters"); + } + + let mut attrs = parent_attrs.clone(); + attrs.add_attrs(&enm.attrs); + let variant_parent_attrs = attrs.attrs_for_inheritance(AttrInheritContext::Variant); + + Enum { + name: (&enm.ident).into(), + docs: Docs::from_attrs(&enm.attrs), + variants: enm + .variants + .iter() + .map(|v| { + if !matches!(v.fields, syn::Fields::Unit) { + panic!("Enums cannot have fields, we only support C-like enums"); + } + let new_discriminant = v + .discriminant + .as_ref() + .map(|d| { + // Reparsing, signed literals are represented + // as a negation expression + let lit: Result = syn::parse2(d.1.to_token_stream()); + if let Ok(syn::Lit::Int(ref lit_int)) = lit { + lit_int.base10_parse::().unwrap() + } else { + panic!("Expected a discriminant to be a constant integer"); + } + }) + .unwrap_or_else(|| last_discriminant + 1); + + last_discriminant = new_discriminant; + let mut v_attrs = variant_parent_attrs.clone(); + v_attrs.add_attrs(&v.attrs); + ( + (&v.ident).into(), + new_discriminant, + Docs::from_attrs(&v.attrs), + v_attrs, + ) + }) + .collect(), + methods: vec![], + attrs, + } + } +} + +#[cfg(test)] +mod tests { + use insta::{self, Settings}; + + use syn; + + use super::Enum; + + #[test] + fn simple_enum() { + let mut settings = Settings::new(); + settings.set_sort_maps(true); + + settings.bind(|| { + insta::assert_yaml_snapshot!(Enum::new( + &syn::parse_quote! { + /// Some docs. + #[diplomat::rust_link(foo::Bar, Enum)] + enum MyLocalEnum { + Abc, + /// Some more docs. + Def + } + }, + &Default::default() + )); + }); + } + + #[test] + fn enum_with_discr() { + let mut settings = Settings::new(); + settings.set_sort_maps(true); + + settings.bind(|| { + insta::assert_yaml_snapshot!(Enum::new( + &syn::parse_quote! { + /// Some docs. + #[diplomat::rust_link(foo::Bar, Enum)] + enum DiscriminantedEnum { + Abc = -1, + Def = 0, + Ghi = 1, + Jkl = 2, + } + }, + &Default::default() + )); + }); + } +} diff --git a/deps/crates/vendor/diplomat_core/src/ast/functions.rs b/deps/crates/vendor/diplomat_core/src/ast/functions.rs new file mode 100644 index 00000000000000..c3e1840c9f93aa --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/functions.rs @@ -0,0 +1,116 @@ +use serde::Serialize; +use syn::ItemFn; + +use crate::ast::{Attrs, Docs, Ident, LifetimeEnv, Param, PathType, TypeName}; + +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Debug)] +#[non_exhaustive] +/// Represents a free function not associated with any types. +pub struct Function { + pub name: Ident, + pub abi_name: Ident, + // corresponds to the types in Function(Vec>, Box) + // the callback type; except here the params aren't anonymous + pub params: Vec, + pub output_type: Option, + pub lifetimes: LifetimeEnv, + pub attrs: Attrs, + pub docs: Docs, +} + +impl Function { + pub(crate) fn from_syn(f: &ItemFn, parent_attrs: &Attrs) -> Function { + let ident: Ident = (&f.sig.ident).into(); + if f.sig.receiver().is_some() { + panic!("Cannot use self parameter in free function {ident:?}") + } + + let mut attrs = parent_attrs.clone(); + attrs.add_attrs(&f.attrs); + + let concat_func_ident = if attrs.abi_rename.is_empty() { + format!("diplomat_external_{ident}") + } else { + attrs.abi_rename.apply(ident.as_str().into()).to_string() + }; + + let extern_ident = syn::Ident::new(&concat_func_ident, f.sig.ident.span()); + + let path_type = PathType::from(&f.sig); + + let all_params = f + .sig + .inputs + .iter() + .filter_map(|a| match a { + syn::FnArg::Receiver(_) => None, + syn::FnArg::Typed(ref t) => Some(Param::from_syn(t, path_type.clone())), + }) + .collect::>(); + + let output_type = match &f.sig.output { + syn::ReturnType::Type(_, return_typ) => Some(TypeName::from_syn( + return_typ.as_ref(), + Some(path_type.clone()), + )), + syn::ReturnType::Default => None, + }; + + let lifetimes = LifetimeEnv::from_function_item(f, &all_params[..], output_type.as_ref()); + + Self { + name: ident, + abi_name: (&extern_ident).into(), + params: all_params, + output_type, + lifetimes, + attrs, + docs: Docs::from_attrs(&f.attrs), + } + } +} + +#[cfg(test)] +mod tests { + use insta; + + use syn; + + use crate::ast::{Attrs, Function}; + + #[test] + fn test_free_function() { + insta::assert_yaml_snapshot!(Function::from_syn( + &syn::parse_quote! { + fn some_func(a : f32, b: f64) { + + } + }, + &Attrs::default() + )); + } + + #[test] + fn test_free_function_output() { + insta::assert_yaml_snapshot!(Function::from_syn( + &syn::parse_quote! { + fn some_func(a : SomeType) -> Option<()> { + + } + }, + &Attrs::default() + )); + } + + #[test] + fn test_free_function_lifetimes() { + insta::assert_yaml_snapshot!(Function::from_syn( + &syn::parse_quote! { + fn some_func<'a>(a : &'a SomeType) -> Option<&'a SomeType> { + + } + }, + &Attrs::default() + )); + } +} diff --git a/deps/crates/vendor/diplomat_core/src/ast/idents.rs b/deps/crates/vendor/diplomat_core/src/ast/idents.rs new file mode 100644 index 00000000000000..2177923b5d2d3f --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/idents.rs @@ -0,0 +1,86 @@ +use proc_macro2::Span; +use quote::{ToTokens, TokenStreamExt}; +use serde::{Deserialize, Serialize}; +use std::borrow::{Borrow, Cow}; +use std::fmt; + +/// An identifier, analogous to `syn::Ident` and `proc_macro2::Ident`. +#[derive(Hash, Eq, PartialEq, Serialize, Clone, Debug, Ord, PartialOrd)] +#[serde(transparent)] +pub struct Ident(Cow<'static, str>); + +impl Ident { + /// Validate a string + fn validate(string: &str) -> syn::Result<()> { + syn::parse_str::(string).map(|_| {}) + } + + /// Attempt to create a new `Ident`. + /// + /// This function fails if the input isn't valid according to + /// `proc_macro2::Ident`'s invariants. + pub fn try_new(string: String) -> syn::Result { + Self::validate(&string).map(|_| Self(Cow::from(string))) + } + + pub fn to_syn(&self) -> syn::Ident { + syn::Ident::new(self.as_str(), Span::call_site()) + } + + /// Get the `&str` representation. + pub fn as_str(&self) -> &str { + &self.0 + } + + /// An [`Ident`] containing "this". + pub const THIS: Self = Ident(Cow::Borrowed("this")); +} + +impl From<&'static str> for Ident { + fn from(string: &'static str) -> Self { + Self::validate(string).unwrap(); + Self(Cow::from(string)) + } +} + +impl From for Ident { + fn from(string: String) -> Self { + Self::validate(&string).unwrap(); + Self(Cow::from(string)) + } +} + +impl<'de> Deserialize<'de> for Ident { + /// The derived `Deserialize` allows for creating `Ident`s that do not uphold + /// the proper invariants. This custom impl ensures that this cannot happen. + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + Ok(Ident::from(String::deserialize(deserializer)?)) + } +} + +impl Borrow for Ident { + fn borrow(&self) -> &str { + self.as_str() + } +} + +impl fmt::Display for Ident { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.as_str().fmt(f) + } +} + +impl From<&syn::Ident> for Ident { + fn from(ident: &syn::Ident) -> Self { + Self(Cow::from(ident.to_string())) + } +} + +impl ToTokens for Ident { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + tokens.append(self.to_syn()); + } +} diff --git a/deps/crates/vendor/diplomat_core/src/ast/lifetimes.rs b/deps/crates/vendor/diplomat_core/src/ast/lifetimes.rs new file mode 100644 index 00000000000000..17b5d22485b290 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/lifetimes.rs @@ -0,0 +1,637 @@ +use proc_macro2::Span; +use quote::{quote, ToTokens}; +use serde::{Deserialize, Serialize}; +use std::fmt; + +use super::{Attrs, Docs, Ident, Param, SelfParam, TraitSelfParam, TypeName}; + +/// A named lifetime, e.g. `'a`. +/// +/// # Invariants +/// +/// Cannot be `'static` or `'_`, use [`Lifetime`] to represent those instead. +#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, PartialOrd, Ord)] +#[serde(transparent)] +pub struct NamedLifetime(Ident); + +impl NamedLifetime { + pub fn name(&self) -> &Ident { + &self.0 + } +} + +impl<'de> Deserialize<'de> for NamedLifetime { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + // Special `Deserialize` impl to ensure invariants. + let named = Ident::deserialize(deserializer)?; + if named.as_str() == "static" { + panic!("cannot be static"); + } + Ok(NamedLifetime(named)) + } +} + +impl From<&syn::Lifetime> for NamedLifetime { + fn from(lt: &syn::Lifetime) -> Self { + Lifetime::from(lt).to_named().expect("cannot be static") + } +} + +impl From<&NamedLifetime> for NamedLifetime { + fn from(this: &NamedLifetime) -> Self { + this.clone() + } +} + +impl PartialEq for NamedLifetime { + fn eq(&self, other: &syn::Lifetime) -> bool { + other.ident == self.0.as_str() + } +} + +impl fmt::Display for NamedLifetime { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "'{}", self.0) + } +} + +impl ToTokens for NamedLifetime { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + use proc_macro2::{Punct, Spacing}; + Punct::new('\'', Spacing::Joint).to_tokens(tokens); + self.0.to_tokens(tokens); + } +} + +/// A lifetime dependency graph used for tracking which lifetimes outlive, +/// and are outlived by, other lifetimes. +/// +/// It is similar to [`syn::LifetimeDef`], except it can also track lifetime +/// bounds defined in the `where` clause. +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub struct LifetimeEnv { + pub(crate) nodes: Vec, +} + +impl LifetimeEnv { + /// Construct an empty [`LifetimeEnv`]. + /// + /// To create one outside of this module, use `LifetimeEnv::from_method_item` + /// or `LifetimeEnv::from` on `&syn::Generics`. + fn new() -> Self { + Self { nodes: vec![] } + } + + /// Iterate through the names of the lifetimes in scope. + pub fn names(&self) -> impl Iterator + Clone { + self.nodes.iter().map(|node| &node.lifetime) + } + + /// Returns a [`LifetimeEnv`] for a method, accounting for lifetimes and bounds + /// defined in both the impl block and the method, as well as implicit lifetime + /// bounds in the optional `self` param, other param, and optional return type. + /// For example, the type `&'a Foo<'b>` implies `'b: 'a`. + pub fn from_method_item( + method: &syn::ImplItemFn, + impl_generics: Option<&syn::Generics>, + self_param: Option<&SelfParam>, + params: &[Param], + return_type: Option<&TypeName>, + ) -> Self { + let mut this = LifetimeEnv::new(); + // The impl generics _must_ be loaded into the env first, since the method + // generics might use lifetimes defined in the impl, and `extend_generics` + // panics if `'a: 'b` where `'b` isn't declared by the time it finishes. + if let Some(generics) = impl_generics { + this.extend_generics(generics); + } + this.extend_generics(&method.sig.generics); + + if let Some(self_param) = self_param { + this.extend_implicit_lifetime_bounds(&self_param.to_typename(), None); + } + for param in params { + this.extend_implicit_lifetime_bounds(¶m.ty, None); + } + if let Some(return_type) = return_type { + this.extend_implicit_lifetime_bounds(return_type, None); + } + + this + } + + pub fn from_trait_item( + trait_fct_item: &syn::TraitItem, + self_param: Option<&TraitSelfParam>, + params: &[Param], + return_type: Option<&TypeName>, + ) -> Self { + let mut this = LifetimeEnv::new(); + if let syn::TraitItem::Fn(_) = trait_fct_item { + if let Some(self_param) = self_param { + this.extend_implicit_lifetime_bounds(&self_param.to_typename(), None); + } + for param in params { + this.extend_implicit_lifetime_bounds(¶m.ty, None); + } + if let Some(return_type) = return_type { + this.extend_implicit_lifetime_bounds(return_type, None); + } + } else { + panic!( + "Diplomat traits can only have associated methods and no other associated items." + ) + } + this + } + + pub fn from_trait(trt: &syn::ItemTrait) -> Self { + if trt.generics.lifetimes().next().is_some() { + panic!("Diplomat traits are not allowed to have any lifetime parameters") + } + LifetimeEnv::new() + } + + pub fn from_enum_item( + enm: &syn::ItemEnum, + variant_fields: &[(Option, TypeName, Docs, Attrs)], + ) -> Self { + let mut this = LifetimeEnv::new(); + this.extend_generics(&enm.generics); + for (_, typ, _, _) in variant_fields { + this.extend_implicit_lifetime_bounds(typ, None); + } + this + } + + /// Returns a [`LifetimeEnv`] for a struct, accounding for lifetimes and bounds + /// defined in the struct generics, as well as implicit lifetime bounds in + /// the struct's fields. For example, the field `&'a Foo<'b>` implies `'b: 'a`. + pub fn from_struct_item( + strct: &syn::ItemStruct, + fields: &[(Ident, TypeName, Docs, Attrs)], + ) -> Self { + let mut this = LifetimeEnv::new(); + this.extend_generics(&strct.generics); + for (_, typ, _, _) in fields { + this.extend_implicit_lifetime_bounds(typ, None); + } + this + } + + pub fn from_function_item( + f: &syn::ItemFn, + params: &[Param], + return_type: Option<&TypeName>, + ) -> Self { + let mut this = LifetimeEnv::new(); + this.extend_generics(&f.sig.generics); + for param in params { + this.extend_implicit_lifetime_bounds(¶m.ty, None); + } + if let Some(return_type) = return_type { + this.extend_implicit_lifetime_bounds(return_type, None); + } + this + } + + /// Traverse a type, adding any implicit lifetime bounds that arise from + /// having a reference to an opaque containing a lifetime. + /// For example, the type `&'a Foo<'b>` implies `'b: 'a`. + fn extend_implicit_lifetime_bounds( + &mut self, + typ: &TypeName, + behind_ref: Option<&NamedLifetime>, + ) { + match typ { + TypeName::Named(path_type) => { + if let Some(borrow_lifetime) = behind_ref { + let explicit_longer_than_borrow = + LifetimeTransitivity::longer_than(self, borrow_lifetime); + let mut implicit_longer_than_borrow = vec![]; + + for path_lifetime in path_type.lifetimes.iter() { + if let Lifetime::Named(path_lifetime) = path_lifetime { + if !explicit_longer_than_borrow.contains(&path_lifetime) { + implicit_longer_than_borrow.push(path_lifetime); + } + } + } + + self.extend_bounds( + implicit_longer_than_borrow + .into_iter() + .map(|path_lifetime| (path_lifetime, Some(borrow_lifetime))), + ); + } + } + TypeName::Reference(lifetime, _, typ) => { + let behind_ref = if let Lifetime::Named(named) = lifetime { + Some(named) + } else { + None + }; + self.extend_implicit_lifetime_bounds(typ, behind_ref); + } + TypeName::Option(typ, _) => self.extend_implicit_lifetime_bounds(typ, None), + TypeName::Result(ok, err, _) => { + self.extend_implicit_lifetime_bounds(ok, None); + self.extend_implicit_lifetime_bounds(err, None); + } + _ => {} + } + } + + /// Add the lifetimes from generic parameters and where bounds. + fn extend_generics(&mut self, generics: &syn::Generics) { + let generic_bounds = generics.params.iter().map(|generic| match generic { + syn::GenericParam::Type(_) => panic!("generic types are unsupported"), + syn::GenericParam::Lifetime(def) => (&def.lifetime, &def.bounds), + syn::GenericParam::Const(_) => panic!("const generics are unsupported"), + }); + + let generic_defs = generic_bounds.clone().map(|(lifetime, _)| lifetime); + + self.extend_lifetimes(generic_defs); + self.extend_bounds(generic_bounds); + + if let Some(ref where_clause) = generics.where_clause { + self.extend_bounds(where_clause.predicates.iter().map(|pred| match pred { + syn::WherePredicate::Type(_) => panic!("trait bounds are unsupported"), + syn::WherePredicate::Lifetime(pred) => (&pred.lifetime, &pred.bounds), + _ => panic!("Found unknown kind of where predicate"), + })); + } + } + + /// Returns the number of lifetimes in the graph. + pub fn len(&self) -> usize { + self.nodes.len() + } + + /// Returns `true` if the graph contains no lifetimes. + pub fn is_empty(&self) -> bool { + self.nodes.is_empty() + } + + /// `<'a, 'b, 'c>` + /// + /// Write the existing lifetimes, excluding bounds, as generic parameters. + /// + /// To include lifetime bounds, use [`LifetimeEnv::lifetime_defs_to_tokens`]. + pub fn lifetimes_to_tokens(&self) -> proc_macro2::TokenStream { + if self.is_empty() { + return quote! {}; + } + + let lifetimes = self.nodes.iter().map(|node| &node.lifetime); + quote! { <#(#lifetimes),*> } + } + + /// Returns the index of a lifetime in the graph, or `None` if the lifetime + /// isn't in the graph. + pub(crate) fn id(&self, lifetime: &L) -> Option + where + NamedLifetime: PartialEq, + { + self.nodes + .iter() + .position(|node| &node.lifetime == lifetime) + } + + /// Add isolated lifetimes to the graph. + fn extend_lifetimes<'a, L, I>(&mut self, iter: I) + where + NamedLifetime: PartialEq + From<&'a L>, + L: 'a, + I: IntoIterator, + { + for lifetime in iter { + if self.id(lifetime).is_some() { + panic!( + "lifetime name `{}` declared twice in the same scope", + NamedLifetime::from(lifetime) + ); + } + + self.nodes.push(LifetimeNode { + lifetime: lifetime.into(), + shorter: vec![], + longer: vec![], + }); + } + } + + /// Add edges to the lifetime graph. + /// + /// This method is decoupled from [`LifetimeEnv::extend_lifetimes`] because + /// generics can define new lifetimes, while `where` clauses cannot. + /// + /// # Panics + /// + /// This method panics if any of the lifetime bounds aren't already defined + /// in the graph. This isn't allowed by rustc in the first place, so it should + /// only ever occur when deserializing an invalid [`LifetimeEnv`]. + fn extend_bounds<'a, L, B, I>(&mut self, iter: I) + where + NamedLifetime: PartialEq + From<&'a L>, + L: 'a, + B: IntoIterator, + I: IntoIterator, + { + for (lifetime, bounds) in iter { + let long = self.id(lifetime).expect("use of undeclared lifetime, this is a bug: try calling `LifetimeEnv::extend_lifetimes` first"); + for bound in bounds { + let short = self + .id(bound) + .expect("cannot use undeclared lifetime as a bound"); + self.nodes[short].longer.push(long); + self.nodes[long].shorter.push(short); + } + } + } +} + +impl fmt::Display for LifetimeEnv { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.to_token_stream().fmt(f) + } +} + +impl ToTokens for LifetimeEnv { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + for node in self.nodes.iter() { + let lifetime = &node.lifetime; + if node.shorter.is_empty() { + tokens.extend(quote! { #lifetime, }); + } else { + let bounds = node.shorter.iter().map(|&id| &self.nodes[id].lifetime); + tokens.extend(quote! { #lifetime: #(#bounds)+*, }); + } + } + } +} + +/// Serialize a [`LifetimeEnv`] as a map from lifetimes to their bounds. +impl Serialize for LifetimeEnv { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + use serde::ser::SerializeMap; + let mut seq = serializer.serialize_map(Some(self.len()))?; + + for node in self.nodes.iter() { + /// Helper type for serializing bounds. + struct Bounds<'a> { + ids: &'a [usize], + nodes: &'a [LifetimeNode], + } + + impl<'a> Serialize for Bounds<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + use serde::ser::SerializeSeq; + let mut seq = serializer.serialize_seq(Some(self.ids.len()))?; + for &id in self.ids { + seq.serialize_element(&self.nodes[id].lifetime)?; + } + seq.end() + } + } + + seq.serialize_entry( + &node.lifetime, + &Bounds { + ids: &node.shorter[..], + nodes: &self.nodes, + }, + )?; + } + seq.end() + } +} + +impl<'de> Deserialize<'de> for LifetimeEnv { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + use std::collections::BTreeMap; + + let m: BTreeMap> = + Deserialize::deserialize(deserializer)?; + + let mut this = LifetimeEnv::new(); + this.extend_lifetimes(m.keys()); + this.extend_bounds(m.iter()); + Ok(this) + } +} + +/// A lifetime, along with ptrs to all lifetimes that are explicitly +/// shorter/longer than it. +/// +/// This type is internal to [`LifetimeGraph`]- the ptrs are stored as `usize`s, +/// meaning that they may be invalid if a `LifetimeEdges` is created in one +/// `LifetimeGraph` and then used in another. +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub(crate) struct LifetimeNode { + /// The name of the lifetime. + pub(crate) lifetime: NamedLifetime, + + /// Pointers to all lifetimes that this lives _at least_ as long as. + /// + /// Note: This doesn't account for transitivity. + pub(crate) shorter: Vec, + + /// Pointers to all lifetimes that live _at least_ as long as this. + /// + /// Note: This doesn't account for transitivity. + pub(crate) longer: Vec, +} + +/// A lifetime, analogous to [`syn::Lifetime`]. +#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] +#[non_exhaustive] +pub enum Lifetime { + /// The `'static` lifetime. + Static, + + /// A named lifetime, like `'a`. + Named(NamedLifetime), + + /// An elided lifetime. + Anonymous, +} + +impl Lifetime { + /// Returns the inner `NamedLifetime` if the lifetime is the `Named` variant, + /// otherwise `None`. + pub fn to_named(self) -> Option { + if let Lifetime::Named(named) = self { + return Some(named); + } + None + } + + /// Returns a reference to the inner `NamedLifetime` if the lifetime is the + /// `Named` variant, otherwise `None`. + pub fn as_named(&self) -> Option<&NamedLifetime> { + if let Lifetime::Named(named) = self { + return Some(named); + } + None + } +} + +impl fmt::Display for Lifetime { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Lifetime::Static => "'static".fmt(f), + Lifetime::Named(ref named) => named.fmt(f), + Lifetime::Anonymous => "'_".fmt(f), + } + } +} + +impl ToTokens for Lifetime { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + match self { + Lifetime::Static => syn::Lifetime::new("'static", Span::call_site()).to_tokens(tokens), + Lifetime::Named(ref s) => s.to_tokens(tokens), + Lifetime::Anonymous => syn::Lifetime::new("'_", Span::call_site()).to_tokens(tokens), + }; + } +} + +impl From<&syn::Lifetime> for Lifetime { + fn from(lt: &syn::Lifetime) -> Self { + if lt.ident == "static" { + Self::Static + } else { + Self::Named(NamedLifetime((<.ident).into())) + } + } +} + +impl From<&Option> for Lifetime { + fn from(lt: &Option) -> Self { + lt.as_ref().map(Into::into).unwrap_or(Self::Anonymous) + } +} + +impl Lifetime { + /// Converts the [`Lifetime`] back into an AST node that can be spliced into a program. + pub fn to_syn(&self) -> Option { + match *self { + Self::Static => Some(syn::Lifetime::new("'static", Span::call_site())), + Self::Anonymous => None, + Self::Named(ref s) => Some(syn::Lifetime::new(&s.to_string(), Span::call_site())), + } + } +} + +/// Collect all lifetimes that are either longer_or_shorter +pub struct LifetimeTransitivity<'env> { + env: &'env LifetimeEnv, + visited: Vec, + out: Vec<&'env NamedLifetime>, + longer_or_shorter: LongerOrShorter, +} + +impl<'env> LifetimeTransitivity<'env> { + /// Returns a new [`LifetimeTransitivity`] that finds all longer lifetimes. + pub fn longer(env: &'env LifetimeEnv) -> Self { + Self::new(env, LongerOrShorter::Longer) + } + + /// Returns a new [`LifetimeTransitivity`] that finds all shorter lifetimes. + pub fn shorter(env: &'env LifetimeEnv) -> Self { + Self::new(env, LongerOrShorter::Shorter) + } + + /// Returns all the lifetimes longer than a provided `NamedLifetime`. + pub fn longer_than(env: &'env LifetimeEnv, named: &NamedLifetime) -> Vec<&'env NamedLifetime> { + let mut this = Self::new(env, LongerOrShorter::Longer); + this.visit(named); + this.finish() + } + + /// Returns all the lifetimes shorter than the provided `NamedLifetime`. + pub fn shorter_than(env: &'env LifetimeEnv, named: &NamedLifetime) -> Vec<&'env NamedLifetime> { + let mut this = Self::new(env, LongerOrShorter::Shorter); + this.visit(named); + this.finish() + } + + /// Returns a new [`LifetimeTransitivity`]. + fn new(env: &'env LifetimeEnv, longer_or_shorter: LongerOrShorter) -> Self { + LifetimeTransitivity { + env, + visited: vec![false; env.len()], + out: vec![], + longer_or_shorter, + } + } + + /// Visits a lifetime, as well as all the nodes it's transitively longer or + /// shorter than, depending on how the `LifetimeTransitivity` was constructed. + pub fn visit(&mut self, named: &NamedLifetime) { + if let Some(id) = self + .env + .nodes + .iter() + .position(|node| node.lifetime == *named) + { + self.dfs(id); + } + } + + /// Performs depth-first search through the `LifetimeEnv` created at construction + /// for all nodes longer or shorter than the node at the provided index, + /// depending on how the `LifetimeTransitivity` was constructed. + fn dfs(&mut self, index: usize) { + // Note: all of these indexings SHOULD be valid because + // `visited.len() == nodes.len()`, and the ids come from + // calling `Iterator::position` on `nodes`, which never shrinks. + // So we should be able to change these to `get_unchecked`... + if !self.visited[index] { + self.visited[index] = true; + + let node = &self.env.nodes[index]; + self.out.push(&node.lifetime); + for &edge_index in self.longer_or_shorter.edges(node).iter() { + self.dfs(edge_index); + } + } + } + + /// Returns the transitively reachable lifetimes. + pub fn finish(self) -> Vec<&'env NamedLifetime> { + self.out + } +} + +/// A helper type for [`LifetimeTransitivity`] determining whether to find the +/// transitively longer or transitively shorter lifetimes. +enum LongerOrShorter { + Longer, + Shorter, +} + +impl LongerOrShorter { + /// Returns either the indices of the longer or shorter lifetimes, depending + /// on `self`. + fn edges<'node>(&self, node: &'node LifetimeNode) -> &'node [usize] { + match self { + LongerOrShorter::Longer => &node.longer[..], + LongerOrShorter::Shorter => &node.shorter[..], + } + } +} diff --git a/deps/crates/vendor/diplomat_core/src/ast/macros.rs b/deps/crates/vendor/diplomat_core/src/ast/macros.rs new file mode 100644 index 00000000000000..36fd4d57f0d36c --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/macros.rs @@ -0,0 +1,637 @@ +use std::{ + collections::{BTreeMap, HashMap}, + fmt::Debug, +}; + +use proc_macro2::{TokenStream, TokenTree}; +use quote::{ToTokens, TokenStreamExt}; +use syn::{ + braced, bracketed, + buffer::{Cursor, TokenBuffer}, + parenthesized, + parse::{self, Parse, ParseStream}, + token, Error, Ident, ImplItem, ImplItemMacro, Item, ItemMacro, Token, +}; + +#[derive(Default)] +pub struct Macros { + defs: BTreeMap, +} + +impl Macros { + pub fn new() -> Macros { + Macros { + defs: BTreeMap::new(), + } + } + + pub fn add_item_macro(&mut self, input: &ItemMacro) { + assert!( + input.ident.is_some(), + "Expected macro_rules! def. Got {input:?}" + ); + let m = input.mac.parse_body::(); + if let Ok(mac) = m { + let ident = input.ident.clone().unwrap(); + self.defs.insert(ident, mac); + } + } + + pub fn evaluate_item_macro(&self, input: &ItemMacro) -> Vec { + assert!(input.ident.is_none(), "Expected macro usage. Got {input:?}"); + let m = input.mac.parse_body::(); + if let Ok(mac) = m { + // FIXME: Extremely hacky. In the future for importing macros, we'll want to do something else. + let ident = input.mac.path.segments.last().unwrap().ident.clone(); + + if let Some(def) = self.defs.get(&ident) { + def.evaluate(mac) + } else { + panic!("Could not find definition for {ident}. Have you tried creating a #[diplomat::macro_rules] macro_rules! {ident} definition?"); + } + } else { + // We handle errors automatically in `diplomat/macro` + Vec::new() + } + } + + pub fn evaluate_impl_item_macro(&self, input: &ImplItemMacro) -> Vec { + let m: syn::Result = input.mac.parse_body(); + // FIXME: Extremely hacky. In the future for importing macros, we'll want to do something else. + let path_ident = input.mac.path.segments.last().unwrap().ident.clone(); + + if let Ok(matched) = m { + if let Some(def) = self.defs.get(&path_ident) { + def.evaluate(matched) + } else { + panic!("Could not find definition for {path_ident}. Have you tried creating a #[diplomat::macro_rules] macro_rules! {path_ident} definition?"); + } + } else { + // We handle errors automatically in `diplomat/macro` + Vec::new() + } + } +} + +macro_rules! define_macro_fragments { + ($($i:ident($p:path)),*) => { + #[derive(Debug)] + pub enum MacroFrag { + $( + $i($p), + )* + } + + impl ToTokens for MacroFrag { + fn to_token_stream(&self) -> TokenStream { + let mut tokens = TokenStream::new(); + self.to_tokens(&mut tokens); + tokens + } + + fn to_tokens(&self, tokens : &mut TokenStream) { + match self { + $( + MacroFrag::$i(item) => item.to_tokens(tokens), + )* + } + } + + fn into_token_stream(self) -> TokenStream + where + Self: Sized, + { + match self { + $( + MacroFrag::$i(item) => item.to_token_stream(), + )* + } + } + } + + $( + impl From<$p> for MacroFrag { + fn from(value : $p) -> MacroFrag { + MacroFrag::$i(value) + } + } + )* + } +} + +define_macro_fragments! { + Block(syn::Block), + Expr(syn::Expr), + Ident(syn::Ident), + Item(syn::Item), + Lifetime(syn::Lifetime), + Literal(syn::Lit), + Meta(syn::Meta), + // TODO: + Pat(syn::Pat), + // TODO: + // PatParam() + Path(syn::Path), + Stmt(syn::Stmt), + TokenTree(proc_macro2::TokenTree), + Ty(syn::Type), + Vis(syn::Visibility) +} + +#[derive(Debug, Clone)] +/// Represents $Identifier:MacroFragSpec (see https://doc.rust-lang.org/reference/macros-by-example.html#railroad-MacroMatch) +pub struct MacroIdent { + /// represents Identifier. + pub ident: Ident, + /// Represents MacroFragSpec. Parsed in construction of [`MacroDef`] + pub ty: Ident, +} + +impl Parse for MacroIdent { + fn parse(input: parse::ParseStream) -> syn::Result { + input.parse::()?; + let ident: Ident = input.parse()?; + input.parse::()?; + let ty: Ident = input.parse()?; + Ok(Self { ident, ty }) + } +} + +/// Hack to read information from the TokenTree while saving the rest to be later copied into a buffer. +/// Will attempt to read `T`, and on a success all of the unread tokens after the stream will be written to `remaining`. +struct ParsePartial { + item: T, + remaining: TokenStream, +} + +impl Parse for ParsePartial { + fn parse(input: ParseStream) -> syn::Result { + let item = input.parse::()?; + let remaining = input.parse()?; + Ok(Self { item, remaining }) + } +} + +impl ParsePartial +where + MacroFrag: From, +{ + fn try_parse( + i: &MacroIdent, + cursor: &Cursor, + args: &mut HashMap, + ) -> syn::Result { + let out = syn::parse2::>(cursor.token_stream())?; + + args.insert(i.ident.clone(), MacroFrag::from(out.item)); + + let buf = TokenBuffer::new2(out.remaining); + Ok(buf) + } +} + +#[derive(Debug)] +#[non_exhaustive] +/// A site where a macro is used (i.e., `example!(...)`) +/// Constructed in [`MacroUse::parse`] (called by [`MacroDef::evaluate`]) when a previously defined macro is used. We use the definition of [`MacroDef`] to then construct the args in the used macro. +pub struct MacroUse { + /// The arguments $argname:MacroFragSpec passed to the macro. Indexed by `argname`. Used for substitution during [`MacroDef::evaluate`]. + args: HashMap, +} + +impl MacroUse { + /// Not an official implementation of [`syn::parse::Parse`], since we need to know the [`MacroDef`] to know how to extract [`MacroUse::args`]. + fn parse(def: &MacroDef, stream: TokenStream) -> syn::Result { + let mut args = HashMap::new(); + + Self::parse_macro_matcher(&def.matcher.matches, stream, &mut args)?; + + Ok(Self { args }) + } + + fn parse_macro_matcher( + matches: &[MacroMatch], + stream: TokenStream, + args: &mut HashMap, + ) -> syn::Result<()> { + let mut buf = TokenBuffer::new2(stream); + let mut c = buf.begin(); + + let mut match_iter = matches.iter(); + while let Some((tt, next)) = c.token_tree() { + let curr_match = match_iter.next(); + match curr_match { + Some(MacroMatch::Ident(i)) => match i.ty.to_string().as_str() { + "block" => { + if let TokenTree::Group(..) = &tt { + args.insert( + i.ident.clone(), + MacroFrag::Block(syn::parse2::(tt.into())?), + ); + c = next; + } else { + return Err(Error::new( + c.span(), + format!("${}:block expected. Got {tt:?}", i.ident), + )); + } + } + "expr" => { + buf = ParsePartial::::try_parse(i, &c, args)?; + c = buf.begin(); + } + "ident" => { + buf = ParsePartial::::try_parse(i, &c, args)?; + c = buf.begin(); + } + "item" => { + buf = ParsePartial::::try_parse(i, &c, args)?; + c = buf.begin(); + } + "lifetime" => { + buf = ParsePartial::::try_parse(i, &c, args)?; + c = buf.begin(); + } + "literal" => { + buf = ParsePartial::::try_parse(i, &c, args)?; + c = buf.begin(); + } + "meta" => { + buf = ParsePartial::::try_parse(i, &c, args)?; + c = buf.begin(); + } + "pat" => { + return Err(Error::new( + c.span(), + format!("${}:pat MacroFragSpec currently unsupported.", i.ident), + )); + } + "path" => { + buf = ParsePartial::::try_parse(i, &c, args)?; + c = buf.begin(); + } + "stmt" => { + // Syn expects a semicolon, Rust does not. This constitutes a parsing problem. + return Err(Error::new( + c.span(), + format!("${}:stmt MacroFragSpec currently unsupported.", i.ident), + )); + // buf = MaybeParse::::try_parse(i, &c, args)?; + + // c = buf.begin(); + } + "tt" => { + args.insert(i.ident.clone(), MacroFrag::TokenTree(tt)); + c = next; + } + "ty" => { + buf = ParsePartial::::try_parse(i, &c, args)?; + c = buf.begin(); + } + "vis" => { + buf = ParsePartial::::try_parse(i, &c, args)?; + c = buf.begin(); + } + _ => { + return Err(Error::new( + c.span(), + format!("${}, unsupported MacroFragSpec :{}", i.ident, i.ty), + )); + } + }, + Some(MacroMatch::Tokens(t)) => { + Self::get_tokens_match(&mut c, t)?; + } + Some(MacroMatch::MacroMatcher(matcher)) => { + if let TokenTree::Group(g) = &tt { + Self::parse_macro_matcher(&matcher.matches, g.stream(), args)?; + c = next; + } else { + return Err(Error::new( + c.span(), + format!("Macro use error: expected {:?}", matcher.delim), + )); + } + } + None => { + return Err(Error::new( + c.span(), + format!("Macro use error, expected no more tokens. Got {tt:?}"), + )) + } + } + } + Ok(()) + } + + fn get_tokens_match(cursor: &mut Cursor, t: &TokenStream) -> syn::Result<()> { + let other_iter = t.clone().into_iter(); + for other_tt in other_iter { + let maybe_tt = cursor.token_tree(); + + if let Some((tt, next)) = maybe_tt { + let matches = match &tt { + TokenTree::Group(..) => unreachable!( + "Unexpected group token found in MacroMatch, this should not be possible." + ), + TokenTree::Ident(i) => { + if let TokenTree::Ident(other_i) = &other_tt { + i.clone() == other_i.clone() + } else { + false + } + } + TokenTree::Literal(l) => { + if let TokenTree::Literal(other_l) = &other_tt { + // TODO: Is this okay? Does this work? + l.to_string() == other_l.to_string() + } else { + false + } + } + TokenTree::Punct(p) => { + if let TokenTree::Punct(other_p) = &other_tt { + other_p.as_char() == p.as_char() + } else { + false + } + } + }; + + if !matches { + return Err(Error::new( + cursor.span(), + format!("Error reading macro use: expected {other_tt:?}, got {tt:?}"), + )); + } + + *cursor = next; + } else { + return Err(Error::new( + cursor.span(), + format!( + "Error reading macro use: Unexpected end of tokens, expected {other_tt:?}" + ), + )); + } + } + Ok(()) + } +} + +#[derive(Debug)] +/// A token representing part of a macro's arguments. +/// Used for determining how to parse [`MacroUse`]. +/// First constructed with [`MacroMatcher::parse`] inside of [`MacroDef::parse`]. Then, we compare with [`MacroUse::parse_macro_matcher`]. +pub enum MacroMatch { + /// A token, excluding $ or delimeters. See https://doc.rust-lang.org/reference/tokens.html#grammar-Token + Tokens(TokenStream), + /// A delimeter-separated vector of [`MacroMatch`]. + MacroMatcher(MacroMatcher), + /// A $ident:MacroFragSpec pairing. + Ident(MacroIdent), + // TODO: $(MacroMatch+) MacroRepSep? MacroRepOp +} + +macro_rules! accepted_tokens { + ($lookahead:ident, $tokens:ident, $input:ident, [$($i:path),+], [$($p:ident),+]) => { + $( + if $lookahead.peek($i) { + $input.parse::<$i>()?.to_tokens(&mut $tokens); + } + )* + $( + if $lookahead.peek(token::$p) { + + $input.parse::()?.to_tokens(&mut $tokens); + } + )* + }; +} + +impl Parse for MacroMatch { + fn parse(input: parse::ParseStream) -> syn::Result { + let lookahead = input.lookahead1(); + let mut tokens = TokenStream::new(); + + if lookahead.peek(Token![$]) { + return Ok(MacroMatch::Ident(input.parse()?)); + } else if lookahead.peek(token::Brace) + || lookahead.peek(token::Bracket) + || lookahead.peek(token::Paren) + { + return Ok(MacroMatch::MacroMatcher(input.parse()?)); + } + + accepted_tokens!( + lookahead, + tokens, + input, + [syn::Ident, syn::Lit, syn::Lifetime], + // Not including the Eq symbols (OrEq, AndEq), since they confuse the parser. + [ + Eq, Lt, Ne, Ge, Gt, Not, Tilde, Plus, Minus, Star, Slash, Percent, Caret, And, Or, + Shl, Shr, At, Dot, Comma, Semi, Colon, Pound, Question, Underscore + ] + ); + + if !tokens.is_empty() { + Ok(MacroMatch::Tokens(tokens)) + } else { + Err(Error::new( + input.span(), + format!("Did not recognize token. {input:?}"), + )) + } + } +} + +#[derive(Debug)] +/// Represents any given macro definition's arguments, and information on how to parse them for use. +/// A MacroMatcher is a delimited list of [`MacroMatch`]es. When you call the macro `example!(...)`, the macro matcher is the parentheses delimited tokens: `(...)`. +/// Used to compare a [`MacroDef`] against a [`MacroUse`] when parsing arguments. +pub struct MacroMatcher { + pub delim: proc_macro2::Delimiter, + pub matches: Vec, +} + +impl Parse for MacroMatcher { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let lookahead = input.lookahead1(); + + let mut matches = Vec::new(); + + let delim; + let arm; + + if lookahead.peek(token::Paren) { + delim = proc_macro2::Delimiter::Parenthesis; + parenthesized!(arm in input); + } else if lookahead.peek(token::Brace) { + delim = proc_macro2::Delimiter::Brace; + braced!(arm in input); + } else if lookahead.peek(token::Bracket) { + delim = proc_macro2::Delimiter::Bracket; + bracketed!(arm in input); + } else { + return Err(Error::new(input.span(), "Expected {}, (), or []")); + } + + while !arm.is_empty() { + matches.push(arm.parse::()?); + } + + Ok(Self { delim, matches }) + } +} + +#[derive(Debug)] +#[non_exhaustive] +/// Struct for defining a macro (i.e., `macro_rules! example`) +pub struct MacroDef { + pub matcher: MacroMatcher, + pub body: TokenStream, +} + +impl Parse for MacroDef { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + // Read the matcher: + let matcher = input.parse::()?; + + let _arrow = input.parse::]>()?; + + // Now the expansion: + let arm_body; + braced!(arm_body in input); + + let body = arm_body.parse::()?; + + let _semicolon = input.parse::()?; + + if !input.is_empty() { + return Err(syn::Error::new( + input.span(), + "Diplomat does not support macros of more than one arm.", + )); + } + + // We don't support any other rules, so we ignore them. + + Ok(Self { matcher, body }) + } +} + +impl MacroDef { + pub fn validate(input: ItemMacro) -> TokenStream { + let r = input.mac.parse_body::(); + + if let Err(e) = r { + e.to_compile_error() + } else { + TokenStream::default() + } + } + + fn parse_group(matched: &MacroUse, inner: Cursor) -> TokenStream { + let mut stream = TokenStream::new(); + + let mut c = inner; + while let Some((tt, next)) = c.token_tree() { + match &tt { + TokenTree::Punct(p) if p.as_char() == '$' => { + if let Some((tt, next)) = next.token_tree() { + if let TokenTree::Ident(i) = tt { + matched.args[&i].to_tokens(&mut stream); + c = next; + } else { + panic!("Expected ident next to $, got {tt:?}"); + } + } else { + panic!("Expected token tree."); + } + } + TokenTree::Group(g) => { + let (inner, _, next) = c.group(g.delimiter()).unwrap(); + let group = + proc_macro2::Group::new(g.delimiter(), Self::parse_group(matched, inner)); + // Once we detect a group, we push it to the array for syn to evaluate. + stream.append(group); + c = next; + } + _ => { + stream.append(tt); + c = next + } + } + } + + stream + } + + fn evaluate_buf(&self, matched: MacroUse) -> TokenStream { + let mut stream = TokenStream::new(); + + let buf = TokenBuffer::new2(self.body.clone()); + let mut c = buf.begin(); + // Search until we find a token to replace: + while let Some((tt, next)) = c.token_tree() { + match &tt { + TokenTree::Punct(punct) if punct.as_char() == '$' => { + if let Some((tt, next)) = next.token_tree() { + if let TokenTree::Ident(i) = tt { + matched.args[&i].to_tokens(&mut stream); + c = next; + } else { + panic!("Expected ident next to $, got {tt:?}"); + } + } else { + panic!("Expected token tree."); + } + } + TokenTree::Group(g) => { + let (inner, _, next) = c.group(g.delimiter()).unwrap(); + // We need to read inside of any groups to find and replace `$` idents. + let group = + proc_macro2::Group::new(g.delimiter(), Self::parse_group(&matched, inner)); + stream.append(group); + c = next; + } + _ => { + stream.append(tt); + c = next + } + } + } + + stream + } + + fn evaluate(&self, matched: TokenStream) -> Vec { + let macro_use = MacroUse::parse(self, matched).unwrap_or_else(|e| panic!("{}", e)); + let stream = self.evaluate_buf(macro_use); + + // Now we have a stream to read through. We read through the whole thing and assume each thing we read is a top level item. + let maybe_list = syn::parse_str::>(&stream.to_string()); + if let Ok(i) = maybe_list { + i.items + } else { + panic!("Macro expansion error: {:?}", maybe_list.unwrap_err()); + } + } +} + +#[derive(Debug)] +struct ItemList { + items: Vec, +} + +impl Parse for ItemList { + fn parse(input: parse::ParseStream) -> syn::Result { + let mut items = Vec::new(); + while !input.is_empty() { + items.push(input.parse::()?); + } + + Ok(Self { items }) + } +} diff --git a/deps/crates/vendor/diplomat_core/src/ast/methods.rs b/deps/crates/vendor/diplomat_core/src/ast/methods.rs new file mode 100644 index 00000000000000..1b67a5fd4c3707 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/methods.rs @@ -0,0 +1,615 @@ +use serde::{Deserialize, Serialize}; +use std::ops::ControlFlow; + +use super::docs::Docs; +use super::{Attrs, Ident, Lifetime, LifetimeEnv, Mutability, PathType, TypeName}; + +/// A method declared in the `impl` associated with an FFI struct. +/// Includes both static and non-static methods, which can be distinguished +/// by inspecting [`Method::self_param`]. +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Debug)] +#[non_exhaustive] +pub struct Method { + /// The name of the method as initially declared. + pub name: Ident, + + /// Lines of documentation for the method. + pub docs: Docs, + + /// The name of the generated `extern "C"` function + pub abi_name: Ident, + + /// The `self` param of the method, if any. + pub self_param: Option, + + /// All non-`self` params taken by the method. + pub params: Vec, + + /// The return type of the method, if any. + pub return_type: Option, + + /// The lifetimes introduced in this method and surrounding impl block. + pub lifetime_env: LifetimeEnv, + + /// The list of `cfg` attributes (if any). + /// + /// These are strings instead of `syn::Attribute` or `proc_macro2::TokenStream` + /// because those types are not `PartialEq`, `Hash`, `Serialize`, etc. + pub attrs: Attrs, +} + +impl Method { + /// Extracts a [`Method`] from an AST node inside an `impl`. + pub fn from_syn( + m: &syn::ImplItemFn, + self_path_type: PathType, + impl_generics: Option<&syn::Generics>, + impl_attrs: &Attrs, + ) -> Method { + let mut attrs = impl_attrs.clone(); + attrs.add_attrs(&m.attrs); + + let self_ident = self_path_type.path.elements.last().unwrap(); + let method_ident = &m.sig.ident; + let concat_method_ident = format!("{self_ident}_{method_ident}"); + let extern_ident = syn::Ident::new( + &attrs.abi_rename.apply(concat_method_ident.into()), + m.sig.ident.span(), + ); + + let all_params = m + .sig + .inputs + .iter() + .filter_map(|a| match a { + syn::FnArg::Receiver(_) => None, + syn::FnArg::Typed(ref t) => Some(Param::from_syn(t, self_path_type.clone())), + }) + .collect::>(); + + let self_param = m + .sig + .receiver() + .map(|rec| SelfParam::from_syn(rec, self_path_type.clone())); + + let return_ty = match &m.sig.output { + syn::ReturnType::Type(_, return_typ) => { + // When we allow lifetime elision, this is where we would want to + // support it so we can insert the expanded explicit lifetimes. + Some(TypeName::from_syn( + return_typ.as_ref(), + Some(self_path_type), + )) + } + syn::ReturnType::Default => None, + }; + + let lifetime_env = LifetimeEnv::from_method_item( + m, + impl_generics, + self_param.as_ref(), + &all_params[..], + return_ty.as_ref(), + ); + + Method { + name: Ident::from(method_ident), + docs: Docs::from_attrs(&m.attrs), + abi_name: Ident::from(&extern_ident), + self_param, + params: all_params, + return_type: return_ty, + lifetime_env, + attrs, + } + } + + /// Returns the parameters that the output is lifetime-bound to. + /// + /// # Examples + /// + /// Given the following method: + /// ```ignore + /// fn foo<'a, 'b: 'a, 'c>(&'a self, bar: Bar<'b>, baz: Baz<'c>) -> FooBar<'a> { ... } + /// ``` + /// Then this method would return the `&'a self` and `bar: Bar<'b>` params + /// because `'a` is in the return type, and `'b` must live at least as long + /// as `'a`. It wouldn't include `baz: Baz<'c>` though, because the return + /// type isn't bound by `'c` in any way. + /// + /// # Panics + /// + /// This method may panic if `TypeName::check_result_type_validity` (called by + /// `Method::check_validity`) doesn't pass first, since the result type may + /// contain elided lifetimes that we depend on for this method. The validity + /// checks ensure that the return type doesn't elide any lifetimes, ensuring + /// that this method will produce correct results. + pub fn borrowed_params(&self) -> BorrowedParams<'_> { + // To determine which params the return type is bound to, we just have to + // find the params that contain a lifetime that's also in the return type. + if let Some(ref return_type) = self.return_type { + // The lifetimes that must outlive the return type + let lifetimes = return_type.longer_lifetimes(&self.lifetime_env); + + let held_self_param = self.self_param.as_ref().filter(|self_param| { + // Check if `self` is a reference with a lifetime in the return type. + if let Some((Lifetime::Named(ref name), _)) = self_param.reference { + if lifetimes.contains(&name) { + return true; + } + } + self_param.path_type.lifetimes.iter().any(|lt| { + if let Lifetime::Named(name) = lt { + lifetimes.contains(&name) + } else { + false + } + }) + }); + + // Collect all the params that contain a named lifetime that's also + // in the return type. + let held_params = self + .params + .iter() + .filter_map(|param| { + let mut lt_kind = LifetimeKind::ReturnValue; + param + .ty + .visit_lifetimes(&mut |lt, _| { + // Thanks to `TypeName::visit_lifetimes`, we can + // traverse the lifetimes without allocations and + // short-circuit if we find a match. + match lt { + Lifetime::Named(name) if lifetimes.contains(&name) => { + return ControlFlow::Break(()); + } + Lifetime::Static => { + lt_kind = LifetimeKind::Static; + return ControlFlow::Break(()); + } + _ => {} + }; + ControlFlow::Continue(()) + }) + .is_break() + .then_some((param, lt_kind)) + }) + .collect(); + + BorrowedParams(held_self_param, held_params) + } else { + BorrowedParams(None, vec![]) + } + } + + /// Checks whether the method qualifies for special write handling. + /// To qualify, a method must: + /// - not return any value + /// - have the last argument be an `&mut diplomat_runtime::DiplomatWrite` + /// + /// Typically, methods of this form will be transformed in the bindings to a + /// method that doesn't take the write as an argument but instead creates + /// one locally and just returns the final string. + pub fn is_write_out(&self) -> bool { + let return_compatible = self + .return_type + .as_ref() + .map(|return_type| match return_type { + TypeName::Unit => true, + TypeName::Result(ok, _, _) | TypeName::Option(ok, _) => { + matches!(ok.as_ref(), TypeName::Unit) + } + + _ => false, + }) + .unwrap_or(true); + + return_compatible && self.params.last().map(Param::is_write).unwrap_or(false) + } + + /// Checks if any parameters are write (regardless of other compatibilities for write output) + pub fn has_write_param(&self) -> bool { + self.params.iter().any(|p| p.is_write()) + } + + /// Returns the documentation block + pub fn docs(&self) -> &Docs { + &self.docs + } +} + +/// The `self` parameter taken by a [`Method`]. +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Debug)] +#[non_exhaustive] +pub struct SelfParam { + /// The lifetime and mutability of the `self` param, if it's a reference. + pub reference: Option<(Lifetime, Mutability)>, + + /// The type of the parameter, which will be a named reference to + /// the associated struct, + pub path_type: PathType, + + /// Associated attributes with this self parameter. Used in Demo Generation, mostly. + pub attrs: Attrs, +} + +impl SelfParam { + pub fn to_typename(&self) -> TypeName { + let typ = TypeName::Named(self.path_type.clone()); + if let Some((ref lifetime, ref mutability)) = self.reference { + return TypeName::Reference(lifetime.clone(), *mutability, Box::new(typ)); + } + typ + } + + pub fn from_syn(rec: &syn::Receiver, path_type: PathType) -> Self { + SelfParam { + reference: rec + .reference + .as_ref() + .map(|(_, lt)| (lt.into(), Mutability::from_syn(&rec.mutability))), + path_type, + attrs: Attrs::from_attrs(&rec.attrs), + } + } +} + +/// The `self` parameter taken by a [`TraitMethod`]. +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Debug, Deserialize)] +#[non_exhaustive] +pub struct TraitSelfParam { + /// The lifetime and mutability of the `self` param, if it's a reference. + pub reference: Option<(Lifetime, Mutability)>, + + /// The trait of the parameter, which will be a named reference to + /// the associated trait, + pub path_trait: PathType, +} + +impl TraitSelfParam { + pub fn to_typename(&self) -> TypeName { + let typ = TypeName::ImplTrait(self.path_trait.clone()); + if let Some((ref lifetime, ref mutability)) = self.reference { + return TypeName::Reference(lifetime.clone(), *mutability, Box::new(typ)); + } + typ + } + + pub fn from_syn(rec: &syn::Receiver, path_trait: PathType) -> Self { + TraitSelfParam { + reference: rec + .reference + .as_ref() + .map(|(_, lt)| (lt.into(), Mutability::from_syn(&rec.mutability))), + path_trait, + } + } +} + +/// A parameter taken by a [`Method`], not including `self`. +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Debug)] +#[non_exhaustive] +pub struct Param { + /// The name of the parameter in the original method declaration. + pub name: Ident, + + /// The type of the parameter. + pub ty: TypeName, + + /// Parameter attributes (like #[diplomat::demo(label = "Out")]) + pub attrs: Attrs, +} + +impl Param { + /// Check if this parameter is a Write + pub fn is_write(&self) -> bool { + match self.ty { + TypeName::Reference(_, Mutability::Mutable, ref w) => **w == TypeName::Write, + _ => false, + } + } + + pub fn from_syn(t: &syn::PatType, self_path_type: PathType) -> Self { + let ident = match t.pat.as_ref() { + syn::Pat::Ident(ident) => ident, + _ => panic!("Unexpected param type"), + }; + + let attrs = Attrs::from_attrs(&t.attrs); + + Param { + name: (&ident.ident).into(), + ty: TypeName::from_syn(&t.ty, Some(self_path_type)), + attrs, + } + } +} + +/// The type of lifetime. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum LifetimeKind { + /// Param must live at least as long as the returned object. + ReturnValue, + /// Param must live for the duration of the program. + Static, +} + +#[derive(Default, Debug)] +/// Parameters in a method that might be borrowed in the return type. +#[non_exhaustive] +pub struct BorrowedParams<'a>( + pub Option<&'a SelfParam>, + pub Vec<(&'a Param, LifetimeKind)>, +); + +impl BorrowedParams<'_> { + /// Returns an [`Iterator`] through the names of the parameters that are borrowed + /// for the lifetime of the return value, accepting an `Ident` that the `self` + /// param will be called if present. + pub fn return_names<'a>(&'a self, self_name: &'a Ident) -> impl Iterator { + self.0.iter().map(move |_| self_name).chain( + self.1 + .iter() + .filter(|(_, ltk)| (*ltk == LifetimeKind::ReturnValue)) + .map(|(param, _)| ¶m.name), + ) + } + + /// Returns an [`Iterator`] through the names of the parameters that are borrowed for a + /// static lifetime. + pub fn static_names(&self) -> impl Iterator { + self.1 + .iter() + .filter(|(_, ltk)| (*ltk == LifetimeKind::Static)) + .map(|(param, _)| ¶m.name) + } + + /// Returns `true` if a provided param name is included in the borrowed params, + /// otherwise `false`. + /// + /// This method doesn't check the `self` parameter. Use + /// [`BorrowedParams::borrows_self`] instead. + pub fn contains(&self, param_name: &Ident) -> bool { + self.1.iter().any(|(param, _)| ¶m.name == param_name) + } + + /// Returns `true` if there are no borrowed parameters, otherwise `false`. + pub fn is_empty(&self) -> bool { + self.0.is_none() && self.1.is_empty() + } + + /// Returns `true` if the `self` param is borrowed, otherwise `false`. + pub fn borrows_self(&self) -> bool { + self.0.is_some() + } + + /// Returns `true` if there are any borrowed params, otherwise `false`. + pub fn borrows_params(&self) -> bool { + !self.1.is_empty() + } + + /// Returns the number of borrowed params. + pub fn len(&self) -> usize { + self.1.len() + usize::from(self.0.is_some()) + } +} + +#[cfg(test)] +mod tests { + use insta; + + use syn; + + use crate::ast::{Attrs, Ident, Method, Path, PathType}; + + #[test] + fn static_methods() { + insta::assert_yaml_snapshot!(Method::from_syn( + &syn::parse_quote! { + /// Some docs. + #[diplomat::rust_link(foo::Bar::batz, FnInStruct)] + fn foo(x: u64, y: MyCustomStruct) { + + } + }, + PathType::new(Path::empty().sub_path(Ident::from("MyStructContainingMethod"))), + None, + &Attrs::default() + )); + + insta::assert_yaml_snapshot!(Method::from_syn( + &syn::parse_quote! { + /// Some docs. + /// Some more docs. + /// + /// Even more docs. + #[diplomat::rust_link(foo::Bar::batz, FnInEnum)] + fn foo(x: u64, y: MyCustomStruct) -> u64 { + x + } + }, + PathType::new(Path::empty().sub_path(Ident::from("MyStructContainingMethod"))), + None, + &Attrs::default() + )); + } + + #[test] + fn cfged_method() { + insta::assert_yaml_snapshot!(Method::from_syn( + &syn::parse_quote! { + /// Some docs. + #[diplomat::rust_link(foo::Bar::batz, FnInStruct)] + #[cfg(any(feature = "foo", not(feature = "bar")))] + fn foo(x: u64, y: MyCustomStruct) { + + } + }, + PathType::new(Path::empty().sub_path(Ident::from("MyStructContainingMethod"))), + None, + &Attrs::default() + )); + } + + #[test] + fn nonstatic_methods() { + insta::assert_yaml_snapshot!(Method::from_syn( + &syn::parse_quote! { + fn foo(&self, x: u64, y: MyCustomStruct) { + + } + }, + PathType::new(Path::empty().sub_path(Ident::from("MyStructContainingMethod"))), + None, + &Attrs::default() + )); + + insta::assert_yaml_snapshot!(Method::from_syn( + &syn::parse_quote! { + #[diplomat::rust_link(foo::Bar::batz, FnInStruct)] + fn foo(&mut self, x: u64, y: MyCustomStruct) -> u64 { + x + } + }, + PathType::new(Path::empty().sub_path(Ident::from("MyStructContainingMethod"))), + None, + &Attrs::default() + )); + } + + macro_rules! assert_borrowed_params { + ([$($return_param:ident),*] $(, [$($static_param:ident),*])? => $($tokens:tt)* ) => {{ + let method = Method::from_syn( + &syn::parse_quote! { $($tokens)* }, + PathType::new(Path::empty().sub_path(Ident::from("MyStructContainingMethod"))), + None, + &Attrs::default() + ); + + let borrowed_params = method.borrowed_params(); + // The ident parser in syn doesn't allow `self`, so we use "this" as a placeholder + // and then change it. + let mut actual_return: Vec<&str> = borrowed_params.return_names(&Ident::THIS).map(|ident| ident.as_str()).collect(); + if borrowed_params.0.is_some() { + actual_return[0] = "self"; + } + let expected_return: &[&str] = &[$(stringify!($return_param)),*]; + assert_eq!(actual_return, expected_return); + let actual_static: Vec<&str> = borrowed_params.static_names().map(|ident| ident.as_str()).collect(); + let expected_static: &[&str] = &[$($(stringify!($static_param)),*)?]; + assert_eq!(actual_static, expected_static); + }}; + } + + #[test] + fn static_params_held_by_return_type() { + assert_borrowed_params! { [first, second] => + #[diplomat::rust_link(foo::Bar::batz, FnInStruct)] + fn foo<'a, 'b>(first: &'a First, second: &'b Second, third: &Third) -> Foo<'a, 'b> { + unimplemented!() + } + } + + assert_borrowed_params! { [hold] => + #[diplomat::rust_link(Foo, FnInStruct)] + fn transitivity<'a, 'b: 'a, 'c: 'b, 'd: 'c, 'e: 'd, 'x>(hold: &'x One<'e>, nohold: &One<'x>) -> Box> { + unimplemented!() + } + } + + assert_borrowed_params! { [hold] => + #[diplomat::rust_link(Foo, FnInStruct)] + fn a_le_b_and_b_le_a<'a: 'b, 'b: 'a>(hold: &'b Bar, nohold: &'c Bar) -> Box> { + unimplemented!() + } + } + + assert_borrowed_params! { [a, b, c, d] => + #[diplomat::rust_link(Foo, FnInStruct)] + fn many_dependents<'a, 'b: 'a, 'c: 'a, 'd: 'b, 'x, 'y>(a: &'x One<'a>, b: &'b One<'a>, c: &Two<'x, 'c>, d: &'x Two<'d, 'y>, nohold: &'x Two<'x, 'y>) -> Box> { + unimplemented!() + } + } + + assert_borrowed_params! { [hold] => + #[diplomat::rust_link(Foo, FnInStruct)] + fn return_outlives_param<'short, 'long: 'short>(hold: &Two<'long, 'short>, nohold: &'short One<'short>) -> Box> { + unimplemented!() + } + } + + assert_borrowed_params! { [hold] => + #[diplomat::rust_link(Foo, FnInStruct)] + fn transitivity_deep_types<'a, 'b: 'a, 'c: 'b, 'd: 'c>(hold: Option>>, nohold: &'a Box>>) -> Result>, Error> { + unimplemented!() + } + } + + assert_borrowed_params! { [top, left, right, bottom] => + #[diplomat::rust_link(Foo, FnInStruct)] + fn diamond_top<'top, 'left: 'top, 'right: 'top, 'bottom: 'left + 'right>(top: One<'top>, left: One<'left>, right: One<'right>, bottom: One<'bottom>) -> Box> { + unimplemented!() + } + } + + assert_borrowed_params! { [left, bottom] => + #[diplomat::rust_link(Foo, FnInStruct)] + fn diamond_left<'top, 'left: 'top, 'right: 'top, 'bottom: 'left + 'right>(top: One<'top>, left: One<'left>, right: One<'right>, bottom: One<'bottom>) -> Box> { + unimplemented!() + } + } + + assert_borrowed_params! { [right, bottom] => + #[diplomat::rust_link(Foo, FnInStruct)] + fn diamond_right<'top, 'left: 'top, 'right: 'top, 'bottom: 'left + 'right>(top: One<'top>, left: One<'left>, right: One<'right>, bottom: One<'bottom>) -> Box> { + unimplemented!() + } + } + + assert_borrowed_params! { [bottom] => + #[diplomat::rust_link(Foo, FnInStruct)] + fn diamond_bottom<'top, 'left: 'top, 'right: 'top, 'bottom: 'left + 'right>(top: One<'top>, left: One<'left>, right: One<'right>, bottom: One<'bottom>) -> Box> { + unimplemented!() + } + } + + assert_borrowed_params! { [a, b, c, d] => + #[diplomat::rust_link(Foo, FnInStruct)] + fn diamond_and_nested_types<'a, 'b: 'a, 'c: 'b, 'd: 'b + 'c, 'x, 'y>(a: &'x One<'a>, b: &'y One<'b>, c: &One<'c>, d: &One<'d>, nohold: &One<'x>) -> Box> { + unimplemented!() + } + } + } + + #[test] + fn nonstatic_params_held_by_return_type() { + assert_borrowed_params! { [self] => + #[diplomat::rust_link(foo::Bar::batz, FnInStruct)] + fn foo<'a>(&'a self) -> Foo<'a> { + unimplemented!() + } + } + + assert_borrowed_params! { [self, foo, bar] => + #[diplomat::rust_link(foo::Bar::batz, FnInStruct)] + fn foo<'x, 'y>(&'x self, foo: &'x Foo, bar: &Bar<'y>, baz: &Baz) -> Foo<'x, 'y> { + unimplemented!() + } + } + + assert_borrowed_params! { [self, bar] => + #[diplomat::rust_link(foo::Bar::batz, FnInStruct)] + fn foo<'a, 'b>(&'a self, bar: Bar<'b>) -> Foo<'a, 'b> { + unimplemented!() + } + } + + assert_borrowed_params! { [self, bar], [baz] => + #[diplomat::rust_link(foo::Bar::batz, FnInStruct)] + fn foo<'a, 'b>(&'a self, bar: Bar<'b>, baz: &'static str) -> Foo<'a, 'b, 'static> { + unimplemented!() + } + } + } +} diff --git a/deps/crates/vendor/diplomat_core/src/ast/mod.rs b/deps/crates/vendor/diplomat_core/src/ast/mod.rs new file mode 100644 index 00000000000000..f83f021598afa0 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/mod.rs @@ -0,0 +1,52 @@ +/// As part of the macro expansion and code generation process, Diplomat +/// generates a simplified version of the Rust AST that captures special +/// types such as opaque structs, [`Box`], and [`Result`] with utilities +/// for handling such types. +pub mod attrs; +pub(crate) use attrs::AttrInheritContext; +pub use attrs::Attrs; + +mod methods; +pub use methods::{BorrowedParams, Method, Param, SelfParam, TraitSelfParam}; + +mod modules; +pub use modules::{File, Module}; + +mod structs; +pub use structs::Struct; + +mod opaque; +pub use opaque::OpaqueType; + +mod traits; +pub use traits::{Trait, TraitMethod}; + +mod enums; +pub use enums::Enum; + +mod types; +pub use types::{ + CustomType, LifetimeOrigin, ModSymbol, Mutability, PathType, PrimitiveType, StdlibOrDiplomat, + StringEncoding, TypeName, +}; + +mod functions; +pub use functions::Function; + +pub(crate) mod lifetimes; +pub use lifetimes::{Lifetime, LifetimeEnv, LifetimeTransitivity, NamedLifetime}; + +mod paths; +pub use paths::Path; + +mod idents; +pub use idents::Ident; + +mod docs; +pub use docs::{ + DocType, Docs, DocsUrlGenerator, RustLink, RustLinkDisplay, + TypeReferenceSyntax as DocsTypeReferenceSyntax, +}; + +mod macros; +pub use macros::{MacroDef, MacroUse, Macros}; diff --git a/deps/crates/vendor/diplomat_core/src/ast/modules.rs b/deps/crates/vendor/diplomat_core/src/ast/modules.rs new file mode 100644 index 00000000000000..2d93dba464a2d5 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/modules.rs @@ -0,0 +1,590 @@ +use std::collections::{BTreeMap, HashSet}; +use std::fmt::Write as _; + +use quote::ToTokens; +use serde::Serialize; +use syn::{ImplItem, Item, ItemMod, UseTree, Visibility}; + +use super::{ + AttrInheritContext, Attrs, CustomType, Enum, Ident, Macros, Method, ModSymbol, Mutability, + OpaqueType, Path, PathType, RustLink, Struct, Trait, +}; +use crate::ast::Function; +use crate::environment::*; + +/// Custom Diplomat attribute that can be placed on a struct definition. +#[derive(Debug)] +enum DiplomatStructAttribute { + /// The `#[diplomat::out]` attribute, used for non-opaque structs that + /// contain an owned opaque in the form of a `Box`. + Out, + /// An attribute that can correspond to a type (struct or enum). + TypeAttr(DiplomatTypeAttribute), +} + +/// Custom Diplomat attribute that can be placed on an enum or struct definition. +#[derive(Debug)] +enum DiplomatTypeAttribute { + /// The `#[diplomat::opaque]` attribute, used for marking a type as opaque. + /// Note that opaque structs can be borrowed in return types, but cannot + /// be passed into a function behind a mutable reference. + Opaque, + /// The `#[diplomat::opaque_mut]` attribute, used for marking a type as + /// opaque and mutable. + /// Note that mutable opaque types can never be borrowed in return types + /// (even immutably!), but can be passed into a function behind a mutable + /// reference. + OpaqueMut, +} + +impl DiplomatStructAttribute { + /// Parses a [`DiplomatStructAttribute`] from an array of [`syn::Attribute`]s. + /// If more than one kind is found, an error is returned containing all the + /// ones encountered, since all the current attributes are disjoint. + fn parse(attrs: &[syn::Attribute]) -> Result, Vec> { + let mut buf = String::with_capacity(32); + let mut res = Ok(None); + for attr in attrs { + buf.clear(); + write!(&mut buf, "{}", attr.path().to_token_stream()).unwrap(); + let parsed = match buf.as_str() { + "diplomat :: out" => Some(Self::Out), + "diplomat :: opaque" => Some(Self::TypeAttr(DiplomatTypeAttribute::Opaque)), + "diplomat :: opaque_mut" => Some(Self::TypeAttr(DiplomatTypeAttribute::OpaqueMut)), + _ => None, + }; + + if let Some(parsed) = parsed { + match res { + Ok(None) => res = Ok(Some(parsed)), + Ok(Some(first)) => res = Err(vec![first, parsed]), + Err(ref mut errors) => errors.push(parsed), + } + } + } + + res + } +} + +impl DiplomatTypeAttribute { + /// Parses a [`DiplomatTypeAttribute`] from an array of [`syn::Attribute`]s. + /// If more than one kind is found, an error is returned containing all the + /// ones encountered, since all the current attributes are disjoint. + fn parse(attrs: &[syn::Attribute]) -> Result, Vec> { + let mut buf = String::with_capacity(32); + let mut res = Ok(None); + for attr in attrs { + buf.clear(); + write!(&mut buf, "{}", attr.path().to_token_stream()).unwrap(); + let parsed = match buf.as_str() { + "diplomat :: opaque" => Some(Self::Opaque), + "diplomat :: opaque_mut" => Some(Self::OpaqueMut), + _ => None, + }; + + if let Some(parsed) = parsed { + match res { + Ok(None) => res = Ok(Some(parsed)), + Ok(Some(first)) => res = Err(vec![first, parsed]), + Err(ref mut errors) => errors.push(parsed), + } + } + } + + res + } +} + +#[derive(Clone, Serialize, Debug)] +#[non_exhaustive] +pub struct Module { + pub name: Ident, + pub imports: Vec<(Path, Ident)>, + pub declared_types: BTreeMap, + pub declared_traits: BTreeMap, + pub declared_functions: BTreeMap, + pub sub_modules: Vec, + pub attrs: Attrs, +} + +/// Contains all items needed to build an AST representation of a given [`Module`], +/// as we traverse through [`syn::ItemMod`]. We build this up in [`ModuleBuilder::add`] +struct ModuleBuilder { + custom_types_by_name: BTreeMap, + custom_traits_by_name: BTreeMap, + functions_by_name: BTreeMap, + sub_modules: Vec, + imports: Vec<(Path, Ident)>, + analyze_types: bool, + type_parent_attrs: Attrs, + impl_parent_attrs: Attrs, + mod_macros: Macros, +} + +impl ModuleBuilder { + fn add(&mut self, a: &Item) { + match a { + Item::Use(u) => { + if self.analyze_types { + extract_imports(&Path::empty(), &u.tree, &mut self.imports); + } + } + Item::Struct(strct) => { + if self.analyze_types { + let custom_type = match DiplomatStructAttribute::parse(&strct.attrs[..]) { + Ok(None) => { + CustomType::Struct(Struct::new(strct, false, &self.type_parent_attrs)) + } + Ok(Some(DiplomatStructAttribute::Out)) => { + CustomType::Struct(Struct::new(strct, true, &self.type_parent_attrs)) + } + Ok(Some(DiplomatStructAttribute::TypeAttr( + DiplomatTypeAttribute::Opaque, + ))) => CustomType::Opaque(OpaqueType::new_struct( + strct, + Mutability::Immutable, + &self.type_parent_attrs, + )), + Ok(Some(DiplomatStructAttribute::TypeAttr( + DiplomatTypeAttribute::OpaqueMut, + ))) => CustomType::Opaque(OpaqueType::new_struct( + strct, + Mutability::Mutable, + &self.type_parent_attrs, + )), + Err(errors) => { + panic!("Multiple conflicting Diplomat struct attributes, there can be at most one: {errors:?}"); + } + }; + + self.custom_types_by_name + .insert(Ident::from(&strct.ident), custom_type); + } + } + + Item::Enum(enm) => { + if self.analyze_types { + let ident = (&enm.ident).into(); + let custom_enum = match DiplomatTypeAttribute::parse(&enm.attrs[..]) { + Ok(None) => CustomType::Enum(Enum::new(enm, &self.type_parent_attrs)), + Ok(Some(DiplomatTypeAttribute::Opaque)) => { + CustomType::Opaque(OpaqueType::new_enum( + enm, + Mutability::Immutable, + &self.type_parent_attrs, + )) + } + Ok(Some(DiplomatTypeAttribute::OpaqueMut)) => CustomType::Opaque( + OpaqueType::new_enum(enm, Mutability::Mutable, &self.type_parent_attrs), + ), + Err(errors) => { + panic!("Multiple conflicting Diplomat enum attributes, there can be at most one: {errors:?}"); + } + }; + self.custom_types_by_name.insert(ident, custom_enum); + } + } + + Item::Impl(imp) => { + if self.analyze_types && imp.trait_.is_none() { + let self_path = match imp.self_ty.as_ref() { + syn::Type::Path(s) => PathType::from(s), + _ => panic!("Self type not found"), + }; + let mut impl_attrs = self.impl_parent_attrs.clone(); + impl_attrs.add_attrs(&imp.attrs); + let method_parent_attrs = + impl_attrs.attrs_for_inheritance(AttrInheritContext::MethodFromImpl); + let self_ident = self_path.path.elements.last().unwrap(); + + // Do a prepass to evaluate macros: + let mut impl_item_vec = Vec::new(); + for i in &imp.items { + match i { + ImplItem::Fn(f) => { + impl_item_vec.push(ImplItem::Fn(f.clone())); + } + ImplItem::Macro(mac) => { + let mut items = self.mod_macros.evaluate_impl_item_macro(mac); + impl_item_vec.append(&mut items); + } + _ => {} + } + } + + // Then only add functions to the block: + let mut new_methods = impl_item_vec + .iter() + .filter_map(|i| match i { + ImplItem::Fn(m) => Some(m), + _ => None, + }) + .filter(|m| { + let is_public = matches!(m.vis, Visibility::Public(_)); + let has_diplomat_attrs = m.attrs.iter().any(|a| { + a.path().segments.iter().next().unwrap().ident == "diplomat" + }); + assert!( + is_public || !has_diplomat_attrs, + "Non-public method with diplomat attrs found: {self_ident}::{}", + m.sig.ident + ); + is_public + }) + .map(|m| { + Method::from_syn( + m, + self_path.clone(), + Some(&imp.generics), + &method_parent_attrs, + ) + }) + .collect(); + + match self.custom_types_by_name.get_mut(self_ident) + .expect("Diplomat currently requires impls to be in the same module as their self type") { + CustomType::Struct(strct) => { + strct.methods.append(&mut new_methods); + } + CustomType::Opaque(strct) => { + strct.methods.append(&mut new_methods); + } + CustomType::Enum(enm) => { + enm.methods.append(&mut new_methods); + } + } + } + } + Item::Mod(item_mod) => { + self.sub_modules.push(Module::from_syn(item_mod, false)); + } + Item::Trait(trt) => { + if self.analyze_types { + let ident = (&trt.ident).into(); + let trt = Trait::new(trt, &self.type_parent_attrs); + self.custom_traits_by_name.insert(ident, trt); + } + } + Item::Macro(mac) => { + if let Some(i) = &mac.ident { + let macro_rules_attr = mac.attrs.iter().find(|a| { + a.path() == &syn::parse_str::("diplomat::macro_rules").unwrap() + }); + + if macro_rules_attr.is_some() { + self.mod_macros.add_item_macro(mac); + } else { + println!( + r#"WARNING: Found macro_rules definition "macro_rules! {i}" with no #[diplomat::macro_rules] attribute. This will not be evaluated in Diplomat bindings."# + ); + } + } else { + let items = self.mod_macros.evaluate_item_macro(mac); + for i in items { + self.add(&i); + } + } + } + Item::Fn(f) => { + if self.analyze_types { + let is_public = matches!(f.vis, Visibility::Public(_)); + let has_diplomat_attrs = f + .attrs + .iter() + .any(|a| a.path().segments.iter().next().unwrap().ident == "diplomat"); + assert!( + is_public || !has_diplomat_attrs, + "Non-public function with diplomat attrs found: {}", + f.sig.ident + ); + if is_public { + let parent_attrs = self + .impl_parent_attrs + .attrs_for_inheritance(AttrInheritContext::MethodFromImpl); + let out = Function::from_syn(f, &parent_attrs); + self.functions_by_name.insert(out.name.clone(), out); + } + } + } + _ => {} + } + } +} + +impl Module { + pub fn all_rust_links(&self) -> HashSet<&RustLink> { + let mut rust_links = self + .declared_types + .values() + .flat_map(|t| t.all_rust_links()) + .collect::>(); + + self.sub_modules.iter().for_each(|m| { + rust_links.extend(m.all_rust_links().iter()); + }); + rust_links + } + + pub fn insert_all_types(&self, in_path: Path, out: &mut Env) { + let mut mod_symbols = ModuleEnv::new(self.attrs.clone()); + + self.imports.iter().for_each(|(path, name)| { + mod_symbols.insert(name.clone(), ModSymbol::Alias(path.clone())); + }); + + self.declared_types.iter().for_each(|(k, v)| { + if mod_symbols + .insert(k.clone(), ModSymbol::CustomType(v.clone())) + .is_some() + { + panic!("Two types were declared with the same name, this needs to be implemented (key: {k})"); + } + }); + + self.declared_traits.iter().for_each(|(k, v)| { + if mod_symbols + .insert(k.clone(), ModSymbol::Trait(v.clone())) + .is_some() + { + panic!("Two traits were declared with the same name, this needs to be implemented (key: {k})"); + } + }); + + self.declared_functions.iter().for_each(|(k, f)| { + if mod_symbols.insert(k.clone(), ModSymbol::Function(f.clone())).is_some() { + panic!("Two functions were declared with the same name, this needs to be implemented (key: {k})") + } + }); + + let path_to_self = in_path.sub_path(self.name.clone()); + self.sub_modules.iter().for_each(|m| { + m.insert_all_types(path_to_self.clone(), out); + mod_symbols.insert(m.name.clone(), ModSymbol::SubModule(m.name.clone())); + }); + + out.insert(path_to_self, mod_symbols); + } + + pub fn from_syn(input: &ItemMod, force_analyze: bool) -> Module { + let mod_attrs: Attrs = (&*input.attrs).into(); + + let mut mst = ModuleBuilder { + custom_types_by_name: BTreeMap::new(), + custom_traits_by_name: BTreeMap::new(), + functions_by_name: BTreeMap::new(), + sub_modules: Vec::new(), + imports: Vec::new(), + analyze_types: force_analyze + || input + .attrs + .iter() + .any(|a| a.path().to_token_stream().to_string() == "diplomat :: bridge"), + impl_parent_attrs: mod_attrs + .attrs_for_inheritance(AttrInheritContext::MethodOrImplFromModule), + type_parent_attrs: mod_attrs.attrs_for_inheritance(AttrInheritContext::Type), + mod_macros: Macros::new(), + }; + + input + .content + .as_ref() + .map(|t| &t.1[..]) + .unwrap_or_default() + .iter() + .for_each(|a| { + mst.add(a); + }); + + Module { + name: (&input.ident).into(), + imports: mst.imports, + declared_types: mst.custom_types_by_name, + declared_traits: mst.custom_traits_by_name, + declared_functions: mst.functions_by_name, + sub_modules: mst.sub_modules, + attrs: mod_attrs, + } + } +} + +fn extract_imports(base_path: &Path, use_tree: &UseTree, out: &mut Vec<(Path, Ident)>) { + match use_tree { + UseTree::Name(name) => out.push(( + base_path.sub_path((&name.ident).into()), + (&name.ident).into(), + )), + UseTree::Path(path) => { + extract_imports(&base_path.sub_path((&path.ident).into()), &path.tree, out) + } + UseTree::Glob(_) => todo!("Glob imports are not yet supported"), + UseTree::Group(group) => { + group + .items + .iter() + .for_each(|i| extract_imports(base_path, i, out)); + } + UseTree::Rename(rename) => out.push(( + base_path.sub_path((&rename.ident).into()), + (&rename.rename).into(), + )), + } +} + +#[derive(Serialize, Clone, Debug)] +#[non_exhaustive] +pub struct File { + pub modules: BTreeMap, +} + +impl File { + /// Fuses all declared types into a single environment `HashMap`. + pub fn all_types(&self) -> Env { + let mut out = Env::default(); + let mut top_symbols = ModuleEnv::new(Default::default()); + + self.modules.values().for_each(|m| { + m.insert_all_types(Path::empty(), &mut out); + top_symbols.insert(m.name.clone(), ModSymbol::SubModule(m.name.clone())); + }); + + out.insert(Path::empty(), top_symbols); + + out + } + + pub fn all_rust_links(&self) -> HashSet<&RustLink> { + self.modules + .values() + .flat_map(|m| m.all_rust_links().into_iter()) + .collect() + } +} + +impl From<&syn::File> for File { + /// Get all custom types across all modules defined in a given file. + fn from(file: &syn::File) -> File { + let mut out = BTreeMap::new(); + file.items.iter().for_each(|i| { + if let Item::Mod(item_mod) = i { + out.insert( + item_mod.ident.to_string(), + Module::from_syn(item_mod, false), + ); + } + }); + + File { modules: out } + } +} + +#[cfg(test)] +mod tests { + use insta::{self, Settings}; + + use syn; + + use crate::ast::{File, Module}; + + #[test] + fn simple_mod() { + let mut settings = Settings::new(); + settings.set_sort_maps(true); + + settings.bind(|| { + insta::assert_yaml_snapshot!(Module::from_syn( + &syn::parse_quote! { + mod ffi { + struct NonOpaqueStruct { + a: i32, + b: Box + } + + impl NonOpaqueStruct { + pub fn new(x: i32) -> NonOpaqueStruct { + unimplemented!(); + } + + pub fn set_a(&mut self, new_a: i32) { + self.a = new_a; + } + } + + #[diplomat::opaque] + struct OpaqueStruct { + a: SomeExternalType + } + + impl OpaqueStruct { + pub fn new() -> Box { + unimplemented!(); + } + + pub fn get_string(&self) -> String { + unimplemented!() + } + } + + pub fn test_function() {} + pub fn other_test_function(x : i32) -> NonOpaqueStruct { + unimplemented!(); + } + } + }, + true + )); + }); + } + + #[test] + fn method_visibility() { + let mut settings = Settings::new(); + settings.set_sort_maps(true); + + settings.bind(|| { + insta::assert_yaml_snapshot!(Module::from_syn( + &syn::parse_quote! { + #[diplomat::bridge] + mod ffi { + struct Foo {} + + impl Foo { + pub fn pub_fn() { + unimplemented!() + } + pub(crate) fn pub_crate_fn() { + unimplemented!() + } + pub(super) fn pub_super_fn() { + unimplemented!() + } + fn priv_fn() { + unimplemented!() + } + } + } + }, + true + )); + }); + } + + #[test] + fn import_in_non_diplomat_not_analyzed() { + let mut settings = Settings::new(); + settings.set_sort_maps(true); + + settings.bind(|| { + insta::assert_yaml_snapshot!(File::from(&syn::parse_quote! { + #[diplomat::bridge] + mod ffi { + struct Foo {} + } + + mod other { + use something::*; + } + })); + }); + } +} diff --git a/deps/crates/vendor/diplomat_core/src/ast/opaque.rs b/deps/crates/vendor/diplomat_core/src/ast/opaque.rs new file mode 100644 index 00000000000000..c968f049888c70 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/opaque.rs @@ -0,0 +1,64 @@ +use serde::Serialize; + +use super::docs::Docs; +use super::{Attrs, Ident, LifetimeEnv, Method, Mutability}; + +/// A type annotated with [`diplomat::opaque`] whose fields/variants are not visible. +/// Opaque types cannot be passed by-value across the FFI boundary, so they +/// must be boxed or passed as references. +#[derive(Clone, Serialize, Debug, Hash, PartialEq, Eq)] +#[non_exhaustive] +pub struct OpaqueType { + pub name: Ident, + pub docs: Docs, + pub lifetimes: LifetimeEnv, + pub methods: Vec, + pub mutability: Mutability, + pub attrs: Attrs, + /// The ABI name of the generated destructor + pub dtor_abi_name: Ident, +} + +impl OpaqueType { + /// Extract a [`OpaqueType`] metadata value from an AST node representing a struct. + pub fn new_struct( + strct: &syn::ItemStruct, + mutability: Mutability, + parent_attrs: &Attrs, + ) -> Self { + let mut attrs = parent_attrs.clone(); + attrs.add_attrs(&strct.attrs); + let name = Ident::from(&strct.ident); + OpaqueType { + dtor_abi_name: Self::dtor_abi_name(&name, &attrs), + name, + docs: Docs::from_attrs(&strct.attrs), + lifetimes: LifetimeEnv::from_struct_item(strct, &[]), + methods: vec![], + mutability, + attrs, + } + } + + /// Extract a [`OpaqueType`] metadata value from an AST node representing an enum. + pub fn new_enum(enm: &syn::ItemEnum, mutability: Mutability, parent_attrs: &Attrs) -> Self { + let mut attrs = parent_attrs.clone(); + attrs.add_attrs(&enm.attrs); + let name = Ident::from(&enm.ident); + OpaqueType { + dtor_abi_name: Self::dtor_abi_name(&name, &attrs), + name, + docs: Docs::from_attrs(&enm.attrs), + lifetimes: LifetimeEnv::from_enum_item(enm, &[]), + methods: vec![], + mutability, + attrs, + } + } + + fn dtor_abi_name(name: &Ident, attrs: &Attrs) -> Ident { + let dtor_abi_name = format!("{name}_destroy"); + let dtor_abi_name = String::from(attrs.abi_rename.apply(dtor_abi_name.into())); + Ident::from(dtor_abi_name) + } +} diff --git a/deps/crates/vendor/diplomat_core/src/ast/paths.rs b/deps/crates/vendor/diplomat_core/src/ast/paths.rs new file mode 100644 index 00000000000000..8bd9129081c486 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/paths.rs @@ -0,0 +1,77 @@ +use serde::{Deserialize, Serialize}; +use std::fmt; + +use super::Ident; + +#[derive(Hash, Eq, PartialEq, Deserialize, Serialize, Clone, Debug, Ord, PartialOrd)] +#[non_exhaustive] +pub struct Path { + pub elements: Vec, +} + +impl Path { + pub fn get_super(&self) -> Path { + let mut new_elements = self.elements.clone(); + new_elements.remove(new_elements.len() - 1); + Path { + elements: new_elements, + } + } + + pub fn sub_path(&self, ident: Ident) -> Path { + let mut new_elements = self.elements.clone(); + new_elements.push(ident); + Path { + elements: new_elements, + } + } + + pub fn to_syn(&self) -> syn::Path { + syn::Path { + leading_colon: None, + segments: self + .elements + .iter() + .map(|s| syn::PathSegment { + ident: s.to_syn(), + arguments: syn::PathArguments::None, + }) + .collect(), + } + } + + pub fn from_syn(path: &syn::Path) -> Path { + Path { + elements: path + .segments + .iter() + .map(|seg| (&seg.ident).into()) + .collect(), + } + } + + pub fn empty() -> Path { + Path { elements: vec![] } + } +} + +impl fmt::Display for Path { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if let Some((head, tail)) = self.elements.split_first() { + head.fmt(f)?; + for seg in tail { + "::".fmt(f)?; + seg.fmt(f)?; + } + } + Ok(()) + } +} + +impl FromIterator for Path { + fn from_iter>(iter: T) -> Self { + Path { + elements: iter.into_iter().collect(), + } + } +} diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__attr.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__attr.snap new file mode 100644 index 00000000000000..d105a73ed5ee69 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__attr.snap @@ -0,0 +1,12 @@ +--- +source: core/src/ast/attrs.rs +expression: attr +--- +cfg: + Any: + - BackendName: cpp + - NameValue: + - has + - overloading +meta: namespacing + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfg_attr.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfg_attr.snap new file mode 100644 index 00000000000000..63f2c452187691 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfg_attr.snap @@ -0,0 +1,11 @@ +--- +source: core/src/ast/attrs.rs +expression: attr +--- +key_value_pairs: + - key: test.out + value: "24" + - key: other.out + value: test + - key: somefinal.out + value: "\"testing spaces\"" diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-2.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-2.snap new file mode 100644 index 00000000000000..cc58dea4c16435 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-2.snap @@ -0,0 +1,6 @@ +--- +source: core/src/ast/attrs.rs +expression: attr_cfg +--- +BackendName: cpp + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-3.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-3.snap new file mode 100644 index 00000000000000..635fcc978266c5 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-3.snap @@ -0,0 +1,8 @@ +--- +source: core/src/ast/attrs.rs +expression: attr_cfg +--- +NameValue: + - has + - overloading + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-4.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-4.snap new file mode 100644 index 00000000000000..635fcc978266c5 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-4.snap @@ -0,0 +1,8 @@ +--- +source: core/src/ast/attrs.rs +expression: attr_cfg +--- +NameValue: + - has + - overloading + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-5.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-5.snap new file mode 100644 index 00000000000000..5f7daa1da8f57c --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs-5.snap @@ -0,0 +1,14 @@ +--- +source: core/src/ast/attrs.rs +expression: attr_cfg +--- +Any: + - All: + - Star + - BackendName: cpp + - NameValue: + - has + - overloading + - Not: + BackendName: js + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs.snap new file mode 100644 index 00000000000000..658b25dba3914d --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__cfgs.snap @@ -0,0 +1,6 @@ +--- +source: core/src/ast/attrs.rs +expression: attr_cfg +--- +Star + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__rename-2.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__rename-2.snap new file mode 100644 index 00000000000000..2bb6693273c244 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__rename-2.snap @@ -0,0 +1,8 @@ +--- +source: core/src/ast/attrs.rs +expression: attr +--- +pattern: + replacement: foobar_ + insertion_index: 7 + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__rename.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__rename.snap new file mode 100644 index 00000000000000..2bb6693273c244 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__attrs__tests__rename.snap @@ -0,0 +1,8 @@ +--- +source: core/src/ast/attrs.rs +expression: attr +--- +pattern: + replacement: foobar_ + insertion_index: 7 + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__enums__tests__enum_with_discr.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__enums__tests__enum_with_discr.snap new file mode 100644 index 00000000000000..56d6eafafc90c1 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__enums__tests__enum_with_discr.snap @@ -0,0 +1,37 @@ +--- +source: core/src/ast/enums.rs +expression: "Enum::new(&syn::parse_quote! {\n /// Some docs.\n #[diplomat :: rust_link(foo :: Bar, Enum)] enum\n DiscriminantedEnum { Abc = - 1, Def = 0, Ghi = 1, Jkl = 2, }\n }, &Default::default())" +--- +name: DiscriminantedEnum +docs: + - Some docs. + - - path: + elements: + - foo + - Bar + typ: Enum + display: Normal +variants: + - - Abc + - -1 + - - "" + - [] + - {} + - - Def + - 0 + - - "" + - [] + - {} + - - Ghi + - 1 + - - "" + - [] + - {} + - - Jkl + - 2 + - - "" + - [] + - {} +methods: [] +attrs: {} + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__enums__tests__simple_enum.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__enums__tests__simple_enum.snap new file mode 100644 index 00000000000000..3c509d5348be4a --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__enums__tests__simple_enum.snap @@ -0,0 +1,27 @@ +--- +source: core/src/ast/enums.rs +expression: "Enum::new(&syn::parse_quote! {\n /// Some docs.\n #[diplomat :: rust_link(foo :: Bar, Enum)] enum MyLocalEnum\n {\n Abc, /// Some more docs.\n Def\n }\n }, &Default::default())" +--- +name: MyLocalEnum +docs: + - Some docs. + - - path: + elements: + - foo + - Bar + typ: Enum + display: Normal +variants: + - - Abc + - 0 + - - "" + - [] + - {} + - - Def + - 1 + - - Some more docs. + - [] + - {} +methods: [] +attrs: {} + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__functions__tests__free_function.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__functions__tests__free_function.snap new file mode 100644 index 00000000000000..dfaab5ff15ed9a --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__functions__tests__free_function.snap @@ -0,0 +1,21 @@ +--- +source: core/src/ast/functions.rs +expression: "Function::from_syn(&syn::parse_quote! { fn some_func(a : f32, b: f64) {} },\n&Attrs::default())" +--- +name: some_func +abi_name: diplomat_external_some_func +params: + - name: a + ty: + Primitive: f32 + attrs: {} + - name: b + ty: + Primitive: f64 + attrs: {} +output_type: ~ +lifetimes: {} +attrs: {} +docs: + - "" + - [] diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__functions__tests__free_function_lifetimes.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__functions__tests__free_function_lifetimes.snap new file mode 100644 index 00000000000000..9db7116db8bcdd --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__functions__tests__free_function_lifetimes.snap @@ -0,0 +1,35 @@ +--- +source: core/src/ast/functions.rs +expression: "Function::from_syn(&syn::parse_quote!\n{ fn some_func<'a>(a : &'a SomeType) -> Option<&'a SomeType> {} },\n&Attrs::default())" +--- +name: some_func +abi_name: diplomat_external_some_func +params: + - name: a + ty: + Reference: + - Named: a + - Immutable + - Named: + path: + elements: + - SomeType + lifetimes: [] + attrs: {} +output_type: + Option: + - Reference: + - Named: a + - Immutable + - Named: + path: + elements: + - SomeType + lifetimes: [] + - Stdlib +lifetimes: + a: [] +attrs: {} +docs: + - "" + - [] diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__functions__tests__free_function_output.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__functions__tests__free_function_output.snap new file mode 100644 index 00000000000000..f8bdb1b5e0f01f --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__functions__tests__free_function_output.snap @@ -0,0 +1,24 @@ +--- +source: core/src/ast/functions.rs +expression: "Function::from_syn(&syn::parse_quote!\n{ fn some_func(a : SomeType) -> Option<()> {} }, &Attrs::default())" +--- +name: some_func +abi_name: diplomat_external_some_func +params: + - name: a + ty: + Named: + path: + elements: + - SomeType + lifetimes: [] + attrs: {} +output_type: + Option: + - Unit + - Stdlib +lifetimes: {} +attrs: {} +docs: + - "" + - [] diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__cfged_method.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__cfged_method.snap new file mode 100644 index 00000000000000..245fe61d04448d --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__cfged_method.snap @@ -0,0 +1,34 @@ +--- +source: core/src/ast/methods.rs +expression: "Method::from_syn(&syn::parse_quote! {\n #[doc = r\" Some docs.\"]\n #[diplomat::rust_link(foo::Bar::batz, FnInStruct)]\n #[cfg(any(feature = \"foo\", not(feature = \"bar\")))] fn\n foo(x: u64, y: MyCustomStruct) {}\n },\n PathType::new(Path::empty().sub_path(Ident::from(\"MyStructContainingMethod\"))),\n None, &Attrs::default())" +--- +name: foo +docs: + - Some docs. + - - path: + elements: + - foo + - Bar + - batz + typ: FnInStruct + display: Normal +abi_name: MyStructContainingMethod_foo +self_param: ~ +params: + - name: x + ty: + Primitive: u64 + attrs: {} + - name: y + ty: + Named: + path: + elements: + - MyCustomStruct + lifetimes: [] + attrs: {} +return_type: ~ +lifetime_env: {} +attrs: + cfg: + - "# [cfg (any (feature = \"foo\" , not (feature = \"bar\")))]" diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__nonstatic_methods-2.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__nonstatic_methods-2.snap new file mode 100644 index 00000000000000..5dfc34cc3debab --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__nonstatic_methods-2.snap @@ -0,0 +1,42 @@ +--- +source: core/src/ast/methods.rs +expression: "Method::from_syn(&syn::parse_quote! {\n #[diplomat::rust_link(foo::Bar::batz, FnInStruct)] fn\n foo(&mut self, x: u64, y: MyCustomStruct) -> u64 { x }\n },\n PathType::new(Path::empty().sub_path(Ident::from(\"MyStructContainingMethod\"))),\n None, &Attrs::default())" +--- +name: foo +docs: + - "" + - - path: + elements: + - foo + - Bar + - batz + typ: FnInStruct + display: Normal +abi_name: MyStructContainingMethod_foo +self_param: + reference: + - Anonymous + - Mutable + path_type: + path: + elements: + - MyStructContainingMethod + lifetimes: [] + attrs: {} +params: + - name: x + ty: + Primitive: u64 + attrs: {} + - name: y + ty: + Named: + path: + elements: + - MyCustomStruct + lifetimes: [] + attrs: {} +return_type: + Primitive: u64 +lifetime_env: {} +attrs: {} diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__nonstatic_methods.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__nonstatic_methods.snap new file mode 100644 index 00000000000000..4147b134113fb5 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__nonstatic_methods.snap @@ -0,0 +1,35 @@ +--- +source: core/src/ast/methods.rs +expression: "Method::from_syn(&syn::parse_quote! {\n fn foo(&self, x: u64, y: MyCustomStruct) {}\n },\n PathType::new(Path::empty().sub_path(Ident::from(\"MyStructContainingMethod\"))),\n None, &Attrs::default())" +--- +name: foo +docs: + - "" + - [] +abi_name: MyStructContainingMethod_foo +self_param: + reference: + - Anonymous + - Immutable + path_type: + path: + elements: + - MyStructContainingMethod + lifetimes: [] + attrs: {} +params: + - name: x + ty: + Primitive: u64 + attrs: {} + - name: y + ty: + Named: + path: + elements: + - MyCustomStruct + lifetimes: [] + attrs: {} +return_type: ~ +lifetime_env: {} +attrs: {} diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__static_methods-2.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__static_methods-2.snap new file mode 100644 index 00000000000000..516f511bd0026f --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__static_methods-2.snap @@ -0,0 +1,33 @@ +--- +source: core/src/ast/methods.rs +expression: "Method::from_syn(&syn::parse_quote! {\n #[doc = r\" Some docs.\"] #[doc = r\" Some more docs.\"]\n #[doc = r\"\"] #[doc = r\" Even more docs.\"]\n #[diplomat::rust_link(foo::Bar::batz, FnInEnum)] fn\n foo(x: u64, y: MyCustomStruct) -> u64 { x }\n },\n PathType::new(Path::empty().sub_path(Ident::from(\"MyStructContainingMethod\"))),\n None, &Attrs::default())" +--- +name: foo +docs: + - "Some docs.\nSome more docs.\n\nEven more docs." + - - path: + elements: + - foo + - Bar + - batz + typ: FnInEnum + display: Normal +abi_name: MyStructContainingMethod_foo +self_param: ~ +params: + - name: x + ty: + Primitive: u64 + attrs: {} + - name: y + ty: + Named: + path: + elements: + - MyCustomStruct + lifetimes: [] + attrs: {} +return_type: + Primitive: u64 +lifetime_env: {} +attrs: {} diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__static_methods.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__static_methods.snap new file mode 100644 index 00000000000000..58bc55c51af865 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__methods__tests__static_methods.snap @@ -0,0 +1,32 @@ +--- +source: core/src/ast/methods.rs +expression: "Method::from_syn(&syn::parse_quote! {\n #[doc = r\" Some docs.\"]\n #[diplomat::rust_link(foo::Bar::batz, FnInStruct)] fn\n foo(x: u64, y: MyCustomStruct) {}\n },\n PathType::new(Path::empty().sub_path(Ident::from(\"MyStructContainingMethod\"))),\n None, &Attrs::default())" +--- +name: foo +docs: + - Some docs. + - - path: + elements: + - foo + - Bar + - batz + typ: FnInStruct + display: Normal +abi_name: MyStructContainingMethod_foo +self_param: ~ +params: + - name: x + ty: + Primitive: u64 + attrs: {} + - name: y + ty: + Named: + path: + elements: + - MyCustomStruct + lifetimes: [] + attrs: {} +return_type: ~ +lifetime_env: {} +attrs: {} diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__modules__tests__import_in_non_diplomat_not_analyzed.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__modules__tests__import_in_non_diplomat_not_analyzed.snap new file mode 100644 index 00000000000000..940aba2dcc5850 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__modules__tests__import_in_non_diplomat_not_analyzed.snap @@ -0,0 +1,32 @@ +--- +source: core/src/ast/modules.rs +expression: "File::from(&syn::parse_quote!\n{\n #[diplomat::bridge] mod ffi { struct Foo {} } mod other\n { use something::*; }\n})" +--- +modules: + ffi: + name: ffi + imports: [] + declared_types: + Foo: + Struct: + name: Foo + docs: + - "" + - [] + lifetimes: {} + fields: [] + methods: [] + output_only: false + attrs: {} + declared_traits: {} + declared_functions: {} + sub_modules: [] + attrs: {} + other: + name: other + imports: [] + declared_types: {} + declared_traits: {} + declared_functions: {} + sub_modules: [] + attrs: {} diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__modules__tests__method_visibility.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__modules__tests__method_visibility.snap new file mode 100644 index 00000000000000..19b682aa7fba1a --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__modules__tests__method_visibility.snap @@ -0,0 +1,32 @@ +--- +source: core/src/ast/modules.rs +expression: "Module::from_syn(&syn::parse_quote!\n{\n #[diplomat::bridge] mod ffi\n {\n struct Foo {} impl Foo\n {\n pub fn pub_fn() { unimplemented!() } pub(crate) fn pub_crate_fn()\n { unimplemented!() } pub(super) fn pub_super_fn()\n { unimplemented!() } fn priv_fn() { unimplemented!() }\n }\n }\n}, true)" +--- +name: ffi +imports: [] +declared_types: + Foo: + Struct: + name: Foo + docs: + - "" + - [] + lifetimes: {} + fields: [] + methods: + - name: pub_fn + docs: + - "" + - [] + abi_name: Foo_pub_fn + self_param: ~ + params: [] + return_type: ~ + lifetime_env: {} + attrs: {} + output_only: false + attrs: {} +declared_traits: {} +declared_functions: {} +sub_modules: [] +attrs: {} diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__modules__tests__simple_mod.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__modules__tests__simple_mod.snap new file mode 100644 index 00000000000000..095a9a46098944 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__modules__tests__simple_mod.snap @@ -0,0 +1,159 @@ +--- +source: core/src/ast/modules.rs +expression: "Module::from_syn(&syn::parse_quote!\n{\n mod ffi\n {\n struct NonOpaqueStruct { a: i32, b: Box } impl\n NonOpaqueStruct\n {\n pub fn new(x: i32) -> NonOpaqueStruct { unimplemented!(); } pub fn\n set_a(&mut self, new_a: i32) { self.a = new_a; }\n } #[diplomat::opaque] struct OpaqueStruct { a: SomeExternalType } impl\n OpaqueStruct\n {\n pub fn new() -> Box { unimplemented!(); } pub fn\n get_string(&self) -> String { unimplemented!() }\n } pub fn test_function() {} pub fn other_test_function(x : i32) ->\n NonOpaqueStruct { unimplemented!(); }\n }\n}, true)" +--- +name: ffi +imports: [] +declared_types: + NonOpaqueStruct: + Struct: + name: NonOpaqueStruct + docs: + - "" + - [] + lifetimes: {} + fields: + - - a + - Primitive: i32 + - - "" + - [] + - {} + - - b + - Box: + Named: + path: + elements: + - NonOpaqueStruct + lifetimes: [] + - - "" + - [] + - {} + methods: + - name: new + docs: + - "" + - [] + abi_name: NonOpaqueStruct_new + self_param: ~ + params: + - name: x + ty: + Primitive: i32 + attrs: {} + return_type: + Named: + path: + elements: + - NonOpaqueStruct + lifetimes: [] + lifetime_env: {} + attrs: {} + - name: set_a + docs: + - "" + - [] + abi_name: NonOpaqueStruct_set_a + self_param: + reference: + - Anonymous + - Mutable + path_type: + path: + elements: + - NonOpaqueStruct + lifetimes: [] + attrs: {} + params: + - name: new_a + ty: + Primitive: i32 + attrs: {} + return_type: ~ + lifetime_env: {} + attrs: {} + output_only: false + attrs: {} + OpaqueStruct: + Opaque: + name: OpaqueStruct + docs: + - "" + - [] + lifetimes: {} + methods: + - name: new + docs: + - "" + - [] + abi_name: OpaqueStruct_new + self_param: ~ + params: [] + return_type: + Box: + Named: + path: + elements: + - OpaqueStruct + lifetimes: [] + lifetime_env: {} + attrs: {} + - name: get_string + docs: + - "" + - [] + abi_name: OpaqueStruct_get_string + self_param: + reference: + - Anonymous + - Immutable + path_type: + path: + elements: + - OpaqueStruct + lifetimes: [] + attrs: {} + params: [] + return_type: + Named: + path: + elements: + - String + lifetimes: [] + lifetime_env: {} + attrs: {} + mutability: Immutable + attrs: {} + dtor_abi_name: OpaqueStruct_destroy +declared_traits: {} +declared_functions: + other_test_function: + name: other_test_function + abi_name: diplomat_external_other_test_function + params: + - name: x + ty: + Primitive: i32 + attrs: {} + output_type: + Named: + path: + elements: + - NonOpaqueStruct + lifetimes: [] + lifetimes: {} + attrs: {} + docs: + - "" + - [] + test_function: + name: test_function + abi_name: diplomat_external_test_function + params: [] + output_type: ~ + lifetimes: {} + attrs: {} + docs: + - "" + - [] +sub_modules: [] +attrs: {} diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__structs__tests__simple_struct.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__structs__tests__simple_struct.snap new file mode 100644 index 00000000000000..e3f44b080f7b70 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__structs__tests__simple_struct.snap @@ -0,0 +1,33 @@ +--- +source: core/src/ast/structs.rs +expression: "Struct::new(&syn::parse_quote! {\n #[doc = r\" Some docs.\"]\n #[diplomat::rust_link(foo::Bar, Struct)] struct MyLocalStruct\n { a: i32, b: Box }\n }, true, &Default::default())" +--- +name: MyLocalStruct +docs: + - Some docs. + - - path: + elements: + - foo + - Bar + typ: Struct + display: Normal +lifetimes: {} +fields: + - - a + - Primitive: i32 + - - "" + - [] + - {} + - - b + - Box: + Named: + path: + elements: + - MyLocalStruct + lifetimes: [] + - - "" + - [] + - {} +methods: [] +output_only: true +attrs: {} diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-10.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-10.snap new file mode 100644 index 00000000000000..3873fb410595cf --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-10.snap @@ -0,0 +1,10 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { DiplomatSliceStr<'a> }, None)" +--- +Named: + path: + elements: + - DiplomatSliceStr + lifetimes: + - Named: a diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-11.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-11.snap new file mode 100644 index 00000000000000..1baf16b203e7dd --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-11.snap @@ -0,0 +1,9 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { DiplomatSliceMut<'a, f32> }, None)" +--- +PrimitiveSlice: + - - Named: a + - Mutable + - f32 + - Diplomat diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-12.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-12.snap new file mode 100644 index 00000000000000..cace9c192afc98 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-12.snap @@ -0,0 +1,9 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { DiplomatSlice }, None)" +--- +PrimitiveSlice: + - - Anonymous + - Immutable + - i32 + - Diplomat diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-2.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-2.snap new file mode 100644 index 00000000000000..8a60d74bbd3d08 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-2.snap @@ -0,0 +1,12 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { :: core :: my_type :: Foo }, None)" +--- +Named: + path: + elements: + - core + - my_type + - Foo + lifetimes: [] + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-3.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-3.snap new file mode 100644 index 00000000000000..8aabe3da062d77 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-3.snap @@ -0,0 +1,13 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { :: core :: my_type :: Foo < 'test > },\n None)" +--- +Named: + path: + elements: + - core + - my_type + - Foo + lifetimes: + - Named: test + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-4.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-4.snap new file mode 100644 index 00000000000000..1d7f0c5939df66 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-4.snap @@ -0,0 +1,12 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { Option> }, None)" +--- +Option: + - Named: + path: + elements: + - Ref + lifetimes: + - Named: object + - Stdlib diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-5.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-5.snap new file mode 100644 index 00000000000000..8c8ed1c1d9b701 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-5.snap @@ -0,0 +1,14 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { Foo < 'a, 'b, 'c, 'd > }, None)" +--- +Named: + path: + elements: + - Foo + lifetimes: + - Named: a + - Named: b + - Named: c + - Named: d + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-6.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-6.snap new file mode 100644 index 00000000000000..fbbae2758dff26 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-6.snap @@ -0,0 +1,18 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! {\n very :: long :: path :: to :: my :: Type < 'x, 'y, 'z >\n }, None)" +--- +Named: + path: + elements: + - very + - long + - path + - to + - my + - Type + lifetimes: + - Named: x + - Named: y + - Named: z + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-7.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-7.snap new file mode 100644 index 00000000000000..6bb2a4756c4c58 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-7.snap @@ -0,0 +1,19 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { Result, ErrRef<'c>> },\n None)" +--- +Result: + - Named: + path: + elements: + - OkRef + lifetimes: + - Named: a + - Named: b + - Named: + path: + elements: + - ErrRef + lifetimes: + - Named: c + - Stdlib diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-8.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-8.snap new file mode 100644 index 00000000000000..334fd54d697eed --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-8.snap @@ -0,0 +1,9 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { DiplomatSlice<'a, u16> }, None)" +--- +PrimitiveSlice: + - - Named: a + - Immutable + - u16 + - Diplomat diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-9.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-9.snap new file mode 100644 index 00000000000000..123872a17f121d --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes-9.snap @@ -0,0 +1,8 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { DiplomatOwnedSlice }, None)" +--- +PrimitiveSlice: + - ~ + - i8 + - Diplomat diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes.snap new file mode 100644 index 00000000000000..41047acab8ecd6 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__lifetimes.snap @@ -0,0 +1,12 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { Foo < 'a, 'b > }, None)" +--- +Named: + path: + elements: + - Foo + lifetimes: + - Named: a + - Named: b + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_boxes-2.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_boxes-2.snap new file mode 100644 index 00000000000000..18a72a2ffe95a1 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_boxes-2.snap @@ -0,0 +1,11 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { Box < MyLocalStruct > }, None)" +--- +Box: + Named: + path: + elements: + - MyLocalStruct + lifetimes: [] + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_boxes.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_boxes.snap new file mode 100644 index 00000000000000..30d9ae3e16b4a9 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_boxes.snap @@ -0,0 +1,7 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { Box < i32 > }, None)" +--- +Box: + Primitive: i32 + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_named.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_named.snap new file mode 100644 index 00000000000000..f7763c5f4dd4fc --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_named.snap @@ -0,0 +1,10 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { MyLocalStruct }, None)" +--- +Named: + path: + elements: + - MyLocalStruct + lifetimes: [] + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_option-2.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_option-2.snap new file mode 100644 index 00000000000000..b1136d0a5e0df8 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_option-2.snap @@ -0,0 +1,11 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { Option }, None)" +--- +Option: + - Named: + path: + elements: + - MyLocalStruct + lifetimes: [] + - Stdlib diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_option.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_option.snap new file mode 100644 index 00000000000000..0cfd9547ff12d9 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_option.snap @@ -0,0 +1,7 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { Option }, None)" +--- +Option: + - Primitive: i32 + - Stdlib diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives-2.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives-2.snap new file mode 100644 index 00000000000000..38877277908ca2 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives-2.snap @@ -0,0 +1,6 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { usize }, None)" +--- +Primitive: usize + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives-3.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives-3.snap new file mode 100644 index 00000000000000..2fac7f44aed912 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives-3.snap @@ -0,0 +1,6 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { bool }, None)" +--- +Primitive: bool + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives.snap new file mode 100644 index 00000000000000..5ef0eaf5e550d8 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_primitives.snap @@ -0,0 +1,6 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { i32 }, None)" +--- +Primitive: i32 + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_references-2.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_references-2.snap new file mode 100644 index 00000000000000..396affe3e3b424 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_references-2.snap @@ -0,0 +1,13 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { & mut MyLocalStruct }, None)" +--- +Reference: + - Anonymous + - Mutable + - Named: + path: + elements: + - MyLocalStruct + lifetimes: [] + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_references.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_references.snap new file mode 100644 index 00000000000000..38c72a4bd22858 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_references.snap @@ -0,0 +1,9 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { & i32 }, None)" +--- +Reference: + - Anonymous + - Immutable + - Primitive: i32 + diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-2.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-2.snap new file mode 100644 index 00000000000000..a3c187af191250 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-2.snap @@ -0,0 +1,12 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { DiplomatResult<(), MyLocalStruct> },\n None)" +--- +Result: + - Unit + - Named: + path: + elements: + - MyLocalStruct + lifetimes: [] + - Diplomat diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-3.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-3.snap new file mode 100644 index 00000000000000..e83fdda19cdc66 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-3.snap @@ -0,0 +1,12 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { Result }, None)" +--- +Result: + - Named: + path: + elements: + - MyLocalStruct + lifetimes: [] + - Primitive: i32 + - Stdlib diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-4.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-4.snap new file mode 100644 index 00000000000000..54ddc986f8845b --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result-4.snap @@ -0,0 +1,12 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { Result<(), MyLocalStruct> }, None)" +--- +Result: + - Unit + - Named: + path: + elements: + - MyLocalStruct + lifetimes: [] + - Stdlib diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result.snap new file mode 100644 index 00000000000000..dc28b421ecd82e --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__types__tests__typename_result.snap @@ -0,0 +1,12 @@ +--- +source: core/src/ast/types.rs +expression: "TypeName::from_syn(&syn::parse_quote! { DiplomatResult },\n None)" +--- +Result: + - Named: + path: + elements: + - MyLocalStruct + lifetimes: [] + - Primitive: i32 + - Diplomat diff --git a/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__validity__tests__lifetime_in_return.snap b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__validity__tests__lifetime_in_return.snap new file mode 100644 index 00000000000000..8a0061767a9c64 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/snapshots/diplomat_core__ast__validity__tests__lifetime_in_return.snap @@ -0,0 +1,7 @@ +--- +source: core/src/ast/validity.rs +expression: output +--- +A return type contains elided lifetimes, which aren't yet supported: &Opaque in &Opaque +A return type contains elided lifetimes, which aren't yet supported: Foo in Foo + diff --git a/deps/crates/vendor/diplomat_core/src/ast/structs.rs b/deps/crates/vendor/diplomat_core/src/ast/structs.rs new file mode 100644 index 00000000000000..c43360241c2998 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/structs.rs @@ -0,0 +1,85 @@ +use serde::Serialize; + +use super::docs::Docs; +use super::{Attrs, Ident, LifetimeEnv, Method, PathType, TypeName}; + +/// A struct declaration in an FFI module that is not opaque. +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Debug)] +#[non_exhaustive] +pub struct Struct { + pub name: Ident, + pub docs: Docs, + pub lifetimes: LifetimeEnv, + pub fields: Vec<(Ident, TypeName, Docs, Attrs)>, + pub methods: Vec, + pub output_only: bool, + pub attrs: Attrs, +} + +impl Struct { + /// Extract a [`Struct`] metadata value from an AST node. + pub fn new(strct: &syn::ItemStruct, output_only: bool, parent_attrs: &Attrs) -> Self { + let self_path_type = PathType::extract_self_type(strct); + let fields: Vec<_> = strct + .fields + .iter() + .map(|field| { + use quote::ToTokens; + // Non-opaque tuple structs will never be allowed + let name = field.ident.as_ref().map(Into::into).unwrap_or_else(|| { + panic!( + "non-opaque tuples structs are disallowed ({:?})", + field.ty.to_token_stream().to_string() + ) + }); + let type_name = TypeName::from_syn(&field.ty, Some(self_path_type.clone())); + let docs = Docs::from_attrs(&field.attrs); + + (name, type_name, docs, Attrs::from_attrs(&field.attrs)) + }) + .collect(); + + let lifetimes = LifetimeEnv::from_struct_item(strct, &fields[..]); + let mut attrs = parent_attrs.clone(); + attrs.add_attrs(&strct.attrs); + Struct { + name: (&strct.ident).into(), + docs: Docs::from_attrs(&strct.attrs), + lifetimes, + fields, + methods: vec![], + output_only, + attrs, + } + } +} + +#[cfg(test)] +mod tests { + use insta::{self, Settings}; + + use syn; + + use super::Struct; + + #[test] + fn simple_struct() { + let mut settings = Settings::new(); + settings.set_sort_maps(true); + + settings.bind(|| { + insta::assert_yaml_snapshot!(Struct::new( + &syn::parse_quote! { + /// Some docs. + #[diplomat::rust_link(foo::Bar, Struct)] + struct MyLocalStruct { + a: i32, + b: Box + } + }, + true, + &Default::default() + )); + }); + } +} diff --git a/deps/crates/vendor/diplomat_core/src/ast/traits.rs b/deps/crates/vendor/diplomat_core/src/ast/traits.rs new file mode 100644 index 00000000000000..5cbbc802a452f3 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/traits.rs @@ -0,0 +1,148 @@ +use serde::Serialize; + +use super::docs::Docs; +use super::{Attrs, Ident, LifetimeEnv, Param, PathType, TraitSelfParam, TypeName}; + +/// A trait declaration in an FFI module. +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Debug)] +#[non_exhaustive] +pub struct Trait { + pub name: Ident, + pub lifetimes: LifetimeEnv, + pub methods: Vec, + pub docs: Docs, + pub attrs: Attrs, + pub is_sync: bool, + pub is_send: bool, +} + +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Debug)] +#[non_exhaustive] +pub struct TraitMethod { + pub name: Ident, + pub abi_name: Ident, + pub self_param: Option, + // corresponds to the types in Function(Vec>, Box) + // the callback type; except here the params aren't anonymous + pub params: Vec, + pub output_type: Option, + pub lifetimes: LifetimeEnv, + pub attrs: Attrs, + pub docs: Docs, +} + +impl Trait { + /// Extract a [`Trait`] metadata value from an AST node. + pub fn new(trt: &syn::ItemTrait, parent_attrs: &Attrs) -> Self { + let mut attrs = parent_attrs.clone(); + attrs.add_attrs(&trt.attrs); + + let mut trait_fcts = Vec::new(); + + let self_ident = &trt.ident; + // TODO check this + let self_path_trait = PathType::from(&syn::TraitBound { + paren_token: None, + modifier: syn::TraitBoundModifier::None, + lifetimes: None, // todo this is an assumption + path: syn::PathSegment { + ident: self_ident.clone(), + arguments: syn::PathArguments::None, + } + .into(), + }); + for trait_item in trt.items.iter() { + if let syn::TraitItem::Fn(fct) = trait_item { + let mut fct_attrs = attrs.clone(); + fct_attrs.add_attrs(&fct.attrs); + // copied from the method parsing + let fct_ident = &fct.sig.ident; + let concat_fct_ident = format!("{self_ident}_{fct_ident}"); + let extern_ident = syn::Ident::new( + &attrs.abi_rename.apply(concat_fct_ident.into()), + fct.sig.ident.span(), + ); + + let all_params = fct + .sig + .inputs + .iter() + .filter_map(|a| match a { + syn::FnArg::Receiver(_) => None, + syn::FnArg::Typed(ref t) => { + Some(Param::from_syn(t, self_path_trait.clone())) + } + }) + .collect::>(); + + let self_param = fct + .sig + .receiver() + .map(|rec| TraitSelfParam::from_syn(rec, self_path_trait.clone())); + + let output_type = match &fct.sig.output { + syn::ReturnType::Type(_, return_typ) => Some(TypeName::from_syn( + return_typ.as_ref(), + Some(self_path_trait.clone()), + )), + syn::ReturnType::Default => None, + }; + + let lifetimes = LifetimeEnv::from_trait_item( + trait_item, + self_param.as_ref(), + &all_params[..], + output_type.as_ref(), + ); + + trait_fcts.push(TraitMethod { + name: fct_ident.into(), + abi_name: (&extern_ident).into(), + self_param, + params: all_params, + output_type, + lifetimes, + attrs: fct_attrs, + docs: Docs::from_attrs(&fct.attrs), + }); + } + } + let (mut is_sync, mut is_send) = (false, false); + for supertrait in &trt.supertraits { + if let syn::TypeParamBound::Trait(syn::TraitBound { + path: syn::Path { segments, .. }, + .. + }) = supertrait + { + let mut seg_iter = segments.iter(); + if let Some(syn::PathSegment { ident, .. }) = seg_iter.next() { + if *ident != "std" { + continue; + } + } + if let Some(syn::PathSegment { ident, .. }) = seg_iter.next() { + if *ident != "marker" { + continue; + } + } + if let Some(syn::PathSegment { ident, .. }) = seg_iter.next() { + if *ident == "Send" { + is_send = true; + } else if *ident == "Sync" { + is_sync = true; + } + } + } + } + + Self { + name: (&trt.ident).into(), + methods: trait_fcts, + docs: Docs::from_attrs(&trt.attrs), + lifetimes: LifetimeEnv::from_trait(trt), // TODO + attrs, + is_send, + is_sync, + } + } +} diff --git a/deps/crates/vendor/diplomat_core/src/ast/types.rs b/deps/crates/vendor/diplomat_core/src/ast/types.rs new file mode 100644 index 00000000000000..fec14c7fcf7c0e --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/ast/types.rs @@ -0,0 +1,1794 @@ +use proc_macro2::Span; +use quote::{ToTokens, TokenStreamExt}; +use serde::{Deserialize, Serialize}; +use syn::Token; + +use std::fmt; +use std::ops::ControlFlow; +use std::str::FromStr; + +use super::{ + Attrs, Docs, Enum, Ident, Lifetime, LifetimeEnv, LifetimeTransitivity, Method, NamedLifetime, + OpaqueType, Path, RustLink, Struct, Trait, +}; +use crate::{ast::Function, Env}; + +/// A type declared inside a Diplomat-annotated module. +#[derive(Clone, Serialize, Debug, Hash, PartialEq, Eq)] +#[non_exhaustive] +pub enum CustomType { + /// A non-opaque struct whose fields will be visible across the FFI boundary. + Struct(Struct), + /// A type annotated with [`diplomat::opaque`] whose fields are not visible. + Opaque(OpaqueType), + /// A fieldless enum. + Enum(Enum), +} + +impl CustomType { + /// Get the name of the custom type, which is unique within a module. + pub fn name(&self) -> &Ident { + match self { + CustomType::Struct(strct) => &strct.name, + CustomType::Opaque(strct) => &strct.name, + CustomType::Enum(enm) => &enm.name, + } + } + + /// Get the methods declared in impls of the custom type. + pub fn methods(&self) -> &Vec { + match self { + CustomType::Struct(strct) => &strct.methods, + CustomType::Opaque(strct) => &strct.methods, + CustomType::Enum(enm) => &enm.methods, + } + } + + pub fn attrs(&self) -> &Attrs { + match self { + CustomType::Struct(strct) => &strct.attrs, + CustomType::Opaque(strct) => &strct.attrs, + CustomType::Enum(enm) => &enm.attrs, + } + } + + /// Get the doc lines of the custom type. + pub fn docs(&self) -> &Docs { + match self { + CustomType::Struct(strct) => &strct.docs, + CustomType::Opaque(strct) => &strct.docs, + CustomType::Enum(enm) => &enm.docs, + } + } + + /// Get all rust links on this type and its methods + pub fn all_rust_links(&self) -> impl Iterator + '_ { + [self.docs()] + .into_iter() + .chain(self.methods().iter().map(|m| m.docs())) + .flat_map(|d| d.rust_links().iter()) + } + + pub fn self_path(&self, in_path: &Path) -> Path { + in_path.sub_path(self.name().clone()) + } + + /// Get the lifetimes of the custom type. + pub fn lifetimes(&self) -> Option<&LifetimeEnv> { + match self { + CustomType::Struct(strct) => Some(&strct.lifetimes), + CustomType::Opaque(strct) => Some(&strct.lifetimes), + CustomType::Enum(_) => None, + } + } +} + +/// A symbol declared in a module, which can either be a pointer to another path, +/// or a custom type defined directly inside that module +#[derive(Clone, Serialize, Debug)] +#[non_exhaustive] +pub enum ModSymbol { + /// A symbol that is a pointer to another path. + Alias(Path), + /// A symbol that is a submodule. + SubModule(Ident), + /// A symbol that is a custom type. + CustomType(CustomType), + /// A trait + Trait(Trait), + /// A free function not associated with any type. + Function(Function), +} + +/// A named type that is just a path, e.g. `std::borrow::Cow<'a, T>`. +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Debug)] +#[non_exhaustive] +pub struct PathType { + pub path: Path, + pub lifetimes: Vec, +} + +impl PathType { + pub fn to_syn(&self) -> syn::TypePath { + let mut path = self.path.to_syn(); + + if !self.lifetimes.is_empty() { + if let Some(seg) = path.segments.last_mut() { + let lifetimes = &self.lifetimes; + seg.arguments = + syn::PathArguments::AngleBracketed(syn::parse_quote! { <#(#lifetimes),*> }); + } + } + + syn::TypePath { qself: None, path } + } + + pub fn new(path: Path) -> Self { + Self { + path, + lifetimes: vec![], + } + } + + /// Get the `Self` type from a struct declaration. + /// + /// Consider the following struct declaration: + /// ``` + /// struct RefList<'a> { + /// data: &'a i32, + /// next: Option>, + /// } + /// ``` + /// When determining what type `Self` is in the `next` field, we would have to call + /// this method on the `syn::ItemStruct` that represents this struct declaration. + /// This method would then return a `PathType` representing `RefList<'a>`, so we + /// know that's what `Self` should refer to. + /// + /// The reason this function exists though is so when we convert the fields' types + /// to `PathType`s, we don't panic. We don't actually need to write the struct's + /// field types expanded in the macro, so this function is more for correctness, + pub fn extract_self_type(strct: &syn::ItemStruct) -> Self { + let self_name = (&strct.ident).into(); + + PathType { + path: Path { + elements: vec![self_name], + }, + lifetimes: strct + .generics + .lifetimes() + .map(|lt_def| (<_def.lifetime).into()) + .collect(), + } + } + + /// If this is a [`TypeName::Named`], grab the [`CustomType`] it points to from + /// the `env`, which contains all [`CustomType`]s across all FFI modules. + /// + /// Also returns the path the CustomType is in (useful for resolving fields) + pub fn resolve_with_path<'a>(&self, in_path: &Path, env: &'a Env) -> (Path, &'a CustomType) { + let local_path = &self.path; + let mut cur_path = in_path.clone(); + for (i, elem) in local_path.elements.iter().enumerate() { + match elem.as_str() { + "crate" => { + // TODO(#34): get the name of enclosing crate from env when we support multiple crates + cur_path = Path::empty() + } + + "super" => cur_path = cur_path.get_super(), + + o => match env.get(&cur_path, o) { + Some(ModSymbol::Alias(p)) => { + let mut remaining_elements: Vec = + local_path.elements.iter().skip(i + 1).cloned().collect(); + let mut new_path = p.elements.clone(); + new_path.append(&mut remaining_elements); + return PathType::new(Path { elements: new_path }) + .resolve_with_path(&cur_path.clone(), env); + } + Some(ModSymbol::SubModule(name)) => { + cur_path.elements.push(name.clone()); + } + Some(ModSymbol::CustomType(t)) => { + if i == local_path.elements.len() - 1 { + return (cur_path, t); + } else { + panic!( + "Unexpected custom type when resolving symbol {} in {}", + o, + cur_path.elements.join("::") + ) + } + } + Some(ModSymbol::Trait(trt)) => { + panic!("Found trait {} but expected a type", trt.name); + } + Some(ModSymbol::Function(f)) => { + panic!("Found function {} but expected a type", f.name); + } + None => panic!( + "Could not resolve symbol {} in {}", + o, + cur_path.elements.join("::") + ), + }, + } + } + + panic!( + "Path {} does not point to a custom type", + in_path.elements.join("::") + ) + } + + /// If this is a [`TypeName::Named`], grab the [`CustomType`] it points to from + /// the `env`, which contains all [`CustomType`]s across all FFI modules. + /// + /// If you need to resolve struct fields later, call [`Self::resolve_with_path()`] instead + /// to get the path to resolve the fields in. + pub fn resolve<'a>(&self, in_path: &Path, env: &'a Env) -> &'a CustomType { + self.resolve_with_path(in_path, env).1 + } + + pub fn trait_to_syn(&self) -> syn::TraitBound { + let mut path = self.path.to_syn(); + + if !self.lifetimes.is_empty() { + if let Some(seg) = path.segments.last_mut() { + let lifetimes = &self.lifetimes; + seg.arguments = + syn::PathArguments::AngleBracketed(syn::parse_quote! { <#(#lifetimes),*> }); + } + } + syn::TraitBound { + paren_token: None, + modifier: syn::TraitBoundModifier::None, + lifetimes: None, // todo this is an assumption + path, + } + } + + pub fn resolve_trait_with_path<'a>(&self, in_path: &Path, env: &'a Env) -> (Path, Trait) { + let local_path = &self.path; + let cur_path = in_path.clone(); + for (i, elem) in local_path.elements.iter().enumerate() { + if let Some(ModSymbol::Trait(trt)) = env.get(&cur_path, elem.as_str()) { + if i == local_path.elements.len() - 1 { + return (cur_path, trt.clone()); + } else { + panic!( + "Unexpected custom trait when resolving symbol {} in {}", + trt.name, + cur_path.elements.join("::") + ) + } + } + } + + panic!( + "Path {} does not point to a custom trait", + in_path.elements.join("::") + ) + } + + /// If this is a [`TypeName::Named`], grab the [`CustomType`] it points to from + /// the `env`, which contains all [`CustomType`]s across all FFI modules. + /// + /// If you need to resolve struct fields later, call [`Self::resolve_with_path()`] instead + /// to get the path to resolve the fields in. + pub fn resolve_trait<'a>(&self, in_path: &Path, env: &'a Env) -> Trait { + self.resolve_trait_with_path(in_path, env).1 + } +} + +impl From<&syn::TypePath> for PathType { + fn from(other: &syn::TypePath) -> Self { + let lifetimes = other + .path + .segments + .last() + .and_then(|last| { + if let syn::PathArguments::AngleBracketed(angle_generics) = &last.arguments { + Some( + angle_generics + .args + .iter() + .map(|generic_arg| match generic_arg { + syn::GenericArgument::Lifetime(lifetime) => lifetime.into(), + _ => panic!("generic type arguments are unsupported (type: {other:?}, arg: {generic_arg:?})"), + }) + .collect(), + ) + } else { + None + } + }) + .unwrap_or_default(); + + Self { + path: Path::from_syn(&other.path), + lifetimes, + } + } +} + +impl From<&syn::TraitBound> for PathType { + fn from(other: &syn::TraitBound) -> Self { + let lifetimes = other + .path + .segments + .last() + .and_then(|last| { + if let syn::PathArguments::AngleBracketed(angle_generics) = &last.arguments { + Some( + angle_generics + .args + .iter() + .map(|generic_arg| match generic_arg { + syn::GenericArgument::Lifetime(lifetime) => lifetime.into(), + _ => panic!("generic type arguments are unsupported {other:?}"), + }) + .collect(), + ) + } else { + None + } + }) + .unwrap_or_default(); + + Self { + path: Path::from_syn(&other.path), + lifetimes, + } + } +} + +impl From<&syn::Signature> for PathType { + fn from(other: &syn::Signature) -> Self { + let lifetimes = other + .generics + .params + .iter() + .map(|generic_arg| match generic_arg { + syn::GenericParam::Lifetime(lt) => (<.lifetime).into(), + _ => panic!("generic type arguments are unsupported {other:?}"), + }) + .collect(); + + Self { + path: Path::empty().sub_path((&other.ident).into()), + lifetimes, + } + } +} + +impl From for PathType { + fn from(other: Path) -> Self { + PathType::new(other) + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Debug)] +#[allow(clippy::exhaustive_enums)] // there are only two kinds of mutability we care about +pub enum Mutability { + Mutable, + Immutable, +} + +impl Mutability { + pub fn to_syn(&self) -> Option { + match self { + Mutability::Mutable => Some(syn::token::Mut(Span::call_site())), + Mutability::Immutable => None, + } + } + + pub fn from_syn(t: &Option) -> Self { + match t { + Some(_) => Mutability::Mutable, + None => Mutability::Immutable, + } + } + + /// Returns `true` if `&self` is the mutable variant, otherwise `false`. + pub fn is_mutable(&self) -> bool { + matches!(self, Mutability::Mutable) + } + + /// Returns `true` if `&self` is the immutable variant, otherwise `false`. + pub fn is_immutable(&self) -> bool { + matches!(self, Mutability::Immutable) + } + + /// Shorthand ternary operator for choosing a value based on whether + /// a `Mutability` is mutable or immutable. + /// + /// The following pattern (with very slight variations) shows up often in code gen: + /// ```ignore + /// if mutability.is_mutable() { + /// "" + /// } else { + /// "const " + /// } + /// ``` + /// This is particularly annoying in `write!(...)` statements, where `cargo fmt` + /// expands it to take up 5 lines. + /// + /// This method offers a 1-line alternative: + /// ```ignore + /// mutability.if_mut_else("", "const ") + /// ``` + /// For cases where lazy evaluation is desired, consider using a conditional + /// or a `match` statement. + pub fn if_mut_else(&self, if_mut: T, if_immut: T) -> T { + match self { + Mutability::Mutable => if_mut, + Mutability::Immutable => if_immut, + } + } +} + +/// For types like `Result`/`DiplomatResult`, `&[T]`/`DiplomatSlice` which can be +/// specified using (non-ffi-safe) Rust stdlib types, or FFI-safe `repr(C)` types from +/// `diplomat_runtime`, this tracks which of the two were used. +#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Debug)] +#[allow(clippy::exhaustive_enums)] // This can only have two values +pub enum StdlibOrDiplomat { + Stdlib, + Diplomat, +} + +/// A local type reference, such as the type of a field, parameter, or return value. +/// Unlike [`CustomType`], which represents a type declaration, [`TypeName`]s can compose +/// types through references and boxing, and can also capture unresolved paths. +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Debug)] +#[non_exhaustive] +pub enum TypeName { + /// A built-in Rust scalar primitive. + Primitive(PrimitiveType), + /// An unresolved path to a custom type, which can be resolved after all types + /// are collected with [`TypeName::resolve()`]. + Named(PathType), + /// An optionally mutable reference to another type. + Reference(Lifetime, Mutability, Box), + /// A `Box` type. + Box(Box), + /// An `Option` or DiplomatOption type. + Option(Box, StdlibOrDiplomat), + /// A `Result` or `diplomat_runtime::DiplomatResult` type. + Result(Box, Box, StdlibOrDiplomat), + Write, + /// A `&DiplomatStr` or `Box` type. + /// Owned strings don't have a lifetime. + /// + /// If StdlibOrDiplomat::Stdlib, it's specified using Rust pointer types (&T, Box), + /// if StdlibOrDiplomat::Diplomat, it's specified using DiplomatStrSlice, etc + StrReference(Option, StringEncoding, StdlibOrDiplomat), + /// A `&[T]` or `Box<[T]>` type, where `T` is a primitive. + /// Owned slices don't have a lifetime or mutability. + /// + /// If StdlibOrDiplomat::Stdlib, it's specified using Rust pointer types (&T, Box), + /// if StdlibOrDiplomat::Diplomat, it's specified using DiplomatSlice/DiplomatOwnedSlice/DiplomatSliceMut + PrimitiveSlice( + Option<(Lifetime, Mutability)>, + PrimitiveType, + StdlibOrDiplomat, + ), + /// `&[DiplomatStrSlice]`, etc. Equivalent to `&[&str]` + /// + /// If StdlibOrDiplomat::Stdlib, it's specified as `&[&DiplomatFoo]`, if StdlibOrDiplomat::Diplomat it's specified + /// as `DiplomatSlice<&DiplomatFoo>` + StrSlice(StringEncoding, StdlibOrDiplomat), + /// `&[Struct]`. Meant for passing slices of structs where the struct's layout is known to be shared between Rust + /// and the backend language. Primarily meant for large lists of compound types like `Vector3f64` or `Color4i16`. + /// This is implemented on a per-backend basis. + CustomTypeSlice(Option<(Lifetime, Mutability)>, Box), + /// The `()` type. + Unit, + /// The `Self` type. + SelfType(PathType), + /// std::cmp::Ordering or core::cmp::Ordering + /// + /// The path must be present! Ordering will be parsed as an AST type! + Ordering, + Function(Vec>, Box, Mutability), + ImplTrait(PathType), +} + +#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Debug, Copy)] +#[non_exhaustive] +pub enum StringEncoding { + UnvalidatedUtf8, + UnvalidatedUtf16, + /// The caller guarantees that they're passing valid UTF-8, under penalty of UB + Utf8, +} + +impl StringEncoding { + /// Get the diplomat slice type when specified using diplomat_runtime types + pub fn get_diplomat_slice_type(self, lt: &Option) -> syn::Type { + if let Some(ref lt) = *lt { + let lt = LifetimeGenericsListDisplay(lt); + + match self { + Self::UnvalidatedUtf8 => { + syn::parse_quote_spanned!(Span::call_site() => diplomat_runtime::DiplomatStrSlice #lt) + } + Self::UnvalidatedUtf16 => { + syn::parse_quote_spanned!(Span::call_site() => diplomat_runtime::DiplomatStr16Slice #lt) + } + Self::Utf8 => { + syn::parse_quote_spanned!(Span::call_site() => diplomat_runtime::DiplomatUtf8StrSlice #lt) + } + } + } else { + match self { + Self::UnvalidatedUtf8 => { + syn::parse_quote_spanned!(Span::call_site() => diplomat_runtime::DiplomatOwnedStrSlice) + } + Self::UnvalidatedUtf16 => { + syn::parse_quote_spanned!(Span::call_site() => diplomat_runtime::DiplomatOwnedStr16Slice) + } + Self::Utf8 => { + syn::parse_quote_spanned!(Span::call_site() => diplomat_runtime::DiplomatOwnedUTF8StrSlice) + } + } + } + } + + fn get_diplomat_slice_type_str(self) -> &'static str { + match self { + StringEncoding::Utf8 => "str", + StringEncoding::UnvalidatedUtf8 => "DiplomatStr", + StringEncoding::UnvalidatedUtf16 => "DiplomatStr16", + } + } + /// Get slice type when specified using rust stdlib types + pub fn get_stdlib_slice_type(self, lt: &Option) -> syn::Type { + let inner = match self { + Self::UnvalidatedUtf8 => quote::quote!(DiplomatStr), + Self::UnvalidatedUtf16 => quote::quote!(DiplomatStr16), + Self::Utf8 => quote::quote!(str), + }; + if let Some(ref lt) = *lt { + let lt = ReferenceDisplay(lt, &Mutability::Immutable); + + syn::parse_quote_spanned!(Span::call_site() => #lt #inner) + } else { + syn::parse_quote_spanned!(Span::call_site() => Box<#inner>) + } + } + pub fn get_stdlib_slice_type_str(self) -> &'static str { + match self { + StringEncoding::Utf8 => "DiplomatUtf8Str", + StringEncoding::UnvalidatedUtf8 => "DiplomatStrSlice", + StringEncoding::UnvalidatedUtf16 => "DiplomatStr16Slice", + } + } +} + +fn get_lifetime_from_syn_path(p: &syn::TypePath) -> Lifetime { + if let syn::PathArguments::AngleBracketed(ref generics) = + p.path.segments[p.path.segments.len() - 1].arguments + { + if let Some(syn::GenericArgument::Lifetime(lt)) = generics.args.first() { + return Lifetime::from(lt); + } + } + Lifetime::Anonymous +} + +fn get_ty_from_syn_path(p: &syn::TypePath) -> Option<&syn::Type> { + if let syn::PathArguments::AngleBracketed(ref generics) = + p.path.segments[p.path.segments.len() - 1].arguments + { + for gen in generics.args.iter() { + if let syn::GenericArgument::Type(ref ty) = gen { + return Some(ty); + } + } + } + None +} + +impl TypeName { + /// Is this type safe to be passed across the FFI boundary? + /// + /// This also marks DiplomatOption<&T> as FFI-unsafe: these are technically safe from an ABI standpoint + /// however Diplomat always expects these to be equivalent to a nullable pointer, so Option<&T> is required. + pub fn is_ffi_safe(&self) -> bool { + match self { + TypeName::Primitive(..) | TypeName::Named(_) | TypeName::SelfType(_) | TypeName::Reference(..) | + TypeName::Box(..) | + // can only be passed across the FFI boundary; callbacks and traits are input-only + TypeName::Function(..) | TypeName::ImplTrait(..) | + // These are specified using FFI-safe diplomat_runtime types + TypeName::StrReference(.., StdlibOrDiplomat::Diplomat) | TypeName::StrSlice(.., StdlibOrDiplomat::Diplomat) |TypeName::PrimitiveSlice(.., StdlibOrDiplomat::Diplomat) | TypeName::CustomTypeSlice(..) => true, + // These are special anyway and shouldn't show up in structs + TypeName::Unit | TypeName::Write | TypeName::Result(..) | + // This is basically only useful in return types + TypeName::Ordering | + // These are specified using Rust stdlib types and not safe across FFI + TypeName::StrReference(.., StdlibOrDiplomat::Stdlib) | TypeName::StrSlice(.., StdlibOrDiplomat::Stdlib) | TypeName::PrimitiveSlice(.., StdlibOrDiplomat::Stdlib) => false, + TypeName::Option(inner, stdlib) => match **inner { + // Option<&T>/Option> are the ffi-safe way to specify options + TypeName::Reference(..) | TypeName::Box(..) => *stdlib == StdlibOrDiplomat::Stdlib, + // For other types (primitives, structs, enums) we need DiplomatOption + _ => *stdlib == StdlibOrDiplomat::Diplomat, + } + } + } + + /// What's the FFI safe version of this type? + /// + /// This also marks DiplomatOption<&T> as FFI-unsafe: these are technically safe from an ABI standpoint + /// however Diplomat always expects these to be equivalent to a nullable pointer, so Option<&T> is required. + pub fn ffi_safe_version(&self) -> TypeName { + match self { + TypeName::StrReference(lt, encoding, StdlibOrDiplomat::Stdlib) => { + TypeName::StrReference(lt.clone(), *encoding, StdlibOrDiplomat::Diplomat) + } + TypeName::StrSlice(encoding, StdlibOrDiplomat::Stdlib) => { + TypeName::StrSlice(*encoding, StdlibOrDiplomat::Diplomat) + } + TypeName::PrimitiveSlice(ltmt, prim, StdlibOrDiplomat::Stdlib) => { + TypeName::PrimitiveSlice(ltmt.clone(), *prim, StdlibOrDiplomat::Diplomat) + } + TypeName::Ordering => TypeName::Primitive(PrimitiveType::i8), + TypeName::Option(inner, _stdlib) => match **inner { + // Option<&T>/Option> are the ffi-safe way to specify options + TypeName::Reference(..) | TypeName::Box(..) => { + TypeName::Option(inner.clone(), StdlibOrDiplomat::Stdlib) + } + // For other types (primitives, structs, enums) we need DiplomatOption + _ => TypeName::Option( + Box::new(inner.ffi_safe_version()), + StdlibOrDiplomat::Diplomat, + ), + }, + TypeName::Result(ok, err, StdlibOrDiplomat::Stdlib) => { + TypeName::Result(ok.clone(), err.clone(), StdlibOrDiplomat::Diplomat) + } + _ => self.clone(), + } + } + /// Converts the [`TypeName`] back into an AST node that can be spliced into a program. + pub fn to_syn(&self) -> syn::Type { + match self { + TypeName::Primitive(primitive) => { + let primitive = primitive.to_ident(); + syn::parse_quote_spanned!(Span::call_site() => #primitive) + } + TypeName::Ordering => syn::parse_quote_spanned!(Span::call_site() => i8), + TypeName::Named(name) | TypeName::SelfType(name) => { + // Self also gets expanded instead of turning into `Self` because + // this code is used to generate the `extern "C"` functions, which + // aren't in an impl block. + let name = name.to_syn(); + syn::parse_quote_spanned!(Span::call_site() => #name) + } + TypeName::Reference(lifetime, mutability, underlying) => { + let reference = ReferenceDisplay(lifetime, mutability); + let underlying = underlying.to_syn(); + + syn::parse_quote_spanned!(Span::call_site() => #reference #underlying) + } + TypeName::Box(underlying) => { + let underlying = underlying.to_syn(); + syn::parse_quote_spanned!(Span::call_site() => Box<#underlying>) + } + TypeName::Option(underlying, StdlibOrDiplomat::Stdlib) => { + let underlying = underlying.to_syn(); + syn::parse_quote_spanned!(Span::call_site() => Option<#underlying>) + } + TypeName::Option(underlying, StdlibOrDiplomat::Diplomat) => { + let underlying = underlying.to_syn(); + syn::parse_quote_spanned!(Span::call_site() => diplomat_runtime::DiplomatOption<#underlying>) + } + TypeName::Result(ok, err, StdlibOrDiplomat::Stdlib) => { + let ok = ok.to_syn(); + let err = err.to_syn(); + syn::parse_quote_spanned!(Span::call_site() => Result<#ok, #err>) + } + TypeName::Result(ok, err, StdlibOrDiplomat::Diplomat) => { + let ok = ok.to_syn(); + let err = err.to_syn(); + syn::parse_quote_spanned!(Span::call_site() => diplomat_runtime::DiplomatResult<#ok, #err>) + } + TypeName::Write => { + syn::parse_quote_spanned!(Span::call_site() => diplomat_runtime::DiplomatWrite) + } + TypeName::StrReference(lt, encoding, is_stdlib_type) => { + if *is_stdlib_type == StdlibOrDiplomat::Stdlib { + encoding.get_stdlib_slice_type(lt) + } else { + encoding.get_diplomat_slice_type(lt) + } + } + TypeName::StrSlice(encoding, is_stdlib_type) => { + if *is_stdlib_type == StdlibOrDiplomat::Stdlib { + let inner = encoding.get_stdlib_slice_type(&Some(Lifetime::Anonymous)); + syn::parse_quote_spanned!(Span::call_site() => &[#inner]) + } else { + let inner = encoding.get_diplomat_slice_type(&Some(Lifetime::Anonymous)); + syn::parse_quote_spanned!(Span::call_site() => diplomat_runtime::DiplomatSlice<#inner>) + } + } + TypeName::PrimitiveSlice(ltmt, primitive, is_stdlib_type) => { + if *is_stdlib_type == StdlibOrDiplomat::Stdlib { + primitive.get_stdlib_slice_type(ltmt) + } else { + primitive.get_diplomat_slice_type(ltmt) + } + } + TypeName::CustomTypeSlice(ltmt, type_name) => { + let inner = type_name.to_syn(); + if let Some((ref lt, ref mtbl)) = ltmt { + let reference = ReferenceDisplay(lt, mtbl); + syn::parse_quote_spanned!(Span::call_site() => #reference [#inner]) + } else { + syn::parse_quote_spanned! (Span::call_site() => &[#inner]) + } + } + + TypeName::Unit => syn::parse_quote_spanned!(Span::call_site() => ()), + TypeName::Function(_input_types, output_type, _mutability) => { + // Convert the return type to something FFI-friendly: + let output_type = output_type.ffi_safe_version().to_syn(); + // should be DiplomatCallback + syn::parse_quote_spanned!(Span::call_site() => DiplomatCallback<#output_type>) + } + TypeName::ImplTrait(trt_path) => { + let trait_name = + Ident::from(format!("DiplomatTraitStruct_{}", trt_path.path.elements[0])); + // should be DiplomatTraitStruct_trait_name + syn::parse_quote_spanned!(Span::call_site() => #trait_name) + } + } + } + + /// Extract a [`TypeName`] from a [`syn::Type`] AST node. + /// The following rules are used to infer [`TypeName`] variants: + /// - If the type is a path with a single element that is the name of a Rust primitive, returns a [`TypeName::Primitive`] + /// - If the type is a path with a single element [`Box`], returns a [`TypeName::Box`] with the type parameter recursively converted + /// - If the type is a path with a single element [`Option`], returns a [`TypeName::Option`] with the type parameter recursively converted + /// - If the type is a path with a single element `Self` and `self_path_type` is provided, returns a [`TypeName::Named`] + /// - If the type is a path with a single element [`Result`], returns a [`TypeName::Result`] with the type parameters recursively converted + /// - If the type is a path equal to [`diplomat_runtime::DiplomatResult`], returns a [`TypeName::DiplomatResult`] with the type parameters recursively converted + /// - If the type is a path equal to [`diplomat_runtime::DiplomatWrite`], returns a [`TypeName::Write`] + /// - If the type is a owned or borrowed string type, returns a [`TypeName::StrReference`] + /// - If the type is a owned or borrowed slice of a Rust primitive, returns a [`TypeName::PrimitiveSlice`] + /// - If the type is a reference (`&` or `&mut`), returns a [`TypeName::Reference`] with the referenced type recursively converted + /// - Otherwise, assume that the reference is to a [`CustomType`] in either the current module or another one, returns a [`TypeName::Named`] + pub fn from_syn(ty: &syn::Type, self_path_type: Option) -> TypeName { + match ty { + syn::Type::Reference(r) => { + let lifetime = Lifetime::from(&r.lifetime); + let mutability = Mutability::from_syn(&r.mutability); + + let name = r.elem.to_token_stream().to_string(); + if name.starts_with("DiplomatStr") || name == "str" { + if mutability.is_mutable() { + panic!("mutable string references are disallowed"); + } + if name == "DiplomatStr" { + return TypeName::StrReference( + Some(lifetime), + StringEncoding::UnvalidatedUtf8, + StdlibOrDiplomat::Stdlib, + ); + } else if name == "DiplomatStr16" { + return TypeName::StrReference( + Some(lifetime), + StringEncoding::UnvalidatedUtf16, + StdlibOrDiplomat::Stdlib, + ); + } else if name == "str" { + return TypeName::StrReference( + Some(lifetime), + StringEncoding::Utf8, + StdlibOrDiplomat::Stdlib, + ); + } + } + if let syn::Type::Slice(slice) = &*r.elem { + if let syn::Type::Path(p) = &*slice.elem { + if let Some(primitive) = p + .path + .get_ident() + .and_then(|i| PrimitiveType::from_str(i.to_string().as_str()).ok()) + { + return TypeName::PrimitiveSlice( + Some((lifetime, mutability)), + primitive, + StdlibOrDiplomat::Stdlib, + ); + } + } + if let TypeName::StrReference( + Some(Lifetime::Anonymous), + encoding, + is_stdlib_type, + ) = TypeName::from_syn(&slice.elem, self_path_type.clone()) + { + if is_stdlib_type == StdlibOrDiplomat::Stdlib { + panic!("Slice-of-slice is only supported with DiplomatRuntime slice types (DiplomatStrSlice, DiplomatStr16Slice, DiplomatUtf8StrSlice)"); + } + return TypeName::StrSlice(encoding, StdlibOrDiplomat::Stdlib); + } + return TypeName::CustomTypeSlice( + Some((lifetime, mutability)), + Box::new(TypeName::from_syn(slice.elem.as_ref(), self_path_type)), + ); + } + TypeName::Reference( + lifetime, + mutability, + Box::new(TypeName::from_syn(r.elem.as_ref(), self_path_type)), + ) + } + syn::Type::Path(p) => { + let p_len = p.path.segments.len(); + if let Some(primitive) = p + .path + .get_ident() + .and_then(|i| PrimitiveType::from_str(i.to_string().as_str()).ok()) + { + TypeName::Primitive(primitive) + } else if p_len >= 2 + && p.path.segments[p_len - 2].ident == "cmp" + && p.path.segments[p_len - 1].ident == "Ordering" + { + TypeName::Ordering + } else if p_len == 1 && p.path.segments[0].ident == "Box" { + if let syn::PathArguments::AngleBracketed(type_args) = + &p.path.segments[0].arguments + { + if let syn::GenericArgument::Type(syn::Type::Slice(slice)) = + &type_args.args[0] + { + if let TypeName::Primitive(p) = + TypeName::from_syn(&slice.elem, self_path_type) + { + TypeName::PrimitiveSlice(None, p, StdlibOrDiplomat::Stdlib) + } else { + panic!("Owned slices only support primitives.") + } + } else if let syn::GenericArgument::Type(tpe) = &type_args.args[0] { + if tpe.to_token_stream().to_string() == "DiplomatStr" { + TypeName::StrReference( + None, + StringEncoding::UnvalidatedUtf8, + StdlibOrDiplomat::Stdlib, + ) + } else if tpe.to_token_stream().to_string() == "DiplomatStr16" { + TypeName::StrReference( + None, + StringEncoding::UnvalidatedUtf16, + StdlibOrDiplomat::Stdlib, + ) + } else if tpe.to_token_stream().to_string() == "str" { + TypeName::StrReference( + None, + StringEncoding::Utf8, + StdlibOrDiplomat::Stdlib, + ) + } else { + TypeName::Box(Box::new(TypeName::from_syn(tpe, self_path_type))) + } + } else { + panic!("Expected first type argument for Box to be a type") + } + } else { + panic!("Expected angle brackets for Box type") + } + } else if p_len == 1 && p.path.segments[0].ident == "Option" + || is_runtime_type(p, "DiplomatOption") + { + if let syn::PathArguments::AngleBracketed(type_args) = + &p.path.segments[0].arguments + { + if let syn::GenericArgument::Type(tpe) = &type_args.args[0] { + let stdlib = if p.path.segments[0].ident == "Option" { + StdlibOrDiplomat::Stdlib + } else { + StdlibOrDiplomat::Diplomat + }; + TypeName::Option( + Box::new(TypeName::from_syn(tpe, self_path_type)), + stdlib, + ) + } else { + panic!("Expected first type argument for Option to be a type") + } + } else { + panic!("Expected angle brackets for Option type") + } + } else if p_len == 1 && p.path.segments[0].ident == "Self" { + if let Some(self_path_type) = self_path_type { + TypeName::SelfType(self_path_type) + } else { + panic!("Cannot have `Self` type outside of a method"); + } + } else if is_runtime_type(p, "DiplomatOwnedStrSlice") + || is_runtime_type(p, "DiplomatOwnedStr16Slice") + || is_runtime_type(p, "DiplomatOwnedUTF8StrSlice") + { + let encoding = if is_runtime_type(p, "DiplomatOwnedStrSlice") { + StringEncoding::UnvalidatedUtf8 + } else if is_runtime_type(p, "DiplomatOwnedStr16Slice") { + StringEncoding::UnvalidatedUtf16 + } else { + StringEncoding::Utf8 + }; + + TypeName::StrReference(None, encoding, StdlibOrDiplomat::Diplomat) + } else if is_runtime_type(p, "DiplomatStrSlice") + || is_runtime_type(p, "DiplomatStr16Slice") + || is_runtime_type(p, "DiplomatUtf8StrSlice") + { + let lt = get_lifetime_from_syn_path(p); + + let encoding = if is_runtime_type(p, "DiplomatStrSlice") { + StringEncoding::UnvalidatedUtf8 + } else if is_runtime_type(p, "DiplomatStr16Slice") { + StringEncoding::UnvalidatedUtf16 + } else { + StringEncoding::Utf8 + }; + + TypeName::StrReference(Some(lt), encoding, StdlibOrDiplomat::Diplomat) + } else if is_runtime_type(p, "DiplomatSlice") + || is_runtime_type(p, "DiplomatSliceMut") + || is_runtime_type(p, "DiplomatOwnedSlice") + { + let ltmut = if is_runtime_type(p, "DiplomatOwnedSlice") { + None + } else { + let lt = get_lifetime_from_syn_path(p); + let mutability = if is_runtime_type(p, "DiplomatSlice") { + Mutability::Immutable + } else { + Mutability::Mutable + }; + Some((lt, mutability)) + }; + + let ty = get_ty_from_syn_path(p).expect("Expected type argument to DiplomatSlice/DiplomatSliceMut/DiplomatOwnedSlice"); + + if let syn::Type::Path(p) = &ty { + if let Some(ident) = p.path.get_ident() { + let ident = ident.to_string(); + let i = ident.as_str(); + match i { + "DiplomatStrSlice" => { + return TypeName::StrSlice( + StringEncoding::UnvalidatedUtf8, + StdlibOrDiplomat::Diplomat, + ) + } + "DiplomatStr16Slice" => { + return TypeName::StrSlice( + StringEncoding::UnvalidatedUtf16, + StdlibOrDiplomat::Diplomat, + ) + } + "DiplomatUtf8StrSlice" => { + return TypeName::StrSlice( + StringEncoding::Utf8, + StdlibOrDiplomat::Diplomat, + ) + } + _ => { + if let Ok(prim) = PrimitiveType::from_str(i) { + return TypeName::PrimitiveSlice( + ltmut, + prim, + StdlibOrDiplomat::Diplomat, + ); + } + } + } + } + } + panic!("Found DiplomatSlice/DiplomatSliceMut/DiplomatOwnedSlice without primitive or DiplomatStrSlice-like generic"); + } else if p_len == 1 && p.path.segments[0].ident == "Result" + || is_runtime_type(p, "DiplomatResult") + { + if let syn::PathArguments::AngleBracketed(type_args) = + &p.path.segments.last().unwrap().arguments + { + assert!( + type_args.args.len() > 1, + "Not enough arguments given to Result. Are you using a non-std Result type?" + ); + + if let (syn::GenericArgument::Type(ok), syn::GenericArgument::Type(err)) = + (&type_args.args[0], &type_args.args[1]) + { + let ok = TypeName::from_syn(ok, self_path_type.clone()); + let err = TypeName::from_syn(err, self_path_type); + TypeName::Result( + Box::new(ok), + Box::new(err), + if is_runtime_type(p, "DiplomatResult") { + StdlibOrDiplomat::Diplomat + } else { + StdlibOrDiplomat::Stdlib + }, + ) + } else { + panic!("Expected both type arguments for Result to be a type") + } + } else { + panic!("Expected angle brackets for Result type") + } + } else if is_runtime_type(p, "DiplomatWrite") { + TypeName::Write + } else { + TypeName::Named(PathType::from(p)) + } + } + syn::Type::Tuple(tup) => { + if tup.elems.is_empty() { + TypeName::Unit + } else { + todo!("Tuples are not currently supported") + } + } + syn::Type::ImplTrait(tr) => { + let mut ret_type: Option = None; + for trait_bound in &tr.bounds { + match trait_bound { + syn::TypeParamBound::Trait(syn::TraitBound { path: p, .. }) => { + if ret_type.is_some() { + todo!("Currently don't support implementing multiple traits"); + } + let rel_segs = &p.segments; + let path_seg = &rel_segs[0]; + + // From the FFI side there's no real way to enforce the distinction between these two, + // but we can at least make the void* on the C-API side const or not. + let fn_mutability = match path_seg.ident.to_string().as_str() { + "Fn" => Some(Mutability::Immutable), + "FnMut" => Some(Mutability::Mutable), + _ => None, + }; + + if let Some(mutability) = fn_mutability { + // we're in a function type + // get input and output args + if let syn::PathArguments::Parenthesized( + syn::ParenthesizedGenericArguments { + inputs: input_types, + output: output_type, + .. + }, + ) = &path_seg.arguments + { + // Validate none of the callback lifetimes are named - we only allow default behavior or 'static + for input_type in input_types { + if let syn::Type::Reference(syn::TypeReference { + lifetime: Some(in_lifetime), + .. + }) = input_type + { + panic!("Lifetimes are not allowed on callback parameters: lifetime '{} on trait {} ", in_lifetime.ident, path_seg.ident); + } + } + + let in_types = input_types + .iter() + .map(|in_ty| { + Box::new(TypeName::from_syn( + in_ty, + self_path_type.clone(), + )) + }) + .collect::>>(); + + let out_type = match output_type { + syn::ReturnType::Type(_, output_type) => { + TypeName::from_syn(output_type, self_path_type.clone()) + } + syn::ReturnType::Default => TypeName::Unit, + }; + + // Validate lifetimes + + ret_type = Some(TypeName::Function( + in_types, + Box::new(out_type), + mutability, + )); + continue; + } + panic!("Unsupported function type: {:?}", &path_seg.arguments); + } else { + ret_type = + Some(TypeName::ImplTrait(PathType::from(&syn::TraitBound { + paren_token: None, + modifier: syn::TraitBoundModifier::None, + lifetimes: None, // todo this is an assumption + path: p.clone(), + }))); + continue; + } + } + syn::TypeParamBound::Lifetime(syn::Lifetime { ident, .. }) => { + assert_eq!( + ident, "static", + "only 'static lifetimes are supported on trait objects for now" + ); + } + _ => { + panic!("Unsupported trait component: {trait_bound:?}"); + } + } + } + ret_type.expect("No valid traits found") + } + other => panic!("Unsupported type: {}", other.to_token_stream()), + } + } + + /// Returns `true` if `self` is the `TypeName::SelfType` variant, otherwise + /// `false`. + pub fn is_self(&self) -> bool { + matches!(self, TypeName::SelfType(_)) + } + + /// Recurse down the type tree, visiting all lifetimes. + /// + /// Using this function, you can collect all the lifetimes into a collection, + /// or examine each one without having to make any additional allocations. + pub fn visit_lifetimes<'a, F, B>(&'a self, visit: &mut F) -> ControlFlow + where + F: FnMut(&'a Lifetime, LifetimeOrigin) -> ControlFlow, + { + match self { + TypeName::Named(path_type) | TypeName::SelfType(path_type) => path_type + .lifetimes + .iter() + .try_for_each(|lt| visit(lt, LifetimeOrigin::Named)), + TypeName::Reference(lt, _, ty) => { + ty.visit_lifetimes(visit)?; + visit(lt, LifetimeOrigin::Reference) + } + TypeName::Box(ty) | TypeName::Option(ty, _) => ty.visit_lifetimes(visit), + TypeName::Result(ok, err, _) => { + ok.visit_lifetimes(visit)?; + err.visit_lifetimes(visit) + } + TypeName::StrReference(Some(lt), ..) => visit(lt, LifetimeOrigin::StrReference), + TypeName::PrimitiveSlice(Some((lt, _)), ..) => { + visit(lt, LifetimeOrigin::PrimitiveSlice) + } + _ => ControlFlow::Continue(()), + } + } + + /// Returns `true` if any lifetime satisfies a predicate, otherwise `false`. + /// + /// This method is short-circuiting, meaning that if the predicate ever succeeds, + /// it will return immediately. + pub fn any_lifetime<'a, F>(&'a self, mut f: F) -> bool + where + F: FnMut(&'a Lifetime, LifetimeOrigin) -> bool, + { + self.visit_lifetimes(&mut |lifetime, origin| { + if f(lifetime, origin) { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + }) + .is_break() + } + + /// Returns `true` if all lifetimes satisfy a predicate, otherwise `false`. + /// + /// This method is short-circuiting, meaning that if the predicate ever fails, + /// it will return immediately. + pub fn all_lifetimes<'a, F>(&'a self, mut f: F) -> bool + where + F: FnMut(&'a Lifetime, LifetimeOrigin) -> bool, + { + self.visit_lifetimes(&mut |lifetime, origin| { + if f(lifetime, origin) { + ControlFlow::Continue(()) + } else { + ControlFlow::Break(()) + } + }) + .is_continue() + } + + /// Returns all lifetimes in a [`LifetimeEnv`] that must live at least as + /// long as the type. + pub fn longer_lifetimes<'env>( + &self, + lifetime_env: &'env LifetimeEnv, + ) -> Vec<&'env NamedLifetime> { + self.transitive_lifetime_bounds(LifetimeTransitivity::longer(lifetime_env)) + } + + /// Returns all lifetimes in a [`LifetimeEnv`] that are outlived by the type. + pub fn shorter_lifetimes<'env>( + &self, + lifetime_env: &'env LifetimeEnv, + ) -> Vec<&'env NamedLifetime> { + self.transitive_lifetime_bounds(LifetimeTransitivity::shorter(lifetime_env)) + } + + /// Visits the provided [`LifetimeTransitivity`] value with all `NamedLifetime`s + /// in the type tree, and returns the transitively reachable lifetimes. + fn transitive_lifetime_bounds<'env>( + &self, + mut transitivity: LifetimeTransitivity<'env>, + ) -> Vec<&'env NamedLifetime> { + // We don't use the control flow here + let _ = self.visit_lifetimes(&mut |lifetime, _| -> ControlFlow<()> { + if let Lifetime::Named(named) = lifetime { + transitivity.visit(named); + } + ControlFlow::Continue(()) + }); + transitivity.finish() + } + + pub fn is_zst(&self) -> bool { + // check_zst() prevents non-unit types from being ZSTs + matches!(*self, TypeName::Unit) + } + + pub fn is_pointer(&self) -> bool { + matches!(*self, TypeName::Reference(..) | TypeName::Box(_)) + } +} + +#[non_exhaustive] +pub enum LifetimeOrigin { + Named, + Reference, + StrReference, + PrimitiveSlice, +} + +fn is_runtime_type(p: &syn::TypePath, name: &str) -> bool { + (p.path.segments.len() == 1 && p.path.segments[0].ident == name) + || (p.path.segments.len() == 2 + && p.path.segments[0].ident == "diplomat_runtime" + && p.path.segments[1].ident == name) +} + +impl fmt::Display for TypeName { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + TypeName::Primitive(p) => p.fmt(f), + TypeName::Ordering => write!(f, "Ordering"), + TypeName::Named(p) | TypeName::SelfType(p) => p.fmt(f), + TypeName::Reference(lifetime, mutability, typ) => { + write!(f, "{}{typ}", ReferenceDisplay(lifetime, mutability)) + } + TypeName::Box(typ) => write!(f, "Box<{typ}>"), + TypeName::Option(typ, StdlibOrDiplomat::Stdlib) => write!(f, "Option<{typ}>"), + TypeName::Option(typ, StdlibOrDiplomat::Diplomat) => write!(f, "DiplomatOption<{typ}>"), + TypeName::Result(ok, err, _) => { + write!(f, "Result<{ok}, {err}>") + } + TypeName::Write => "DiplomatWrite".fmt(f), + TypeName::StrReference(lt, encoding, is_stdlib_type) => { + if let Some(lt) = lt { + if *is_stdlib_type == StdlibOrDiplomat::Stdlib { + let lt = ReferenceDisplay(lt, &Mutability::Immutable); + let ty = encoding.get_diplomat_slice_type_str(); + write!(f, "{lt}{ty}") + } else { + let ty = encoding.get_stdlib_slice_type_str(); + let lt = LifetimeGenericsListDisplay(lt); + write!(f, "{ty}{lt}") + } + } else { + match (encoding, is_stdlib_type) { + (_, StdlibOrDiplomat::Stdlib) => { + write!(f, "Box<{}>", encoding.get_diplomat_slice_type_str()) + } + (StringEncoding::Utf8, StdlibOrDiplomat::Diplomat) => { + "DiplomatOwnedUtf8Str".fmt(f) + } + (StringEncoding::UnvalidatedUtf8, StdlibOrDiplomat::Diplomat) => { + "DiplomatOwnedStrSlice".fmt(f) + } + (StringEncoding::UnvalidatedUtf16, StdlibOrDiplomat::Diplomat) => { + "DiplomatOwnedStr16Slice".fmt(f) + } + } + } + } + + TypeName::StrSlice(encoding, StdlibOrDiplomat::Stdlib) => { + let inner = encoding.get_stdlib_slice_type_str(); + + write!(f, "&[&{inner}]") + } + TypeName::StrSlice(encoding, StdlibOrDiplomat::Diplomat) => { + let inner = encoding.get_diplomat_slice_type_str(); + write!(f, "DiplomatSlice<{inner}>") + } + + TypeName::PrimitiveSlice( + Some((lifetime, mutability)), + typ, + StdlibOrDiplomat::Stdlib, + ) => { + write!(f, "{}[{typ}]", ReferenceDisplay(lifetime, mutability)) + } + TypeName::PrimitiveSlice( + Some((lifetime, mutability)), + typ, + StdlibOrDiplomat::Diplomat, + ) => { + let maybemut = if *mutability == Mutability::Immutable { + "" + } else { + "Mut" + }; + let lt = LifetimeGenericsListPartialDisplay(lifetime); + write!(f, "DiplomatSlice{maybemut}<{lt}{typ}>") + } + TypeName::PrimitiveSlice(None, typ, _) => write!(f, "Box<[{typ}]>"), + TypeName::CustomTypeSlice(Some((lifetime, mutability)), type_name) => { + write!(f, "{}[{type_name}]", ReferenceDisplay(lifetime, mutability)) + } + TypeName::CustomTypeSlice(None, type_name) => write!(f, "Box<[{type_name}]>"), + TypeName::Unit => "()".fmt(f), + TypeName::Function(input_types, out_type, _mutability) => { + write!(f, "fn (")?; + for in_typ in input_types.iter() { + write!(f, "{in_typ}")?; + } + write!(f, ")->{out_type}") + } + TypeName::ImplTrait(trt) => { + write!(f, "impl ")?; + trt.fmt(f) + } + } + } +} + +/// An [`fmt::Display`] type for formatting Rust references. +/// +/// # Examples +/// +/// ```ignore +/// let lifetime = Lifetime::from(&syn::parse_str::("'a")); +/// let mutability = Mutability::Mutable; +/// // ... +/// let fmt = format!("{}[u8]", ReferenceDisplay(&lifetime, &mutability)); +/// +/// assert_eq!(fmt, "&'a mut [u8]"); +/// ``` +struct ReferenceDisplay<'a>(&'a Lifetime, &'a Mutability); + +impl<'a> fmt::Display for ReferenceDisplay<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + Lifetime::Static => "&'static ".fmt(f)?, + Lifetime::Named(lifetime) => write!(f, "&{lifetime} ")?, + Lifetime::Anonymous => '&'.fmt(f)?, + } + + if self.1.is_mutable() { + "mut ".fmt(f)?; + } + + Ok(()) + } +} + +impl<'a> quote::ToTokens for ReferenceDisplay<'a> { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let lifetime = self.0.to_syn(); + let mutability = self.1.to_syn(); + + tokens.append_all(quote::quote!(& #lifetime #mutability)) + } +} + +/// An [`fmt::Display`] type for formatting Rust lifetimes as they show up in generics list, when +/// the generics list has no other elements +struct LifetimeGenericsListDisplay<'a>(&'a Lifetime); + +impl<'a> fmt::Display for LifetimeGenericsListDisplay<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + Lifetime::Static => "<'static>".fmt(f), + Lifetime::Named(lifetime) => write!(f, "<{lifetime}>"), + Lifetime::Anonymous => Ok(()), + } + } +} + +impl<'a> quote::ToTokens for LifetimeGenericsListDisplay<'a> { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + if let Lifetime::Anonymous = self.0 { + } else { + let lifetime = self.0.to_syn(); + tokens.append_all(quote::quote!(<#lifetime>)) + } + } +} + +/// An [`fmt::Display`] type for formatting Rust lifetimes as they show up in generics list, when +/// the generics list has another element +struct LifetimeGenericsListPartialDisplay<'a>(&'a Lifetime); + +impl<'a> fmt::Display for LifetimeGenericsListPartialDisplay<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + Lifetime::Static => "'static,".fmt(f), + Lifetime::Named(lifetime) => write!(f, "{lifetime},"), + Lifetime::Anonymous => Ok(()), + } + } +} + +impl<'a> quote::ToTokens for LifetimeGenericsListPartialDisplay<'a> { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + if let Lifetime::Anonymous = self.0 { + } else { + let lifetime = self.0.to_syn(); + tokens.append_all(quote::quote!(#lifetime,)) + } + } +} + +impl fmt::Display for PathType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.path.fmt(f)?; + + if let Some((first, rest)) = self.lifetimes.split_first() { + write!(f, "<{first}")?; + for lifetime in rest { + write!(f, ", {lifetime}")?; + } + '>'.fmt(f)?; + } + Ok(()) + } +} + +/// A built-in Rust primitive scalar type. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Debug)] +#[allow(non_camel_case_types)] +#[allow(clippy::exhaustive_enums)] // there are only these (scalar types) +pub enum PrimitiveType { + i8, + u8, + i16, + u16, + i32, + u32, + i64, + u64, + i128, + u128, + isize, + usize, + f32, + f64, + bool, + char, + /// a primitive byte that is not meant to be interpreted numerically + /// in languages that don't have fine-grained integer types + byte, +} + +impl PrimitiveType { + fn as_code_str(self) -> &'static str { + match self { + PrimitiveType::i8 => "i8", + PrimitiveType::u8 => "u8", + PrimitiveType::i16 => "i16", + PrimitiveType::u16 => "u16", + PrimitiveType::i32 => "i32", + PrimitiveType::u32 => "u32", + PrimitiveType::i64 => "i64", + PrimitiveType::u64 => "u64", + PrimitiveType::i128 => "i128", + PrimitiveType::u128 => "u128", + PrimitiveType::isize => "isize", + PrimitiveType::usize => "usize", + PrimitiveType::f32 => "f32", + PrimitiveType::f64 => "f64", + PrimitiveType::bool => "bool", + PrimitiveType::char => "DiplomatChar", + PrimitiveType::byte => "DiplomatByte", + } + } + + fn to_ident(self) -> proc_macro2::Ident { + proc_macro2::Ident::new(self.as_code_str(), Span::call_site()) + } + + /// Get the type for a slice of this, as specified using Rust stdlib types + pub fn get_stdlib_slice_type(self, lt: &Option<(Lifetime, Mutability)>) -> syn::Type { + let primitive = self.to_ident(); + + if let Some((ref lt, ref mtbl)) = lt { + let reference = ReferenceDisplay(lt, mtbl); + syn::parse_quote_spanned!(Span::call_site() => #reference [#primitive]) + } else { + syn::parse_quote_spanned!(Span::call_site() => Box<[#primitive]>) + } + } + + /// Get the type for a slice of this, as specified using Diplomat runtime types + pub fn get_diplomat_slice_type(self, lt: &Option<(Lifetime, Mutability)>) -> syn::Type { + let primitive = self.to_ident(); + + if let Some((lt, mtbl)) = lt { + let lifetime = LifetimeGenericsListPartialDisplay(lt); + + if *mtbl == Mutability::Immutable { + syn::parse_quote_spanned!(Span::call_site() => diplomat_runtime::DiplomatSlice<#lifetime #primitive>) + } else { + syn::parse_quote_spanned!(Span::call_site() => diplomat_runtime::DiplomatSliceMut<#lifetime #primitive>) + } + } else { + syn::parse_quote_spanned!(Span::call_site() => diplomat_runtime::DiplomatOwnedSlice<#primitive>) + } + } +} + +impl fmt::Display for PrimitiveType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + PrimitiveType::byte => "u8", + PrimitiveType::char => "char", + _ => self.as_code_str(), + } + .fmt(f) + } +} + +impl FromStr for PrimitiveType { + type Err = (); + fn from_str(s: &str) -> Result { + Ok(match s { + "i8" => PrimitiveType::i8, + "u8" => PrimitiveType::u8, + "i16" => PrimitiveType::i16, + "u16" => PrimitiveType::u16, + "i32" => PrimitiveType::i32, + "u32" => PrimitiveType::u32, + "i64" => PrimitiveType::i64, + "u64" => PrimitiveType::u64, + "i128" => PrimitiveType::i128, + "u128" => PrimitiveType::u128, + "isize" => PrimitiveType::isize, + "usize" => PrimitiveType::usize, + "f32" => PrimitiveType::f32, + "f64" => PrimitiveType::f64, + "bool" => PrimitiveType::bool, + "DiplomatChar" => PrimitiveType::char, + "DiplomatByte" => PrimitiveType::byte, + _ => return Err(()), + }) + } +} + +#[cfg(test)] +mod tests { + use insta; + + use syn; + + use super::TypeName; + + #[test] + fn typename_primitives() { + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + i32 + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + usize + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + bool + }, + None + )); + } + + #[test] + fn typename_named() { + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + MyLocalStruct + }, + None + )); + } + + #[test] + fn typename_references() { + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + &i32 + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + &mut MyLocalStruct + }, + None + )); + } + + #[test] + fn typename_boxes() { + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + Box + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + Box + }, + None + )); + } + + #[test] + fn typename_option() { + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + Option + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + Option + }, + None + )); + } + + #[test] + fn typename_result() { + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + DiplomatResult + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + DiplomatResult<(), MyLocalStruct> + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + Result + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + Result<(), MyLocalStruct> + }, + None + )); + } + + #[test] + fn lifetimes() { + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + Foo<'a, 'b> + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + ::core::my_type::Foo + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + ::core::my_type::Foo<'test> + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + Option> + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + Foo<'a, 'b, 'c, 'd> + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + very::long::path::to::my::Type<'x, 'y, 'z> + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + Result, ErrRef<'c>> + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + DiplomatSlice<'a, u16> + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + DiplomatOwnedSlice + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + DiplomatSliceStr<'a> + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + DiplomatSliceMut<'a, f32> + }, + None + )); + + insta::assert_yaml_snapshot!(TypeName::from_syn( + &syn::parse_quote! { + DiplomatSlice + }, + None + )); + } +} diff --git a/deps/crates/vendor/diplomat_core/src/environment.rs b/deps/crates/vendor/diplomat_core/src/environment.rs new file mode 100644 index 00000000000000..67b0f96b5dbcc2 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/environment.rs @@ -0,0 +1,96 @@ +use crate::ast::*; +use std::collections::BTreeMap; +use std::ops::Index; + +/// The type resolution environment +/// +/// Also contains the entire module structure +#[derive(Default, Clone)] +pub struct Env { + pub(crate) env: BTreeMap, +} + +/// The type resolution environment within a specific module +#[derive(Clone)] +pub struct ModuleEnv { + pub(crate) module: BTreeMap, + #[cfg_attr(not(feature = "hir"), allow(unused))] + pub(crate) attrs: Attrs, +} + +impl Env { + pub(crate) fn insert(&mut self, path: Path, module: ModuleEnv) { + self.env.insert(path, module); + } + + /// Given a path to a module and a name, get the item, if any + pub fn get(&self, path: &Path, name: &str) -> Option<&ModSymbol> { + self.env.get(path).and_then(|m| m.module.get(name)) + } + + /// Iterate over all items in the environment + /// + /// This will occur in a stable lexically sorted order by path and then name + pub fn iter_items(&self) -> impl Iterator + '_ { + self.env + .iter() + .flat_map(|(k, v)| v.module.iter().map(move |v2| (k, v2.0, v2.1))) + } + + /// Iterate over all modules + /// + /// This will occur in a stable lexically sorted order by path + pub fn iter_modules(&self) -> impl Iterator + '_ { + self.env.iter() + } +} + +impl ModuleEnv { + pub(crate) fn new(attrs: Attrs) -> Self { + Self { + module: Default::default(), + attrs, + } + } + pub(crate) fn insert(&mut self, name: Ident, symbol: ModSymbol) -> Option { + self.module.insert(name, symbol) + } + + /// Given an item name, fetch it + pub fn get(&self, name: &str) -> Option<&ModSymbol> { + self.module.get(name) + } + + /// Iterate over all name-item pairs in this module + pub fn iter(&self) -> impl Iterator + '_ { + self.module.iter() + } + + /// Iterate over all names in this module + /// + /// This will occur in a stable lexically sorted order by name + pub fn names(&self) -> impl Iterator + '_ { + self.module.keys() + } + + /// Iterate over all items in this module + /// + /// This will occur in a stable lexically sorted order by name + pub fn items(&self) -> impl Iterator + '_ { + self.module.values() + } +} + +impl Index<&Path> for Env { + type Output = ModuleEnv; + fn index(&self, i: &Path) -> &ModuleEnv { + &self.env[i] + } +} + +impl Index<&str> for ModuleEnv { + type Output = ModSymbol; + fn index(&self, i: &str) -> &ModSymbol { + &self.module[i] + } +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/attrs.rs b/deps/crates/vendor/diplomat_core/src/hir/attrs.rs new file mode 100644 index 00000000000000..31421da626887e --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/attrs.rs @@ -0,0 +1,1650 @@ +//! #[diplomat::attr] and other attributes + +use crate::ast; +use crate::ast::attrs::{AttrInheritContext, DiplomatBackendAttrCfg, StandardAttribute}; +use crate::hir::lowering::ErrorStore; +use crate::hir::{ + EnumVariant, LoweringError, Method, Mutability, OpaqueId, ReturnType, SelfType, SuccessType, + TraitDef, Type, TypeDef, TypeId, +}; +use syn::Meta; + +pub use crate::ast::attrs::RenameAttr; + +/// Diplomat attribute that can be specified on items, methods, and enum variants. These +/// can be used to control the codegen in a particular backend. +/// +/// Most of these are specified via `#[diplomat::attr(some cfg here, attrname)]`, where `some cfg here` +/// can be used to pick which backends something applies to. +#[non_exhaustive] +#[derive(Clone, Default, Debug)] +pub struct Attrs { + /// "disable" this item: do not generate code for it in the backend + /// + /// This attribute is always inherited except to variants + pub disable: bool, + /// Mark this item deprecated in FFI. + pub deprecated: Option, + /// An optional namespace. None is equivalent to the root namespace. + /// + /// This attribute is inherited to types (and is not allowed elsewhere) + pub namespace: Option, + /// Rename this item/method/variant + /// + /// This attribute is inherited except through methods and variants (and is not allowed on variants) + pub rename: RenameAttr, + /// Rename this item in the C ABI. This *must* be respected by backends. + /// + /// This attribute is inherited except through variants + pub abi_rename: RenameAttr, + /// This method is "special": it should generate something other than a regular method on the other side. + /// This can be something like a constructor, an accessor, a stringifier etc. + /// + /// This attribute does not participate in inheritance and must always + /// be specified on individual methods + pub special_method: Option, + /// This user-defined type can be used as the error type in a Result. + pub custom_errors: bool, + + /// This user-defined type has a "default" state that can be computed purely foreign-language-side + /// + /// Can be applied to enum variants to signal the default + pub default: bool, + + /// From #[diplomat::demo()]. Created from [`crate::ast::attrs::Attrs::demo_attrs`]. + /// List of attributes specific to automatic demo generation. + /// Currently just for demo_gen in diplomat-tool (which generates sample webpages), but could be used for broader purposes (i.e., demo Android apps) + pub demo_attrs: DemoInfo, + /// From #[diplomat::attr()]. If true, generates a mocking interface for this type. + pub generate_mocking_interface: bool, + /// From #[diplomat::attr()]. If true, Diplomat will check that this struct has the same memory layout in backends which support it. Allows this struct to be used in slices ([`super::Slice::Struct`]) and to be borrowed in function parameters. + pub abi_compatible: bool, +} + +// #region: Demo specific attributes. + +/// For `#[diplomat::demo(input(...))]`, stored in [DemoInfo::input_cfg]. +#[non_exhaustive] +#[derive(Clone, Default, Debug)] +pub struct DemoInputCFG { + /// `#[diplomat::demo(input(label = "..."))]` + /// Label that this input parameter should have. Let demo_gen pick a valid name if this is empty. + /// + /// For instance + pub label: String, + + /// `#[diplomat::demo(input(default_value = "..."))]` + /// Sets the default value for a parameter. + /// + /// Should ALWAYS be a string. The HTML renderer is expected to do validation for us. + pub default_value: String, +} + +#[non_exhaustive] +#[derive(Clone, Default, Debug)] +pub struct DemoInfo { + /// `#[diplomat::demo(generate)]`. If automatic generation is disabled by default (see [`diplomat_tool::demo_gen::DemoConfig`]), then the below render terminus will be allowed to generate. + pub generate: bool, + + /// `#[diplomat::demo(default_constructor)]` + /// We search for any methods specially tagged with `Constructor`, but if there's are no default Constructors and there's NamedConstructor that you want to be default instead, use this. + /// TODO: Should probably ignore other `Constructors` if a default has been set. + pub default_constructor: bool, + + /// `#[diplomat::demo(external)]` represents an item that we will not evaluate, and should be passed to the rendering engine to provide. + pub external: bool, + + /// `#[diplomat::demo(custom_func = "/file/name/here.mjs")]` can be used above any `struct` definition in the bridge. The linked `.mjs` should contain a JS definition of functions that should be bundled with demo_gen's output. + /// + /// We call these functions "custom functions", as they are JS functions that are not automagically generated by demo_gen, but rather included as part of its JS output in the `RenderInfo` object. + /// + /// For more information on custom functions (and their use), see the relevant chapter in [the book](https://rust-diplomat.github.io/diplomat/demo_gen/custom_functions.html). + /// + /// Files are located relative to lib.rs. + /// + pub custom_func: Option, + + /// `#[diplomat::demo(input(...))]` represents configuration options for anywhere we might expect user input. + pub input_cfg: DemoInputCFG, +} + +// #endregion + +/// Attributes that mark methods as "special" +#[non_exhaustive] +#[derive(Clone, Debug)] +pub enum SpecialMethod { + /// A constructor. + /// + /// Must return Self (or Result for backends with `fallible_constructors` enabled ) + Constructor, + /// A named constructor, with optional name. If the name isn't specified, it will be derived + /// from the method name + /// + /// Must return Self (or Result for backends with `fallible_constructors` enabled ) + NamedConstructor(Option), + + /// A getter, with optional name. If the name isn't specified, it will be derived + /// from the method name + /// + /// Must have no parameters and must return something. + Getter(Option), + /// A setter, with optional name. If the name isn't specified, it will be derived + /// from the method name + /// + /// Must have no return type (aside from potentially a `Result<(), _>`) and must have one parameter + Setter(Option), + /// A stringifier. Must have no parameters and return a string (DiplomatWrite) + Stringifier, + /// A comparison operator. Currently not universally supported + Comparison, + /// An iterator (a type that is mutated to produce new values) + Iterator, + /// An iterable (a type that can produce an iterator) + Iterable, + /// Indexes into the type using an integer + Indexer, + + /// Arithmetic operators. May not return references + Add, + Sub, + Mul, + Div, + + /// In-place arithmetic operators. Must not return a value + AddAssign, + SubAssign, + MulAssign, + DivAssign, +} + +impl SpecialMethod { + pub fn from_path_and_meta(path: &str, meta: &Meta) -> Result, LoweringError> { + let parse_meta = |meta| match StandardAttribute::from_meta(meta) { + Ok(StandardAttribute::String(s)) => Ok(Some(s)), + Ok(StandardAttribute::Empty) => Ok(None), + Ok(_) | Err(_) => Err(LoweringError::Other(format!( + "`{path}` must have a single string parameter or no parameter" + ))), + }; + + match path { + "constructor" => Ok(Some(Self::Constructor)), + "named_constructor" => Ok(Some(Self::NamedConstructor(parse_meta(meta)?))), + "getter" => Ok(Some(Self::Getter(parse_meta(meta)?))), + "setter" => Ok(Some(Self::Setter(parse_meta(meta)?))), + "stringifier" => Ok(Some(Self::Stringifier)), + "comparison" => Ok(Some(Self::Comparison)), + "iterator" => Ok(Some(Self::Iterator)), + "iterable" => Ok(Some(Self::Iterable)), + "indexer" => Ok(Some(Self::Indexer)), + "add" => Ok(Some(Self::Add)), + "sub" => Ok(Some(Self::Sub)), + "mul" => Ok(Some(Self::Mul)), + "div" => Ok(Some(Self::Div)), + "add_assign" => Ok(Some(Self::AddAssign)), + "sub_assign" => Ok(Some(Self::SubAssign)), + "mul_assign" => Ok(Some(Self::MulAssign)), + "div_assign" => Ok(Some(Self::DivAssign)), + _ => Ok(None), + } + } + // Returns the standard operator string (if any) associated with this special method + pub fn operator_str(&self) -> Option<&str> { + match self { + SpecialMethod::Add => Some("+"), + SpecialMethod::Sub => Some("-"), + SpecialMethod::Mul => Some("*"), + SpecialMethod::Div => Some("/"), + SpecialMethod::AddAssign => Some("+="), + SpecialMethod::SubAssign => Some("-="), + SpecialMethod::MulAssign => Some("*="), + SpecialMethod::DivAssign => Some("/="), + SpecialMethod::Indexer => Some("[]"), + _ => None, + } + } +} + +/// For special methods that affect type semantics, whether this type has this method. +/// +/// This will likely only contain a subset of special methods, but feel free to add more as needed. +#[derive(Debug, Default)] +#[non_exhaustive] +pub struct SpecialMethodPresence { + pub comparator: bool, + /// If it is an iterator, the type it iterates over + pub iterator: Option, + /// If it is an iterable, the iterator type it returns (*not* the type it iterates over, + /// perform lookup on that type to access) + pub iterable: Option, +} + +/// Where the attribute was found. Some attributes are only allowed in some contexts +/// (e.g. namespaces cannot be specified on methods) +#[non_exhaustive] // might add module attrs in the future +#[derive(Debug)] +pub enum AttributeContext<'a, 'b> { + Type(TypeDef<'a>), + Trait(&'a TraitDef), + EnumVariant(&'a EnumVariant), + Method(&'a Method, TypeId, &'b mut SpecialMethodPresence), + Function(&'a Method), + Module, + Param, + SelfParam, + Field, +} + +fn maybe_error_unsupported( + auto_found: bool, + attribute: &str, + backend: &str, + errors: &mut ErrorStore, +) { + if !auto_found { + errors.push(LoweringError::Other(format!( + "`{attribute}` not supported in backend {backend}" + ))); + } +} +impl Attrs { + pub fn from_ast( + ast: &ast::Attrs, + validator: &(impl AttributeValidator + ?Sized), + parent_attrs: &Attrs, + errors: &mut ErrorStore, + ) -> Self { + let mut this = parent_attrs.clone(); + // Backends must support this since it applies to the macro/C code. + // No special inheritance, was already appropriately inherited in AST + this.abi_rename = ast.abi_rename.clone(); + + this.deprecated = ast.deprecated.clone(); + + let support = validator.attrs_supported(); + let backend = validator.primary_name(); + for attr in &ast.attrs { + let mut auto_found = false; + match validator.satisfies_cfg(&attr.cfg, Some(&mut auto_found)) { + Ok(satisfies) if !satisfies => continue, + Err(e) => { + errors.push(e); + continue; + } + Ok(_) => {} + }; + + let path = attr.meta.path(); + if let Some(path) = path.get_ident() { + let path = path.to_string(); + + let warn_auto = |errors: &mut ErrorStore| { + if auto_found { + errors.push(LoweringError::Other(format!( + "Diplomat attribute {path:?} gated on 'auto' but is not one that works with 'auto'" + ))); + } + }; + + // Check against the set of attributes that can have platform support + if support.check_string(&path) == Some(false) { + maybe_error_unsupported(auto_found, &path, backend, errors); + continue; + } + + match SpecialMethod::from_path_and_meta(&path, &attr.meta) { + Ok(Some(kind)) => { + if let Some(ref existing) = this.special_method { + errors.push(LoweringError::Other(format!( + "Multiple special method markers found on the same method, found {path} and {existing:?}" + ))); + } else { + this.special_method = Some(kind); + } + } + Err(error) => errors.push(error), + Ok(None) => match path.as_str() { + // No match found in the special methods, check the other keywords + "disable" => { + if let Meta::Path(_) = attr.meta { + if this.disable { + errors.push(LoweringError::Other( + "Duplicate `disable` attribute".into(), + )); + } else { + this.disable = true; + } + } else { + errors.push(LoweringError::Other( + "`disable` must be a simple path".into(), + )) + } + warn_auto(errors); + } + "default" => { + if let Meta::Path(_) = attr.meta { + if this.default { + errors.push(LoweringError::Other( + "Duplicate `default` attribute".into(), + )); + } else { + this.default = true; + } + } else { + errors.push(LoweringError::Other( + "`default` must be a simple path".into(), + )) + } + } + "rename" => { + match RenameAttr::from_meta(&attr.meta) { + Ok(rename) => { + // We use the override extend mode: a single ast::Attrs + // will have had these attributes inherited into the list by appending + // to the end; so a later attribute in the list is more pertinent. + this.rename.extend(&rename); + } + Err(e) => errors.push(LoweringError::Other(format!( + "`rename` attr failed to parse: {e:?}" + ))), + } + warn_auto(errors); + } + "namespace" => match StandardAttribute::from_meta(&attr.meta) { + Ok(StandardAttribute::String(s)) if s.is_empty() => { + this.namespace = None + } + Ok(StandardAttribute::String(s)) => this.namespace = Some(s), + Ok(_) | Err(_) => { + errors.push(LoweringError::Other( + "`namespace` must have a single string parameter".to_string(), + )); + } + }, + "error" => { + this.custom_errors = true; + } + "generate_mocking_interface" => { + if !support.generate_mocking_interface { + maybe_error_unsupported( + auto_found, + "generate_mocking_interface", + backend, + errors, + ); + continue; + } + this.generate_mocking_interface = true; + } + "abi_compatible" => { + if !support.abi_compatibles { + maybe_error_unsupported( + auto_found, + "abi_compatible", + backend, + errors, + ); + continue; + } + this.abi_compatible = true; + } + _ => { + errors.push(LoweringError::Other(format!( + "Unknown diplomat attribute {path}: expected one of: `disable, rename, namespace, constructor, stringifier, comparison, named_constructor, getter, setter, indexer, error`" + ))); + } + }, + } + } + } + + for attr in &ast.demo_attrs { + let path = attr.meta.path(); + if let Some(path_ident) = path.get_ident() { + if path_ident == "external" { + this.demo_attrs.external = true; + } else if path_ident == "default_constructor" { + this.demo_attrs.default_constructor = true; + } else if path_ident == "generate" { + this.demo_attrs.generate = true; + } else if path_ident == "input" { + let meta_list = attr + .meta + .require_list() + .expect("Could not get MetaList, expected #[diplomat::demo(input(...))]"); + + meta_list + .parse_nested_meta(|meta| { + if meta.path.is_ident("label") { + let value = meta.value()?; + let s: syn::LitStr = value.parse()?; + this.demo_attrs.input_cfg.label = s.value(); + Ok(()) + } else if meta.path.is_ident("default_value") { + let value = meta.value()?; + + let str_val: String; + + let ahead = value.lookahead1(); + if ahead.peek(syn::LitFloat) { + let s: syn::LitFloat = value.parse()?; + str_val = s.base10_parse::()?.to_string(); + } else if ahead.peek(syn::LitInt) { + let s: syn::LitInt = value.parse()?; + str_val = s.base10_parse::()?.to_string(); + } else { + let s: syn::LitStr = value.parse()?; + str_val = s.value(); + } + this.demo_attrs.input_cfg.default_value = str_val; + Ok(()) + } else { + Err(meta.error(format!( + "Unsupported ident {:?}", + meta.path.get_ident() + ))) + } + }) + .expect("Could not read input(...)"); + } else if path_ident == "custom_func" { + let v = &attr.meta.require_name_value().unwrap().value; + + if let syn::Expr::Lit(s) = v { + if let syn::Lit::Str(string) = &s.lit { + this.demo_attrs.custom_func = Some(string.value()); + } else { + errors.push(LoweringError::Other(format!( + "#[diplomat::demo(custom_func={s:?}) must be a literal string." + ))); + } + } else { + errors.push(LoweringError::Other(format!( + "#[diplomat::demo(custom_func={v:?}) must be a literal string." + ))); + } + } else { + errors.push(LoweringError::Other(format!( + "Unknown demo_attr: {path_ident:?}" + ))); + } + } else { + errors.push(LoweringError::Other(format!("Unknown demo_attr: {path:?}"))); + } + } + + this + } + + /// Validate that this attribute is allowed in this context + pub(crate) fn validate( + &self, + validator: &(impl AttributeValidator + ?Sized), + mut context: AttributeContext, + errors: &mut ErrorStore, + ) { + // use an exhaustive destructure so new attributes are handled + let Attrs { + disable, + deprecated: _deprecated, + namespace, + rename, + abi_rename, + special_method, + custom_errors, + default, + demo_attrs: _, + generate_mocking_interface, + abi_compatible, + } = &self; + + if *disable && matches!(context, AttributeContext::EnumVariant(..)) { + errors.push(LoweringError::Other( + "`disable` cannot be used on enum variants".into(), + )) + } + + if let Some(ref special) = special_method { + if let AttributeContext::Method(method, self_id, ref mut special_method_presence) = + context + { + let check_param_count = |name: &str, count: usize, errors: &mut ErrorStore| { + if method.params.len() != count { + errors.push(LoweringError::Other(format!( + "{name} must have exactly {count} parameter{}", + if count == 1 { "" } else { "s" } + ))) + } + }; + let check_self_param = |name: &str, need_self: bool, errors: &mut ErrorStore| { + if method.param_self.is_some() != need_self { + errors.push(LoweringError::Other(format!( + "{name} must{} accept a self parameter", + if need_self { "" } else { " not" } + ))); + } + }; + match special { + SpecialMethod::Constructor | SpecialMethod::NamedConstructor(..) => { + check_self_param("Constructors", false, errors); + let output = method.output.success_type(); + match method.output { + ReturnType::Infallible(_) => (), + ReturnType::Fallible(..) => { + // Only report an error if constructors *are* supported but failable constructors *arent* + if validator.attrs_supported().constructors + && !validator.attrs_supported().fallible_constructors + { + errors.push(LoweringError::Other( + "This backend doesn't support fallible constructors" + .to_string(), + )) + } + } + ReturnType::Nullable(..) => { + errors.push(LoweringError::Other("Diplomat doesn't support turning nullable methods into constructors".to_string())); + } + } + + if let SuccessType::OutType(t) = &output { + if t.id() != Some(self_id) { + errors.push(LoweringError::Other( + "Constructors must return Self!".to_string(), + )); + } + } else { + errors.push(LoweringError::Other( + "Constructors must return Self!".to_string(), + )); + } + } + SpecialMethod::Getter(_) => { + if !method.params.is_empty() { + errors + .push(LoweringError::Other("Getter cannot have parameters".into())); + } + if method.param_self.is_none() + && !validator.attrs_supported().static_accessors + { + errors.push(LoweringError::Other(format!("No self parameter on Getter {} but static_acessors are not supported",method.name.as_str()))); + } + + // Currently does not forbid nullable getters, could if desired + } + + SpecialMethod::Setter(_) => { + if !matches!(method.output.success_type(), SuccessType::Unit) { + errors.push(LoweringError::Other("Setters must return unit".into())); + } + if method.param_self.is_none() + && !validator.attrs_supported().static_accessors + { + errors.push(LoweringError::Other(format!("No self parameter on Setter {} but static_acessors are not supported",method.name.as_str()))); + } + check_param_count("Setter", 1, errors); + // Currently does not forbid fallible setters, could if desired + } + SpecialMethod::Stringifier => { + if !method.params.is_empty() { + errors + .push(LoweringError::Other("Getter cannot have parameters".into())); + } + if !matches!(method.output.success_type(), SuccessType::Write) { + errors.push(LoweringError::Other( + "Stringifier must return string".into(), + )); + } + } + SpecialMethod::Comparison => { + check_param_count("Comparator", 1, errors); + if special_method_presence.comparator { + errors.push(LoweringError::Other( + "Cannot define two comparators on the same type".into(), + )); + } + special_method_presence.comparator = true; + // In the long run we can actually support heterogeneous comparators. Not a priority right now. + const COMPARATOR_ERROR: &str = + "Comparator's parameter must be identical to self"; + check_self_param("Comparators", true, errors); + + if let Some(ref selfty) = method.param_self { + if let Some(param) = method.params.first() { + match (&selfty.ty, ¶m.ty) { + (SelfType::Opaque(p), Type::Opaque(p2)) => { + if p.tcx_id != p2.tcx_id { + errors.push(LoweringError::Other( + COMPARATOR_ERROR.into(), + )); + } + + if p.owner.mutability != Mutability::Immutable + || p2.owner.mutability != Mutability::Immutable + { + errors.push(LoweringError::Other( + "comparators must accept immutable parameters" + .into(), + )); + } + + if p2.optional.0 { + errors.push(LoweringError::Other( + "comparators must accept non-optional parameters" + .into(), + )); + } + } + (SelfType::Struct(p), Type::Struct(p2)) => { + if p.tcx_id != p2.tcx_id { + errors.push(LoweringError::Other( + COMPARATOR_ERROR.into(), + )); + } + + if p.owner + .as_borrowed() + .map(|o| !o.mutability.is_immutable()) + .unwrap_or(false) + || p2 + .owner + .as_borrowed() + .map(|o| !o.mutability.is_immutable()) + .unwrap_or(false) + { + errors.push(LoweringError::Other( + "comparators must accept immutable parameters" + .into(), + )); + } + } + (SelfType::Enum(p), Type::Enum(p2)) => { + if p.tcx_id != p2.tcx_id { + errors.push(LoweringError::Other( + COMPARATOR_ERROR.into(), + )); + } + } + _ => { + errors.push(LoweringError::Other(COMPARATOR_ERROR.into())); + } + } + } + } + } + SpecialMethod::Iterator => { + if special_method_presence.iterator.is_some() { + errors.push(LoweringError::Other( + "Cannot mark type as iterator twice".into(), + )); + } + check_param_count("Iterator", 0, errors); + // In theory we could support struct and enum iterators. The benefit is slight: + // it generates probably inefficient code whilst being rather weird when it comes to the + // "structs and enums convert across the boundary" norm for backends. + // + // Essentially, the `&mut self` behavior won't work right. + // + // Furthermore, in some backends (like Dart) defining an iterator may requiring adding fields, + // which may not be possible for enums, and would still be an odd-one-out field for structs.g s + check_self_param("Iterator", true, errors); + if let Some(this) = &method.param_self { + if !matches!(this.ty, SelfType::Opaque(..)) { + errors.push(LoweringError::Other( + "Iterators only allowed on opaques".into(), + )) + } + } + + if let ReturnType::Nullable(ref o) = method.output { + if let SuccessType::Unit = o { + errors.push(LoweringError::Other( + "Iterator method must return something".into(), + )); + } + special_method_presence.iterator = Some(o.clone()); + } else if let ReturnType::Infallible(SuccessType::OutType( + crate::hir::OutType::Opaque( + ref o @ crate::hir::OpaquePath { + optional: crate::hir::Optional(true), + .. + }, + ), + )) = method.output + { + let mut o = o.clone(); + o.optional = crate::hir::Optional(false); + + special_method_presence.iterator = + Some(SuccessType::OutType(crate::hir::OutType::Opaque(o))); + } else { + errors.push(LoweringError::Other( + "Iterator method must return nullable value".into(), + )); + } + } + SpecialMethod::Iterable => { + if special_method_presence.iterable.is_some() { + errors.push(LoweringError::Other( + "Cannot mark type as iterable twice".into(), + )); + } + check_param_count("Iterator", 0, errors); + check_self_param("Iterables", true, errors); + + match method.output.success_type() { + SuccessType::OutType(ty) => { + if let Some(TypeId::Opaque(id)) = ty.id() { + special_method_presence.iterable = Some(id); + } else { + errors.push(LoweringError::Other( + "Iterables must return a custom opaque type".into(), + )) + } + } + _ => errors.push(LoweringError::Other( + "Iterables must return a custom type".into(), + )), + } + } + SpecialMethod::Indexer => { + check_param_count("Indexer", 1, errors); + check_self_param("Indexer", true, errors); + + if method.output.success_type().is_unit() { + errors.push(LoweringError::Other("Indexer must return a value".into())); + } + } + e @ (SpecialMethod::Add + | SpecialMethod::Sub + | SpecialMethod::Mul + | SpecialMethod::Div) => { + let name = match e { + SpecialMethod::Add => "Add", + SpecialMethod::Sub => "Sub", + SpecialMethod::Mul => "Mul", + SpecialMethod::Div => "Div", + _ => unreachable!(), + }; + + check_param_count(name, 1, errors); + check_self_param(name, true, errors); + + if method.output.success_type().is_unit() { + errors + .push(LoweringError::Other(format!("{name} must return a value"))); + } + } + e @ (SpecialMethod::AddAssign + | SpecialMethod::SubAssign + | SpecialMethod::MulAssign + | SpecialMethod::DivAssign) => { + let name = match e { + SpecialMethod::AddAssign => "AddAssign", + SpecialMethod::SubAssign => "SubAssign", + SpecialMethod::MulAssign => "MulAssign", + SpecialMethod::DivAssign => "DivAssign", + _ => unreachable!(), + }; + check_param_count(name, 1, errors); + check_self_param(name, true, errors); + if let Some(self_param) = &method.param_self { + if matches!(self_param.ty, SelfType::Struct(_) | SelfType::Enum(_)) { + errors.push(LoweringError::Other("*Assign arithmetic operations not allowed on non-opaque types. \ + Use the non-mutating arithmetic operators instead".to_string())); + } else if self_param.ty.is_immutably_borrowed() { + errors.push(LoweringError::Other(format!( + "{name} must take self by mutable reference" + ))); + } + } + if !method.output.success_type().is_unit() { + errors.push(LoweringError::Other(format!( + "{name} must not return a value" + ))); + } + } + } + } else { + errors.push(LoweringError::Other(format!("Special method (type {special:?}) not allowed on non-method context {context:?}"))) + } + } + + if namespace.is_some() + && matches!( + context, + AttributeContext::Method(..) | AttributeContext::EnumVariant(..) + ) + { + errors.push(LoweringError::Other( + "`namespace` can only be used on types".to_string(), + )); + } + if *default && !matches!(context, AttributeContext::EnumVariant(..)) { + errors.push(LoweringError::Other( + "`default` can only be used on types and enum variants".to_string(), + )); + } + if matches!( + context, + AttributeContext::Param | AttributeContext::SelfParam | AttributeContext::Field + ) { + if *disable { + errors.push(LoweringError::Other(format!( + "`disable`s cannot be used on an {context:?}." + ))); + } + + if namespace.is_some() { + errors.push(LoweringError::Other(format!( + "`namespace` cannot be used on an {context:?}." + ))); + } + + if !rename.is_empty() || !abi_rename.is_empty() { + errors.push(LoweringError::Other(format!( + "`rename`s cannot be used on an {context:?}." + ))); + } + + if special_method.is_some() { + errors.push(LoweringError::Other(format!( + "{context:?} cannot be special methods." + ))); + } + } + + if *custom_errors + && !matches!( + context, + AttributeContext::Type(..) + | AttributeContext::Trait(..) + | AttributeContext::Function(..) + ) + { + errors.push(LoweringError::Other( + "`error` can only be used on types".to_string(), + )); + } + if *generate_mocking_interface + && !matches!(context, AttributeContext::Type(TypeDef::Opaque(..))) + { + errors.push(LoweringError::Other( + "`generate_mocking_interface` can only be used on opaque types".to_string(), + )); + } + + if *abi_compatible && !matches!(context, AttributeContext::Type(TypeDef::Struct(..))) { + errors.push(LoweringError::Other( + "`abi_compatible` can only be used on non-output-only struct types.".into(), + )); + } + } + + pub(crate) fn for_inheritance(&self, context: AttrInheritContext) -> Attrs { + let rename = self.rename.attrs_for_inheritance(context, false); + + // Disabling shouldn't inherit to variants + let disable = if context == AttrInheritContext::Variant { + false + } else { + self.disable + }; + let namespace = if matches!( + context, + AttrInheritContext::Module | AttrInheritContext::Type + ) { + self.namespace.clone() + } else { + None + }; + + Attrs { + disable, + deprecated: None, + rename, + namespace, + // Should not inherit from enums to their variants + default: false, + // Was already inherited on the AST side + abi_rename: Default::default(), + // Never inherited + special_method: None, + // Not inherited + custom_errors: false, + demo_attrs: Default::default(), + // Not inherited + generate_mocking_interface: false, + abi_compatible: false, + } + } +} + +/// Non-exhaustive list of what attributes and other features your backend is able to handle, based on #[diplomat::attr(...)] contents. +/// Set this through an [`AttributeValidator`]. +/// +/// See [`SpecialMethod`] and [`Attrs`] for your specific implementation needs. +/// +/// For example, the current dart backend supports [`BackendAttrSupport::constructors`]. So when it encounters: +/// ```ignore +/// struct Sample {} +/// impl Sample { +/// #[diplomat::attr(constructor)] +/// pub fn new() -> Box { +/// Box::new(Sample{}) +/// } +/// } +/// +/// ``` +/// +/// It generates +/// ```dart +/// factory Sample() +/// ``` +/// +/// If a backend does not support a specific `#[diplomat::attr(...)]`, it may error. +#[non_exhaustive] +#[derive(Copy, Clone, Debug, Default)] +pub struct BackendAttrSupport { + /// Namespacing types, e.g. C++ `namespace`. + pub namespacing: bool, + /// Rust can directly acccess the memory of this language, like C and C++. + /// This is not supported in any garbage-collected language. + pub memory_sharing: bool, + /// This language's structs are non-exhaustive by default, i.e. adding + /// fields is not a breaking change. + pub non_exhaustive_structs: bool, + /// Whether the language supports method overloading + pub method_overloading: bool, + /// Whether the language uses UTF-8 strings + pub utf8_strings: bool, + /// Whether the language uses UTF-16 strings + pub utf16_strings: bool, + /// Whether the language supports using slices with 'static lifetimes. + pub static_slices: bool, + + /// Whether the language supports marking types as having a default value + pub defaults: bool, + + // Special methods + /// Marking a method as a constructor to generate special constructor methods. + pub constructors: bool, + /// Marking a method as a named constructor to generate special named constructor methods. + pub named_constructors: bool, + /// Marking constructors as being able to return errors. This is possible in languages where + /// errors are thrown as exceptions (Dart), but not for example in C++, where errors are + /// returned as values (constructors usually have to return the type itself). + pub fallible_constructors: bool, + /// Marking methods as field getters and setters, see [`SpecialMethod::Getter`] and [`SpecialMethod::Setter`] + pub accessors: bool, + /// Marking *static* methods as field getters and setters, see [`SpecialMethod::Getter`] and [`SpecialMethod::Setter`] + pub static_accessors: bool, + /// Marking a method as the `to_string` method, which is special in this language. + pub stringifiers: bool, + /// Marking a method as the `compare_to` method, which is special in this language. + pub comparators: bool, + /// Marking a method as the `next` method, which is special in this language. + pub iterators: bool, + /// Marking a method as the `iterator` method, which is special in this language. + pub iterables: bool, + /// Marking a method as the `[]` operator, which is special in this language. + pub indexing: bool, + /// Marking a method as an arithmetic operator (+-*/[=]) + pub arithmetic: bool, + /// Support for Option and Option + pub option: bool, + /// Allowing callback arguments + pub callbacks: bool, + /// Allowing traits + pub traits: bool, + /// Marking a user-defined type as being a valid error result type. + pub custom_errors: bool, + /// Traits are safe to Send between threads (safe to mark as std::marker::Send) + pub traits_are_send: bool, + /// Traits are safe to Sync between threads (safe to mark as std::marker::Sync) + pub traits_are_sync: bool, + /// Whether to generate mocking interface. + pub generate_mocking_interface: bool, + /// Passing of structs that only hold (non-slice) primitive types + /// (for use in slices and languages that support taking direct pointers to structs): + pub abi_compatibles: bool, + /// Whether or not the language supports &Struct or &mut Struct + pub struct_refs: bool, + /// Whether the language supports generating functions not associated with any type. + pub free_functions: bool, +} + +impl BackendAttrSupport { + #[cfg(test)] + fn all_true() -> Self { + Self { + namespacing: true, + memory_sharing: true, + non_exhaustive_structs: true, + method_overloading: true, + utf8_strings: true, + utf16_strings: true, + static_slices: true, + defaults: true, + + constructors: true, + named_constructors: true, + fallible_constructors: true, + static_accessors: true, + accessors: true, + stringifiers: true, + comparators: true, + iterators: true, + iterables: true, + indexing: true, + arithmetic: true, + option: true, + callbacks: true, + traits: true, + custom_errors: true, + traits_are_send: true, + traits_are_sync: true, + generate_mocking_interface: true, + abi_compatibles: true, + struct_refs: true, + free_functions: true, + } + } + + fn check_string(&self, v: &str) -> Option { + match v { + "namespacing" => Some(self.namespacing), + "memory_sharing" => Some(self.memory_sharing), + "non_exhaustive_structs" => Some(self.non_exhaustive_structs), + "method_overloading" => Some(self.method_overloading), + "utf8_strings" => Some(self.utf8_strings), + "utf16_strings" => Some(self.utf16_strings), + "static_slices" => Some(self.static_slices), + "default" => Some(self.defaults), + "constructors" => Some(self.constructors), + "named_constructors" => Some(self.named_constructors), + "fallible_constructors" => Some(self.fallible_constructors), + "accessors" => Some(self.accessors), + "stringifiers" => Some(self.stringifiers), + "comparators" => Some(self.comparators), + "iterators" => Some(self.iterators), + "iterables" => Some(self.iterables), + "indexing" => Some(self.indexing), + "arithmetic" => Some(self.arithmetic), + "option" => Some(self.option), + "callbacks" => Some(self.callbacks), + "traits" => Some(self.traits), + "custom_errors" => Some(self.custom_errors), + "traits_are_send" => Some(self.traits_are_send), + "traits_are_sync" => Some(self.traits_are_sync), + "abi_compatibles" => Some(self.abi_compatibles), + "struct_refs" => Some(self.struct_refs), + "free_functions" => Some(self.free_functions), + _ => None, + } + } +} + +/// Defined by backends when validating attributes +pub trait AttributeValidator { + /// The primary name of the backend, for use in diagnostics + fn primary_name(&self) -> &str; + /// Does this backend satisfy `cfg(backend_name)`? + /// (Backends are allowed to satisfy multiple backend names, useful when there + /// are multiple backends for a language) + fn is_backend(&self, backend_name: &str) -> bool; + /// does this backend satisfy cfg(name = value)? + fn is_name_value(&self, name: &str, value: &str) -> Result; + /// What backedn attrs does this support? + fn attrs_supported(&self) -> BackendAttrSupport; + + /// Provided, checks if type satisfies a `DiplomatBackendAttrCfg` + /// + /// auto_found helps check for `auto`, which is only allowed within `any` and at the top level. When `None`, + /// `auto` is not allowed. + fn satisfies_cfg( + &self, + cfg: &DiplomatBackendAttrCfg, + mut auto_found: Option<&mut bool>, + ) -> Result { + Ok(match *cfg { + DiplomatBackendAttrCfg::Not(ref c) => !self.satisfies_cfg(c, None)?, + DiplomatBackendAttrCfg::Any(ref cs) => { + #[allow(clippy::needless_option_as_deref)] + // False positive: we need this for reborrowing + for c in cs { + if self.satisfies_cfg(c, auto_found.as_deref_mut())? { + return Ok(true); + } + } + false + } + DiplomatBackendAttrCfg::All(ref cs) => { + for c in cs { + if !self.satisfies_cfg(c, None)? { + return Ok(false); + } + } + true + } + DiplomatBackendAttrCfg::Auto => { + if let Some(found) = auto_found { + *found = true; + return Ok(true); + } else { + return Err(LoweringError::Other("auto in diplomat::attr() is only allowed at the top level and within `any`".into())); + } + } + DiplomatBackendAttrCfg::Star => true, + DiplomatBackendAttrCfg::BackendName(ref n) => self.is_backend(n), + DiplomatBackendAttrCfg::NameValue(ref n, ref v) => self.is_name_value(n, v)?, + }) + } + + // Provided, constructs an attribute + fn attr_from_ast( + &self, + ast: &ast::Attrs, + parent_attrs: &Attrs, + errors: &mut ErrorStore, + ) -> Attrs { + Attrs::from_ast(ast, self, parent_attrs, errors) + } + + // Provided: validates an attribute in the context in which it was constructed + fn validate(&self, attrs: &Attrs, context: AttributeContext, errors: &mut ErrorStore) { + attrs.validate(self, context, errors) + } +} + +/// A basic attribute validator +#[non_exhaustive] +#[derive(Default)] +pub struct BasicAttributeValidator { + /// The primary name of this backend (should be unique, ideally) + pub backend_name: String, + /// The attributes supported + pub support: BackendAttrSupport, + /// Additional names for this backend + pub other_backend_names: Vec, + /// override is_name_value() + #[allow(clippy::type_complexity)] // dyn fn is not that complex + pub is_name_value: Option bool>>, +} + +impl BasicAttributeValidator { + pub fn new(backend_name: &str) -> Self { + BasicAttributeValidator { + backend_name: backend_name.into(), + ..Self::default() + } + } +} + +impl AttributeValidator for BasicAttributeValidator { + fn primary_name(&self) -> &str { + &self.backend_name + } + fn is_backend(&self, backend_name: &str) -> bool { + self.backend_name == backend_name + || self.other_backend_names.iter().any(|n| n == backend_name) + } + fn is_name_value(&self, name: &str, value: &str) -> Result { + Ok(if name == "supports" { + // destructure so new fields are forced to be added + let BackendAttrSupport { + namespacing, + memory_sharing, + non_exhaustive_structs, + method_overloading, + utf8_strings, + utf16_strings, + static_slices, + defaults, + + constructors, + named_constructors, + fallible_constructors, + accessors, + static_accessors, + stringifiers, + comparators, + iterators, + iterables, + indexing, + arithmetic, + option, + callbacks, + traits, + custom_errors, + traits_are_send, + traits_are_sync, + generate_mocking_interface, + abi_compatibles, + struct_refs, + free_functions, + } = self.support; + match value { + "namespacing" => namespacing, + "memory_sharing" => memory_sharing, + "non_exhaustive_structs" => non_exhaustive_structs, + "method_overloading" => method_overloading, + "utf8_strings" => utf8_strings, + "utf16_strings" => utf16_strings, + "static_slices" => static_slices, + "defaults" => defaults, + + "constructors" => constructors, + "named_constructors" => named_constructors, + "fallible_constructors" => fallible_constructors, + "accessors" => accessors, + "static_accessors" => static_accessors, + "stringifiers" => stringifiers, + "comparators" => comparators, + "iterators" => iterators, + "iterables" => iterables, + "indexing" => indexing, + "arithmetic" => arithmetic, + "option" => option, + "callbacks" => callbacks, + "traits" => traits, + "custom_errors" => custom_errors, + "traits_are_send" => traits_are_send, + "traits_are_sync" => traits_are_sync, + "generate_mocking_interface" => generate_mocking_interface, + "abi_compatibles" => abi_compatibles, + "struct_refs" => struct_refs, + "free_functions" => free_functions, + _ => { + return Err(LoweringError::Other(format!( + "Unknown supports = value found: {value}" + ))) + } + } + } else if let Some(ref nv) = self.is_name_value { + nv(name, value) + } else { + false + }) + } + fn attrs_supported(&self) -> BackendAttrSupport { + self.support + } +} + +#[cfg(test)] +mod tests { + use crate::hir; + use std::fmt::Write; + + macro_rules! uitest_lowering_attr { + ($attrs:expr, $($file:tt)*) => { + let parsed: syn::File = syn::parse_quote! { $($file)* }; + + let mut output = String::new(); + + let mut attr_validator = hir::BasicAttributeValidator::new("tests"); + attr_validator.support = $attrs; + match hir::TypeContext::from_syn(&parsed, Default::default(), attr_validator) { + Ok(_context) => (), + Err(e) => { + for (ctx, err) in e { + writeln!(&mut output, "Lowering error in {ctx}: {err}").unwrap(); + } + } + }; + insta::with_settings!({}, { + insta::assert_snapshot!(output) + }); + } + } + + #[test] + fn test_auto() { + uitest_lowering_attr! { hir::BackendAttrSupport { comparators: true, ..Default::default()}, + #[diplomat::bridge] + mod ffi { + use std::cmp; + + #[diplomat::opaque] + #[diplomat::attr(auto, namespace = "should_not_show_up")] + struct Opaque; + + + impl Opaque { + #[diplomat::attr(auto, comparison)] + pub fn comparator_static(&self, other: &Opaque) -> cmp::Ordering { + todo!() + } + #[diplomat::attr(*, iterator)] + pub fn next(&mut self) -> Option { + self.0.next() + } + #[diplomat::attr(auto, rename = "bar")] + pub fn auto_doesnt_work_on_renames(&self) { + } + #[diplomat::attr(auto, disable)] + pub fn auto_doesnt_work_on_disables(&self) { + } + } + + } + } + } + + #[test] + fn test_comparator() { + uitest_lowering_attr! { hir::BackendAttrSupport::all_true(), + #[diplomat::bridge] + mod ffi { + use std::cmp; + + #[diplomat::opaque] + struct Opaque; + + struct Struct { + field: u8 + } + + + impl Opaque { + #[diplomat::attr(auto, comparison)] + pub fn comparator_static(other: &Opaque) -> cmp::Ordering { + todo!() + } + #[diplomat::attr(auto, comparison)] + pub fn comparator_none(&self) -> cmp::Ordering { + todo!() + } + #[diplomat::attr(auto, comparison)] + pub fn comparator_othertype(other: Struct) -> cmp::Ordering { + todo!() + } + #[diplomat::attr(auto, comparison)] + pub fn comparator_badreturn(&self, other: &Opaque) -> u8 { + todo!() + } + #[diplomat::attr(auto, comparison)] + pub fn comparison_correct(&self, other: &Opaque) -> cmp::Ordering { + todo!() + } + pub fn comparison_unmarked(&self, other: &Opaque) -> cmp::Ordering { + todo!() + } + pub fn ordering_wrong(&self, other: cmp::Ordering) { + todo!() + } + #[diplomat::attr(auto, comparison)] + pub fn comparison_mut(&self, other: &mut Opaque) -> cmp::Ordering { + todo!() + } + #[diplomat::attr(auto, comparison)] + pub fn comparison_opt(&self, other: Option<&Opaque>) -> cmp::Ordering { + todo!() + } + } + + impl Struct { + #[diplomat::attr(auto, comparison)] + pub fn comparison_other(self, other: &Opaque) -> cmp::Ordering { + todo!() + } + #[diplomat::attr(auto, comparison)] + pub fn comparison_correct(self, other: Self) -> cmp::Ordering { + todo!() + } + + #[diplomat::attr(auto, comparison)] + pub fn comparison_ref(&self, other: &Self) -> cmp::Ordering { + todo!() + } + + #[diplomat::attr(auto, comparison)] + pub fn comparison_mut(&mut self, other: &Self) -> cmp::Ordering { + todo!() + } + } + } + } + } + + #[test] + fn test_iterator() { + uitest_lowering_attr! { hir::BackendAttrSupport::all_true(), + #[diplomat::bridge] + mod ffi { + + #[diplomat::opaque] + struct Opaque(Vec); + #[diplomat::opaque] + struct OpaqueIterator<'a>(std::slice::Iter<'a>); + + + impl Opaque { + #[diplomat::attr(auto, iterable)] + pub fn iterable<'a>(&'a self) -> Box> { + Box::new(OpaqueIterator(self.0.iter())) + } + } + + impl OpaqueIterator { + #[diplomat::attr(auto, iterator)] + pub fn next(&mut self) -> Option { + self.0.next() + } + } + + #[diplomat::opaque] + struct Broken; + + impl Broken { + #[diplomat::attr(auto, iterable)] + pub fn iterable_no_return(&self) {} + #[diplomat::attr(auto, iterable)] + pub fn iterable_no_self() -> Box { todo!() } + + #[diplomat::attr(auto, iterable)] + pub fn iterable_non_custom(&self) -> u8 { todo!() } + } + + #[diplomat::opaque] + struct BrokenIterator; + + impl BrokenIterator { + #[diplomat::attr(auto, iterator)] + pub fn iterator_no_return(&self) {} + #[diplomat::attr(auto, iterator)] + pub fn iterator_no_self() -> Option { todo!() } + + #[diplomat::attr(auto, iterator)] + pub fn iterator_no_option(&self) -> u8 { todo!() } + } + } + } + } + + #[test] + fn test_unsupported_features() { + uitest_lowering_attr! { hir::BackendAttrSupport::default(), + #[diplomat::bridge] + mod ffi { + use std::cmp; + use diplomat_runtime::DiplomatOption; + + #[diplomat::opaque] + struct Opaque; + + struct Struct { + pub a: u8, + pub b: u8, + pub c: DiplomatOption, + } + + struct Struct2 { + pub a: DiplomatOption, + } + + #[diplomat::out] + struct OutStruct { + pub option: DiplomatOption + } + + + impl Opaque { + pub fn take_option(&self, option: DiplomatOption) { + todo!() + } + // Always ok since this translates to a Resulty return + pub fn returning_option_is_ok(&self) -> Option { + todo!() + } + } + + } + } + } + + #[test] + fn test_mocking_interface_for_opaque_type() { + uitest_lowering_attr! { hir::BackendAttrSupport::all_true(), + #[diplomat::bridge] + mod ffi { + #[diplomat::opaque] + #[diplomat::attr(tests, generate_mocking_interface)] + pub struct Foo { + pub x: u32, + pub y: u32, + } + + impl Foo { + pub fn new() -> Box { + Box::new(Self { x: 0, y: 0 }) + } + + pub fn get_x(&self) -> u32 { + self.x + } + + pub fn get_y(&self) -> u32 { + self.y + } + } + } + } + } + + #[test] + fn test_mocking_interface_for_non_opaque_type() { + uitest_lowering_attr! { hir::BackendAttrSupport::all_true(), + #[diplomat::bridge] + mod ffi { + #[diplomat::attr(tests, generate_mocking_interface)] + pub struct Foo { + pub x: u32, + pub y: u32, + } + + impl Foo { + pub fn new() -> Self { + Self { x: 0, y: 0 } + } + + pub fn get_x(self) -> u32 { + self.x + } + + pub fn get_y(self) -> u32 { + self.y + } + } + } + } + } + + #[test] + fn test_mocking_interface_for_unsupported_backend() { + uitest_lowering_attr! { hir::BackendAttrSupport::default(), + #[diplomat::bridge] + mod ffi { + #[diplomat::attr(tests, generate_mocking_interface)] + pub struct Foo { + pub x: u32, + pub y: u32, + } + + impl Foo { + pub fn new() -> Self { + Self { x: 0, y: 0 } + } + + pub fn get_x(self) -> u32 { + self.x + } + + pub fn get_y(self) -> u32 { + self.y + } + } + } + } + } + + #[test] + fn test_primitive_struct_slices() { + uitest_lowering_attr! { hir::BackendAttrSupport::all_true(), + #[diplomat::bridge] + mod ffi { + #[diplomat::attr(auto, abi_compatible)] + pub struct Foo { + pub x: u32, + pub y: u32 + } + + impl Foo { + pub fn takes_slice(sl : &[Foo]) { + todo!() + } + } + } + } + } + + #[test] + fn test_primitive_struct_slices_for_unsupported_backend() { + uitest_lowering_attr! { hir::BackendAttrSupport::default(), + #[diplomat::bridge] + mod ffi { + #[diplomat::attr(auto, abi_compatible)] + pub struct Foo { + pub x: u32, + pub y: u32 + } + + impl Foo { + pub fn takes_slice(sl : &[Foo]) { + todo!() + } + } + } + } + } + + #[test] + fn test_struct_ref_for_unsupported_backend() { + uitest_lowering_attr! { hir::BackendAttrSupport::default(), + #[diplomat::bridge] + mod ffi { + #[diplomat::attr(auto, abi_compatible)] + pub struct Foo { + pub x: u32, + pub y: u32 + } + + impl Foo { + pub fn takes_mut(&mut self) { + todo!() + } + } + } + } + } +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/defs.rs b/deps/crates/vendor/diplomat_core/src/hir/defs.rs new file mode 100644 index 00000000000000..90f1960ce432de --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/defs.rs @@ -0,0 +1,253 @@ +//! Type definitions for structs, output structs, opaque structs, and enums. + +use super::lifetimes::LifetimeEnv; +use super::{ + Attrs, Callback, Everywhere, IdentBuf, Method, OutputOnly, SpecialMethodPresence, TyPosition, + Type, +}; +use crate::ast::Docs; + +#[non_exhaustive] +pub enum ReturnableStructDef<'tcx> { + Struct(&'tcx StructDef), + OutStruct(&'tcx OutStructDef), +} + +#[derive(Copy, Clone, Debug)] +#[non_exhaustive] +pub enum TypeDef<'tcx> { + Struct(&'tcx StructDef), + OutStruct(&'tcx OutStructDef), + Opaque(&'tcx OpaqueDef), + Enum(&'tcx EnumDef), +} + +#[derive(Debug)] +#[non_exhaustive] +pub struct TraitDef { + // TyPosition: InputOnly + pub docs: Docs, + pub name: IdentBuf, + pub methods: Vec, + pub attrs: Attrs, + pub lifetimes: LifetimeEnv, +} + +/// Structs that can only be returned from methods. +pub type OutStructDef = StructDef; + +/// Structs that can be either inputs or outputs in methods. +#[derive(Debug)] +#[non_exhaustive] +pub struct StructDef { + pub docs: Docs, + pub name: IdentBuf, + pub fields: Vec>, + pub methods: Vec, + pub attrs: Attrs, + pub lifetimes: LifetimeEnv, + pub special_method_presence: SpecialMethodPresence, +} + +/// A struct whose contents are opaque across the FFI boundary, and can only +/// cross when behind a pointer. +/// +/// All opaques can be inputs or outputs when behind a reference, but owned +/// opaques can only be returned since there isn't a general way for most languages +/// to give up ownership. +/// +/// A struct marked with `#[diplomat::opaque]`. +#[derive(Debug)] +#[non_exhaustive] +pub struct OpaqueDef { + pub docs: Docs, + pub name: IdentBuf, + pub methods: Vec, + pub attrs: Attrs, + pub lifetimes: LifetimeEnv, + pub special_method_presence: SpecialMethodPresence, + + /// The ABI name of the generated destructor + pub dtor_abi_name: IdentBuf, +} + +/// The enum type. +#[derive(Debug)] +#[non_exhaustive] +pub struct EnumDef { + pub docs: Docs, + pub name: IdentBuf, + pub variants: Vec, + pub methods: Vec, + pub attrs: Attrs, + pub special_method_presence: SpecialMethodPresence, +} + +/// A field on a [`OutStruct`]s. +pub type OutStructField = StructField; + +/// A field on a [`Struct`]s. +#[derive(Debug)] +#[non_exhaustive] +pub struct StructField { + pub docs: Docs, + pub name: IdentBuf, + pub ty: Type

, + pub attrs: Attrs, +} + +/// A variant of an [`Enum`]. +#[derive(Debug)] +#[non_exhaustive] +pub struct EnumVariant { + pub docs: Docs, + pub name: IdentBuf, + pub discriminant: isize, + pub attrs: Attrs, +} + +impl TraitDef { + pub(super) fn new( + docs: Docs, + name: IdentBuf, + methods: Vec, + attrs: Attrs, + lifetimes: LifetimeEnv, + ) -> Self { + Self { + docs, + name, + methods, + attrs, + lifetimes, + } + } +} + +impl StructDef

{ + pub(super) fn new( + docs: Docs, + name: IdentBuf, + fields: Vec>, + methods: Vec, + attrs: Attrs, + lifetimes: LifetimeEnv, + special_method_presence: SpecialMethodPresence, + ) -> Self { + Self { + docs, + name, + fields, + methods, + attrs, + lifetimes, + special_method_presence, + } + } +} + +impl OpaqueDef { + pub(super) fn new( + docs: Docs, + name: IdentBuf, + methods: Vec, + attrs: Attrs, + lifetimes: LifetimeEnv, + special_method_presence: SpecialMethodPresence, + dtor_abi_name: IdentBuf, + ) -> Self { + Self { + docs, + name, + methods, + attrs, + lifetimes, + special_method_presence, + dtor_abi_name, + } + } +} + +impl EnumDef { + pub(super) fn new( + docs: Docs, + name: IdentBuf, + variants: Vec, + methods: Vec, + attrs: Attrs, + special_method_presence: SpecialMethodPresence, + ) -> Self { + Self { + docs, + name, + variants, + methods, + attrs, + special_method_presence, + } + } +} + +impl<'a, P: TyPosition> From<&'a StructDef

> for TypeDef<'a> { + fn from(x: &'a StructDef

) -> Self { + P::wrap_struct_def(x) + } +} + +impl<'a> From<&'a OpaqueDef> for TypeDef<'a> { + fn from(x: &'a OpaqueDef) -> Self { + TypeDef::Opaque(x) + } +} + +impl<'a> From<&'a EnumDef> for TypeDef<'a> { + fn from(x: &'a EnumDef) -> Self { + TypeDef::Enum(x) + } +} + +impl<'tcx> TypeDef<'tcx> { + pub fn name(&self) -> &'tcx IdentBuf { + match *self { + Self::Struct(ty) => &ty.name, + Self::OutStruct(ty) => &ty.name, + Self::Opaque(ty) => &ty.name, + Self::Enum(ty) => &ty.name, + } + } + + pub fn docs(&self) -> &'tcx Docs { + match *self { + Self::Struct(ty) => &ty.docs, + Self::OutStruct(ty) => &ty.docs, + Self::Opaque(ty) => &ty.docs, + Self::Enum(ty) => &ty.docs, + } + } + pub fn methods(&self) -> &'tcx [Method] { + match *self { + Self::Struct(ty) => &ty.methods, + Self::OutStruct(ty) => &ty.methods, + Self::Opaque(ty) => &ty.methods, + Self::Enum(ty) => &ty.methods, + } + } + + pub fn attrs(&self) -> &'tcx Attrs { + match *self { + Self::Struct(ty) => &ty.attrs, + Self::OutStruct(ty) => &ty.attrs, + Self::Opaque(ty) => &ty.attrs, + Self::Enum(ty) => &ty.attrs, + } + } + + pub fn special_method_presence(&self) -> &'tcx SpecialMethodPresence { + match *self { + Self::Struct(ty) => &ty.special_method_presence, + Self::OutStruct(ty) => &ty.special_method_presence, + Self::Opaque(ty) => &ty.special_method_presence, + Self::Enum(ty) => &ty.special_method_presence, + } + } +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/elision.rs b/deps/crates/vendor/diplomat_core/src/hir/elision.rs new file mode 100644 index 00000000000000..71c26f8fda4790 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/elision.rs @@ -0,0 +1,612 @@ +//! This module provides the functionality for lowering lifetimes from the AST +//! to the HIR, while simultaneously inferencing elided lifetimes. +//! +//! Full elision rules can be found in the [Nomicon]. +//! +//! The key factor about lifetime elision is that all elision in the output of +//! the method (if there is any) corresponds to exactly one lifetime in the method +//! arguments, which may or may not be elided. Therefore, our task is to find this +//! potential lifetime first, so that if we encounter an elided lifetime while +//! lowering the output, we know which lifetime it corresponds to. +//! +//! # Unspoken Rules of Elision. +//! +//! Broadly speaking, the Nomicon defines the elision rules are such: +//! 1. If there's a `&self` or `&mut self`, the lifetime of that borrow +//! corresponds to elision in the output. +//! 2. Otherwise, if there's exactly one lifetime in the input, then that lifetime +//! corresponds to elision in the output. +//! 3. If neither of these cases hold, then the output cannot contain elision. +//! +//! What the Nomicon doesn't tell you is that there are weird corner cases around +//! using the `Self` type. Specifically, lifetimes in the `Self` type and in the +//! type of the `self` argument (optional) aren't considered when figuring out +//! which lifetime should correspond to elision in the output. +//! +//! Check out the following code: +//! ```compile_fail +//! struct Foo<'a>(&'a str); +//! +//! impl<'a> Foo<'a> { +//! fn get(self) -> &str { self.0 } +//! } +//! ``` +//! This code will fail to compile because it doesn't look at the `'a` in the +//! `Foo<'a>`, which is what the type of `self` expands to. Therefore, it will +//! conclude that there's nothing for the output to borrow from. +//! This can be fixed by returning `&'a str` though. Many of the design +//! decisions in this module were made to be able to replicate this behavior. +//! +//! You may be asking "why would we care about rejecting code that rustc rejects +//! before it reaches us?" And the answer is this: +//! ```rust +//! # struct Foo<'a>(&'a str); +//! impl<'a> Foo<'a> { +//! fn get(self, s: &str) -> &str { s } +//! } +//! ``` +//! This code is accepted by rustc, since it only considers the lifetime of `s` +//! when searching for a lifetime that corresponds to output elision. If we were +//! to naively look at all the lifetimes, we would see the lifetime in the `self` +//! argument and the lifetime of `s`, making us reject this method. Therefore, we +//! have to be extremely careful when traversing lifetimes, and make sure that +//! lifetimes of `Self` are lowered but _not_ considered for elision, while other +//! lifetimes are lowered while also being considered for elision. +//! +//! # Lowering and Inference +//! +//! Lowering and elision inference is broken into three distinct stages: +//! 1. Lowering the borrow in `&self` or `&mut self`, if there is one. +//! 2. Lowering lifetimes of other params. +//! 3. Lowering lifetimes of the output. +//! +//! Although each stage fundementally lowers lifetimes, they behave differently +//! when lowering elided lifetimes. Naturally, this module represents each stage +//! as a state in a state machine. +//! +//! The first state is represented by the [`SelfParamLifetimeLowerer`] type. +//! Since there is either zero or one occurrences of `&self` or `&mut self`, it +//! exposes the `.no_self_ref()` and `.lower_self_ref(lt)` methods respectively, +//! which consume the `SelfParamLifetimeLowerer` and return the next state, +//! [`ParamLifetimeLowerer`], as well as the lowered lifetime. The reason these +//! are two distinct types is that the lifetime in `&self` and `&mut self` takes +//! precedence over any other lifetimes in the input, so `.lower_self_ref(lt)` +//! tells the next state that the candidate lifetime is already found, and to +//! generate fresh anonymous lifetimes for any elided lifetimes. +//! +//! The second state is represented by the [`ParamLifetimeLowerer`] type. +//! It implements a helper trait, [`LifetimeLowerer`], which abstracts the lowering +//! of references and generic lifetimes. Internally, it wraps an [`ElisionSource`], +//! which acts as a state machine for tracking candidate lifetimes to correspond +//! to elision in the output. When a lifetime that's not in the type of the `self` +//! argument or in the expanded generics of the `Self` type is visited, this +//! state machine is potentially updated to another state. If the lifetime is +//! anonymous, it's added to the internal list of nodes that go into the final +//! [`LifetimeEnv`] after lowering. Once all the lifetimes in the input are +//! lowered, the `into_return_ltl()` method is called to transition into the +//! final state. +//! +//! The third and final state is represented by the [`ReturnLifetimeLowerer`] type. +//! Similar to `ParamLifetimeLowerer`, it also implements the [`LifetimeLowerer`] +//! helper trait. However, it differs from `ParamLifetimeLowerer` since instead +//! of potentially updating the internal `ElisionSource` when visiting a lifetime, +//! it instead reads from it when an elided lifetime occurs. Once all the output +//! lifetimes are lowered, `.finish()` is called to return the finalized +//! [`LifetimeEnv`]. +//! +//! [Nomicon]: https://doc.rust-lang.org/nomicon/lifetime-elision.html + +use super::lifetimes::{BoundedLifetime, Lifetime, LifetimeEnv, Lifetimes, MaybeStatic}; +use super::LoweringContext; +use crate::ast; +use smallvec::SmallVec; + +/// Lower [`ast::Lifetime`]s to [`Lifetime`]s. +/// +/// This helper traits allows the [`lower_type`] and [`lower_out_type`] methods +/// to abstractly lower lifetimes without concern for what sort of tracking +/// goes on. In particular, elision inference requires updating internal state +/// when visiting lifetimes in the input. +pub trait LifetimeLowerer { + /// Lowers an [`ast::Lifetime`]. + fn lower_lifetime(&mut self, lifetime: &ast::Lifetime) -> MaybeStatic; + + /// Lowers a slice of [`ast::Lifetime`]s by calling + /// [`LifetimeLowerer::lower_lifetime`] repeatedly. + /// + /// `type_generics` is the full list of generics on the type definition of the type + /// this lifetimes list is found on (needed for generating anon lifetimes) + fn lower_lifetimes( + &mut self, + lifetimes: &[ast::Lifetime], + type_generics: &ast::LifetimeEnv, + ) -> Lifetimes { + let mut lifetimes = Lifetimes::from_fn(lifetimes, |lifetime| self.lower_lifetime(lifetime)); + + for _ in lifetimes.as_slice().len()..type_generics.nodes.len() { + lifetimes.append_lifetime(self.lower_lifetime(&ast::Lifetime::Anonymous)) + } + lifetimes + } + + /// Lowers a slice of [`ast::Lifetime`], where the strategy may vary depending + /// on whether or not the lifetimes are expanded from the `Self` type. + /// + /// The distinction between this and [`LifetimeLowerer::lower_lifetimes`] is + /// that if `Self` expands to a type with anonymous lifetimes like `Foo<'_>`, + /// then multiple instances of `Self` should expand to have the same anonymous + /// lifetime, and this lifetime can be cached inside of the `self` argument. + /// Additionally, elision inferences knows to not search inside the generics + /// of `Self` types for candidate lifetimes to correspond to elided lifetimes + /// in the output. + /// + /// `type_generics` is the full list of generics on the type definition of the type + /// this generics list is found on (needed for generating anon lifetimes) + fn lower_generics( + &mut self, + lifetimes: &[ast::Lifetime], + type_generics: &ast::LifetimeEnv, + is_self: bool, + ) -> Lifetimes; +} + +/// A state machine for tracking which lifetime in a function's parameters +/// may correspond to elided lifetimes in the output. +#[derive(Copy, Clone)] +enum ElisionSource { + /// No borrows in the input, no elision. + NoBorrows, + /// `&self` or `&mut self`, elision allowed. + SelfParam(MaybeStatic), + /// One param contains a borrow, elision allowed. + OneParam(MaybeStatic), + /// Multiple borrows and no self borrow, no elision. + MultipleBorrows, +} + +impl ElisionSource { + /// Potentially transition to a new state. + fn visit_lifetime(&mut self, lifetime: MaybeStatic) { + match self { + ElisionSource::NoBorrows => *self = ElisionSource::OneParam(lifetime), + ElisionSource::SelfParam(_) => { + // References to self have the highest precedence, do nothing. + } + ElisionSource::OneParam(_) => *self = ElisionSource::MultipleBorrows, + ElisionSource::MultipleBorrows => { + // There's ambiguity. This is valid when there's no elision in + // the output. + } + }; + } +} + +/// A type for storing shared information between the different states of elision +/// inference. +/// +/// This contains data for generating fresh elided lifetimes, looking up named +/// lifetimes, and caching lifetimes of `Self`. +pub(super) struct BaseLifetimeLowerer<'ast> { + lifetime_env: &'ast ast::LifetimeEnv, + self_lifetimes: Option, + nodes: SmallVec<[BoundedLifetime; super::lifetimes::INLINE_NUM_LIFETIMES]>, + num_lifetimes: usize, +} + +/// The first phase of output elision inference. +/// +/// In the first phase, the type signature of the `&self` or `&mut self` type +/// is lowered into its HIR representation, if present. According to elision +/// rules, this reference has the highest precedence as the lifetime that +/// goes into elision in the output, and so it's checked first. +pub(super) struct SelfParamLifetimeLowerer<'ast> { + base: BaseLifetimeLowerer<'ast>, +} + +/// The second phase of output elision inference. +/// +/// In the second phase, all lifetimes in the parameter type signatures +/// (besides the lifetime of self, if present) are lowered. If a self param +/// didn't claim the potential output elided lifetime, then if there's a +/// single lifetime (elided or not) in the inputs, it will claim the +/// potential output elided lifetime. +pub(super) struct ParamLifetimeLowerer<'ast> { + elision_source: ElisionSource, + base: BaseLifetimeLowerer<'ast>, +} + +/// The third and final phase of output elision inference. +/// +/// In the third phase, the type signature of the output type is lowered into +/// its HIR representation. If one of the input lifetimes were marked as +/// responsible for any elision in the output, then anonymous lifetimes get +/// that lifetime. If none did and there is elision in the output, then +/// rustc should have errored and said the elision was ambiguous, meaning +/// that state should be impossible so it panics. +pub(super) struct ReturnLifetimeLowerer<'ast> { + elision_source: ElisionSource, + base: BaseLifetimeLowerer<'ast>, +} + +impl<'ast> BaseLifetimeLowerer<'ast> { + /// Returns a [`Lifetime`] representing a new anonymous lifetime, and + /// pushes it to the nodes vector. + fn new_elided(&mut self) -> Lifetime { + let index = self.num_lifetimes; + self.num_lifetimes += 1; + Lifetime::new(index) + } + + /// Lowers a single [`ast::Lifetime`]. If the lifetime is elided, then a fresh + /// [`ImplicitLifetime`] is generated. + fn lower_lifetime(&mut self, lifetime: &ast::Lifetime) -> MaybeStatic { + match lifetime { + ast::Lifetime::Static => MaybeStatic::Static, + ast::Lifetime::Named(named) => { + MaybeStatic::NonStatic(Lifetime::from_ast(named, self.lifetime_env)) + } + ast::Lifetime::Anonymous => MaybeStatic::NonStatic(self.new_elided()), + } + } + + /// Retrieves the cached `Self` lifetimes, or caches newly generated + /// lifetimes and returns those. + fn self_lifetimes_or_new(&mut self, ast_lifetimes: &[ast::Lifetime]) -> Lifetimes { + if let Some(lifetimes) = &self.self_lifetimes { + lifetimes.clone() + } else { + let lifetimes = Lifetimes::from_fn(ast_lifetimes, |lt| self.lower_lifetime(lt)); + self.self_lifetimes = Some(lifetimes.clone()); + lifetimes + } + } +} + +impl<'ast> SelfParamLifetimeLowerer<'ast> { + /// Returns a new [`SelfParamLifetimeLowerer`]. + pub fn new( + lifetime_env: &'ast ast::LifetimeEnv, + ctx: &mut LoweringContext, + ) -> Result { + let mut hir_nodes = Ok(SmallVec::new()); + + for ast_node in lifetime_env.nodes.iter() { + let lifetime = ctx.lower_ident(ast_node.lifetime.name(), "named lifetime"); + match (lifetime, &mut hir_nodes) { + (Ok(lifetime), Ok(hir_nodes)) => { + hir_nodes.push(BoundedLifetime::new( + lifetime, + ast_node.longer.iter().map(|i| Lifetime::new(*i)).collect(), + ast_node.shorter.iter().map(|i| Lifetime::new(*i)).collect(), + )); + } + _ => hir_nodes = Err(()), + } + } + + hir_nodes.map(|nodes| Self { + base: BaseLifetimeLowerer { + lifetime_env, + self_lifetimes: None, + num_lifetimes: nodes.len(), + nodes, + }, + }) + } + + /// Lowers the lifetime of `&self` or `&mut self`. + /// + /// The lifetimes of `&self` and `&mut self` are special, because they + /// automatically take priority over any other lifetime in the input for + /// being tied to any elided lifetimes in the output. + /// + /// Along with returning the lowered lifetime, this method also returns the + /// next state in elision inference, the [`ParamLifetimeLowerer`]. + pub fn lower_self_ref( + mut self, + lifetime: &ast::Lifetime, + ) -> (MaybeStatic, ParamLifetimeLowerer<'ast>) { + let self_lifetime = self.base.lower_lifetime(lifetime); + + ( + self_lifetime, + self.into_param_ltl(ElisionSource::SelfParam(self_lifetime)), + ) + } + + /// Acknowledges that there's no `&self` or `&mut self`, and transitions + /// to the next state, [`ParamLifetimeLowerer`]. + pub fn no_self_ref(self) -> ParamLifetimeLowerer<'ast> { + self.into_param_ltl(ElisionSource::NoBorrows) + } + + /// Transition into the next state, [`ParamLifetimeLowerer`]. + fn into_param_ltl(self, elision_source: ElisionSource) -> ParamLifetimeLowerer<'ast> { + ParamLifetimeLowerer { + elision_source, + base: self.base, + } + } +} + +impl<'ast> ParamLifetimeLowerer<'ast> { + /// Once all lifetimes in the parameters are lowered, this function is + /// called to transition to the next state, [`ReturnLifetimeLowerer`]. + pub fn into_return_ltl(self) -> ReturnLifetimeLowerer<'ast> { + ReturnLifetimeLowerer { + elision_source: self.elision_source, + base: self.base, + } + } +} + +impl<'ast> LifetimeLowerer for ParamLifetimeLowerer<'ast> { + fn lower_lifetime(&mut self, borrow: &ast::Lifetime) -> MaybeStatic { + let lifetime = self.base.lower_lifetime(borrow); + self.elision_source.visit_lifetime(lifetime); + lifetime + } + + fn lower_generics( + &mut self, + lifetimes: &[ast::Lifetime], + type_generics: &ast::LifetimeEnv, + is_self: bool, + ) -> Lifetimes { + if is_self { + self.base.self_lifetimes_or_new(lifetimes) + } else { + self.lower_lifetimes(lifetimes, type_generics) + } + } +} + +impl<'ast> ReturnLifetimeLowerer<'ast> { + /// Finalize the lifetimes in the method, returning the resulting [`LifetimeEnv`]. + pub fn finish(self) -> LifetimeEnv { + LifetimeEnv::new(self.base.nodes, self.base.num_lifetimes) + } +} + +impl<'ast> LifetimeLowerer for ReturnLifetimeLowerer<'ast> { + fn lower_lifetime(&mut self, borrow: &ast::Lifetime) -> MaybeStatic { + match borrow { + ast::Lifetime::Static => MaybeStatic::Static, + ast::Lifetime::Named(named) => { + MaybeStatic::NonStatic(Lifetime::from_ast(named, self.base.lifetime_env)) + } + ast::Lifetime::Anonymous => match self.elision_source { + ElisionSource::SelfParam(lifetime) | ElisionSource::OneParam(lifetime) => lifetime, + ElisionSource::NoBorrows => { + panic!("nothing to borrow from, this shouldn't pass rustc's checks") + } + ElisionSource::MultipleBorrows => { + panic!("source of elision is ambiguous, this shouldn't pass rustc's checks") + } + }, + } + } + + fn lower_generics( + &mut self, + lifetimes: &[ast::Lifetime], + type_generics: &ast::LifetimeEnv, + is_self: bool, + ) -> Lifetimes { + if is_self { + self.base.self_lifetimes_or_new(lifetimes) + } else { + self.lower_lifetimes(lifetimes, type_generics) + } + } +} + +impl LifetimeLowerer for &ast::LifetimeEnv { + fn lower_lifetime(&mut self, lifetime: &ast::Lifetime) -> MaybeStatic { + match lifetime { + ast::Lifetime::Static => MaybeStatic::Static, + ast::Lifetime::Named(named) => MaybeStatic::NonStatic(Lifetime::from_ast(named, self)), + ast::Lifetime::Anonymous => { + panic!("anonymous lifetime inside struct, this shouldn't pass rustc's checks") + } + } + } + + fn lower_generics( + &mut self, + lifetimes: &[ast::Lifetime], + type_generics: &ast::LifetimeEnv, + _: bool, + ) -> Lifetimes { + self.lower_lifetimes(lifetimes, type_generics) + } +} + +// Things to test: +// 1. ensure that if there are multiple inputs that are `Self`, where `Self` has +// an elided lifetime, all expansions of `Self` have the same anonymous lifetimes. + +#[cfg(test)] +mod tests { + use strck::IntoCk; + + /// Convert a syntax tree into a [`TypeContext`]. + macro_rules! tcx { + ($($tokens:tt)*) => {{ + let m = crate::ast::Module::from_syn(&syn::parse_quote! { $($tokens)* }, true); + + let mut env = crate::Env::default(); + let mut top_symbols = crate::ModuleEnv::new(Default::default()); + + m.insert_all_types(crate::ast::Path::empty(), &mut env); + top_symbols.insert(m.name.clone(), crate::ast::ModSymbol::SubModule(m.name.clone())); + + env.insert(crate::ast::Path::empty(), top_symbols); + + let mut backend = crate::hir::BasicAttributeValidator::new("test-backend"); + backend.support.static_slices = true; + + // Don't run validation: it will error on elision. We want this code to support + // elision even if we don't actually allow it, since good diagnostics involve understanding + // broken code. + let (_, tcx) = crate::hir::TypeContext::from_ast_without_validation(&env, Default::default(), backend).unwrap(); + + tcx + }} + } + + macro_rules! do_test { + ($($tokens:tt)*) => {{ + let mut settings = insta::Settings::new(); + settings.set_sort_maps(true); + + settings.bind(|| { + let tcx = tcx! { $($tokens)* }; + + insta::assert_debug_snapshot!(tcx); + }) + }} + } + + #[test] + fn simple_mod() { + do_test! { + mod ffi { + #[diplomat::opaque] + struct Opaque<'a> { + s: DiplomatStrSlice<'a>, + } + + struct Struct<'a> { + s: DiplomatStrSlice<'a>, + } + + #[diplomat::out] + struct OutStruct<'a> { + inner: Box>, + } + + impl<'a> OutStruct<'a> { + pub fn new(s: &'a DiplomatStr) -> Self { + Self { inner: Box::new(Opaque { s }) } + } + + } + + impl<'a> Struct<'a> { + pub fn rustc_elision(self, s: &DiplomatStr) -> &DiplomatStr { + s + } + } + } + } + } + + #[test] + fn test_elision_in_struct() { + let tcx = tcx! { + mod ffi { + #[diplomat::opaque] + struct Opaque; + + #[diplomat::opaque] + struct Opaque2<'a>(&'a str); + + impl Opaque { + // This should have two elided lifetimes + pub fn elided(&self, x: &Opaque2) { + + } + } + } + }; + + let method = &tcx + .opaques() + .iter() + .find(|def| def.name == "Opaque") + .unwrap() + .methods[0]; + + assert_eq!( + method.lifetime_env.num_lifetimes(), + 3, + "elided() must have three anon lifetimes" + ); + insta::assert_debug_snapshot!(method); + } + + #[test] + fn test_borrowing_fields() { + use std::collections::BTreeMap; + use std::fmt; + + let tcx = tcx! { + mod ffi { + #[diplomat::opaque] + pub struct Opaque; + + struct Input<'p, 'q> { + p_data: &'p Opaque, + q_data: &'q Opaque, + name: DiplomatStrSlice<'static>, + inner: Inner<'q>, + } + + struct Inner<'a> { + more_data: DiplomatStrSlice<'a>, + } + + struct Output<'p,'q> { + p_data: &'p Opaque, + q_data: &'q Opaque, + } + + impl<'a, 'b> Input<'a, 'b> { + pub fn as_output(self, _s: &'static DiplomatStr) -> Output<'b, 'a> { + Output { data: self.data } + } + + } + } + }; + + let method = &tcx + .structs() + .iter() + .find(|def| def.name == "Input") + .unwrap() + .methods[0]; + + let visitor = method.borrowing_field_visitor(&tcx, "this".ck().unwrap()); + let mut lt_to_borrowing_fields: BTreeMap<_, Vec<_>> = BTreeMap::new(); + visitor.visit_borrowing_fields(|lt, bf| { + lt_to_borrowing_fields + .entry(lt) + .or_default() + .push(DebugBorrowingField(bf)); + }); + + struct DebugBorrowingField<'m>(crate::hir::borrowing_field::BorrowingField<'m>); + + impl<'m> fmt::Debug for DebugBorrowingField<'m> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("\"")?; + self.0.try_backtrace(|i, ident| { + if i != 0 { + f.write_str(".")?; + } + f.write_str(ident.as_str()) + })?; + f.write_str("\"") + } + } + + let mut settings = insta::Settings::new(); + settings.set_sort_maps(true); + + settings.bind(|| { + insta::assert_debug_snapshot!(lt_to_borrowing_fields); + }) + } +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/lifetimes.rs b/deps/crates/vendor/diplomat_core/src/hir/lifetimes.rs new file mode 100644 index 00000000000000..b6c4d407ac973e --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/lifetimes.rs @@ -0,0 +1,453 @@ +//! Lifetime information for types. +#![allow(dead_code)] + +use super::IdentBuf; +use crate::ast; +use core::fmt::Debug; +use core::hash::Hash; + +use smallvec::{smallvec, SmallVec}; +use std::borrow::{Borrow, Cow}; + +/// Convenience const representing the number of lifetimes a [`LifetimeEnv`] +/// can hold inline before needing to dynamically allocate. +pub(crate) const INLINE_NUM_LIFETIMES: usize = 4; + +/// The lifetimes and bounds found on a method or type definition +#[derive(Debug)] +pub struct LifetimeEnv { + /// List of named lifetimes in scope of the method, and their bounds + nodes: SmallVec<[BoundedLifetime; INLINE_NUM_LIFETIMES]>, + + /// Only relevant for method LifetimeEnvs (otherwise this is nodes.len()) + /// + /// The number of named _and_ anonymous lifetimes in the method. + /// We store the sum since it represents the upper bound on what indices + /// are in range of the graph. If we make a [`Lifetimes`] with + /// `num_lifetimes` entries, then `Lifetime`s that convert into + /// `Lifetime`s will fall into this range, and we'll know that it's + /// a named lifetime if it's < `nodes.len()`, or that it's an anonymous + /// lifetime if it's < `num_lifetimes`. Otherwise, we'd have to make a + /// distinction in `Lifetime` about which context it's in. + num_lifetimes: usize, +} + +impl LifetimeEnv { + /// Format a lifetime indexing this env for use in code + pub fn fmt_lifetime(&self, lt: impl Borrow) -> Cow<'_, str> { + // we use Borrow here so that this can be used in templates where there's autoborrowing + let lt = *lt.borrow(); + if let Some(lt) = self.nodes.get(lt.0) { + Cow::from(lt.ident.as_str()) + } else if lt.0 < self.num_lifetimes { + format!("anon_{}", lt.0 - self.nodes.len()).into() + } else { + panic!("Found out of range lifetime: Got {lt:?} for env with {} nodes and {} total lifetimes", self.nodes.len(), self.num_lifetimes); + } + } + + /// Get an iterator of all lifetimes that this must live as long as (including itself) + /// with the first lifetime always being returned first + pub fn all_shorter_lifetimes( + &self, + lt: impl Borrow, + ) -> impl Iterator + '_ { + // we use Borrow here so that this can be used in templates where there's autoborrowing + let lt = *lt.borrow(); + // longer = true, since we are looking for lifetimes this is longer than + LifetimeTransitivityIterator::new(self, lt.0, false) + } + + /// Same as all_shorter_lifetimes but the other way + pub fn all_longer_lifetimes( + &self, + lt: impl Borrow, + ) -> impl Iterator + '_ { + // we use Borrow here so that this can be used in templates where there's autoborrowing + let lt = *lt.borrow(); + LifetimeTransitivityIterator::new(self, lt.0, true) + } + + // List all named and unnamed lifetimes + pub fn num_lifetimes(&self) -> usize { + self.num_lifetimes + } + + pub fn all_lifetimes(&self) -> impl ExactSizeIterator { + (0..self.num_lifetimes()).map(Lifetime::new) + } + + /// Get the bounds for a named lifetime (none for unnamed lifetimes) + pub(super) fn get_bounds(&self, named_lifetime: Lifetime) -> Option<&BoundedLifetime> { + self.nodes.get(named_lifetime.0) + } + + /// Returns a new [`LifetimeEnv`]. + pub(super) fn new( + nodes: SmallVec<[BoundedLifetime; INLINE_NUM_LIFETIMES]>, + num_lifetimes: usize, + ) -> Self { + Self { + nodes, + num_lifetimes, + } + } + + /// Returns a fresh [`Lifetimes`] corresponding to `self`. + pub fn lifetimes(&self) -> Lifetimes { + let indices = (0..self.num_lifetimes) + .map(|index| MaybeStatic::NonStatic(Lifetime::new(index))) + .collect(); + + Lifetimes { indices } + } + + /// Returns a new [`SubtypeLifetimeVisitor`], which can visit all reachable + /// lifetimes + pub fn subtype_lifetimes_visitor(&self, visit_fn: F) -> SubtypeLifetimeVisitor<'_, F> + where + F: FnMut(Lifetime), + { + SubtypeLifetimeVisitor::new(self, visit_fn) + } +} + +/// A lifetime in a [`LifetimeEnv`], which keeps track of which lifetimes it's +/// longer and shorter than. +/// +/// Invariant: for a BoundedLifetime found inside a LifetimeEnv, all short/long connections +/// should be bidirectional. +#[derive(Debug)] +pub(super) struct BoundedLifetime { + pub(super) ident: IdentBuf, + /// Lifetimes longer than this (not transitive) + /// + /// These are the inverse graph edges compared to `shorter` + pub(super) longer: SmallVec<[Lifetime; 2]>, + /// Lifetimes this is shorter than (not transitive) + /// + /// These match `'a: 'b + 'c` bounds + pub(super) shorter: SmallVec<[Lifetime; 2]>, +} + +impl BoundedLifetime { + /// Returns a new [`BoundedLifetime`]. + pub(super) fn new( + ident: IdentBuf, + longer: SmallVec<[Lifetime; 2]>, + shorter: SmallVec<[Lifetime; 2]>, + ) -> Self { + Self { + ident, + longer, + shorter, + } + } +} + +/// Visit subtype lifetimes recursively, keeping track of which have already +/// been visited. +pub struct SubtypeLifetimeVisitor<'lt, F> { + lifetime_env: &'lt LifetimeEnv, + visited: SmallVec<[bool; INLINE_NUM_LIFETIMES]>, + visit_fn: F, +} + +impl<'lt, F> SubtypeLifetimeVisitor<'lt, F> +where + F: FnMut(Lifetime), +{ + fn new(lifetime_env: &'lt LifetimeEnv, visit_fn: F) -> Self { + Self { + lifetime_env, + visited: smallvec![false; lifetime_env.nodes.len()], + visit_fn, + } + } + + /// Visit more sublifetimes. This method tracks which lifetimes have already + /// been visited, and uses this to not visit the same lifetime twice. + pub fn visit_subtypes(&mut self, method_lifetime: Lifetime) { + if let Some(visited @ false) = self.visited.get_mut(method_lifetime.0) { + *visited = true; + + (self.visit_fn)(method_lifetime); + + for longer in self.lifetime_env.nodes[method_lifetime.0].longer.iter() { + self.visit_subtypes(*longer) + } + } else { + debug_assert!( + method_lifetime.0 > self.lifetime_env.num_lifetimes, + "method lifetime has an internal index that's not in range of the lifetime env" + ); + } + } +} + +/// Wrapper type for `Lifetime` and `Lifetime`, indicating that it may +/// be the `'static` lifetime. +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[allow(clippy::exhaustive_enums)] // this will only ever have two variants +pub enum MaybeStatic { + Static, + NonStatic(T), +} + +impl MaybeStatic { + /// Maps the lifetime, if it's not the `'static` lifetime, to another + /// non-static lifetime. + pub(super) fn map_nonstatic(self, f: F) -> MaybeStatic + where + F: FnOnce(T) -> R, + { + match self { + MaybeStatic::Static => MaybeStatic::Static, + MaybeStatic::NonStatic(lifetime) => MaybeStatic::NonStatic(f(lifetime)), + } + } + + /// Maps the lifetime, if it's not the `'static` lifetime, to a potentially + /// static lifetime. + pub(super) fn flat_map_nonstatic(self, f: F) -> MaybeStatic + where + F: FnOnce(T) -> MaybeStatic, + { + match self { + MaybeStatic::Static => MaybeStatic::Static, + MaybeStatic::NonStatic(lifetime) => f(lifetime), + } + } +} + +/// A lifetime that exists as part of a type name, struct signature, or method signature. +/// +/// This index only makes sense in the context of a surrounding type or method; since +/// this is essentially an index into that type/method's lifetime list. +#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)] +pub struct Lifetime(usize); + +/// A set of lifetimes found on a type name, struct signature, or method signature +#[derive(Clone, Debug)] +pub struct Lifetimes { + indices: SmallVec<[MaybeStatic; 2]>, +} + +impl Lifetime { + pub(super) const fn new(index: usize) -> Self { + Self(index) + } +} + +impl Lifetimes { + /// Returns an iterator over the contained [`Lifetime`]s. + pub fn lifetimes(&self) -> impl ExactSizeIterator> + '_ { + self.indices.iter().copied() + } + + pub(super) fn as_slice(&self) -> &[MaybeStatic] { + self.indices.as_slice() + } +} + +impl Lifetime { + /// Returns a [`Lifetime`] from its AST counterparts. + pub(super) fn from_ast(named: &ast::NamedLifetime, lifetime_env: &ast::LifetimeEnv) -> Self { + let index = lifetime_env + .id(named) + .unwrap_or_else(|| panic!("lifetime `{named}` not found in lifetime env")); + Self::new(index) + } + + /// Returns a new [`MaybeStatic`] representing `self` in the + /// scope of the method that it appears in. + /// + /// For example, if we have some `Foo<'a>` type with a field `&'a Bar`, then + /// we can call this on the `'a` on the field. If `Foo` was `Foo<'static>` + /// in the method, then this will return `MaybeStatic::Static`. But if it + /// was `Foo<'b>`, then this will return `MaybeStatic::NonStatic` containing + /// the `Lifetime` corresponding to `'b`. + pub fn as_method_lifetime(self, method_lifetimes: &Lifetimes) -> MaybeStatic { + method_lifetimes.indices[self.0] + } +} + +impl Lifetimes { + pub(super) fn from_fn(lifetimes: &[ast::Lifetime], lower_fn: F) -> Self + where + F: FnMut(&ast::Lifetime) -> MaybeStatic, + { + Self { + indices: lifetimes.iter().map(lower_fn).collect(), + } + } + + /// Append an additional lifetime. Used to tack on anon lifetimes + pub(super) fn append_lifetime(&mut self, lifetime: MaybeStatic) { + self.indices.push(lifetime) + } + + /// Returns a new [`Lifetimes`] representing the lifetimes in the scope + /// of the method this type appears in. + /// + /// # Examples + /// + /// ```rust + /// # struct Alice<'a>(&'a ()); + /// # struct Bob<'b>(&'b ()); + /// struct Foo<'a, 'b> { + /// alice: Alice<'a>, + /// bob: Bob<'b>, + /// } + /// + /// fn bar<'x, 'y>(arg: Foo<'x, 'y>) {} + /// ``` + /// Here, `Foo` will have a [`Lifetimes`] containing `['a, 'b]`, + /// and `bar` will have a [`Lifetimes`] containing `{'x: 'x, 'y: 'y}`. + /// When we enter the scope of `Foo` as a type, we use this method to combine + /// the two to get a new [`Lifetimes`] representing the mapping from + /// lifetimes in `Foo`'s scope to lifetimes in `bar`s scope: `{'a: 'x, 'b: 'y}`. + /// + /// This tells us that `arg.alice` has lifetime `'x` in the method, and + /// that `arg.bob` has lifetime `'y`. + pub fn as_method_lifetimes(&self, method_lifetimes: &Lifetimes) -> Lifetimes { + let indices = self + .indices + .iter() + .map(|maybe_static_lt| { + maybe_static_lt.flat_map_nonstatic(|lt| lt.as_method_lifetime(method_lifetimes)) + }) + .collect(); + + Lifetimes { indices } + } +} + +struct LifetimeTransitivityIterator<'env> { + env: &'env LifetimeEnv, + visited: Vec, + queue: Vec, + longer: bool, +} + +impl<'env> LifetimeTransitivityIterator<'env> { + // Longer is whether we are looking for lifetimes longer or shorter than this + fn new(env: &'env LifetimeEnv, starting: usize, longer: bool) -> Self { + Self { + env, + visited: vec![false; env.num_lifetimes()], + queue: vec![starting], + longer, + } + } +} + +impl<'env> Iterator for LifetimeTransitivityIterator<'env> { + type Item = Lifetime; + + fn next(&mut self) -> Option { + while let Some(next) = self.queue.pop() { + if self.visited[next] { + continue; + } + self.visited[next] = true; + + if let Some(named) = self.env.nodes.get(next) { + let edge_dir = if self.longer { + &named.longer + } else { + &named.shorter + }; + self.queue.extend(edge_dir.iter().map(|i| i.0)); + } + + return Some(Lifetime::new(next)); + } + None + } +} + +/// Convenience type for linking the lifetimes found at a type *use* site (e.g. `&'c Foo<'a, 'b>`) +/// with the lifetimes found at its *def* site (e.g. `struct Foo<'x, 'y>`). +/// +/// Construct this by calling `.linked_lifetimes()` on a StructPath or OpaquePath +pub struct LinkedLifetimes<'def, 'tcx> { + env: &'tcx LifetimeEnv, + self_lt: Option>, + lifetimes: &'def Lifetimes, +} + +impl<'def, 'tcx> LinkedLifetimes<'def, 'tcx> { + pub(crate) fn new( + env: &'tcx LifetimeEnv, + self_lt: Option>, + lifetimes: &'def Lifetimes, + ) -> Self { + debug_assert_eq!( + lifetimes.lifetimes().len(), + env.all_lifetimes().len(), + "Should only link lifetimes between a type and its def" + ); + Self { + env, + self_lt, + lifetimes, + } + } + + /// Takes a lifetime at the def site and produces one at the use site + pub fn def_to_use(&self, def_lt: Lifetime) -> MaybeStatic { + *self + .lifetimes + .as_slice() + .get(def_lt.0) + .expect("All def site lifetimes must be used!") + } + + /// The lifetime env at the def site. Def lifetimes should be resolved + /// against this. + pub fn def_env(&self) -> &'tcx LifetimeEnv { + self.env + } + + /// Link lifetimes from the use site to lifetimes from the def site, only including + /// lifetimes found at the def site. + /// + /// This will *not* include the self-lifetime, i.e. for an opaque use site `&'c Foo<'a, 'b>` + /// this will not include `'c` (but you can obtain it from [`Self::self_lifetime()`])) + /// + /// The return iterator returns pairs of (use_lt, def_lt), in order. + /// + /// This behaves identically to [`Self::lifetimes_all()`] for `LinkedLifetimes` constructed + /// from anything other than a borrowing opaque. + pub fn lifetimes_def_only( + &self, + ) -> impl Iterator, Lifetime)> + '_ { + self.lifetimes.lifetimes().zip(self.env.all_lifetimes()) + } + + /// If there is a self-lifetime (e.g. `'c` on `&'c Foo<'a, 'b>`), return it. This lifetime + /// isn't found at the def site. + pub fn self_lifetime(&self) -> Option> { + self.self_lt + } + + /// Link lifetimes from the use site to lifetimes from the def site, including self lifetimes. + /// + /// This returns Options since self-lifetimes do not map to anything at the def site. + /// + /// The return iterator returns pairs of (use_lt, def_lt), in order, with the first entry potentially being + /// the self lifetime (which has a def_lt of None). + /// + /// This behaves identically to [`Self::lifetimes_all()`] for `LinkedLifetimes` constructed + /// from anything other than a borrowing opaque. + pub fn lifetimes_all( + &self, + ) -> impl Iterator, Option)> + '_ { + self.self_lt.iter().map(|i| (*i, None)).chain( + self.lifetimes + .lifetimes() + .zip(self.env.all_lifetimes().map(Some)), + ) + } +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/lowering.rs b/deps/crates/vendor/diplomat_core/src/hir/lowering.rs new file mode 100644 index 00000000000000..c92dc42d3d1973 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/lowering.rs @@ -0,0 +1,1958 @@ +use super::{ + AttributeContext, AttributeValidator, Attrs, Borrow, BoundedLifetime, Callback, CallbackParam, + EnumDef, EnumPath, EnumVariant, Everywhere, IdentBuf, InputOnly, Lifetime, LifetimeEnv, + LifetimeLowerer, LookupId, MaybeOwn, Method, NonOptional, OpaqueDef, OpaquePath, Optional, + OutStructDef, OutStructField, OutStructPath, OutType, Param, ParamLifetimeLowerer, ParamSelf, + PrimitiveType, ReturnLifetimeLowerer, ReturnType, ReturnableStructPath, + SelfParamLifetimeLowerer, SelfType, Slice, SpecialMethod, SpecialMethodPresence, StructDef, + StructField, StructPath, SuccessType, SymbolId, TraitDef, TraitParamSelf, TraitPath, + TyPosition, Type, TypeDef, TypeId, +}; +use crate::ast::attrs::AttrInheritContext; +use crate::{ast, Env}; +use core::fmt; +use strck::IntoCk; + +/// An error from lowering the AST to the HIR. +#[derive(Debug)] +#[non_exhaustive] +pub enum LoweringError { + /// The purpose of having this is that translating to the HIR has enormous + /// potential for really detailed error handling and giving suggestions. + /// + /// Unfortunately, working out what the error enum should look like to enable + /// this is really hard. The plan is that once the lowering code is completely + /// written, we ctrl+F for `"LoweringError::Other"` in the lowering code, and turn every + /// instance into an specialized enum variant, generalizing where possible + /// without losing any information. + Other(String), +} + +impl fmt::Display for LoweringError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Self::Other(ref s) => s.fmt(f), + } + } +} + +#[derive(Default, Clone)] +pub struct ErrorContext { + item: String, + subitem: Option, +} + +impl fmt::Display for ErrorContext { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if let Some(ref subitem) = self.subitem { + write!(f, "{}::{subitem}", self.item) + } else { + self.item.fmt(f) + } + } +} + +impl fmt::Debug for ErrorContext { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +/// An error store, which one can push errors to. It keeps track of the +/// current "context" for the error, usually a type or a type::method. `'tree` +/// is the AST/HIR tree it is temporarily borrowing from for the context. +#[derive(Default)] +pub struct ErrorStore<'tree> { + /// The errors + errors: Vec, + /// The current context (types, modules) + item: &'tree str, + /// The current sub-item context (methods, etc) + subitem: Option<&'tree str>, +} + +pub type ErrorAndContext = (ErrorContext, LoweringError); + +/// Where a type was found +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] +enum TypeLoweringContext { + Struct, + Callback, + Method, +} + +impl<'tree> ErrorStore<'tree> { + /// Push an error to the error store + pub fn push(&mut self, error: LoweringError) { + let context = ErrorContext { + item: self.item.into(), + subitem: self.subitem.map(|s| s.into()), + }; + self.errors.push((context, error)); + } + + pub(super) fn take_errors(&mut self) -> Vec { + core::mem::take(&mut self.errors) + } + + pub(super) fn is_empty(&self) -> bool { + self.errors.is_empty() + } + + pub(super) fn set_item(&mut self, item: &'tree str) { + self.item = item; + self.subitem = None; + } + pub(super) fn set_subitem(&mut self, subitem: &'tree str) { + self.subitem = Some(subitem); + } +} + +pub(super) struct LoweringContext<'ast> { + pub lookup_id: LookupId<'ast>, + pub errors: ErrorStore<'ast>, + pub env: &'ast Env, + pub attr_validator: Box, + pub cfg: super::LoweringConfig, +} + +/// An item and the info needed to +pub(crate) struct ItemAndInfo<'ast, Ast> { + pub(crate) item: &'ast Ast, + pub(crate) in_path: &'ast ast::Path, + /// Any parent attributes resolved from the module, for a type context + pub(crate) ty_parent_attrs: Attrs, + + /// Any parent attributes resolved from the module, for a method context + pub(crate) method_parent_attrs: Attrs, + pub(crate) id: SymbolId, +} + +impl<'ast> LoweringContext<'ast> { + /// Lowers an [`ast::Ident`]s into an [`hir::IdentBuf`]. + /// + /// If there are any errors, they're pushed to `errors` and `Err` is returned. + pub(super) fn lower_ident( + &mut self, + ident: &ast::Ident, + context: &'static str, + ) -> Result { + match ident.as_str().ck() { + Ok(name) => Ok(name.to_owned()), + Err(e) => { + self.errors.push(LoweringError::Other(format!( + "Ident `{ident}` from {context} could not be turned into a Rust ident: {e}" + ))); + Err(()) + } + } + } + + /// Lowers multiple items at once + fn lower_all( + &mut self, + ast_defs: impl ExactSizeIterator>, + lower: impl Fn(&mut Self, ItemAndInfo<'ast, Ast>) -> Result, + ) -> Result, ()> { + let mut hir_types = Ok(Vec::with_capacity(ast_defs.len())); + + for def in ast_defs { + let hir_type = lower(self, def); + + match (hir_type, &mut hir_types) { + (Ok(hir_type), Ok(hir_types)) => hir_types.push(hir_type), + _ => hir_types = Err(()), + } + } + + hir_types + } + + pub(super) fn lower_all_enums( + &mut self, + ast_defs: impl ExactSizeIterator>, + ) -> Result, ()> { + self.lower_all(ast_defs, Self::lower_enum) + } + pub(super) fn lower_all_structs( + &mut self, + ast_defs: impl ExactSizeIterator>, + ) -> Result, ()> { + self.lower_all(ast_defs, Self::lower_struct) + } + pub(super) fn lower_all_out_structs( + &mut self, + ast_defs: impl ExactSizeIterator>, + ) -> Result, ()> { + self.lower_all(ast_defs, Self::lower_out_struct) + } + pub(super) fn lower_all_opaques( + &mut self, + ast_defs: impl ExactSizeIterator>, + ) -> Result, ()> { + self.lower_all(ast_defs, Self::lower_opaque) + } + pub(super) fn lower_all_traits( + &mut self, + ast_defs: impl ExactSizeIterator>, + ) -> Result, ()> { + self.lower_all(ast_defs, Self::lower_trait) + } + + pub(super) fn lower_all_functions( + &mut self, + ast_defs: impl ExactSizeIterator>, + ) -> Result, ()> { + self.lower_all(ast_defs, Self::lower_function) + } + + fn lower_enum(&mut self, item: ItemAndInfo<'ast, ast::Enum>) -> Result { + let ast_enum = item.item; + self.errors.set_item(ast_enum.name.as_str()); + let name = self.lower_ident(&ast_enum.name, "enum name"); + let attrs = self.attr_validator.attr_from_ast( + &ast_enum.attrs, + &item.ty_parent_attrs, + &mut self.errors, + ); + + let mut variants = Ok(Vec::with_capacity(ast_enum.variants.len())); + let variant_parent_attrs = attrs.for_inheritance(AttrInheritContext::Variant); + for (ident, discriminant, docs, attrs) in ast_enum.variants.iter() { + let name = self.lower_ident(ident, "enum variant"); + let attrs = + self.attr_validator + .attr_from_ast(attrs, &variant_parent_attrs, &mut self.errors); + match (name, &mut variants) { + (Ok(name), Ok(variants)) => { + let variant = EnumVariant { + docs: docs.clone(), + name, + discriminant: *discriminant, + attrs, + }; + self.attr_validator.validate( + &variant.attrs, + AttributeContext::EnumVariant(&variant), + &mut self.errors, + ); + variants.push(variant); + } + _ => variants = Err(()), + } + } + + let mut special_method_presence = SpecialMethodPresence::default(); + let methods = if attrs.disable { + Vec::new() + } else { + self.lower_all_methods( + &ast_enum.methods[..], + item.in_path, + &item.method_parent_attrs, + item.id.try_into()?, + &mut special_method_presence, + )? + }; + + let def = EnumDef::new( + ast_enum.docs.clone(), + name?, + variants?, + methods, + attrs, + special_method_presence, + ); + + self.attr_validator.validate( + &def.attrs, + AttributeContext::Type(TypeDef::from(&def)), + &mut self.errors, + ); + + Ok(def) + } + + fn lower_opaque(&mut self, item: ItemAndInfo<'ast, ast::OpaqueType>) -> Result { + let ast_opaque = item.item; + self.errors.set_item(ast_opaque.name.as_str()); + let name = self.lower_ident(&ast_opaque.name, "opaque name"); + let dtor_abi_name = self.lower_ident(&ast_opaque.dtor_abi_name, "opaque dtor abi name"); + + let attrs = self.attr_validator.attr_from_ast( + &ast_opaque.attrs, + &item.ty_parent_attrs, + &mut self.errors, + ); + let mut special_method_presence = SpecialMethodPresence::default(); + let methods = if attrs.disable { + Vec::new() + } else { + self.lower_all_methods( + &ast_opaque.methods[..], + item.in_path, + &item.method_parent_attrs, + item.id.try_into()?, + &mut special_method_presence, + )? + }; + let lifetimes = self.lower_type_lifetime_env(&ast_opaque.lifetimes); + + let def = OpaqueDef::new( + ast_opaque.docs.clone(), + name?, + methods, + attrs, + lifetimes?, + special_method_presence, + dtor_abi_name?, + ); + self.attr_validator.validate( + &def.attrs, + AttributeContext::Type(TypeDef::from(&def)), + &mut self.errors, + ); + Ok(def) + } + + fn lower_struct(&mut self, item: ItemAndInfo<'ast, ast::Struct>) -> Result { + let ast_struct = item.item; + self.errors.set_item(ast_struct.name.as_str()); + let struct_name = self.lower_ident(&ast_struct.name, "struct name")?; + + let mut fields = Ok(Vec::with_capacity(ast_struct.fields.len())); + + let attrs = self.attr_validator.attr_from_ast( + &ast_struct.attrs, + &item.ty_parent_attrs, + &mut self.errors, + ); + // Only compute fields if the type isn't disabled, otherwise we may encounter forbidden types + if !attrs.disable { + for (name, ty, docs, attrs) in ast_struct.fields.iter() { + let name = self.lower_ident(name, "struct field name")?; + if !ty.is_ffi_safe() { + let ffisafe = ty.ffi_safe_version(); + self.errors.push(LoweringError::Other(format!( + "Found FFI-unsafe type {ty} in struct field {struct_name}.{name}, consider using {ffisafe}", + ))); + } + let ty = self.lower_type::( + ty, + &mut &ast_struct.lifetimes, + TypeLoweringContext::Struct, + item.in_path, + ); + + let field_attrs = + self.attr_validator + .attr_from_ast(attrs, &Attrs::default(), &mut self.errors); + + self.attr_validator.validate( + &field_attrs, + AttributeContext::Field, + &mut self.errors, + ); + + match (ty, &mut fields) { + (Ok(ty), Ok(fields)) => fields.push(StructField { + docs: docs.clone(), + name, + ty, + attrs: field_attrs, + }), + _ => fields = Err(()), + } + } + } + let lifetimes = self.lower_type_lifetime_env(&ast_struct.lifetimes); + + let mut special_method_presence = SpecialMethodPresence::default(); + let methods = if attrs.disable { + Vec::new() + } else if ast_struct.fields.is_empty() { + if !ast_struct.methods.is_empty() { + self.errors.push(LoweringError::Other(format!( + "Methods on ZST structs are not yet implemented: {}", + ast_struct.name + ))); + return Err(()); + } else { + Vec::new() + } + } else { + self.lower_all_methods( + &ast_struct.methods[..], + item.in_path, + &item.method_parent_attrs, + item.id.try_into()?, + &mut special_method_presence, + )? + }; + let def = StructDef::new( + ast_struct.docs.clone(), + struct_name, + fields?, + methods, + attrs, + lifetimes?, + special_method_presence, + ); + + self.attr_validator.validate( + &def.attrs, + AttributeContext::Type(TypeDef::from(&def)), + &mut self.errors, + ); + Ok(def) + } + + fn lower_trait(&mut self, item: ItemAndInfo<'ast, ast::Trait>) -> Result { + let ast_trait = item.item; + self.errors.set_item(ast_trait.name.as_str()); + let trait_name = self.lower_ident(&ast_trait.name, "trait name")?; + + let attrs = self.attr_validator.attr_from_ast( + &ast_trait.attrs, + &item.ty_parent_attrs, + &mut self.errors, + ); + + if ast_trait.is_send && !self.attr_validator.attrs_supported().traits_are_send { + self.errors.push(LoweringError::Other( + "Traits are not safe to std::marker::Send in this backend".into(), + )); + } + if ast_trait.is_sync && !self.attr_validator.attrs_supported().traits_are_sync { + self.errors.push(LoweringError::Other( + "Traits are not safe to std::marker::Send in this backend".into(), + )); + } + + let fcts = if attrs.disable { + Vec::new() + } else { + let mut fcts = Vec::with_capacity(ast_trait.methods.len()); + for ast_trait_method in ast_trait.methods.iter() { + let trait_method_attrs = self.attr_validator.attr_from_ast( + &ast_trait_method.attrs, + &attrs, + &mut self.errors, + ); + + if trait_method_attrs.disable { + continue; + } + + fcts.push(self.lower_trait_method(ast_trait_method, item.in_path, &attrs)?); + } + fcts + }; + let lifetimes = self.lower_type_lifetime_env(&ast_trait.lifetimes); + let def = TraitDef::new(ast_trait.docs.clone(), trait_name, fcts, attrs, lifetimes?); + + self.attr_validator + .validate(&def.attrs, AttributeContext::Trait(&def), &mut self.errors); + Ok(def) + } + + fn lower_trait_method( + &mut self, + ast_trait_method: &'ast ast::TraitMethod, + in_path: &ast::Path, + parent_trait_attrs: &Attrs, + ) -> Result { + self.errors.set_subitem(ast_trait_method.name.as_str()); + let name = ast_trait_method.name.clone(); + let self_param_ltl = SelfParamLifetimeLowerer::new(&ast_trait_method.lifetimes, self)?; + let (param_self, mut param_ltl) = + if let Some(self_param) = ast_trait_method.self_param.as_ref() { + let (param_self, param_ltl) = + self.lower_trait_self_param(self_param, self_param_ltl, in_path)?; + (Some(param_self), param_ltl) + } else { + (None, SelfParamLifetimeLowerer::no_self_ref(self_param_ltl)) + }; + + let params = + self.lower_many_callback_params(&ast_trait_method.params, &mut param_ltl, in_path)?; + + let return_type = self.lower_callback_return_type( + ast_trait_method.output_type.as_ref(), + &mut param_ltl, + in_path, + )?; + + let attrs = self.attr_validator.attr_from_ast( + &ast_trait_method.attrs, + parent_trait_attrs, + &mut self.errors, + ); + + Ok(Callback { + param_self, + params, + output: Box::new(return_type), + name: Some(self.lower_ident(&name, "trait name")?), + attrs: Some(attrs), + docs: Some(ast_trait_method.docs.clone()), + }) + } + + fn lower_function( + &mut self, + ast_function: ItemAndInfo<'ast, ast::Function>, + ) -> Result { + self.errors.set_item(ast_function.item.name.as_str()); + let name = ast_function.item.name.clone(); + let param_ltl = SelfParamLifetimeLowerer::no_self_ref(SelfParamLifetimeLowerer::new( + &ast_function.item.lifetimes, + self, + )?); + + let (ast_params, takes_write) = match ast_function.item.params.split_last() { + Some((last, remaining)) if last.is_write() => (remaining, true), + _ => (&ast_function.item.params[..], false), + }; + + let attrs = self.attr_validator.attr_from_ast( + &ast_function.item.attrs, + &ast_function.ty_parent_attrs, + &mut self.errors, + ); + + if !attrs.disable && !self.attr_validator.attrs_supported().free_functions { + self.errors.push(LoweringError::Other( + format!("Could not lower public function {}, backend does not support free functions. Try #[diplomat::attr(not(supports = free_functions), disable)].", ast_function.item.name.as_str()) + )); + return Err(()); + } + + let (params, return_type, lifetime_env) = if !attrs.disable { + let (params, return_ltl) = + self.lower_many_params(ast_params, param_ltl, ast_function.in_path)?; + + let (return_type, lifetime_env) = self.lower_return_type( + ast_function.item.output_type.as_ref(), + takes_write, + return_ltl, + ast_function.in_path, + )?; + (params, return_type, lifetime_env) + } else { + ( + Vec::new(), + ReturnType::Infallible(SuccessType::Unit), + LifetimeEnv::new(smallvec::SmallVec::new(), 0), + ) + }; + + let def = Method { + docs: ast_function.item.docs.clone(), + name: self.lower_ident(&name, "function name")?, + abi_name: self.lower_ident(&ast_function.item.abi_name, "function abi name")?, + lifetime_env, + param_self: None, + params, + output: return_type, + attrs: attrs.clone(), + }; + + self.attr_validator + .validate(&attrs, AttributeContext::Function(&def), &mut self.errors); + + Ok(def) + } + + fn lower_out_struct( + &mut self, + item: ItemAndInfo<'ast, ast::Struct>, + ) -> Result { + let ast_out_struct = item.item; + self.errors.set_item(ast_out_struct.name.as_str()); + let name = self.lower_ident(&ast_out_struct.name, "out-struct name"); + + let attrs = self.attr_validator.attr_from_ast( + &ast_out_struct.attrs, + &item.ty_parent_attrs, + &mut self.errors, + ); + let fields = { + let mut fields = Ok(Vec::with_capacity(ast_out_struct.fields.len())); + // Only compute fields if the type isn't disabled, otherwise we may encounter forbidden types + if !attrs.disable { + for (name, ty, docs, attrs) in ast_out_struct.fields.iter() { + let name = self.lower_ident(name, "out-struct field name"); + let ty = self.lower_out_type( + ty, + &mut &ast_out_struct.lifetimes, + item.in_path, + TypeLoweringContext::Struct, + false, + ); + + match (name, ty, &mut fields) { + (Ok(name), Ok(ty), Ok(fields)) => fields.push(OutStructField { + docs: docs.clone(), + name, + ty, + attrs: self.attr_validator.attr_from_ast( + attrs, + &Attrs::default(), + &mut self.errors, + ), + }), + _ => fields = Err(()), + } + } + } + + fields + }; + let mut special_method_presence = SpecialMethodPresence::default(); + let methods = if attrs.disable { + Vec::new() + } else { + self.lower_all_methods( + &ast_out_struct.methods[..], + item.in_path, + &item.method_parent_attrs, + item.id.try_into()?, + &mut special_method_presence, + )? + }; + + let lifetimes = self.lower_type_lifetime_env(&ast_out_struct.lifetimes); + let def = OutStructDef::new( + ast_out_struct.docs.clone(), + name?, + fields?, + methods, + attrs, + lifetimes?, + special_method_presence, + ); + + self.attr_validator.validate( + &def.attrs, + AttributeContext::Type(TypeDef::from(&def)), + &mut self.errors, + ); + Ok(def) + } + + /// Lowers an [`ast::Method`]s an [`hir::Method`]. + /// + /// If there are any errors, they're pushed to `errors` and `None` is returned. + fn lower_method( + &mut self, + method: &'ast ast::Method, + in_path: &ast::Path, + attrs: Attrs, + self_id: TypeId, + special_method_presence: &mut SpecialMethodPresence, + ) -> Result { + let name = self.lower_ident(&method.name, "method name"); + + let (ast_params, takes_write) = match method.params.split_last() { + Some((last, remaining)) if last.is_write() => (remaining, true), + _ => (&method.params[..], false), + }; + + let self_param_ltl = SelfParamLifetimeLowerer::new(&method.lifetime_env, self)?; + + let (param_self, param_ltl) = if let Some(self_param) = method.self_param.as_ref() { + let (param_self, param_ltl) = + self.lower_self_param(self_param, self_param_ltl, &method.abi_name, in_path)?; + (Some(param_self), param_ltl) + } else { + (None, SelfParamLifetimeLowerer::no_self_ref(self_param_ltl)) + }; + + let (params, return_ltl) = self.lower_many_params(ast_params, param_ltl, in_path)?; + + let (output, lifetime_env) = self.lower_return_type( + method.return_type.as_ref(), + takes_write, + return_ltl, + in_path, + )?; + + let abi_name = self.lower_ident(&method.abi_name, "method abi name")?; + let hir_method = Method { + docs: method.docs.clone(), + name: name?, + abi_name, + lifetime_env, + param_self, + params, + output, + attrs, + }; + + self.attr_validator.validate( + &hir_method.attrs, + AttributeContext::Method(&hir_method, self_id, special_method_presence), + &mut self.errors, + ); + + let is_comparison = matches!( + hir_method.attrs.special_method, + Some(SpecialMethod::Comparison) + ); + if is_comparison && method.return_type != Some(ast::TypeName::Ordering) { + self.errors.push(LoweringError::Other( + "Found comparison method that does not return cmp::Ordering".into(), + )); + return Err(()); + } + + Ok(hir_method) + } + + /// Lowers many [`ast::Method`]s into a vector of [`hir::Method`]s. + /// + /// If there are any errors, they're pushed to `errors` and `None` is returned. + fn lower_all_methods( + &mut self, + ast_methods: &'ast [ast::Method], + in_path: &ast::Path, + method_parent_attrs: &Attrs, + self_id: TypeId, + special_method_presence: &mut SpecialMethodPresence, + ) -> Result, ()> { + let mut methods = Ok(Vec::with_capacity(ast_methods.len())); + + let mut has_unnamed_constructor = false; + for method in ast_methods { + self.errors.set_subitem(method.name.as_str()); + let attrs = self.attr_validator.attr_from_ast( + &method.attrs, + method_parent_attrs, + &mut self.errors, + ); + if attrs.disable { + continue; + } + let method = + self.lower_method(method, in_path, attrs, self_id, special_method_presence); + match (method, &mut methods) { + (Ok(method), Ok(methods)) => { + if matches!( + method.attrs.special_method, + Some(SpecialMethod::Constructor) + ) { + if !has_unnamed_constructor { + methods.push(method); + has_unnamed_constructor = true; + } else { + self.errors.push(LoweringError::Other(format!( + "At most one unnamed constructor is allowed, see https://github.com/rust-diplomat/diplomat/issues/234 if you need overloading (extra abi_name: {})", + method.abi_name.as_str() + ))); + } + } else { + methods.push(method); + } + } + _ => methods = Err(()), + } + } + + methods + } + + /// Lowers an [`ast::TypeName`]s into a [`hir::Type`] (for non-output types) + /// + /// If there are any errors, they're pushed to `errors` and `None` is returned. + fn lower_type>( + &mut self, + ty: &ast::TypeName, + ltl: &mut impl LifetimeLowerer, + context: TypeLoweringContext, + in_path: &ast::Path, + ) -> Result, ()> { + let mut disallow_in_callbacks = |msg: &str| { + if context == TypeLoweringContext::Callback { + self.errors.push(LoweringError::Other(msg.into())); + Err(()) + } else { + Ok(()) + } + }; + match ty { + ast::TypeName::Primitive(prim) => Ok(Type::Primitive(PrimitiveType::from_ast(*prim))), + ast::TypeName::Ordering => { + self.errors.push(LoweringError::Other("Found cmp::Ordering in parameter or struct field, it is only allowed in return types".to_string())); + Err(()) + } + ast::TypeName::Named(path) | ast::TypeName::SelfType(path) => match path + .resolve(in_path, self.env) + { + ast::CustomType::Struct(strct) => { + if strct.fields.is_empty() { + self.errors.push(LoweringError::Other(format!( + "zero-size types are not allowed as method arguments: {ty} in {path}" + ))); + return Err(()); + } + if let Some(tcx_id) = self.lookup_id.resolve_struct(strct) { + let lifetimes = + ltl.lower_generics(&path.lifetimes[..], &strct.lifetimes, ty.is_self()); + + Ok(Type::Struct(StructPath::new( + lifetimes, + tcx_id, + MaybeOwn::Own, + ))) + } else if self.lookup_id.resolve_out_struct(strct).is_some() { + self.errors.push(LoweringError::Other(format!("found struct in input that is marked with #[diplomat::out]: {ty} in {path}"))); + Err(()) + } else { + unreachable!("struct `{}` wasn't found in the set of structs or out-structs, this is a bug.", strct.name); + } + } + ast::CustomType::Opaque(_) => { + self.errors.push(LoweringError::Other(format!( + "Opaque passed by value: {path}" + ))); + Err(()) + } + ast::CustomType::Enum(enm) => { + let tcx_id = self + .lookup_id + .resolve_enum(enm) + .expect("can't find enum in lookup map, which contains all enums from env"); + + Ok(Type::Enum(EnumPath::new(tcx_id))) + } + }, + ast::TypeName::ImplTrait(path) => { + if !self.attr_validator.attrs_supported().traits { + self.errors.push(LoweringError::Other( + "Traits are not supported by this backend".into(), + )); + } + let trt = path.resolve_trait(in_path, self.env); + let tcx_id = self + .lookup_id + .resolve_trait(&trt) + .expect("can't find trait in lookup map, which contains all traits from env"); + let lifetimes = + ltl.lower_generics(&path.lifetimes[..], &trt.lifetimes, ty.is_self()); + + Ok(Type::ImplTrait(P::build_trait_path(TraitPath::new( + lifetimes, tcx_id, + )))) + } + ast::TypeName::Reference(lifetime, mutability, ref_ty) => match ref_ty.as_ref() { + ast::TypeName::Named(path) | ast::TypeName::SelfType(path) => { + match path.resolve(in_path, self.env) { + ast::CustomType::Opaque(opaque) => { + let borrow = Borrow::new(ltl.lower_lifetime(lifetime), *mutability); + let lifetimes = ltl.lower_generics( + &path.lifetimes[..], + &opaque.lifetimes, + ref_ty.is_self(), + ); + let tcx_id = self.lookup_id.resolve_opaque(opaque).expect( + "can't find opaque in lookup map, which contains all opaques from env", + ); + + Ok(Type::Opaque(OpaquePath::new( + lifetimes, + Optional(false), + borrow, + tcx_id, + ))) + } + ast::CustomType::Struct(st) => { + disallow_in_callbacks( + "Cannot return references to structs from callbacks", + )?; + if self.attr_validator.attrs_supported().struct_refs { + let borrow = Borrow::new(ltl.lower_lifetime(lifetime), *mutability); + let lifetimes = ltl.lower_generics( + &path.lifetimes[..], + &st.lifetimes, + ref_ty.is_self(), + ); + let tcx_id = self.lookup_id.resolve_struct(st).expect( + "Can't find struct in lookup map, which contains all structs from env" + ); + Ok(Type::Struct(StructPath::new( + lifetimes, + tcx_id, + MaybeOwn::Borrow(borrow), + ))) + } else { + self.errors.push(LoweringError::Other("found &T in input where T is a struct. The backend must support struct_refs.".to_string())); + Err(()) + } + } + _ => { + self.errors.push(LoweringError::Other(format!("found &T in input where T is a custom type, but not opaque. T = {ref_ty}"))); + Err(()) + } + } + } + _ => { + self.errors.push(LoweringError::Other(format!("found &T in input where T isn't a custom type and therefore not opaque. T = {ref_ty}"))); + Err(()) + } + }, + ast::TypeName::Box(box_ty) => { + self.errors.push(match box_ty.as_ref() { + ast::TypeName::Named(path) | ast::TypeName::SelfType(path) => { + match path.resolve(in_path, self.env) { + ast::CustomType::Opaque(_) => LoweringError::Other(format!("found Box in input where T is an opaque, but owned opaques aren't allowed in inputs. try &T instead? T = {path}")), + _ => LoweringError::Other(format!("found Box in input where T is a custom type but not opaque. non-opaques can't be behind pointers, and opaques in inputs can't be owned. T = {path}")), + } + } + _ => LoweringError::Other(format!("found Box in input where T isn't a custom type. T = {box_ty}")), + }); + Err(()) + } + ast::TypeName::Option(opt_ty, stdlib) => { + match opt_ty.as_ref() { + ast::TypeName::Reference(lifetime, mutability, ref_ty) => match ref_ty.as_ref() + { + ast::TypeName::Named(path) | ast::TypeName::SelfType(path) => match path + .resolve(in_path, self.env) + { + ast::CustomType::Opaque(opaque) => { + if *stdlib == ast::StdlibOrDiplomat::Diplomat { + self.errors.push(LoweringError::Other("found DiplomatOption<&T>, please use Option<&T> (DiplomatOption is for primitives, structs, and enums)".to_string())); + return Err(()); + } + let borrow = Borrow::new(ltl.lower_lifetime(lifetime), *mutability); + let lifetimes = ltl.lower_generics( + &path.lifetimes, + &opaque.lifetimes, + ref_ty.is_self(), + ); + let tcx_id = self.lookup_id.resolve_opaque(opaque).expect( + "can't find opaque in lookup map, which contains all opaques from env", + ); + + Ok(Type::Opaque(OpaquePath::new( + lifetimes, + Optional(true), + borrow, + tcx_id, + ))) + } + _ => { + self.errors.push(LoweringError::Other(format!("found Option<&T> in input where T is a custom type, but it's not opaque. T = {ref_ty}"))); + Err(()) + } + }, + _ => { + self.errors.push(LoweringError::Other(format!("found Option<&T> in input, but T isn't a custom type and therefore not opaque. T = {ref_ty}"))); + Err(()) + } + }, + ast::TypeName::Named(path) | ast::TypeName::SelfType(path) => { + match path.resolve(in_path, self.env) { + ast::CustomType::Opaque(_) => { + self.errors.push(LoweringError::Other("Found Option where T is opaque, opaque types must be behind a reference".into())); + Err(()) + } + _ => { + if context == TypeLoweringContext::Struct + && *stdlib == ast::StdlibOrDiplomat::Stdlib + { + self.errors.push(LoweringError::Other("Found Option for struct/enum T in a struct field, please use DiplomatOption".into())); + return Err(()); + } + if !self.attr_validator.attrs_supported().option { + self.errors.push(LoweringError::Other("Options of structs/enums/primitives not supported by this backend".into())); + } + let inner = self.lower_type(opt_ty, ltl, context, in_path)?; + Ok(Type::DiplomatOption(Box::new(inner))) + } + } + } + ast::TypeName::Primitive(prim) => { + if context == TypeLoweringContext::Struct + && *stdlib == ast::StdlibOrDiplomat::Stdlib + { + self.errors.push(LoweringError::Other("Found Option for primitive T in a struct field, please use DiplomatOption".into())); + return Err(()); + } + if !self.attr_validator.attrs_supported().option { + self.errors.push(LoweringError::Other( + "Options of structs/enums/primitives not supported by this backend" + .into(), + )); + } + Ok(Type::DiplomatOption(Box::new(Type::Primitive( + PrimitiveType::from_ast(*prim), + )))) + } + ast::TypeName::StrSlice(encoding, _stdlib) => Ok(Type::DiplomatOption( + Box::new(Type::Slice(Slice::Strs(*encoding))), + )), + ast::TypeName::StrReference(..) | ast::TypeName::PrimitiveSlice(..) => { + let inner = self.lower_type(opt_ty, ltl, context, in_path)?; + Ok(Type::DiplomatOption(Box::new(inner))) + } + ast::TypeName::Box(box_ty) => { + // we could see whats in the box here too + self.errors.push(LoweringError::Other(format!("found Option> in input, but box isn't allowed in inputs. T = {box_ty}"))); + Err(()) + } + _ => { + self.errors.push(LoweringError::Other(format!("found Option in input, where T isn't a reference but Option in inputs requires that T is a reference to an opaque. T = {opt_ty}"))); + Err(()) + } + } + } + ast::TypeName::Result(_, _, _) => { + self.errors.push(LoweringError::Other( + "Results can only appear as the top-level return type of methods".into(), + )); + Err(()) + } + ast::TypeName::Write => { + self.errors.push(LoweringError::Other( + "DiplomatWrite can only appear as the last parameter of a method".into(), + )); + Err(()) + } + ast::TypeName::StrReference(lifetime, encoding, _stdlib) => { + if lifetime.is_none() { + disallow_in_callbacks("Cannot return owned slices from callbacks")?; + } + let new_lifetime = lifetime.as_ref().map(|lt| ltl.lower_lifetime(lt)); + if let Some(super::MaybeStatic::Static) = new_lifetime { + if !self.attr_validator.attrs_supported().static_slices { + self.errors.push(LoweringError::Other( + "'static string slice types are not supported. Try #[diplomat::attr(not(supports = static_slices), disable)]".into() + )); + } + } + Ok(Type::Slice(Slice::Str(new_lifetime, *encoding))) + } + ast::TypeName::StrSlice(encoding, _stdlib) => Ok(Type::Slice(Slice::Strs(*encoding))), + ast::TypeName::PrimitiveSlice(lm, prim, _stdlib) => { + if lm.is_none() { + disallow_in_callbacks("Cannot return owned slices from callbacks")?; + } + let new_lifetime = lm + .as_ref() + .map(|(lt, m)| Borrow::new(ltl.lower_lifetime(lt), *m)); + + if let Some(b) = new_lifetime { + if let super::MaybeStatic::Static = b.lifetime { + if !self.attr_validator.attrs_supported().static_slices { + self.errors.push(LoweringError::Other( + format!("'static {prim:?} slice types not supported. Try #[diplomat::attr(not(supports = static_slices), disable)]") + )); + } + } + } + + Ok(Type::Slice(Slice::Primitive( + new_lifetime.into(), + PrimitiveType::from_ast(*prim), + ))) + } + ast::TypeName::CustomTypeSlice(lm, type_name) => { + match type_name.as_ref() { + ast::TypeName::Named(path) => match path.resolve(in_path, self.env) { + ast::CustomType::Struct(..) => { + if !self.attr_validator.attrs_supported().abi_compatibles { + self.errors.push(LoweringError::Other( + "Primitive struct slices are not supported by this backend" + .into(), + )); + } + } + _ => self.errors.push(LoweringError::Other(format!( + "{type_name} slices are not supported." + ))), + }, + _ => self.errors.push(LoweringError::Other(format!( + "{type_name} slices are not supported." + ))), + } + + let new_lifetime = lm + .as_ref() + .map(|(lt, m)| Borrow::new(ltl.lower_lifetime(lt), *m)); + + if let Some(b) = new_lifetime { + if let super::MaybeStatic::Static = b.lifetime { + if !self.attr_validator.attrs_supported().static_slices { + self.errors.push(LoweringError::Other( + format!("'static {type_name:?} slice types not supported. Try #[diplomat::attr(not(supports = static_slices), disable)]") + )); + } + } + } + + match type_name.as_ref() { + ast::TypeName::Named(path) => match path.resolve(in_path, self.env) { + ast::CustomType::Struct(..) => { + let inner = self.lower_type::

(type_name, ltl, context, in_path)?; + match inner { + Type::Struct(st) => { + Ok(Type::Slice(Slice::Struct(new_lifetime.into(), st))) + } + _ => unreachable!(), + } + } + _ => { + self.errors.push(LoweringError::Other( + format!("Cannot have custom type {type_name} in a slice. Custom slices can only contain primitive-only structs.") + )); + Err(()) + } + }, + _ => { + self.errors.push(LoweringError::Other(format!( + "Cannot make a slice from type {type_name}" + ))); + Err(()) + } + } + } + ast::TypeName::Function(input_types, out_type, _mutability) => { + disallow_in_callbacks("Cannot nest callbacks")?; + if !self.attr_validator.attrs_supported().callbacks { + self.errors.push(LoweringError::Other( + "Callback arguments are not supported by this backend".into(), + )); + } + if context == TypeLoweringContext::Struct { + self.errors.push(LoweringError::Other( + "Callbacks currently unsupported in structs".into(), + )); + return Err(()); + } + let mut params: Vec = Vec::new(); + for in_ty in input_types.iter() { + let param = + self.lower_callback_param(/* anonymous */ None, in_ty, ltl, in_path)?; + + params.push(param) + } + + Ok(Type::Callback(P::build_callback(Callback { + param_self: None, + params, + output: Box::new(self.lower_callback_return_type( + Some(out_type), + ltl, + in_path, + )?), + name: None, + attrs: None, + docs: None, + }))) + } + ast::TypeName::Unit => { + self.errors.push(LoweringError::Other("Unit types can only appear as the return value of a method, or as the Ok/Err variants of a returned result".into())); + Err(()) + } + } + } + + /// Lowers an [`ast::TypeName`]s into an [`hir::OutType`]. + /// + /// If there are any errors, they're pushed to `errors` and `None` is returned. + fn lower_out_type( + &mut self, + ty: &ast::TypeName, + ltl: &mut impl LifetimeLowerer, + in_path: &ast::Path, + context: TypeLoweringContext, + in_result_option: bool, + ) -> Result { + match ty { + ast::TypeName::Primitive(prim) => { + Ok(OutType::Primitive(PrimitiveType::from_ast(*prim))) + } + ast::TypeName::Ordering => { + if context == TypeLoweringContext::Struct { + self.errors.push(LoweringError::Other( + "Found cmp::Ordering in struct field, it is only allowed in return types" + .to_string(), + )); + Err(()) + } else { + Ok(Type::Primitive(PrimitiveType::Ordering)) + } + } + ast::TypeName::Named(path) | ast::TypeName::SelfType(path) => { + match path.resolve(in_path, self.env) { + ast::CustomType::Struct(strct) => { + if !in_result_option && strct.fields.is_empty() { + self.errors.push(LoweringError::Other(format!("Found zero-size struct outside a `Result` or `Option`: {ty} in {in_path}"))); + return Err(()); + } + let lifetimes = + ltl.lower_generics(&path.lifetimes, &strct.lifetimes, ty.is_self()); + + if let Some(tcx_id) = self.lookup_id.resolve_struct(strct) { + Ok(OutType::Struct(ReturnableStructPath::Struct( + StructPath::new(lifetimes, tcx_id, MaybeOwn::Own), + ))) + } else if let Some(tcx_id) = self.lookup_id.resolve_out_struct(strct) { + Ok(OutType::Struct(ReturnableStructPath::OutStruct( + OutStructPath::new(lifetimes, tcx_id, MaybeOwn::Own), + ))) + } else { + unreachable!("struct `{}` wasn't found in the set of structs or out-structs, this is a bug.", strct.name); + } + } + ast::CustomType::Opaque(_) => { + self.errors.push(LoweringError::Other(format!( + "Opaque passed by value in input: {path}" + ))); + Err(()) + } + ast::CustomType::Enum(enm) => { + let tcx_id = self.lookup_id.resolve_enum(enm).expect( + "can't find enum in lookup map, which contains all enums from env", + ); + + Ok(OutType::Enum(EnumPath::new(tcx_id))) + } + } + } + ast::TypeName::Reference(lifetime, mutability, ref_ty) => match ref_ty.as_ref() { + ast::TypeName::Named(path) | ast::TypeName::SelfType(path) => { + match path.resolve(in_path, self.env) { + ast::CustomType::Opaque(opaque) => { + let borrow = Borrow::new(ltl.lower_lifetime(lifetime), *mutability); + let lifetimes = ltl.lower_generics( + &path.lifetimes, + &opaque.lifetimes, + ref_ty.is_self(), + ); + let tcx_id = self.lookup_id.resolve_opaque(opaque).expect( + "can't find opaque in lookup map, which contains all opaques from env", + ); + + Ok(OutType::Opaque(OpaquePath::new( + lifetimes, + Optional(false), + MaybeOwn::Borrow(borrow), + tcx_id, + ))) + } + _ => { + self.errors.push(LoweringError::Other(format!("found &T in output where T is a custom type, but not opaque. T = {ref_ty}"))); + Err(()) + } + } + } + _ => { + self.errors.push(LoweringError::Other(format!("found &T in output where T isn't a custom type and therefore not opaque. T = {ref_ty}, path = {in_path:?}"))); + Err(()) + } + }, + ast::TypeName::Box(box_ty) => match box_ty.as_ref() { + ast::TypeName::Named(path) | ast::TypeName::SelfType(path) => { + match path.resolve(in_path, self.env) { + ast::CustomType::Opaque(opaque) => { + let lifetimes = ltl.lower_generics( + &path.lifetimes, + &opaque.lifetimes, + box_ty.is_self(), + ); + let tcx_id = self.lookup_id.resolve_opaque(opaque).expect( + "can't find opaque in lookup map, which contains all opaques from env", + ); + + Ok(OutType::Opaque(OpaquePath::new( + lifetimes, + Optional(false), + MaybeOwn::Own, + tcx_id, + ))) + } + _ => { + self.errors.push(LoweringError::Other(format!("found Box in output where T is a custom type but not opaque. non-opaques can't be behind pointers. T = {path}"))); + Err(()) + } + } + } + _ => { + self.errors.push(LoweringError::Other(format!( + "found Box in output where T isn't a custom type. T = {box_ty}" + ))); + Err(()) + } + }, + ast::TypeName::Option(opt_ty, stdlib) => match opt_ty.as_ref() { + ast::TypeName::Reference(lifetime, mutability, ref_ty) => match ref_ty.as_ref() { + ast::TypeName::Named(path) | ast::TypeName::SelfType(path) => { + match path.resolve(in_path, self.env) { + ast::CustomType::Opaque(opaque) => { + if *stdlib == ast::StdlibOrDiplomat::Diplomat { + self.errors.push(LoweringError::Other("found DiplomatOption<&T>, please use Option<&T> (DiplomatOption is for primitives, structs, and enums)".to_string())); + return Err(()); + } + let borrow = Borrow::new(ltl.lower_lifetime(lifetime), *mutability); + let lifetimes = ltl.lower_generics( + &path.lifetimes, + &opaque.lifetimes, + ref_ty.is_self(), + ); + let tcx_id = self.lookup_id.resolve_opaque(opaque).expect( + "can't find opaque in lookup map, which contains all opaques from env", + ); + + Ok(OutType::Opaque(OpaquePath::new( + lifetimes, + Optional(true), + MaybeOwn::Borrow(borrow), + tcx_id, + ))) + } + _ => { + self.errors.push(LoweringError::Other(format!("found Option<&T> where T is a custom type, but it's not opaque. T = {ref_ty}"))); + Err(()) + } + } + } + _ => { + self.errors.push(LoweringError::Other(format!("found Option<&T>, but T isn't a custom type and therefore not opaque. T = {ref_ty}"))); + Err(()) + } + }, + ast::TypeName::Box(box_ty) => match box_ty.as_ref() { + ast::TypeName::Named(path) | ast::TypeName::SelfType(path) => { + match path.resolve(in_path, self.env) { + ast::CustomType::Opaque(opaque) => { + if *stdlib == ast::StdlibOrDiplomat::Diplomat { + self.errors.push(LoweringError::Other("found DiplomatOption>, please use Option> (DiplomatOption is for primitives, structs, and enums)".to_string())); + return Err(()); + } + let lifetimes = ltl.lower_generics( + &path.lifetimes, + &opaque.lifetimes, + box_ty.is_self(), + ); + let tcx_id = self.lookup_id.resolve_opaque(opaque).expect( + "can't find opaque in lookup map, which contains all opaques from env", + ); + + Ok(OutType::Opaque(OpaquePath::new( + lifetimes, + Optional(true), + MaybeOwn::Own, + tcx_id, + ))) + } + _ => { + self.errors.push(LoweringError::Other(format!("found Option> where T is a custom type, but it's not opaque. T = {box_ty}"))); + Err(()) + } + } + } + _ => { + self.errors.push(LoweringError::Other(format!("found Option>, but T isn't a custom type and therefore not opaque. T = {box_ty}"))); + Err(()) + } + }, + ast::TypeName::Named(path) | ast::TypeName::SelfType(path) => { + match path.resolve(in_path, self.env) { + ast::CustomType::Opaque(_) => { + self.errors.push(LoweringError::Other("Found Option where T is opaque, opaque types must be behind a reference".into())); + Err(()) + } + _ => { + if context == TypeLoweringContext::Struct + && *stdlib == ast::StdlibOrDiplomat::Stdlib + { + self.errors.push(LoweringError::Other("Found Option for struct/enum T in a struct field, please use DiplomatOption".into())); + return Err(()); + } + if !self.attr_validator.attrs_supported().option { + self.errors.push(LoweringError::Other("Options of structs/enums/primitives not supported by this backend".into())); + } + let inner = self.lower_out_type(opt_ty, ltl, in_path, context, true)?; + Ok(Type::DiplomatOption(Box::new(inner))) + } + } + } + ast::TypeName::Primitive(prim) => { + if context == TypeLoweringContext::Struct + && *stdlib == ast::StdlibOrDiplomat::Stdlib + { + self.errors.push(LoweringError::Other("Found Option for primitive T in a struct field, please use DiplomatOption".into())); + return Err(()); + } + if !self.attr_validator.attrs_supported().option { + self.errors.push(LoweringError::Other( + "Options of structs/enums/primitives not supported by this backend" + .into(), + )); + } + Ok(Type::DiplomatOption(Box::new(Type::Primitive( + PrimitiveType::from_ast(*prim), + )))) + } + _ => { + self.errors.push(LoweringError::Other(format!("found Option, where T isn't a reference but Option requires that T is a reference to an opaque. T = {opt_ty}"))); + Err(()) + } + }, + ast::TypeName::Result(_, _, _) => { + self.errors.push(LoweringError::Other( + "Results can only appear as the top-level return type of methods".into(), + )); + Err(()) + } + ast::TypeName::Write => { + self.errors.push(LoweringError::Other( + "DiplomatWrite can only appear as the last parameter of a method".into(), + )); + Err(()) + } + ast::TypeName::PrimitiveSlice(None, _, _stdlib) + | ast::TypeName::StrReference(None, _, _stdlib) => { + self.errors.push(LoweringError::Other( + "Owned slices cannot be returned".into(), + )); + Err(()) + } + ast::TypeName::StrReference(Some(l), encoding, _stdlib) => Ok(OutType::Slice( + Slice::Str(Some(ltl.lower_lifetime(l)), *encoding), + )), + ast::TypeName::StrSlice(.., _stdlib) => { + self.errors.push(LoweringError::Other( + "String slices can only be an input type".into(), + )); + Err(()) + } + ast::TypeName::PrimitiveSlice(Some((lt, m)), prim, _stdlib) => { + Ok(OutType::Slice(Slice::Primitive( + MaybeOwn::Borrow(Borrow::new(ltl.lower_lifetime(lt), *m)), + PrimitiveType::from_ast(*prim), + ))) + } + ast::TypeName::CustomTypeSlice(ltmt, type_name) => { + let new_lifetime = ltmt + .as_ref() + .map(|(lt, m)| Borrow::new(ltl.lower_lifetime(lt), *m)); + + if let Some(b) = new_lifetime { + if let super::MaybeStatic::Static = b.lifetime { + if !self.attr_validator.attrs_supported().static_slices { + self.errors.push(LoweringError::Other( + format!("'static {type_name:?} slice types not supported. Try #[diplomat::attr(not(supports = static_slices), disable)]") + )); + } + } + } + + match &type_name.as_ref() { + ast::TypeName::Named(path) => match path.resolve(in_path, self.env) { + ast::CustomType::Struct(..) => { + let inner = self.lower_out_type( + type_name, + ltl, + in_path, + context, + in_result_option, + )?; + match inner { + Type::Struct(st) => { + Ok(Type::Slice(Slice::Struct(new_lifetime.into(), st))) + } + _ => unreachable!(), + } + } + _ => { + self.errors.push(LoweringError::Other( + format!("Cannot have custom type {type_name} in a slice. Custom slices can only contain primitive-only structs.") + )); + Err(()) + } + }, + _ => { + self.errors.push(LoweringError::Other(format!( + "Cannot make a slice from type {type_name}" + ))); + Err(()) + } + } + } + ast::TypeName::Unit => { + self.errors.push(LoweringError::Other("Unit types can only appear as the return value of a method, or as the Ok/Err variants of a returned result".into())); + Err(()) + } + ast::TypeName::Function(..) => { + self.errors.push(LoweringError::Other( + "Function types can only be an input type".into(), + )); + Err(()) + } + ast::TypeName::ImplTrait(_) => { + self.errors.push(LoweringError::Other( + "Trait impls can only be an input type".into(), + )); + Err(()) + } + } + } + + /// Lowers an [`ast::SelfParam`] into an [`hir::ParamSelf`]. + /// + /// If there are any errors, they're pushed to `errors` and `None` is returned. + fn lower_self_param( + &mut self, + self_param: &ast::SelfParam, + self_param_ltl: SelfParamLifetimeLowerer<'ast>, + method_full_path: &ast::Ident, // for better error msg + in_path: &ast::Path, + ) -> Result<(ParamSelf, ParamLifetimeLowerer<'ast>), ()> { + match self_param.path_type.resolve(in_path, self.env) { + ast::CustomType::Struct(strct) => { + if let Some(tcx_id) = self.lookup_id.resolve_struct(strct) { + let (borrow, mut param_ltl) = if let Some((lt, mt)) = &self_param.reference { + if self.attr_validator.attrs_supported().struct_refs { + let (borrow_lt, param_ltl) = self_param_ltl.lower_self_ref(lt); + let borrow = Borrow::new(borrow_lt, *mt); + + (MaybeOwn::Borrow(borrow), param_ltl) + } else { + self.errors.push(LoweringError::Other(format!("Method `{method_full_path}` takes a reference to a struct as a self parameter, which isn't allowed. Backend must support struct_refs."))); + return Err(()); + } + } else { + (MaybeOwn::Own, self_param_ltl.no_self_ref()) + }; + + let attrs = self.attr_validator.attr_from_ast( + &self_param.attrs, + &Attrs::default(), + &mut self.errors, + ); + + // Even if we explicitly write out the type of `self` like + // `self: Foo<'a>`, the `'a` is still not considered for + // elision according to rustc, so is_self=true. + let type_lifetimes = param_ltl.lower_generics( + &self_param.path_type.lifetimes[..], + &strct.lifetimes, + true, + ); + + self.attr_validator.validate( + &attrs, + AttributeContext::SelfParam, + &mut self.errors, + ); + + Ok(( + ParamSelf::new( + SelfType::Struct(StructPath::new(type_lifetimes, tcx_id, borrow)), + attrs, + ), + param_ltl, + )) + } else if self.lookup_id.resolve_out_struct(strct).is_some() { + if let Some((lifetime, _)) = &self_param.reference { + self.errors.push(LoweringError::Other(format!("Method `{method_full_path}` takes an out-struct as the self parameter, which isn't allowed. Also, it's behind a reference, `{lifetime}`, but only opaques can be behind references"))); + Err(()) + } else { + self.errors.push(LoweringError::Other(format!("Method `{method_full_path}` takes an out-struct as the self parameter, which isn't allowed"))); + Err(()) + } + } else { + unreachable!( + "struct `{}` wasn't found in the set of structs or out-structs, this is a bug.", + strct.name + ); + } + } + ast::CustomType::Opaque(opaque) => { + let tcx_id = self + .lookup_id + .resolve_opaque(opaque) + .expect("opaque is in env"); + + if let Some((lifetime, mutability)) = &self_param.reference { + let (borrow_lifetime, mut param_ltl) = self_param_ltl.lower_self_ref(lifetime); + let borrow = Borrow::new(borrow_lifetime, *mutability); + let lifetimes = param_ltl.lower_generics( + &self_param.path_type.lifetimes, + &opaque.lifetimes, + true, + ); + + let attrs = self.attr_validator.attr_from_ast( + &self_param.attrs, + &Attrs::default(), + &mut self.errors, + ); + + self.attr_validator.validate( + &attrs, + AttributeContext::SelfParam, + &mut self.errors, + ); + + Ok(( + ParamSelf::new( + SelfType::Opaque(OpaquePath::new( + lifetimes, + NonOptional, + borrow, + tcx_id, + )), + attrs, + ), + param_ltl, + )) + } else { + self.errors.push(LoweringError::Other(format!("Method `{method_full_path}` takes an opaque by value as the self parameter, but opaques as inputs must be behind refs"))); + Err(()) + } + } + ast::CustomType::Enum(enm) => { + let tcx_id = self.lookup_id.resolve_enum(enm).expect("enum is in env"); + + let attrs = self.attr_validator.attr_from_ast( + &self_param.attrs, + &Attrs::default(), + &mut self.errors, + ); + + self.attr_validator + .validate(&attrs, AttributeContext::SelfParam, &mut self.errors); + + Ok(( + ParamSelf::new(SelfType::Enum(EnumPath::new(tcx_id)), attrs), + self_param_ltl.no_self_ref(), + )) + } + } + } + + fn lower_trait_self_param( + &mut self, + self_param: &ast::TraitSelfParam, + self_param_ltl: SelfParamLifetimeLowerer<'ast>, + in_path: &ast::Path, + ) -> Result<(TraitParamSelf, ParamLifetimeLowerer<'ast>), ()> { + let trt = self_param.path_trait.resolve_trait(in_path, self.env); + if let Some(tcx_id) = self.lookup_id.resolve_trait(&trt) { + // check this -- I think we should be able to have both self and non-self + if let Some((lifetime, _)) = &self_param.reference { + let (_, mut param_ltl) = self_param_ltl.lower_self_ref(lifetime); + let lifetimes = param_ltl.lower_generics( + &self_param.path_trait.lifetimes, + &trt.lifetimes, + true, + ); + + Ok(( + TraitParamSelf::new(TraitPath::new(lifetimes, tcx_id)), + param_ltl, + )) + } else { + let mut param_ltl = self_param_ltl.no_self_ref(); + + let type_lifetimes = param_ltl.lower_generics( + &self_param.path_trait.lifetimes[..], + &trt.lifetimes, + true, + ); + + Ok(( + TraitParamSelf::new(TraitPath::new(type_lifetimes, tcx_id)), + param_ltl, + )) + } + } else { + unreachable!( + "Trait `{}` wasn't found in the set of traits; this is a bug.", + trt.name + ); + } + } + + /// Lowers an [`ast::Param`] into an [`hir::Param`]. + /// + /// If there are any errors, they're pushed to `errors` and `None` is returned. + /// + /// Note that this expects that if there was a DiplomatWrite param at the end in + /// the method, it's not passed into here. + fn lower_param( + &mut self, + param: &ast::Param, + ltl: &mut impl LifetimeLowerer, + in_path: &ast::Path, + ) -> Result { + let name = self.lower_ident(¶m.name, "param name"); + let ty = self.lower_type::(¶m.ty, ltl, TypeLoweringContext::Method, in_path); + + // No parent attrs because parameters do not have a strictly clear parent. + let attrs = + self.attr_validator + .attr_from_ast(¶m.attrs, &Attrs::default(), &mut self.errors); + + self.attr_validator + .validate(&attrs, AttributeContext::Param, &mut self.errors); + + Ok(Param::new(name?, ty?, attrs)) + } + + /// Lowers many [`ast::Param`]s into a vector of [`hir::Param`]s. + /// + /// If there are any errors, they're pushed to `errors` and `None` is returned. + /// + /// Note that this expects that if there was a DiplomatWrite param at the end in + /// the method, `ast_params` was sliced to not include it. This happens in + /// `self.lower_method`, the caller of this function. + fn lower_many_params( + &mut self, + ast_params: &[ast::Param], + mut param_ltl: ParamLifetimeLowerer<'ast>, + in_path: &ast::Path, + ) -> Result<(Vec, ReturnLifetimeLowerer<'ast>), ()> { + let mut params = Ok(Vec::with_capacity(ast_params.len())); + + for param in ast_params { + let param = self.lower_param(param, &mut param_ltl, in_path); + + match (param, &mut params) { + (Ok(param), Ok(params)) => { + params.push(param); + } + _ => params = Err(()), + } + } + + Ok((params?, param_ltl.into_return_ltl())) + } + + fn lower_callback_param( + &mut self, + name: Option, + ty: &ast::TypeName, + ltl: &mut impl LifetimeLowerer, + in_path: &ast::Path, + ) -> Result { + let ty = self.lower_out_type( + ty, + ltl, + in_path, + TypeLoweringContext::Callback, + false, /* in_result_option */ + )?; + + if !self.cfg.unsafe_references_in_callbacks + && ty + .lifetimes() + .any(|lt| matches!(lt, super::MaybeStatic::NonStatic(..))) + { + // Slices are copied in non-memory sharing backends + if !matches!(ty, Type::Slice(_)) { + self.errors.push(LoweringError::Other("Callbacks cannot take references since they can be unsafely persisted, set `unsafe_references_in_callbacks` config to override.".into() )); + } + } + + Ok(CallbackParam { name, ty }) + } + + fn lower_many_callback_params( + &mut self, + ast_params: &[ast::Param], + param_ltl: &mut ParamLifetimeLowerer<'ast>, + in_path: &ast::Path, + ) -> Result, ()> { + let mut params = Ok(Vec::with_capacity(ast_params.len())); + + for param in ast_params { + let name = self.lower_ident(¶m.name, "param name")?; + let param = self.lower_callback_param(Some(name), ¶m.ty, param_ltl, in_path); + + match (param, &mut params) { + (Ok(param), Ok(params)) => { + params.push(param); + } + _ => params = Err(()), + } + } + params + } + + /// Lowers the return type of an [`ast::Method`] into a [`hir::ReturnFallability`]. + /// + /// If there are any errors, they're pushed to `errors` and `None` is returned. + fn lower_return_type( + &mut self, + return_type: Option<&ast::TypeName>, + takes_write: bool, + mut return_ltl: ReturnLifetimeLowerer<'_>, + in_path: &ast::Path, + ) -> Result<(ReturnType, LifetimeEnv), ()> { + let write_or_unit = if takes_write { + SuccessType::Write + } else { + SuccessType::Unit + }; + match return_type.unwrap_or(&ast::TypeName::Unit) { + ast::TypeName::Result(ok_ty, err_ty, _) => { + let ok_ty = match ok_ty.as_ref() { + ast::TypeName::Unit => Ok(write_or_unit), + ty => self + .lower_out_type( + ty, + &mut return_ltl, + in_path, + TypeLoweringContext::Method, + true, + ) + .map(SuccessType::OutType), + }; + let err_ty = match err_ty.as_ref() { + ast::TypeName::Unit => Ok(None), + ty => self + .lower_out_type( + ty, + &mut return_ltl, + in_path, + TypeLoweringContext::Method, + true, + ) + .map(Some), + }; + + match (ok_ty, err_ty) { + (Ok(ok_ty), Ok(err_ty)) => Ok(ReturnType::Fallible(ok_ty, err_ty)), + _ => Err(()), + } + } + ty @ ast::TypeName::Option(value_ty, _stdlib) => match &**value_ty { + ast::TypeName::Box(..) | ast::TypeName::Reference(..) => self + .lower_out_type( + ty, + &mut return_ltl, + in_path, + TypeLoweringContext::Method, + true, + ) + .map(SuccessType::OutType) + .map(ReturnType::Infallible), + ast::TypeName::Unit => Ok(ReturnType::Nullable(write_or_unit)), + _ => self + .lower_out_type( + value_ty, + &mut return_ltl, + in_path, + TypeLoweringContext::Method, + true, + ) + .map(SuccessType::OutType) + .map(ReturnType::Nullable), + }, + ast::TypeName::Unit => Ok(ReturnType::Infallible(write_or_unit)), + ty => self + .lower_out_type( + ty, + &mut return_ltl, + in_path, + TypeLoweringContext::Method, + false, + ) + .map(|ty| ReturnType::Infallible(SuccessType::OutType(ty))), + } + .map(|r_ty| (r_ty, return_ltl.finish())) + } + + fn lower_callback_return_type( + &mut self, + return_type: Option<&ast::TypeName>, + ltl: &mut impl LifetimeLowerer, + in_path: &ast::Path, + ) -> Result, ()> { + match return_type.unwrap_or(&ast::TypeName::Unit) { + ast::TypeName::Result(ok_ty, err_ty, _) => { + let ok_ty = match ok_ty.as_ref() { + ast::TypeName::Unit => Ok(SuccessType::Unit), + ty => self + .lower_type(ty, ltl, TypeLoweringContext::Callback, in_path) + .map(SuccessType::OutType), + }; + let err_ty = match err_ty.as_ref() { + ast::TypeName::Unit => Ok(None), + ty => self + .lower_type(ty, ltl, TypeLoweringContext::Callback, in_path) + .map(Some), + }; + + match (ok_ty, err_ty) { + (Ok(ok_ty), Ok(err_ty)) => Ok(ReturnType::Fallible(ok_ty, err_ty)), + _ => Err(()), + } + } + ty @ ast::TypeName::Option(value_ty, stdlib) => match &**value_ty { + ast::TypeName::Box(t) | ast::TypeName::Reference(_, _, t) => { + match &**t { + ast::TypeName::Named(t) | ast::TypeName::SelfType(t) => { + let ty = t.resolve(&t.path, self.env); + if let ast::CustomType::Opaque(..) = ty { + if *stdlib == ast::StdlibOrDiplomat::Diplomat { + self.errors.push(LoweringError::Other("found DiplomatOption, where T is opaque. Please use Option<&T> (DiplomatOption is for primitives, structs, and enums)".to_string())); + return Err(()); + } + } + } + _ => {} + } + self.lower_type(ty, ltl, TypeLoweringContext::Callback, in_path) + .map(SuccessType::OutType) + .map(ReturnType::Infallible) + } + ast::TypeName::Unit => Ok(ReturnType::Nullable(SuccessType::Unit)), + _ => self + .lower_type(value_ty, ltl, TypeLoweringContext::Callback, in_path) + .map(SuccessType::OutType) + .map(ReturnType::Nullable), + }, + ast::TypeName::Unit => Ok(ReturnType::Infallible(SuccessType::Unit)), + ty => self + .lower_type(ty, ltl, TypeLoweringContext::Callback, in_path) + .map(|ty| ReturnType::Infallible(SuccessType::OutType(ty))), + } + } + + fn lower_named_lifetime( + &mut self, + lifetime: &ast::lifetimes::LifetimeNode, + ) -> Result { + Ok(BoundedLifetime { + ident: self.lower_ident(lifetime.lifetime.name(), "lifetime")?, + longer: lifetime.longer.iter().copied().map(Lifetime::new).collect(), + shorter: lifetime + .shorter + .iter() + .copied() + .map(Lifetime::new) + .collect(), + }) + } + + /// Lowers a lifetime env found on a type + /// + /// Should not be extended to return LifetimeEnv, which needs to use the lifetime + /// lowerers to handle elision. + fn lower_type_lifetime_env(&mut self, ast: &ast::LifetimeEnv) -> Result { + let nodes = ast + .nodes + .iter() + .map(|lt| self.lower_named_lifetime(lt)) + .collect::>()?; + + Ok(LifetimeEnv::new(nodes, ast.nodes.len())) + } +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/methods.rs b/deps/crates/vendor/diplomat_core/src/hir/methods.rs new file mode 100644 index 00000000000000..16190e8b3fc506 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/methods.rs @@ -0,0 +1,312 @@ +//! Methods for types and navigating lifetimes within methods. + +use std::collections::BTreeSet; +use std::ops::Deref; + +use super::{ + Attrs, Docs, Ident, IdentBuf, InputOnly, OutType, OutputOnly, SelfType, TraitPath, Type, + TypeContext, +}; + +use super::lifetimes::{Lifetime, LifetimeEnv, Lifetimes, MaybeStatic}; + +use borrowing_field::BorrowingFieldVisitor; +use borrowing_param::BorrowingParamVisitor; + +pub mod borrowing_field; +pub mod borrowing_param; + +/// A method exposed to Diplomat. +/// Used for representing both free functions ([`crate::ast::Function`]) and struct methods ([`crate::ast::Method`]). +/// The only difference between a free function and a struct method in this struct is that [`Self::param_self`] will always be `None` for a free function. +#[derive(Debug)] +#[non_exhaustive] +pub struct Method { + /// Documentation specified on the method + pub docs: Docs, + /// The name of the method as initially declared. + pub name: IdentBuf, + /// The name of the generated `extern "C"` function + pub abi_name: IdentBuf, + /// The lifetimes introduced in this method and surrounding impl block. + pub lifetime_env: LifetimeEnv, + + /// An &self, &mut self, or Self parameter + pub param_self: Option, + /// The parameters of the method + pub params: Vec, + /// The output type, including whether it returns a Result/Option/Writeable/etc + pub output: ReturnType, + /// Resolved (and inherited) diplomat::attr attributes on this method + pub attrs: Attrs, +} + +pub trait CallbackInstantiationFunctionality { + #[allow(clippy::result_unit_err)] + fn get_inputs(&self) -> Result<&[CallbackParam], ()>; // the types of the parameters + #[allow(clippy::result_unit_err)] + fn get_output_type(&self) -> Result<&ReturnType, ()>; +} + +#[derive(Debug, Clone)] +#[non_exhaustive] +// Note: we do not support borrowing across callbacks +pub struct Callback { + pub param_self: Option, // this is None for callbacks as method arguments + pub params: Vec, + pub output: Box>, // this will be used in Rust (note: can technically be a callback, or void) + pub name: Option, + pub attrs: Option, + pub docs: Option, +} + +// uninstantiatable; represents no callback allowed +#[derive(Debug, Clone)] +#[non_exhaustive] +pub enum NoCallback {} + +impl CallbackInstantiationFunctionality for Callback { + fn get_inputs(&self) -> Result<&[CallbackParam], ()> { + Ok(&self.params) + } + fn get_output_type(&self) -> Result<&ReturnType, ()> { + Ok(&self.output) + } +} + +impl CallbackInstantiationFunctionality for NoCallback { + fn get_inputs(&self) -> Result<&[CallbackParam], ()> { + Err(()) + } + fn get_output_type(&self) -> Result<&ReturnType, ()> { + Err(()) + } +} + +/// Type that the method returns. +#[derive(Debug, Clone)] +#[non_exhaustive] +pub enum SuccessType { + /// Conceptually returns a string, which gets written to the `write: DiplomatWrite` argument + Write, + /// A Diplomat type. Some types can be outputs, but not inputs, which is expressed by the `OutType` parameter. + OutType(Type

), + /// A `()` type in Rust. + Unit, +} + +/// Whether or not the method returns a value or a result. +#[derive(Debug, Clone)] +#[allow(clippy::exhaustive_enums)] // this only exists for fallible/infallible, breaking changes for more complex returns are ok +pub enum ReturnType { + Infallible(SuccessType

), + Fallible(SuccessType

, Option>), + Nullable(SuccessType

), +} + +/// The `self` parameter of a method. +#[derive(Debug)] +#[non_exhaustive] +pub struct ParamSelf { + pub ty: SelfType, + pub attrs: Attrs, +} + +#[derive(Debug, Clone)] +#[non_exhaustive] +pub struct TraitParamSelf { + pub trait_path: TraitPath, +} + +/// A parameter in a method. +#[derive(Debug)] +#[non_exhaustive] +pub struct Param { + pub name: IdentBuf, + pub ty: Type, + pub attrs: Attrs, +} + +/// A parameter in a callback +/// No name, since all we get is the callback type signature +#[derive(Debug, Clone)] +#[non_exhaustive] +pub struct CallbackParam { + pub ty: Type, + pub name: Option, +} + +impl SuccessType { + /// Returns whether the variant is `Write`. + pub fn is_write(&self) -> bool { + matches!(self, SuccessType::Write) + } + + /// Returns whether the variant is `Unit`. + pub fn is_unit(&self) -> bool { + matches!(self, SuccessType::Unit) + } + + pub fn as_type(&self) -> Option<&OutType> { + match self { + SuccessType::OutType(ty) => Some(ty), + _ => None, + } + } +} + +impl Deref for ReturnType { + type Target = SuccessType; + + fn deref(&self) -> &Self::Target { + match self { + ReturnType::Infallible(ret) | ReturnType::Fallible(ret, _) | Self::Nullable(ret) => ret, + } + } +} + +impl ReturnType { + /// Returns `true` if the FFI function returns `void`. Not that this is different from `is_unit`, + /// which will be true for `DiplomatResult<(), E>` and false for infallible write. + pub fn is_ffi_unit(&self) -> bool { + matches!( + self, + ReturnType::Infallible(SuccessType::Unit | SuccessType::Write) + ) + } + + /// The "main" return type of this function: the Ok, Some, or regular type + pub fn success_type(&self) -> &SuccessType { + match &self { + Self::Infallible(s) => s, + Self::Fallible(s, _) => s, + Self::Nullable(s) => s, + } + } + + /// Get the list of method lifetimes actually used by the method return type + /// + /// Most input lifetimes aren't actually used. An input lifetime is generated + /// for each borrowing parameter but is only important if we use it in the return. + pub fn used_method_lifetimes(&self) -> BTreeSet { + let mut set = BTreeSet::new(); + + let mut add_to_set = |ty: &OutType| { + for lt in ty.lifetimes() { + if let MaybeStatic::NonStatic(lt) = lt { + set.insert(lt); + } + } + }; + + match self { + ReturnType::Infallible(SuccessType::OutType(ref ty)) + | ReturnType::Nullable(SuccessType::OutType(ref ty)) => add_to_set(ty), + ReturnType::Fallible(ref ok, ref err) => { + if let SuccessType::OutType(ref ty) = ok { + add_to_set(ty) + } + if let Some(ref ty) = err { + add_to_set(ty) + } + } + _ => (), + } + + set + } + + pub fn with_contained_types(&self, mut f: impl FnMut(&OutType)) { + match self { + Self::Infallible(SuccessType::OutType(o)) + | Self::Nullable(SuccessType::OutType(o)) + | Self::Fallible(SuccessType::OutType(o), None) => f(o), + Self::Fallible(SuccessType::OutType(o), Some(o2)) => { + f(o); + f(o2) + } + Self::Fallible(_, Some(o)) => f(o), + _ => (), + } + } +} + +impl ParamSelf { + pub(super) fn new(ty: SelfType, attrs: Attrs) -> Self { + Self { ty, attrs } + } + + /// Return the number of fields and leaves that will show up in the [`BorrowingFieldVisitor`]. + /// + /// This method is used to calculate how much space to allocate upfront. + fn field_leaf_lifetime_counts(&self, tcx: &TypeContext) -> (usize, usize) { + match self.ty { + SelfType::Opaque(_) => (1, 1), + SelfType::Struct(ref ty) => ty.resolve(tcx).fields.iter().fold((1, 0), |acc, field| { + let inner = field.ty.field_leaf_lifetime_counts(tcx); + (acc.0 + inner.0, acc.1 + inner.1) + }), + SelfType::Enum(_) => (0, 0), + } + } +} + +impl TraitParamSelf { + pub(super) fn new(trait_path: TraitPath) -> Self { + Self { trait_path } + } +} + +impl Param { + pub(super) fn new(name: IdentBuf, ty: Type, attrs: Attrs) -> Self { + Self { name, ty, attrs } + } +} + +impl Method { + /// Returns a fresh [`Lifetimes`] corresponding to `self`. + pub fn method_lifetimes(&self) -> Lifetimes { + self.lifetime_env.lifetimes() + } + + /// Returns a new [`BorrowingParamVisitor`], which can *shallowly* link output lifetimes + /// to the parameters they borrow from. + /// + /// This is useful for backends which wish to have lifetime codegen for methods only handle the local + /// method lifetime, and delegate to generated code on structs for handling the internals of struct lifetimes. + /// + /// `force_include_slices` is right now *just* for the JS backend. + /// Because the JS backend requires us to know information about the allocation of each slice, + /// then we need to grab that information in the [`BorrowingParamVisitor`]. + /// See [`BorrowingParamVisitor::new`] for more. + pub fn borrowing_param_visitor<'tcx>( + &'tcx self, + tcx: &'tcx TypeContext, + force_include_slices: bool, + ) -> BorrowingParamVisitor<'tcx> { + BorrowingParamVisitor::new(self, tcx, force_include_slices) + } + + /// Returns a new [`BorrowingFieldVisitor`], which allocates memory to + /// efficiently represent all fields (and their paths!) of the inputs that + /// have a lifetime. + /// + /// This is useful for backends which wish to "splat out" lifetime edge codegen for methods, + /// linking each borrowed input param/field (however deep it may be in a struct) to a borrowed output param/field. + /// + /// ```ignore + /// # use std::collections::BTreeMap; + /// let visitor = method.borrowing_field_visitor(&tcx, "this".ck().unwrap()); + /// let mut map = BTreeMap::new(); + /// visitor.visit_borrowing_fields(|lifetime, field| { + /// map.entry(lifetime).or_default().push(field); + /// }) + /// ``` + pub fn borrowing_field_visitor<'m>( + &'m self, + tcx: &'m TypeContext, + self_name: &'m Ident, + ) -> BorrowingFieldVisitor<'m> { + BorrowingFieldVisitor::new(self, tcx, self_name) + } +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/methods/borrowing_field.rs b/deps/crates/vendor/diplomat_core/src/hir/methods/borrowing_field.rs new file mode 100644 index 00000000000000..efbb2e16340a16 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/methods/borrowing_field.rs @@ -0,0 +1,357 @@ +//! Tools for traversing all borrows in method parameters and return types, transitively +//! +//! This is useful for backends which wish to "splat out" lifetime edge codegen for methods, +//! linking each borrowed input param/field (however deep it may be in a struct) to a borrowed output param/field. + +use std::fmt::{self, Write}; + +use smallvec::SmallVec; + +use crate::hir::{ + paths, Borrow, Ident, Method, SelfType, Slice, StructPath, TyPosition, Type, TypeContext, +}; + +use crate::hir::lifetimes::{Lifetime, Lifetimes, MaybeStatic}; + +/// An id for indexing into a [`BorrowingFieldsVisitor`]. +#[derive(Copy, Clone, Debug)] +struct ParentId(usize); + +impl ParentId { + /// Pushes a new parent to the vec, returning the corresponding [`ParentId`]. + fn new<'m>( + parent: Option, + name: &'m Ident, + parents: &mut SmallVec<[(Option, &'m Ident); 4]>, + ) -> Self { + let this = ParentId(parents.len()); + parents.push((parent, name)); + this + } +} + +/// Convenience const representing the number of nested structs a [`BorrowingFieldVisitor`] +/// can hold inline before needing to dynamically allocate. +const INLINE_NUM_PARENTS: usize = 4; + +/// Convenience const representing the number of borrowed fields a [`BorrowingFieldVisitor`] +/// can hold inline before needing to dynamically allocate. +const INLINE_NUM_LEAVES: usize = 8; + +/// A tree of lifetimes mapping onto a specific instantiation of a type tree. +/// +/// Each `BorrowingFieldsVisitor` corresponds to the type of an input of a method. +/// +/// Obtain from [`Method::borrowing_field_visitor()`]. +pub struct BorrowingFieldVisitor<'m> { + parents: SmallVec<[(Option, &'m Ident); INLINE_NUM_PARENTS]>, + leaves: SmallVec<[BorrowingFieldVisitorLeaf; INLINE_NUM_LEAVES]>, +} + +/// A leaf of a lifetime tree capable of tracking its parents. +#[derive(Copy, Clone)] +pub struct BorrowingField<'m> { + /// All inner nodes in the tree. When tracing from the root, we jump around + /// this slice based on indices, but don't necessarily use all of them. + parents: &'m [(Option, &'m Ident)], + + /// The unpacked field that is a leaf on the tree. + leaf: &'m BorrowingFieldVisitorLeaf, +} + +/// Non-recursive input-output types that contain lifetimes +enum BorrowingFieldVisitorLeaf { + Opaque(ParentId, MaybeStatic, Lifetimes), + Slice(ParentId, MaybeStatic), +} + +impl<'m> BorrowingFieldVisitor<'m> { + /// Visits every borrowing field and method lifetime that it uses. + /// + /// The idea is that you could use this to construct a mapping from + /// `Lifetime`s to `BorrowingField`s. We choose to use a visitor + /// pattern to avoid having to + /// + /// This would be convenient in the JavaScript backend where if you're + /// returning an `NonOpaque<'a, 'b>` from Rust, you need to pass a + /// `[[all input borrowing fields with 'a], [all input borrowing fields with 'b]]` + /// array into `NonOpaque`'s constructor. + /// + /// Alternatively, you could use such a map in the C++ backend by recursing + /// down the return type and keeping track of which fields you've recursed + /// into so far, and when you hit some lifetime 'a, generate docs saying + /// "path.to.current.field must be outlived by {borrowing fields of input that + /// contain 'a}". + pub fn visit_borrowing_fields<'a, F>(&'a self, mut visit: F) + where + F: FnMut(MaybeStatic, BorrowingField<'a>), + { + for leaf in self.leaves.iter() { + let borrowing_field = BorrowingField { + parents: self.parents.as_slice(), + leaf, + }; + + match leaf { + BorrowingFieldVisitorLeaf::Opaque(_, lt, method_lifetimes) => { + visit(*lt, borrowing_field); + for lt in method_lifetimes.lifetimes() { + visit(lt, borrowing_field); + } + } + BorrowingFieldVisitorLeaf::Slice(_, lt) => { + visit(*lt, borrowing_field); + } + } + } + } + + /// Returns a new `BorrowingFieldsVisitor` containing all the lifetime trees of the arguments + /// in only two allocations. + pub(crate) fn new(method: &'m Method, tcx: &'m TypeContext, self_name: &'m Ident) -> Self { + let (parents, leaves) = method + .param_self + .as_ref() + .map(|param_self| param_self.field_leaf_lifetime_counts(tcx)) + .into_iter() + .chain( + method + .params + .iter() + .map(|param| param.ty.field_leaf_lifetime_counts(tcx)), + ) + .reduce(|acc, x| (acc.0 + x.0, acc.1 + x.1)) + .map(|(num_fields, num_leaves)| { + let num_params = method.params.len() + usize::from(method.param_self.is_some()); + let mut parents = SmallVec::with_capacity(num_fields + num_params); + let mut leaves = SmallVec::with_capacity(num_leaves); + let method_lifetimes = method.method_lifetimes(); + + if let Some(param_self) = method.param_self.as_ref() { + let parent = ParentId::new(None, self_name, &mut parents); + match ¶m_self.ty { + SelfType::Opaque(ty) => { + Self::visit_opaque( + &ty.lifetimes, + &ty.borrowed().lifetime, + parent, + &method_lifetimes, + &mut leaves, + ); + } + SelfType::Struct(ty) => { + Self::visit_struct( + ty, + tcx, + parent, + &method_lifetimes, + &mut parents, + &mut leaves, + ); + } + SelfType::Enum(_) => {} + } + } + + for param in method.params.iter() { + let parent = ParentId::new(None, param.name.as_ref(), &mut parents); + Self::from_type( + ¶m.ty, + tcx, + parent, + &method_lifetimes, + &mut parents, + &mut leaves, + ); + } + + // sanity check that the preallocations were correct + debug_assert_eq!( + parents.capacity(), + std::cmp::max(INLINE_NUM_PARENTS, num_fields + num_params) + ); + debug_assert_eq!( + leaves.capacity(), + std::cmp::max(INLINE_NUM_LEAVES, num_leaves) + ); + (parents, leaves) + }) + .unwrap_or_default(); + + Self { parents, leaves } + } + + /// Returns a new [`BorrowingFieldsVisitor`] corresponding to a type. + fn from_type>( + ty: &'m Type

, + tcx: &'m TypeContext, + parent: ParentId, + method_lifetimes: &Lifetimes, + parents: &mut SmallVec<[(Option, &'m Ident); 4]>, + leaves: &mut SmallVec<[BorrowingFieldVisitorLeaf; 8]>, + ) { + match ty { + Type::Opaque(path) => { + Self::visit_opaque( + &path.lifetimes, + &path.borrowed().lifetime, + parent, + method_lifetimes, + leaves, + ); + } + Type::Slice(slice) => { + Self::visit_slice(slice, parent, method_lifetimes, leaves); + } + Type::Struct(path) => { + Self::visit_struct(path, tcx, parent, method_lifetimes, parents, leaves); + } + _ => {} + } + } + + /// Add an opaque as a leaf during construction of a [`BorrowingFieldsVisitor`]. + fn visit_opaque( + lifetimes: &'m Lifetimes, + borrow: &'m MaybeStatic, + parent: ParentId, + method_lifetimes: &Lifetimes, + leaves: &mut SmallVec<[BorrowingFieldVisitorLeaf; 8]>, + ) { + let method_borrow_lifetime = + borrow.flat_map_nonstatic(|lt| lt.as_method_lifetime(method_lifetimes)); + let method_type_lifetimes = lifetimes.as_method_lifetimes(method_lifetimes); + leaves.push(BorrowingFieldVisitorLeaf::Opaque( + parent, + method_borrow_lifetime, + method_type_lifetimes, + )); + } + + /// Add a slice as a leaf during construction of a [`BorrowingFieldsVisitor`]. + fn visit_slice( + slice: &Slice

, + parent: ParentId, + method_lifetimes: &Lifetimes, + leaves: &mut SmallVec<[BorrowingFieldVisitorLeaf; 8]>, + ) { + if let Some(lifetime) = slice.lifetime() { + let method_lifetime = + lifetime.flat_map_nonstatic(|lt| lt.as_method_lifetime(method_lifetimes)); + leaves.push(BorrowingFieldVisitorLeaf::Slice(parent, method_lifetime)); + } + } + + /// Add a struct as a parent and recurse down leaves during construction of a + /// [`BorrowingFieldsVisitor`]. + fn visit_struct( + ty: &paths::StructPath, + tcx: &'m TypeContext, + parent: ParentId, + method_lifetimes: &Lifetimes, + parents: &mut SmallVec<[(Option, &'m Ident); 4]>, + leaves: &mut SmallVec<[BorrowingFieldVisitorLeaf; 8]>, + ) { + let method_type_lifetimes = ty.lifetimes.as_method_lifetimes(method_lifetimes); + for field in ty.resolve(tcx).fields.iter() { + Self::from_type( + &field.ty, + tcx, + ParentId::new(Some(parent), field.name.as_ref(), parents), + &method_type_lifetimes, + parents, + leaves, + ); + } + } +} + +impl<'m> BorrowingField<'m> { + /// Visit fields in order. + /// + /// If `self` represents the field `param.first.second`, then calling [`BorrowingField::trace`] + /// will visit the following in order: `"param"`, `"first"`, `"second"`. + pub fn backtrace(&self, mut visit: F) + where + F: FnMut(usize, &'m Ident), + { + let (parent, ident) = match self.leaf { + BorrowingFieldVisitorLeaf::Opaque(id, ..) | BorrowingFieldVisitorLeaf::Slice(id, _) => { + self.parents[id.0] + } + }; + + self.backtrace_rec(parent, ident, &mut visit); + } + + /// Recursively visits fields in order from root to leaf by building up the + /// stack, and then visiting fields as it unwinds. + fn backtrace_rec(&self, parent: Option, ident: &'m Ident, visit: &mut F) -> usize + where + F: FnMut(usize, &'m Ident), + { + let from_end = if let Some(id) = parent { + let (parent, ident) = self.parents[id.0]; + self.backtrace_rec(parent, ident, visit) + } else { + 0 + }; + + visit(from_end, ident); + + from_end + 1 + } + + /// Fallibly visits fields in order. + /// + /// This method is similar to [`BorrowinfField::backtrace`], but short-circuits + /// when an `Err` is returned. + pub fn try_backtrace(&self, mut visit: F) -> Result<(), E> + where + F: FnMut(usize, &'m Ident) -> Result<(), E>, + { + let (parent, ident) = match self.leaf { + BorrowingFieldVisitorLeaf::Opaque(id, ..) | BorrowingFieldVisitorLeaf::Slice(id, _) => { + self.parents[id.0] + } + }; + + self.try_backtrace_rec(parent, ident, &mut visit)?; + + Ok(()) + } + + /// Recursively visits fields in order from root to leaf by building up the + /// stack, and then visiting fields as it unwinds. + fn try_backtrace_rec( + &self, + parent: Option, + ident: &'m Ident, + visit: &mut F, + ) -> Result + where + F: FnMut(usize, &'m Ident) -> Result<(), E>, + { + let from_end = if let Some(id) = parent { + let (parent, ident) = self.parents[id.0]; + self.try_backtrace_rec(parent, ident, visit)? + } else { + 0 + }; + + visit(from_end, ident)?; + + Ok(from_end + 1) + } +} + +impl<'m> fmt::Display for BorrowingField<'m> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.try_backtrace(|i, ident| { + if i != 0 { + f.write_char('.')?; + } + f.write_str(ident.as_str()) + }) + } +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/methods/borrowing_param.rs b/deps/crates/vendor/diplomat_core/src/hir/methods/borrowing_param.rs new file mode 100644 index 00000000000000..1e7b8b404ecac8 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/methods/borrowing_param.rs @@ -0,0 +1,418 @@ +//! Tools for traversing all borrows in method parameters and return types, shallowly +//! +//! This is useful for backends which wish to figure out the borrowing relationships between parameters +//! and return values, +//! and then delegate how lifetimes get mapped to fields to the codegen for those types respectively. +//! +//! +//! # Typical usage +//! +//! In managed languages, to ensure the GC doesn't prematurely clean up the borrowed-from object, +//! we use the technique of stashing a borrowed-from object as a field of a borrowed-to object. +//! This is called a "lifetime edge" (since it's an edge in the GC graph). An "edge array" is typically +//! a stash of all the edges on an object, or all the edges corresponding to a particular lifetime. +//! +//! This stashing is primarily driven by method codegen, which is where actual borrow relationships can be set up. +//! +//! Typically, codegen for a method should instantiate a [`BorrowedParamVisitor`] and uses it to [`BorrowedParamVisitor::visit_param()`] each input parameter to determine if it needs to be linked into an edge. +//! Whilst doing so, it may return useful [`ParamBorrowInfo`] which provides additional information on handling structs and slices. More on structs later. +//! At the end of the visiting, [`BorrowedLifetimeInfo::borrow_map()`] can be called to get a list of relevant input edges: each lifetime that participates in borrowing, +//! and a list of parameter names that it borrows from. +//! +//! This visitor will automatically handle transitive lifetime relationships as well. +//! +//! These edges should be put together into "edge arrays" which then get passed down to output types, handling transitive lifetimes as necessary. +//! +//! ## Method codegen for slices +//! +//! Slices are strange: in managed languages a host slice will not be a Rust slice, unlike other borrowed host values (a borrowed host opaque is just a borrowed Rust +//! opaque). We need to convert these across the boundary by allocating a temporary arena or something. +//! +//! If the slice doesn't participate in borrowing, this is easy: just allocate a temporary arena. However, if not, we need to allocate an arena with a finalizer (or something similar) +//! and add that arena to the edge instead. [`LifetimeEdgeKind`] has special handling for this. +//! +//! Whether or not the slice participates in borrowing is found out from the [`ParamBorrowInfo`] returned by [`BorrowedParamVisitor::visit_param()`]. +//! +//! # Method codegen for struct params +//! +//! Structs can contain many lifetimes and have relationships between them. Generally, a Diplomat struct is a "bag of stuff"; it is converted to a host value that is structlike, with fields +//! individually converted. +//! +//! Diplomat enforces that struct lifetime bounds never imply additional bounds on methods during HIR validation, so the relationships between struct +//! lifetimes are not relevant for code here (and as such you should hopefully never need to call [`LifetimeEnv::all_longer_lifetimes()`]) +//! for a struct env). +//! +//! The borrowing technique in this module allows a lot of things to be delegated to structs. As will be explained below, structs will have: +//! +//! - A `fields_for_lifetime_foo()` set of methods that returns all non-slice fields corresponding to a lifetime +//! - "append array" outparams for stashing edges when converting from host-to-Rust +//! - Some way of passing down edge arrays to individual borrowed fields when constructing Rust-to-host +//! +//! In methods, when constructing the edge arrays, `fields_for_lifetime_foo()` for every borrowed param can be appended to each +//! one whenever [`LifetimeEdgeKind::StructLifetime`] asks you to do so. The code needs to handle lifetime +//! transitivity, since the struct will not be doing so. Fortunately the edges produced by [`BorrowedParamVisitor`] already do so. +//! +//! Then, when converting structs host-to-Rust, every edge array relevant to a struct lifetime should be passed in for an append array. Append arrays +//! are nested arrays: they are an array of edge arrays. The struct will append further things to the edge array. +//! +//! Finally, when converting Rust-to-host, if producing a struct, make sure to pass in all the edge arrays. +//! +//! # Struct codegen +//! +//! At a high level, struct codegen needs to deal with lifetimes in three places: +//! +//! - A `fields_for_lifetime_foo()` set of methods that returns all non-slice fields corresponding to a lifetime +//! - "append array" outparams for stashing edges when converting from host-to-Rust +//! - Some way of passing down edge arrays to individual borrowed fields when constructing Rust-to-host +//! +//! The backend may choose to handle just slices via append arrays, or handle all borrowing there, in which case `fields_for_lifetime_foo()` isn't necessary. +//! +//! `fields_for_lifetime_foo()` should return an iterator/list/etc corresponding to each field that *directly* borrows from lifetime foo. +//! This may include calling `fields_for_lifetime_bar()` on fields that are themselves structs. As mentioned previously, lifetime relationships +//! are handled by methods and don't need to be dealt with here. There are no helpers for doing this but it's just a matter of +//! filtering for fields using the lifetime, except for handling nested structs ([`StructBorrowInfo::compute_for_struct_field()`]) +//! +//! Append arrays are similarly straightforward: for each lifetime on the struct, the host-to-Rust constructor should accept a list of edge arrays. For slice fields, +//! if the appropriate list is nonempty, the slice's arena edge should be appended to all of the edge arrays in it. These arrays should also be passed down to struct fields +//! appropriately: [`StructBorrowInfo::compute_for_struct_field()`] is super helpful for getting a list edges something should get passed down to. +//! +//! Finally, when converting Rust-to-host, the relevant lifetime edges should be proxied down to the final host type constructors who can stash them wherever needed. +//! This is one again a matter of filtering fields by the lifetimes they use, and for nested structs you can use [`StructBorrowInfo::compute_for_struct_field()`]. + +use std::collections::{BTreeMap, BTreeSet}; + +use crate::hir::{self, Method, StructDef, StructPath, TyPosition, TypeContext}; + +use crate::hir::lifetimes::{Lifetime, LifetimeEnv, MaybeStatic}; +use crate::hir::ty_position::StructPathLike; + +/// A visitor for processing method parameters/returns and understanding their borrowing relationships, shallowly. +/// +/// This produces a list of lifetime "edges" per lifetime in the output producing a borrow. +/// +/// Each `BorrowingFieldsVisitor` corresponds to the type of an input of a method. +/// +/// Obtain from [`Method::borrowing_param_visitor()`]. +pub struct BorrowingParamVisitor<'tcx> { + tcx: &'tcx TypeContext, + used_method_lifetimes: BTreeSet, + borrow_map: BTreeMap>, +} + +/// A single lifetime "edge" from a parameter to a value +#[non_exhaustive] +#[derive(Clone, Debug)] +pub struct LifetimeEdge<'tcx> { + pub param_name: String, + pub kind: LifetimeEdgeKind<'tcx>, +} + +#[non_exhaustive] +#[derive(Copy, Clone, Debug)] +pub enum LifetimeEdgeKind<'tcx> { + /// Just an opaque parameter directly being borrowed. + OpaqueParam, + /// A slice being converted and then borrowed. These often need to be handled differently + /// when they are borrowed as the borrow will need to create an edge + SliceParam, + /// A lifetime parameter of a struct, given the lifetime context and the struct-def lifetime for that struct. + /// + /// The boolean is whether or not the struct is optional. + /// + /// Using this, you can generate code that "asks" the struct for the lifetime-relevant field edges + StructLifetime(&'tcx LifetimeEnv, Lifetime, bool), +} + +#[non_exhaustive] +#[derive(Clone, Debug)] +pub struct BorrowedLifetimeInfo<'tcx> { + // Initializers for all inputs to the edge array from parameters, except for slices (slices get handled + // differently) + pub incoming_edges: Vec>, + // All lifetimes longer than this. When this lifetime is borrowed from, data corresponding to + // the other lifetimes may also be borrowed from. + pub all_longer_lifetimes: BTreeSet, +} + +impl<'tcx> BorrowingParamVisitor<'tcx> { + pub(crate) fn new( + method: &'tcx Method, + tcx: &'tcx TypeContext, + force_include_slices: bool, + ) -> Self { + let mut used_method_lifetimes = method.output.used_method_lifetimes(); + + // If we need to track the lifetime of slices, we just need to make sure to add a slice's + // lifetime to the used_method_lifetimes set. + // + // Currently this is done recursively, but as mentioned in + // https://github.com/rust-diplomat/diplomat/pull/839#discussion_r2031764206, + // a long term solution would involve re-designing the lifetimes map to track lifetimes + // that involve slices. + if force_include_slices { + if let Some(s) = &method.param_self { + if let hir::SelfType::Struct(s) = &s.ty { + let st = s.resolve(tcx); + for f in &st.fields { + BorrowingParamVisitor::add_slices_to_used_lifetimes( + &mut used_method_lifetimes, + method, + tcx, + &f.ty, + ); + } + } + } + + for p in &method.params { + BorrowingParamVisitor::add_slices_to_used_lifetimes( + &mut used_method_lifetimes, + method, + tcx, + &p.ty, + ); + } + } + + let borrow_map = used_method_lifetimes + .iter() + .map(|lt| { + ( + *lt, + BorrowedLifetimeInfo { + incoming_edges: Vec::new(), + all_longer_lifetimes: method + .lifetime_env + .all_longer_lifetimes(lt) + .collect(), + }, + ) + }) + .collect(); + BorrowingParamVisitor { + tcx, + used_method_lifetimes, + borrow_map, + } + } + + /// Given a specific [hir::Type] `ty`, find the lifetimes of slices associated with `ty` and add them to `set`. + /// + /// We're only interested in non-static, bounded lifetimes (since those are ones we can explicitly de-allocate). + fn add_slices_to_used_lifetimes>( + set: &mut BTreeSet, + method: &'tcx Method, + tcx: &'tcx TypeContext, + ty: &hir::Type

, + ) { + match ty { + hir::Type::Struct(s) => { + let st = s.resolve(tcx); + for f in &st.fields { + BorrowingParamVisitor::add_slices_to_used_lifetimes(set, method, tcx, &f.ty); + } + } + hir::Type::Slice(s) => { + if let Some(MaybeStatic::NonStatic(lt)) = s.lifetime() { + if method.lifetime_env.get_bounds(*lt).is_some() { + set.insert(*lt); + } + } + } + _ => {} + } + } + + /// Get the cached list of used method lifetimes. Same as calling `.used_method_lifetimes()` on `method.output` + pub fn used_method_lifetimes(&self) -> &BTreeSet { + &self.used_method_lifetimes + } + + /// Get the final borrow map, listing lifetime edges for each output lfietime + pub fn borrow_map(self) -> BTreeMap> { + self.borrow_map + } + + /// Processes a parameter, adding it to the borrow_map for any lifetimes it references. Returns further information about the type of borrow. + /// + /// This basically boils down to: For each lifetime that is actually relevant to borrowing in this method, check if that + /// lifetime or lifetimes longer than it are used by this parameter. In other words, check if + /// it is possible for data in the return type with this lifetime to have been borrowed from this parameter. + /// If so, add code that will yield the ownership-relevant parts of this object to incoming_edges for that lifetime. + pub fn visit_param>( + &mut self, + ty: &hir::Type

, + param_name: &str, + ) -> ParamBorrowInfo<'tcx> { + let mut is_borrowed = false; + if self.used_method_lifetimes.is_empty() { + if let hir::Type::Slice(..) = *ty { + return ParamBorrowInfo::TemporarySlice; + } else { + return ParamBorrowInfo::NotBorrowed; + } + } + + // Structs have special handling: structs are purely Dart-side, so if you borrow + // from a struct, you really are borrowing from the internal fields. + if let hir::Type::Struct(s) = ty { + let mut borrowed_struct_lifetime_map = BTreeMap::>::new(); + let link = s.link_lifetimes(self.tcx); + for (method_lifetime, method_lifetime_info) in &mut self.borrow_map { + // Note that ty.lifetimes()/s.lifetimes() is lifetimes + // in the *use* context, i.e. lifetimes on the Type that reference the + // indices of the method's lifetime arrays. Their *order* references + // the indices of the underlying struct def. We need to link the two, + // since the _fields_for_lifetime_foo() methods are named after + // the *def* context lifetime. + // + // Concretely, if we have struct `Foo<'a, 'b>` and our method + // accepts `Foo<'x, 'y>`, we need to output _fields_for_lifetime_a()/b not x/y. + // + // This is a struct so lifetimes_def_only() is fine to call + for (use_lt, def_lt) in link.lifetimes_def_only() { + if let MaybeStatic::NonStatic(use_lt) = use_lt { + if method_lifetime_info.all_longer_lifetimes.contains(&use_lt) { + let edge = LifetimeEdge { + param_name: param_name.into(), + kind: LifetimeEdgeKind::StructLifetime( + link.def_env(), + def_lt, + ty.is_option(), + ), + }; + method_lifetime_info.incoming_edges.push(edge); + + is_borrowed = true; + + borrowed_struct_lifetime_map + .entry(def_lt) + .or_default() + .insert(*method_lifetime); + // Do *not* break the inner loop here: even if we found *one* matching lifetime + // in this struct that may not be all of them, there may be some other fields that are borrowed + } + } + } + } + if is_borrowed { + ParamBorrowInfo::Struct(StructBorrowInfo { + env: link.def_env(), + borrowed_struct_lifetime_map, + }) + } else { + ParamBorrowInfo::NotBorrowed + } + } else { + for method_lifetime in self.borrow_map.values_mut() { + for lt in ty.lifetimes() { + if let MaybeStatic::NonStatic(lt) = lt { + if method_lifetime.all_longer_lifetimes.contains(<) { + let kind = match ty { + hir::Type::Slice(..) => LifetimeEdgeKind::SliceParam, + hir::Type::Opaque(..) => LifetimeEdgeKind::OpaqueParam, + _ => unreachable!("Types other than slices, opaques, and structs cannot have lifetimes") + }; + + let edge = LifetimeEdge { + param_name: param_name.into(), + kind, + }; + + method_lifetime.incoming_edges.push(edge); + is_borrowed = true; + // Break the inner loop: we've already determined this + break; + } + } + } + } + match (is_borrowed, ty) { + (true, &hir::Type::Slice(..)) => ParamBorrowInfo::BorrowedSlice, + (false, &hir::Type::Slice(..)) => ParamBorrowInfo::TemporarySlice, + (false, _) => ParamBorrowInfo::NotBorrowed, + (true, _) => ParamBorrowInfo::BorrowedOpaque, + } + } + } +} + +/// Information relevant to borrowing for producing conversions +#[derive(Clone, Debug)] +#[non_exhaustive] +pub enum ParamBorrowInfo<'tcx> { + /// No borrowing constraints. This means the parameter + /// is not borrowed by the output and also does not need temporary borrows + NotBorrowed, + /// A slice that is not borrowed by the output (but will still need temporary allocation) + TemporarySlice, + /// A slice that is borrowed by the output + BorrowedSlice, + /// A struct parameter that is borrowed by the output + Struct(StructBorrowInfo<'tcx>), + /// An opaque type that is borrowed + BorrowedOpaque, +} + +/// Information about the lifetimes of a struct parameter that are borrowed by a method output or by a wrapping struct +#[derive(Clone, Debug)] +#[non_exhaustive] +pub struct StructBorrowInfo<'tcx> { + /// This is the struct's lifetime environment + pub env: &'tcx LifetimeEnv, + /// A map from (borrow-relevant) struct lifetimes to lifetimes in the method (or wrapping struct) that may flow from it + pub borrowed_struct_lifetime_map: BTreeMap>, +} + +impl<'tcx> StructBorrowInfo<'tcx> { + /// Get borrowing info for a struct field, if it does indeed borrow + /// + /// The lifetime map produced here does not handle lifetime dependencies: the expectation is that the struct + /// machinery generated by this will be called by method code that handles these dependencies. We try to handle + /// lifetime dependencies in ONE place. + pub fn compute_for_struct_field( + struc: &StructDef

, + field: &P::StructPath, + tcx: &'tcx TypeContext, + ) -> Option { + if field.lifetimes().as_slice().is_empty() { + return None; + } + + let mut borrowed_struct_lifetime_map = BTreeMap::>::new(); + + let link = field.link_lifetimes(tcx); + + for outer_lt in struc.lifetimes.all_lifetimes() { + // Note that field.lifetimes() + // in the *use* context, i.e. lifetimes on the Type that reference the + // indices of the outer struct's lifetime arrays. Their *order* references + // the indices of the underlying struct def. We need to link the two, + // since the _fields_for_lifetime_foo() methods are named after + // the *def* context lifetime. + // + // This is a struct so lifetimes_def_only() is fine to call + for (use_lt, def_lt) in link.lifetimes_def_only() { + if let MaybeStatic::NonStatic(use_lt) = use_lt { + // We do *not* need to transitively check for longer lifetimes here: + // + if outer_lt == use_lt { + borrowed_struct_lifetime_map + .entry(def_lt) + .or_default() + .insert(outer_lt); + } + } + } + } + if borrowed_struct_lifetime_map.is_empty() { + // if the inner struct is only statics + None + } else { + Some(StructBorrowInfo { + env: link.def_env(), + borrowed_struct_lifetime_map, + }) + } + } +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/mod.rs b/deps/crates/vendor/diplomat_core/src/hir/mod.rs new file mode 100644 index 00000000000000..94fe611239e515 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/mod.rs @@ -0,0 +1,31 @@ +//! Experimental high-level representation (HIR) for Diplomat. +//! +//! Enabled with the `"hir"` Cargo feature + +mod attrs; +mod defs; +mod elision; +mod lifetimes; +mod lowering; +mod methods; +mod paths; +mod primitives; +mod ty_position; +mod type_context; +mod types; +pub use attrs::*; +pub use defs::*; +pub(super) use elision::*; +pub use lifetimes::*; +pub(super) use lowering::*; +pub use methods::*; +pub use paths::*; +pub use primitives::*; +pub use ty_position::*; +pub use type_context::*; +pub use types::*; + +pub use lowering::{ErrorAndContext, ErrorContext, LoweringError}; + +pub use crate::ast::{Docs, DocsTypeReferenceSyntax, DocsUrlGenerator}; +pub use strck::ident::rust::{Ident, IdentBuf}; diff --git a/deps/crates/vendor/diplomat_core/src/hir/paths.rs b/deps/crates/vendor/diplomat_core/src/hir/paths.rs new file mode 100644 index 00000000000000..cc102a716158ef --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/paths.rs @@ -0,0 +1,249 @@ +use super::lifetimes::{Lifetimes, LinkedLifetimes}; +use super::{ + Borrow, EnumDef, EnumId, Everywhere, Mutability, OpaqueDef, OpaqueId, OpaqueOwner, + OutStructDef, OutputOnly, ReturnableStructDef, StructDef, TraitId, TyPosition, TypeContext, +}; + +/// Path to a struct that may appear as an output. +#[derive(Debug, Clone)] +#[non_exhaustive] +pub enum ReturnableStructPath { + Struct(StructPath), + OutStruct(OutStructPath), +} + +/// Path to a struct that can only be used as an output. +pub type OutStructPath = StructPath; + +/// Path to a struct that can be used in inputs and outputs. +#[derive(Debug, Clone)] +#[non_exhaustive] +pub struct StructPath { + pub lifetimes: Lifetimes, + pub tcx_id: P::StructId, + pub owner: MaybeOwn, +} + +#[derive(Debug, Clone)] +#[non_exhaustive] +pub struct TraitPath { + pub lifetimes: Lifetimes, + pub tcx_id: TraitId, +} + +/// Non-instantiable enum to denote the trait path in +/// TyPositions that don't allow traits (anything not InputOnly) +#[derive(Debug, Clone)] +#[non_exhaustive] +pub enum NoTraitPath {} + +/// Path to an opaque. +/// +/// There are three kinds of opaques that Diplomat uses, so this type has two +/// generic arguments to differentiate between the three, while still showing +/// that the three are all paths to opaques. The monomorphized versions that +/// Diplomat uses are: +/// +/// 1. `OpaquePath`: Opaques in return types, +/// which can be optional and either owned or borrowed. +/// 2. `OpaquePath`: Opaques in method parameters, which can +/// be optional but must be borrowed, since most languages don't have a way to +/// entirely give up ownership of a value. +/// 3. `OpaquePath`: Opaques in the `&self` position, which +/// cannot be optional and must be borrowed for the same reason as above. +#[derive(Debug, Clone)] +#[non_exhaustive] +pub struct OpaquePath { + pub lifetimes: Lifetimes, + pub optional: Opt, + pub owner: Owner, + pub tcx_id: OpaqueId, +} + +#[derive(Debug, Copy, Clone)] +pub struct Optional(pub(super) bool); + +#[derive(Debug, Copy, Clone)] +#[allow(clippy::exhaustive_structs)] // marker type +pub struct NonOptional; + +impl OpaquePath { + pub fn is_optional(&self) -> bool { + self.optional.0 + } + + pub fn is_owned(&self) -> bool { + self.owner.is_owned() + } +} + +impl OpaquePath { + pub fn wrap_optional(self) -> OpaquePath { + OpaquePath { + lifetimes: self.lifetimes, + optional: Optional(false), + owner: self.owner, + tcx_id: self.tcx_id, + } + } +} + +impl OpaquePath { + pub fn as_borrowed(&self) -> Option<&Borrow> { + self.owner.as_borrowed() + } +} + +impl OpaquePath { + pub fn borrowed(&self) -> &Borrow { + &self.owner + } +} + +/// Path to an enum. +#[derive(Debug, Clone)] +#[non_exhaustive] +pub struct EnumPath { + pub tcx_id: EnumId, +} + +/// Determine whether a type is owned or borrowed. +/// +/// Ownership in the case of opaques is `Box`, in the case of structs is +/// `Struct`, and in the case of slices is `Box<[T]>`. +#[derive(Copy, Clone, Debug)] +#[allow(clippy::exhaustive_enums)] // only two answers to this question +pub enum MaybeOwn { + Own, + Borrow(Borrow), +} + +impl MaybeOwn { + pub fn as_borrowed(&self) -> Option<&Borrow> { + match self { + MaybeOwn::Own => None, + MaybeOwn::Borrow(borrow) => Some(borrow), + } + } + + pub fn is_owned(&self) -> bool { + matches!(*self, Self::Own) + } + + /// Returns the mutability of this potential-borrow + /// + /// Owned types are mutable + pub fn mutability(&self) -> Mutability { + match *self { + Self::Own => Mutability::Mutable, + Self::Borrow(b) => b.mutability, + } + } +} + +impl From> for MaybeOwn { + fn from(other: Option) -> Self { + other.map(Self::Borrow).unwrap_or(Self::Own) + } +} +impl ReturnableStructPath { + pub fn resolve<'tcx>(&self, tcx: &'tcx TypeContext) -> ReturnableStructDef<'tcx> { + match self { + ReturnableStructPath::Struct(path) => ReturnableStructDef::Struct(path.resolve(tcx)), + ReturnableStructPath::OutStruct(path) => { + ReturnableStructDef::OutStruct(path.resolve(tcx)) + } + } + } + + pub(crate) fn lifetimes(&self) -> &Lifetimes { + match self { + Self::Struct(p) => &p.lifetimes, + Self::OutStruct(p) => &p.lifetimes, + } + } +} + +impl StructPath

{ + /// Returns a new [`EnumPath`]. + pub(super) fn new(lifetimes: Lifetimes, tcx_id: P::StructId, owner: MaybeOwn) -> Self { + Self { + lifetimes, + tcx_id, + owner, + } + } +} +impl StructPath { + /// Returns the [`StructDef`] that this path references. + pub fn resolve<'tcx>(&self, tcx: &'tcx TypeContext) -> &'tcx StructDef { + tcx.resolve_struct(self.tcx_id) + } +} + +impl OutStructPath { + /// Returns the [`OutStructDef`] that this path references. + pub fn resolve<'tcx>(&self, tcx: &'tcx TypeContext) -> &'tcx OutStructDef { + tcx.resolve_out_struct(self.tcx_id) + } + + /// Get a map of lifetimes used on this path to lifetimes as named in the def site. See [`LinkedLifetimes`] + /// for more information. + pub fn link_lifetimes<'def, 'tcx>( + &'def self, + tcx: &'tcx TypeContext, + ) -> LinkedLifetimes<'def, 'tcx> { + let struc = self.resolve(tcx); + let env = &struc.lifetimes; + LinkedLifetimes::new(env, None, &self.lifetimes) + } +} + +impl OpaquePath { + /// Returns a new [`OpaquePath`]. + pub(super) fn new(lifetimes: Lifetimes, optional: Opt, owner: Owner, tcx_id: OpaqueId) -> Self { + Self { + lifetimes, + optional, + owner, + tcx_id, + } + } + + /// Returns the [`OpaqueDef`] that this path references. + pub fn resolve<'tcx>(&self, tcx: &'tcx TypeContext) -> &'tcx OpaqueDef { + tcx.resolve_opaque(self.tcx_id) + } +} + +impl OpaquePath { + /// Get a map of lifetimes used on this path to lifetimes as named in the def site. See [`LinkedLifetimes`] + /// for more information. + pub fn link_lifetimes<'def, 'tcx>( + &'def self, + tcx: &'tcx TypeContext, + ) -> LinkedLifetimes<'def, 'tcx> { + let opaque = self.resolve(tcx); + let env = &opaque.lifetimes; + LinkedLifetimes::new(env, self.owner.lifetime(), &self.lifetimes) + } +} + +impl EnumPath { + /// Returns a new [`EnumPath`]. + pub(super) fn new(tcx_id: EnumId) -> Self { + Self { tcx_id } + } + + /// Returns the [`EnumDef`] that this path references. + pub fn resolve<'tcx>(&self, tcx: &'tcx TypeContext) -> &'tcx EnumDef { + tcx.resolve_enum(self.tcx_id) + } +} + +impl TraitPath { + /// Returns a new [`TraitPath`]. + pub(super) fn new(lifetimes: Lifetimes, tcx_id: TraitId) -> Self { + Self { lifetimes, tcx_id } + } +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/primitives.rs b/deps/crates/vendor/diplomat_core/src/hir/primitives.rs new file mode 100644 index 00000000000000..3122391addc682 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/primitives.rs @@ -0,0 +1,141 @@ +//! Primitives types that can cross the FFI boundary. +use crate::ast; + +/// 8, 16, 32, and 64-bit signed and unsigned integers. +#[derive(Copy, Clone, Debug)] +#[allow(clippy::exhaustive_enums)] // there are only these +pub enum IntType { + I8, + I16, + I32, + I64, + U8, + U16, + U32, + U64, +} + +/// Platform-dependent signed and unsigned size types. +#[derive(Copy, Clone, Debug)] +#[allow(clippy::exhaustive_enums)] // there are only these +pub enum IntSizeType { + Isize, + Usize, +} + +/// 128-bit signed and unsigned integers. +#[derive(Copy, Clone, Debug)] +#[allow(clippy::exhaustive_enums)] // there are only these +pub enum Int128Type { + I128, + U128, +} + +/// 32 and 64-bit floating point numbers. +#[derive(Copy, Clone, Debug)] +#[allow(clippy::exhaustive_enums)] // there are only these +pub enum FloatType { + F32, + F64, +} + +/// All primitive types. +#[derive(Copy, Clone, Debug)] +#[allow(clippy::exhaustive_enums)] // there are only these +pub enum PrimitiveType { + Bool, + Char, + /// a primitive byte that is not meant to be interpreted numerically + /// in languages that don't have fine-grained integer types + Byte, + /// an i8 that is either -1, 0, or 1 + Ordering, + Int(IntType), + IntSize(IntSizeType), + Int128(Int128Type), + Float(FloatType), +} + +impl IntType { + /// Returns the string representation of `self`. + pub fn as_str(&self) -> &'static str { + match self { + IntType::I8 => "i8", + IntType::I16 => "i16", + IntType::I32 => "i32", + IntType::I64 => "i64", + IntType::U8 => "u8", + IntType::U16 => "u16", + IntType::U32 => "u32", + IntType::U64 => "u64", + } + } +} + +impl IntSizeType { + /// Returns the string representation of `self`. + pub fn as_str(&self) -> &'static str { + match self { + IntSizeType::Isize => "isize", + IntSizeType::Usize => "usize", + } + } +} + +impl Int128Type { + /// Returns the string representation of `self`. + pub fn as_str(&self) -> &'static str { + match self { + Int128Type::I128 => "i128", + Int128Type::U128 => "u128", + } + } +} + +impl FloatType { + /// Returns the string representation of `self`. + pub fn as_str(&self) -> &'static str { + match self { + FloatType::F32 => "f32", + FloatType::F64 => "f64", + } + } +} + +impl PrimitiveType { + pub(super) fn from_ast(prim: ast::PrimitiveType) -> Self { + match prim { + ast::PrimitiveType::i8 => PrimitiveType::Int(IntType::I8), + ast::PrimitiveType::u8 => PrimitiveType::Int(IntType::U8), + ast::PrimitiveType::i16 => PrimitiveType::Int(IntType::I16), + ast::PrimitiveType::u16 => PrimitiveType::Int(IntType::U16), + ast::PrimitiveType::i32 => PrimitiveType::Int(IntType::I32), + ast::PrimitiveType::u32 => PrimitiveType::Int(IntType::U32), + ast::PrimitiveType::i64 => PrimitiveType::Int(IntType::I64), + ast::PrimitiveType::u64 => PrimitiveType::Int(IntType::U64), + ast::PrimitiveType::isize => PrimitiveType::IntSize(IntSizeType::Isize), + ast::PrimitiveType::usize => PrimitiveType::IntSize(IntSizeType::Usize), + ast::PrimitiveType::i128 => PrimitiveType::Int128(Int128Type::I128), + ast::PrimitiveType::u128 => PrimitiveType::Int128(Int128Type::U128), + ast::PrimitiveType::f32 => PrimitiveType::Float(FloatType::F32), + ast::PrimitiveType::f64 => PrimitiveType::Float(FloatType::F64), + ast::PrimitiveType::bool => PrimitiveType::Bool, + ast::PrimitiveType::char => PrimitiveType::Char, + ast::PrimitiveType::byte => PrimitiveType::Byte, + } + } + + /// Returns the string representation of `self`. + pub fn as_str(&self) -> &'static str { + match self { + PrimitiveType::Bool => "bool", + PrimitiveType::Char => "char", + PrimitiveType::Byte => "byte", + PrimitiveType::Ordering => "ordering", + PrimitiveType::Int(ty) => ty.as_str(), + PrimitiveType::IntSize(ty) => ty.as_str(), + PrimitiveType::Int128(ty) => ty.as_str(), + PrimitiveType::Float(ty) => ty.as_str(), + } + } +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__auto.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__auto.snap new file mode 100644 index 00000000000000..393e422d3b8eb5 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__auto.snap @@ -0,0 +1,6 @@ +--- +source: core/src/hir/attrs.rs +expression: output +--- +Lowering error in Opaque::auto_doesnt_work_on_renames: Diplomat attribute "rename" gated on 'auto' but is not one that works with 'auto' +Lowering error in Opaque::auto_doesnt_work_on_disables: Diplomat attribute "disable" gated on 'auto' but is not one that works with 'auto' diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__comparator.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__comparator.snap new file mode 100644 index 00000000000000..f940fc190a8d01 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__comparator.snap @@ -0,0 +1,22 @@ +--- +source: core/src/hir/attrs.rs +expression: output +--- +Lowering error in Struct::comparison_other: Comparator's parameter must be identical to self +Lowering error in Struct::comparison_correct: Cannot define two comparators on the same type +Lowering error in Struct::comparison_ref: Cannot define two comparators on the same type +Lowering error in Struct::comparison_mut: Cannot define two comparators on the same type +Lowering error in Struct::comparison_mut: comparators must accept immutable parameters +Lowering error in Opaque::comparator_static: Comparators must accept a self parameter +Lowering error in Opaque::comparator_none: Comparator must have exactly 1 parameter +Lowering error in Opaque::comparator_none: Cannot define two comparators on the same type +Lowering error in Opaque::comparator_othertype: Cannot define two comparators on the same type +Lowering error in Opaque::comparator_othertype: Comparators must accept a self parameter +Lowering error in Opaque::comparator_badreturn: Cannot define two comparators on the same type +Lowering error in Opaque::comparator_badreturn: Found comparison method that does not return cmp::Ordering +Lowering error in Opaque::comparison_correct: Cannot define two comparators on the same type +Lowering error in Opaque::ordering_wrong: Found cmp::Ordering in parameter or struct field, it is only allowed in return types +Lowering error in Opaque::comparison_mut: Cannot define two comparators on the same type +Lowering error in Opaque::comparison_mut: comparators must accept immutable parameters +Lowering error in Opaque::comparison_opt: Cannot define two comparators on the same type +Lowering error in Opaque::comparison_opt: comparators must accept non-optional parameters diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__iterator.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__iterator.snap new file mode 100644 index 00000000000000..56f36c3dbfc629 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__iterator.snap @@ -0,0 +1,12 @@ +--- +source: core/src/hir/attrs.rs +expression: output +--- +Lowering error in Broken::iterable_no_return: Iterables must return a custom type +Lowering error in Broken::iterable_no_self: Iterables must accept a self parameter +Lowering error in Broken::iterable_non_custom: Cannot mark type as iterable twice +Lowering error in Broken::iterable_non_custom: Iterables must return a custom opaque type +Lowering error in BrokenIterator::iterator_no_return: Iterator method must return nullable value +Lowering error in BrokenIterator::iterator_no_self: Iterator must accept a self parameter +Lowering error in BrokenIterator::iterator_no_option: Cannot mark type as iterator twice +Lowering error in BrokenIterator::iterator_no_option: Iterator method must return nullable value diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_non_opaque_type.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_non_opaque_type.snap new file mode 100644 index 00000000000000..1962f0c5325e74 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_non_opaque_type.snap @@ -0,0 +1,5 @@ +--- +source: core/src/hir/attrs.rs +expression: output +--- +Lowering error in Foo::get_y: `generate_mocking_interface` can only be used on opaque types diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_opaque_type.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_opaque_type.snap new file mode 100644 index 00000000000000..faef0ffb1f1e5e --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_opaque_type.snap @@ -0,0 +1,5 @@ +--- +source: core/src/hir/attrs.rs +expression: output +--- + diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_unsupported_backend.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_unsupported_backend.snap new file mode 100644 index 00000000000000..07f0004657b420 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__mocking_interface_for_unsupported_backend.snap @@ -0,0 +1,5 @@ +--- +source: core/src/hir/attrs.rs +expression: output +--- +Lowering error in Foo: `generate_mocking_interface` not supported in backend tests diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__primitive_struct_slices.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__primitive_struct_slices.snap new file mode 100644 index 00000000000000..faef0ffb1f1e5e --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__primitive_struct_slices.snap @@ -0,0 +1,5 @@ +--- +source: core/src/hir/attrs.rs +expression: output +--- + diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__primitive_struct_slices_for_unsupported_backend.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__primitive_struct_slices_for_unsupported_backend.snap new file mode 100644 index 00000000000000..1ead8b5e6a346a --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__primitive_struct_slices_for_unsupported_backend.snap @@ -0,0 +1,5 @@ +--- +source: core/src/hir/attrs.rs +expression: output +--- +Lowering error in Foo::takes_slice: Primitive struct slices are not supported by this backend diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__struct_ref_for_unsupported_backend.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__struct_ref_for_unsupported_backend.snap new file mode 100644 index 00000000000000..7f6546d05f7662 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__struct_ref_for_unsupported_backend.snap @@ -0,0 +1,5 @@ +--- +source: core/src/hir/attrs.rs +expression: output +--- +Lowering error in Foo::takes_mut: Method `Foo_takes_mut` takes a reference to a struct as a self parameter, which isn't allowed. Backend must support struct_refs. diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__unsupported_features.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__unsupported_features.snap new file mode 100644 index 00000000000000..f66b6091fc81e2 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__attrs__tests__unsupported_features.snap @@ -0,0 +1,8 @@ +--- +source: core/src/hir/attrs.rs +expression: output +--- +Lowering error in OutStruct: Options of structs/enums/primitives not supported by this backend +Lowering error in Struct: Options of structs/enums/primitives not supported by this backend +Lowering error in Struct2: Options of structs/enums/primitives not supported by this backend +Lowering error in Opaque::take_option: Options of structs/enums/primitives not supported by this backend diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__elision__tests__borrowing_fields.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__elision__tests__borrowing_fields.snap new file mode 100644 index 00000000000000..472844269a4517 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__elision__tests__borrowing_fields.snap @@ -0,0 +1,25 @@ +--- +source: core/src/hir/elision.rs +expression: lt_to_borrowing_fields +--- +{ + Static: [ + "this.name", + "_s", + ], + NonStatic( + Lifetime( + 0, + ), + ): [ + "this.p_data", + ], + NonStatic( + Lifetime( + 1, + ), + ): [ + "this.q_data", + "this.inner.more_data", + ], +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__elision__tests__elision_in_struct.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__elision__tests__elision_in_struct.snap new file mode 100644 index 00000000000000..be3a97e2573c93 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__elision__tests__elision_in_struct.snap @@ -0,0 +1,152 @@ +--- +source: core/src/hir/elision.rs +expression: method +--- +Method { + docs: Docs( + "", + [], + ), + name: "elided", + abi_name: "Opaque_elided", + lifetime_env: LifetimeEnv { + nodes: [], + num_lifetimes: 3, + }, + param_self: Some( + ParamSelf { + ty: Opaque( + OpaquePath { + lifetimes: Lifetimes { + indices: [], + }, + optional: NonOptional, + owner: Borrow { + lifetime: NonStatic( + Lifetime( + 0, + ), + ), + mutability: Immutable, + }, + tcx_id: OpaqueId( + 0, + ), + }, + ), + attrs: Attrs { + disable: false, + deprecated: None, + namespace: None, + rename: RenameAttr { + pattern: None, + }, + abi_rename: RenameAttr { + pattern: None, + }, + special_method: None, + custom_errors: false, + default: false, + demo_attrs: DemoInfo { + generate: false, + default_constructor: false, + external: false, + custom_func: None, + input_cfg: DemoInputCFG { + label: "", + default_value: "", + }, + }, + generate_mocking_interface: false, + abi_compatible: false, + }, + }, + ), + params: [ + Param { + name: "x", + ty: Opaque( + OpaquePath { + lifetimes: Lifetimes { + indices: [ + NonStatic( + Lifetime( + 2, + ), + ), + ], + }, + optional: Optional( + false, + ), + owner: Borrow { + lifetime: NonStatic( + Lifetime( + 1, + ), + ), + mutability: Immutable, + }, + tcx_id: OpaqueId( + 1, + ), + }, + ), + attrs: Attrs { + disable: false, + deprecated: None, + namespace: None, + rename: RenameAttr { + pattern: None, + }, + abi_rename: RenameAttr { + pattern: None, + }, + special_method: None, + custom_errors: false, + default: false, + demo_attrs: DemoInfo { + generate: false, + default_constructor: false, + external: false, + custom_func: None, + input_cfg: DemoInputCFG { + label: "", + default_value: "", + }, + }, + generate_mocking_interface: false, + abi_compatible: false, + }, + }, + ], + output: Infallible( + Unit, + ), + attrs: Attrs { + disable: false, + deprecated: None, + namespace: None, + rename: RenameAttr { + pattern: None, + }, + abi_rename: RenameAttr { + pattern: None, + }, + special_method: None, + custom_errors: false, + default: false, + demo_attrs: DemoInfo { + generate: false, + default_constructor: false, + external: false, + custom_func: None, + input_cfg: DemoInputCFG { + label: "", + default_value: "", + }, + }, + generate_mocking_interface: false, + abi_compatible: false, + }, +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__elision__tests__simple_mod.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__elision__tests__simple_mod.snap new file mode 100644 index 00000000000000..573a80de44011f --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__elision__tests__simple_mod.snap @@ -0,0 +1,528 @@ +--- +source: core/src/hir/elision.rs +expression: tcx +--- +TypeContext { + out_structs: [ + StructDef { + docs: Docs( + "", + [], + ), + name: "OutStruct", + fields: [ + StructField { + docs: Docs( + "", + [], + ), + name: "inner", + ty: Opaque( + OpaquePath { + lifetimes: Lifetimes { + indices: [ + NonStatic( + Lifetime( + 0, + ), + ), + ], + }, + optional: Optional( + false, + ), + owner: Own, + tcx_id: OpaqueId( + 0, + ), + }, + ), + attrs: Attrs { + disable: false, + deprecated: None, + namespace: None, + rename: RenameAttr { + pattern: None, + }, + abi_rename: RenameAttr { + pattern: None, + }, + special_method: None, + custom_errors: false, + default: false, + demo_attrs: DemoInfo { + generate: false, + default_constructor: false, + external: false, + custom_func: None, + input_cfg: DemoInputCFG { + label: "", + default_value: "", + }, + }, + generate_mocking_interface: false, + abi_compatible: false, + }, + }, + ], + methods: [ + Method { + docs: Docs( + "", + [], + ), + name: "new", + abi_name: "OutStruct_new", + lifetime_env: LifetimeEnv { + nodes: [ + BoundedLifetime { + ident: "a", + longer: [], + shorter: [], + }, + ], + num_lifetimes: 1, + }, + param_self: None, + params: [ + Param { + name: "s", + ty: Slice( + Str( + Some( + NonStatic( + Lifetime( + 0, + ), + ), + ), + UnvalidatedUtf8, + ), + ), + attrs: Attrs { + disable: false, + deprecated: None, + namespace: None, + rename: RenameAttr { + pattern: None, + }, + abi_rename: RenameAttr { + pattern: None, + }, + special_method: None, + custom_errors: false, + default: false, + demo_attrs: DemoInfo { + generate: false, + default_constructor: false, + external: false, + custom_func: None, + input_cfg: DemoInputCFG { + label: "", + default_value: "", + }, + }, + generate_mocking_interface: false, + abi_compatible: false, + }, + }, + ], + output: Infallible( + OutType( + Struct( + OutStruct( + StructPath { + lifetimes: Lifetimes { + indices: [ + NonStatic( + Lifetime( + 0, + ), + ), + ], + }, + tcx_id: OutStructId( + 0, + ), + owner: Own, + }, + ), + ), + ), + ), + attrs: Attrs { + disable: false, + deprecated: None, + namespace: None, + rename: RenameAttr { + pattern: None, + }, + abi_rename: RenameAttr { + pattern: None, + }, + special_method: None, + custom_errors: false, + default: false, + demo_attrs: DemoInfo { + generate: false, + default_constructor: false, + external: false, + custom_func: None, + input_cfg: DemoInputCFG { + label: "", + default_value: "", + }, + }, + generate_mocking_interface: false, + abi_compatible: false, + }, + }, + ], + attrs: Attrs { + disable: false, + deprecated: None, + namespace: None, + rename: RenameAttr { + pattern: None, + }, + abi_rename: RenameAttr { + pattern: None, + }, + special_method: None, + custom_errors: false, + default: false, + demo_attrs: DemoInfo { + generate: false, + default_constructor: false, + external: false, + custom_func: None, + input_cfg: DemoInputCFG { + label: "", + default_value: "", + }, + }, + generate_mocking_interface: false, + abi_compatible: false, + }, + lifetimes: LifetimeEnv { + nodes: [ + BoundedLifetime { + ident: "a", + longer: [], + shorter: [], + }, + ], + num_lifetimes: 1, + }, + special_method_presence: SpecialMethodPresence { + comparator: false, + iterator: None, + iterable: None, + }, + }, + ], + structs: [ + StructDef { + docs: Docs( + "", + [], + ), + name: "Struct", + fields: [ + StructField { + docs: Docs( + "", + [], + ), + name: "s", + ty: Slice( + Str( + Some( + NonStatic( + Lifetime( + 0, + ), + ), + ), + UnvalidatedUtf8, + ), + ), + attrs: Attrs { + disable: false, + deprecated: None, + namespace: None, + rename: RenameAttr { + pattern: None, + }, + abi_rename: RenameAttr { + pattern: None, + }, + special_method: None, + custom_errors: false, + default: false, + demo_attrs: DemoInfo { + generate: false, + default_constructor: false, + external: false, + custom_func: None, + input_cfg: DemoInputCFG { + label: "", + default_value: "", + }, + }, + generate_mocking_interface: false, + abi_compatible: false, + }, + }, + ], + methods: [ + Method { + docs: Docs( + "", + [], + ), + name: "rustc_elision", + abi_name: "Struct_rustc_elision", + lifetime_env: LifetimeEnv { + nodes: [ + BoundedLifetime { + ident: "a", + longer: [], + shorter: [], + }, + ], + num_lifetimes: 2, + }, + param_self: Some( + ParamSelf { + ty: Struct( + StructPath { + lifetimes: Lifetimes { + indices: [ + NonStatic( + Lifetime( + 0, + ), + ), + ], + }, + tcx_id: StructId( + 0, + ), + owner: Own, + }, + ), + attrs: Attrs { + disable: false, + deprecated: None, + namespace: None, + rename: RenameAttr { + pattern: None, + }, + abi_rename: RenameAttr { + pattern: None, + }, + special_method: None, + custom_errors: false, + default: false, + demo_attrs: DemoInfo { + generate: false, + default_constructor: false, + external: false, + custom_func: None, + input_cfg: DemoInputCFG { + label: "", + default_value: "", + }, + }, + generate_mocking_interface: false, + abi_compatible: false, + }, + }, + ), + params: [ + Param { + name: "s", + ty: Slice( + Str( + Some( + NonStatic( + Lifetime( + 1, + ), + ), + ), + UnvalidatedUtf8, + ), + ), + attrs: Attrs { + disable: false, + deprecated: None, + namespace: None, + rename: RenameAttr { + pattern: None, + }, + abi_rename: RenameAttr { + pattern: None, + }, + special_method: None, + custom_errors: false, + default: false, + demo_attrs: DemoInfo { + generate: false, + default_constructor: false, + external: false, + custom_func: None, + input_cfg: DemoInputCFG { + label: "", + default_value: "", + }, + }, + generate_mocking_interface: false, + abi_compatible: false, + }, + }, + ], + output: Infallible( + OutType( + Slice( + Str( + Some( + NonStatic( + Lifetime( + 1, + ), + ), + ), + UnvalidatedUtf8, + ), + ), + ), + ), + attrs: Attrs { + disable: false, + deprecated: None, + namespace: None, + rename: RenameAttr { + pattern: None, + }, + abi_rename: RenameAttr { + pattern: None, + }, + special_method: None, + custom_errors: false, + default: false, + demo_attrs: DemoInfo { + generate: false, + default_constructor: false, + external: false, + custom_func: None, + input_cfg: DemoInputCFG { + label: "", + default_value: "", + }, + }, + generate_mocking_interface: false, + abi_compatible: false, + }, + }, + ], + attrs: Attrs { + disable: false, + deprecated: None, + namespace: None, + rename: RenameAttr { + pattern: None, + }, + abi_rename: RenameAttr { + pattern: None, + }, + special_method: None, + custom_errors: false, + default: false, + demo_attrs: DemoInfo { + generate: false, + default_constructor: false, + external: false, + custom_func: None, + input_cfg: DemoInputCFG { + label: "", + default_value: "", + }, + }, + generate_mocking_interface: false, + abi_compatible: false, + }, + lifetimes: LifetimeEnv { + nodes: [ + BoundedLifetime { + ident: "a", + longer: [], + shorter: [], + }, + ], + num_lifetimes: 1, + }, + special_method_presence: SpecialMethodPresence { + comparator: false, + iterator: None, + iterable: None, + }, + }, + ], + opaques: [ + OpaqueDef { + docs: Docs( + "", + [], + ), + name: "Opaque", + methods: [], + attrs: Attrs { + disable: false, + deprecated: None, + namespace: None, + rename: RenameAttr { + pattern: None, + }, + abi_rename: RenameAttr { + pattern: None, + }, + special_method: None, + custom_errors: false, + default: false, + demo_attrs: DemoInfo { + generate: false, + default_constructor: false, + external: false, + custom_func: None, + input_cfg: DemoInputCFG { + label: "", + default_value: "", + }, + }, + generate_mocking_interface: false, + abi_compatible: false, + }, + lifetimes: LifetimeEnv { + nodes: [ + BoundedLifetime { + ident: "a", + longer: [], + shorter: [], + }, + ], + num_lifetimes: 1, + }, + special_method_presence: SpecialMethodPresence { + comparator: false, + iterator: None, + iterable: None, + }, + dtor_abi_name: "Opaque_destroy", + }, + ], + enums: [], + traits: [], + functions: [], +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__basic_lowering.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__basic_lowering.snap new file mode 100644 index 00000000000000..b89b5d222ca422 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__basic_lowering.snap @@ -0,0 +1,17 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in BadStructFields: Found FFI-unsafe type Option in struct field BadStructFields.field1, consider using DiplomatOption +Lowering error in BadStructFields: Found Option for primitive T in a struct field, please use DiplomatOption +Lowering error in BadStructFields: Found FFI-unsafe type Result in struct field BadStructFields.field2, consider using Result +Lowering error in BadStructFields: Results can only appear as the top-level return type of methods +Lowering error in InStructWithOutField: found Box in input where T is an opaque, but owned opaques aren't allowed in inputs. try &T instead? T = OtherOpaque +Lowering error in InStructWithOutField: found struct in input that is marked with #[diplomat::out]: OutStruct in OutStruct +Lowering error in Opaque::use_foo_ref: found &T in input where T is a struct. The backend must support struct_refs. +Lowering error in Opaque::return_foo_box: found Box in output where T is a custom type but not opaque. non-opaques can't be behind pointers. T = Foo +Lowering error in Opaque::use_self: Method `Opaque_use_self` takes an opaque by value as the self parameter, but opaques as inputs must be behind refs +Lowering error in Opaque::return_self: Method `Opaque_return_self` takes an opaque by value as the self parameter, but opaques as inputs must be behind refs +Lowering error in Opaque::use_opaque_owned: Opaque passed by value: OtherOpaque +Lowering error in Opaque::return_opaque_owned: Opaque passed by value in input: OtherOpaque +Lowering error in Opaque::use_out_as_in: found struct in input that is marked with #[diplomat::out]: OutStruct in OutStruct diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__callback_borrowing_fails.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__callback_borrowing_fails.snap new file mode 100644 index 00000000000000..94c9797218fe9f --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__callback_borrowing_fails.snap @@ -0,0 +1,5 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in Foo::apply_callback: Callbacks cannot take references since they can be unsafely persisted, set `unsafe_references_in_callbacks` config to override. diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__callback_borrowing_fails_with_unsafe_borrows.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__callback_borrowing_fails_with_unsafe_borrows.snap new file mode 100644 index 00000000000000..faaaf03da4e2c3 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__callback_borrowing_fails_with_unsafe_borrows.snap @@ -0,0 +1,6 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in Foo::apply_callback_owned_slice: Cannot return owned slices from callbacks +Lowering error in Foo::apply_callback_borrowed_struct: Cannot return references to structs from callbacks diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__lifetime_in_return.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__lifetime_in_return.snap new file mode 100644 index 00000000000000..59cbfc8f55ac3c --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__lifetime_in_return.snap @@ -0,0 +1,6 @@ +--- +source: core/src/hir/type_context.rs +assertion_line: 970 +expression: output +--- +Lowering error in Opaque::returns_foo_ref: found &T in output where T is a custom type, but not opaque. T = Foo diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__mut_struct.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__mut_struct.snap new file mode 100644 index 00000000000000..89806691dff699 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__mut_struct.snap @@ -0,0 +1,5 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- + diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__mut_struct_fails.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__mut_struct_fails.snap new file mode 100644 index 00000000000000..0bb1911449c51c --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__mut_struct_fails.snap @@ -0,0 +1,5 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in Foo::takes_mut: found &T in output where T is a custom type, but not opaque. T = Foo diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__non_opaque_move.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__non_opaque_move.snap new file mode 100644 index 00000000000000..bbda28062b82ce --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__non_opaque_move.snap @@ -0,0 +1,8 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in NonOpaque::foo: Method `NonOpaque_foo` takes a reference to a struct as a self parameter, which isn't allowed. Backend must support struct_refs. +Lowering error in Opaque::bar: found &T in output where T is a custom type, but not opaque. T = NonOpaque +Lowering error in Opaque::baz: found &T in input where T is a struct. The backend must support struct_refs. +Lowering error in Opaque::quux: found Box in output where T is a custom type but not opaque. non-opaques can't be behind pointers. T = NonOpaque diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__non_primitive_struct_slices_fails.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__non_primitive_struct_slices_fails.snap new file mode 100644 index 00000000000000..fd1581621572b6 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__non_primitive_struct_slices_fails.snap @@ -0,0 +1,6 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in Foo: Struct "Foo" cannot have any lifetimes if it is marked as ABI compatible. +Lowering error in Foo: Cannot construct a slice of "Foo" with non-primitive, non-struct field "z" diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_checks_with_error.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_checks_with_error.snap new file mode 100644 index 00000000000000..76bf3f06ea41a1 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_checks_with_error.snap @@ -0,0 +1,7 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in OpaqueStruct::new: Opaque passed by value in input: OpaqueStruct +Lowering error in OpaqueStruct::get_i32: Method `OpaqueStruct_get_i32` takes an opaque by value as the self parameter, but opaques as inputs must be behind refs + diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_checks_with_safe_use.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_checks_with_safe_use.snap new file mode 100644 index 00000000000000..ea2e6fc7c2ecf1 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_checks_with_safe_use.snap @@ -0,0 +1,5 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in NonOpaqueStruct: Methods on ZST structs are not yet implemented: NonOpaqueStruct diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_ffi.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_ffi.snap new file mode 100644 index 00000000000000..f6c4fee4463225 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__opaque_ffi.snap @@ -0,0 +1,9 @@ +--- +source: core/src/hir/type_context.rs +assertion_line: 691 +expression: output +--- +Lowering error in MyOpaqueEnum::new_broken: Opaque passed by value in input: MyOpaqueEnum +Lowering error in MyOpaqueEnum::do_thing_broken: Method `MyOpaqueEnum_do_thing_broken` takes an opaque by value as the self parameter, but opaques as inputs must be behind refs +Lowering error in MyOpaqueStruct::new_broken: Opaque passed by value in input: MyOpaqueStruct +Lowering error in MyOpaqueStruct::do_thing_broken: Method `MyOpaqueStruct_do_thing_broken` takes an opaque by value as the self parameter, but opaques as inputs must be behind refs diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__option.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__option.snap new file mode 100644 index 00000000000000..ad13fa52f8853a --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__option.snap @@ -0,0 +1,11 @@ +--- +source: core/src/hir/type_context.rs +assertion_line: 1060 +expression: output +--- +Lowering error in BrokenStruct: Found FFI-unsafe type Option in struct field BrokenStruct.regular_option, consider using DiplomatOption +Lowering error in BrokenStruct: Found Option for primitive T in a struct field, please use DiplomatOption +Lowering error in BrokenStruct: Found FFI-unsafe type Option in struct field BrokenStruct.regular_option, consider using DiplomatOption +Lowering error in BrokenStruct: Found Option for struct/enum T in a struct field, please use DiplomatOption +Lowering error in Foo::diplo_option_ref: found DiplomatOption<&T>, please use Option<&T> (DiplomatOption is for primitives, structs, and enums) +Lowering error in Foo::diplo_option_box: found DiplomatOption>, please use Option> (DiplomatOption is for primitives, structs, and enums) diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__option_invalid.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__option_invalid.snap new file mode 100644 index 00000000000000..0d200ec16a36fb --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__option_invalid.snap @@ -0,0 +1,8 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in Foo: Found FFI-unsafe type Option in struct field Foo.field, consider using DiplomatOption +Lowering error in Foo: Found Option for primitive T in a struct field, please use DiplomatOption +Lowering error in Foo::do_thing: found Option in input, where T isn't a reference but Option in inputs requires that T is a reference to an opaque. T = Option +Lowering error in Foo::do_thing2: Results can only appear as the top-level return type of methods diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__option_valid.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__option_valid.snap new file mode 100644 index 00000000000000..fbd4d2c119e7fc --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__option_valid.snap @@ -0,0 +1,8 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in Foo: found Option> in input, but box isn't allowed in inputs. T = u8 +Lowering error in Foo::do_thing: found Option> in input, but box isn't allowed in inputs. T = u32 +Lowering error in Foo::do_thing2: found Option<&T> in input, but T isn't a custom type and therefore not opaque. T = u32 + diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__required_implied_bounds.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__required_implied_bounds.snap new file mode 100644 index 00000000000000..d57f9ea35c1d0d --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__required_implied_bounds.snap @@ -0,0 +1,11 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in Opaque::use_foo: Method should explicitly include this lifetime bound from param foo: 'y: 'x (comes from source type's 'b: 'a) +Lowering error in Opaque::use_foo: Method should explicitly include this lifetime bound from param foo: 'z: 'y (comes from source type's 'c: 'b) +Lowering error in Opaque::return_foo: Method should explicitly include this lifetime bound from return type: 'y: 'x (comes from source type's 'b: 'a) +Lowering error in Opaque::return_foo: Method should explicitly include this lifetime bound from return type: 'z: 'y (comes from source type's 'c: 'b) +Lowering error in Opaque::return_result_foo: Method should explicitly include this lifetime bound from return type: 'y: 'x (comes from source type's 'b: 'a) +Lowering error in Opaque::return_result_foo: Method should explicitly include this lifetime bound from return type: 'z: 'y (comes from source type's 'c: 'b) + diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__return_struct_slice.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__return_struct_slice.snap new file mode 100644 index 00000000000000..1d372ced81db8a --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__return_struct_slice.snap @@ -0,0 +1,5 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in Foo::returns_slice: `abi_compatible` can only be used on non-output-only struct types. diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__struct_forbidden.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__struct_forbidden.snap new file mode 100644 index 00000000000000..41ee009b0e5649 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__struct_forbidden.snap @@ -0,0 +1,10 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in Crimes: Found FFI-unsafe type &'a str in struct field Crimes.slice1, consider using DiplomatUtf8Str<'a> +Lowering error in Crimes: Found FFI-unsafe type &'a DiplomatStr in struct field Crimes.slice1, consider using DiplomatStrSlice<'a> +Lowering error in Crimes: Found FFI-unsafe type &'a [u8] in struct field Crimes.slice2, consider using DiplomatSlice<'a,u8> +Lowering error in Crimes: Found FFI-unsafe type Box in struct field Crimes.slice3, consider using DiplomatOwnedUtf8Str +Lowering error in Crimes: Found FFI-unsafe type Box in struct field Crimes.slice3, consider using DiplomatOwnedStrSlice +Lowering error in Crimes: Found FFI-unsafe type Box<[u8]> in struct field Crimes.slice4, consider using Box<[u8]> diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__struct_ref_fails.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__struct_ref_fails.snap new file mode 100644 index 00000000000000..da59cb9a3d54aa --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__struct_ref_fails.snap @@ -0,0 +1,6 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in Foo: Struct "Foo" field "foo" cannot be borrowed. Structs cannot be borrowed inside of other structs, try removing the borrow and storing the struct directly. +Lowering error in Foo::out: Found lifetimes used in struct references also used in the return type: 'a diff --git a/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__zst_non_opaque.snap b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__zst_non_opaque.snap new file mode 100644 index 00000000000000..b7c6e27eb4ac05 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/snapshots/diplomat_core__hir__type_context__tests__zst_non_opaque.snap @@ -0,0 +1,5 @@ +--- +source: core/src/hir/type_context.rs +expression: output +--- +Lowering error in NonOpaque: Methods on ZST structs are not yet implemented: NonOpaque diff --git a/deps/crates/vendor/diplomat_core/src/hir/ty_position.rs b/deps/crates/vendor/diplomat_core/src/hir/ty_position.rs new file mode 100644 index 00000000000000..9d6ffc57f07e64 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/ty_position.rs @@ -0,0 +1,335 @@ +use super::lifetimes::{Lifetime, Lifetimes, MaybeStatic}; +use super::{ + Borrow, Callback, CallbackInstantiationFunctionality, LinkedLifetimes, MaybeOwn, Mutability, + NoCallback, NoTraitPath, OutStructId, ReturnableStructPath, StructDef, StructId, StructPath, + TraitId, TraitPath, TypeContext, TypeDef, TypeId, +}; +use core::fmt::Debug; + +/// Abstraction over where a type can appear in a function signature. +/// +/// # "Output only" and "everywhere" types +/// +/// While Rust is able to give up ownership of values, languages that Diplomat +/// supports (C++, Javascript, etc.) generally cannot. For example, we can +/// construct a `Box` in a Rust function and _return_ it to the other +/// language as a pointer. However, we cannot _accept_ `Box` as an input +/// because there's nothing stopping other languages from using that value again. +/// Therefore, we classify boxed opaques as "output only" types, since they can +/// only be returned from Rust but not taken as inputs. +/// +/// Furthermore, Diplomat also supports "bag o' stuff" structs where all fields get +/// translated at the boundary. If one contains an "output only" type as a field, +/// then the whole struct must also be "output only". In particular, this means +/// that if a boxed opaque is nested in a bunch of "bag o' stuff" structs, than +/// all of those structs must also be "output only". +/// +/// Currently, there are only two classes of structs: those that are "output only", +/// and those that are not. These are represented by the types [`OutputOnly`] +/// and [`Everywhere`] marker types respectively, which are the _only_ two types +/// that implement [`TyPosition`]. +/// +/// # How does abstraction help? +/// +/// The HIR was designed around the idea of making invalid states unrepresentable. +/// Since "output only" types can contain values that "everywhere" types cannot, +/// it doesn't make sense for them to be represented in the same type, even if +/// they're mostly the same. One of these differences is that opaques (which are +/// always behind a pointer) can only be represented as a borrow in "everywhere" +/// types, but can additionally be represented as owned in "output only" types. +/// If we were to use the same type for both, then backends working with "everywhere" +/// types would constantly have unreachable statements for owned opaque cases. +/// +/// That being said, "output only" and "everywhere" types are still mostly the +/// same, so this trait allows us to describe the differences. For example, the +/// HIR uses a singular [`Type`](super::Type) type for representing both +/// "output only" types and "everywhere" types, since it takes advantage of this +/// traits associated types to "fill in" the different parts: +/// ```ignore +/// pub enum Type { +/// Primitive(PrimitiveType), +/// Opaque(OpaquePath), +/// Struct(P::StructPath), +/// Enum(EnumPath), +/// Slice(Slice), +/// } +/// ``` +/// +/// When `P` takes on [`Everywhere`], this signature becomes: +/// ```ignore +/// pub enum Type { +/// Primitive(PrimitiveType), +/// Opaque(OpaquePath), +/// Struct(StructPath), +/// Enum(EnumPath), +/// Slice(Slice), +/// } +/// ``` +/// +/// This allows us to represent any kind of type that can appear "everywhere" +/// i.e. in inputs or outputs. Notice how the second generic in the `Opaque` +/// variant becomes [`Borrow`]. This describes the semantics of the pointer that +/// the opaque lives behind, and shows that for "everywhere" types, opaques +/// can _only_ be represented as living behind a borrow. +/// +/// Contrast this to when `P` takes on [`OutputOnly`]: +/// ```ignore +/// pub enum Type { +/// Primitive(PrimitiveType), +/// Opaque(OpaquePath), +/// Struct(OutStructPath), +/// Enum(EnumPath), +/// Slice(Slice), +/// } +/// ``` +/// Here, the second generic of the `Opaque` variant becomes [`MaybeOwn`], meaning +/// that "output only" types can contain opaques that are either borrowed _or_ owned. +/// +/// Therefore, this trait allows be extremely precise about making invalid states +/// unrepresentable, while also reducing duplicated code. +/// +pub trait TyPosition: Debug + Copy +where + for<'tcx> TypeDef<'tcx>: From<&'tcx StructDef>, +{ + const IN_OUT_STATUS: InputOrOutput; + type CallbackInstantiation: Debug + CallbackInstantiationFunctionality + Clone; + + /// Type representing how we can point to opaques, which must always be behind a pointer. + /// + /// The types represented by [`OutputOnly`] are capable of either owning or + /// borrowing opaques, and so the associated type for that impl is [`MaybeOwn`]. + /// + /// On the other hand, types represented by [`Everywhere`] can only contain + /// borrowes, so the associated type for that impl is [`Borrow`]. + type OpaqueOwnership: Debug + OpaqueOwner + Clone; + + type StructId: Debug + Clone; + + type StructPath: Debug + StructPathLike + Clone; + + type TraitPath: Debug + TraitIdGetter + Clone; + + fn wrap_struct_def<'tcx>(def: &'tcx StructDef) -> TypeDef<'tcx>; + fn build_callback(cb: Callback) -> Self::CallbackInstantiation; + fn build_trait_path(trait_path: TraitPath) -> Self::TraitPath; +} + +/// Directionality of the type +#[non_exhaustive] +pub enum InputOrOutput { + Input, + Output, + InputOutput, +} + +pub trait TraitIdGetter { + fn id(&self) -> TraitId; +} + +/// One of 3 types implementing [`TyPosition`], representing types that can be +/// used as both input and output to functions. +/// +/// The restricted versions of this type are [`OutputOnly`] and [`InputOnly`]. +#[derive(Debug, Copy, Clone)] +#[non_exhaustive] +pub struct Everywhere; + +/// One of 3 types implementing [`TyPosition`], representing types that can +/// only be used as return types in functions. +/// +/// The directional opposite of this type is [`InputOnly`]. +#[derive(Debug, Copy, Clone)] +#[non_exhaustive] +pub struct OutputOnly; + +/// One of 3 types implementing [`TyPosition`], representing types that can +/// only be used as input types in functions. +/// +/// The directional opposite of this type is [`OutputOnly`]. +#[derive(Debug, Copy, Clone)] +#[non_exhaustive] +pub struct InputOnly; + +impl TyPosition for Everywhere { + const IN_OUT_STATUS: InputOrOutput = InputOrOutput::InputOutput; + type OpaqueOwnership = Borrow; + type StructId = StructId; + type StructPath = StructPath; + type CallbackInstantiation = NoCallback; + type TraitPath = NoTraitPath; + + fn wrap_struct_def<'tcx>(def: &'tcx StructDef) -> TypeDef<'tcx> { + TypeDef::Struct(def) + } + fn build_callback(_cb: Callback) -> Self::CallbackInstantiation { + panic!("Callbacks must be input-only"); + } + fn build_trait_path(_trait_path: TraitPath) -> Self::TraitPath { + panic!("Traits must be input-only"); + } +} + +impl TyPosition for OutputOnly { + const IN_OUT_STATUS: InputOrOutput = InputOrOutput::Output; + type OpaqueOwnership = MaybeOwn; + type StructId = OutStructId; + type StructPath = ReturnableStructPath; + type CallbackInstantiation = NoCallback; + type TraitPath = NoTraitPath; + + fn wrap_struct_def<'tcx>(def: &'tcx StructDef) -> TypeDef<'tcx> { + TypeDef::OutStruct(def) + } + fn build_callback(_cb: Callback) -> Self::CallbackInstantiation { + panic!("Callbacks must be input-only"); + } + fn build_trait_path(_trait_path: TraitPath) -> Self::TraitPath { + panic!("Traits must be input-only"); + } +} + +impl TyPosition for InputOnly { + const IN_OUT_STATUS: InputOrOutput = InputOrOutput::Input; + type OpaqueOwnership = Borrow; + type StructId = StructId; + type StructPath = StructPath; + type CallbackInstantiation = Callback; + type TraitPath = TraitPath; + + fn wrap_struct_def<'tcx>(_def: &'tcx StructDef) -> TypeDef<'tcx> { + panic!("Input-only structs are not currently supported"); + } + fn build_callback(cb: Callback) -> Self::CallbackInstantiation { + cb + } + fn build_trait_path(trait_path: TraitPath) -> Self::TraitPath { + trait_path + } +} + +pub trait StructPathLike { + fn lifetimes(&self) -> &Lifetimes; + fn id(&self) -> TypeId; + fn owner(&self) -> MaybeOwn; + + /// Get a map of lifetimes used on this path to lifetimes as named in the def site. See [`LinkedLifetimes`] + /// for more information. + fn link_lifetimes<'def, 'tcx>( + &'def self, + tcx: &'tcx TypeContext, + ) -> LinkedLifetimes<'def, 'tcx>; +} + +impl StructPathLike for StructPath { + fn lifetimes(&self) -> &Lifetimes { + &self.lifetimes + } + fn id(&self) -> TypeId { + self.tcx_id.into() + } + + fn owner(&self) -> MaybeOwn { + self.owner + } + + fn link_lifetimes<'def, 'tcx>( + &'def self, + tcx: &'tcx TypeContext, + ) -> LinkedLifetimes<'def, 'tcx> { + let struc = self.resolve(tcx); + let env = &struc.lifetimes; + LinkedLifetimes::new(env, None, &self.lifetimes) + } +} + +impl StructPathLike for ReturnableStructPath { + fn lifetimes(&self) -> &Lifetimes { + self.lifetimes() + } + fn id(&self) -> TypeId { + match self { + ReturnableStructPath::Struct(p) => p.tcx_id.into(), + ReturnableStructPath::OutStruct(p) => p.tcx_id.into(), + } + } + + fn owner(&self) -> MaybeOwn { + MaybeOwn::Own + } + + fn link_lifetimes<'def, 'tcx>( + &'def self, + tcx: &'tcx TypeContext, + ) -> LinkedLifetimes<'def, 'tcx> { + match self { + Self::Struct(p) => p.link_lifetimes(tcx), + Self::OutStruct(p) => p.link_lifetimes(tcx), + } + } +} + +impl TraitIdGetter for TraitPath { + fn id(&self) -> TraitId { + self.tcx_id + } +} + +impl TraitIdGetter for NoTraitPath { + fn id(&self) -> TraitId { + panic!("Trait path not allowed here, no trait ID valid"); + } +} + +/// Abstraction over how a type can hold a pointer to an opaque. +/// +/// This trait is designed as a helper abstraction for the `OpaqueOwnership` +/// associated type in the [`TyPosition`] trait. As such, only has two implementing +/// types: [`MaybeOwn`] and [`Borrow`] for the [`OutputOnly`] and [`Everywhere`] +/// implementations of [`TyPosition`] respectively. +pub trait OpaqueOwner { + /// Return the mutability of this owner + fn mutability(&self) -> Option; + + fn is_owned(&self) -> bool; + + /// Return the lifetime of the borrow, if any. + fn lifetime(&self) -> Option>; +} + +impl OpaqueOwner for MaybeOwn { + fn mutability(&self) -> Option { + match self { + MaybeOwn::Own => None, + MaybeOwn::Borrow(b) => b.mutability(), + } + } + + fn is_owned(&self) -> bool { + match self { + MaybeOwn::Own => true, + MaybeOwn::Borrow(_) => false, + } + } + + fn lifetime(&self) -> Option> { + match self { + MaybeOwn::Own => None, + MaybeOwn::Borrow(b) => b.lifetime(), + } + } +} + +impl OpaqueOwner for Borrow { + fn mutability(&self) -> Option { + Some(self.mutability) + } + + fn is_owned(&self) -> bool { + false + } + + fn lifetime(&self) -> Option> { + Some(self.lifetime) + } +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/type_context.rs b/deps/crates/vendor/diplomat_core/src/hir/type_context.rs new file mode 100644 index 00000000000000..68979367d7b81d --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/type_context.rs @@ -0,0 +1,1396 @@ +//! Store all the types contained in the HIR. + +use super::lowering::{ErrorAndContext, ErrorStore, ItemAndInfo}; +use super::ty_position::StructPathLike; +use super::{ + AttributeValidator, Attrs, EnumDef, LoweringContext, LoweringError, MaybeOwn, MaybeStatic, + OpaqueDef, OutStructDef, StructDef, TraitDef, TypeDef, +}; +use crate::ast::attrs::AttrInheritContext; +#[allow(unused_imports)] // use in docs links +use crate::hir; +use crate::hir::Method; +use crate::{ast, Env}; +use core::fmt::{self, Display}; +use smallvec::SmallVec; +use std::borrow::Cow; +use std::collections::{BTreeSet, HashMap}; +use std::ops::Index; + +/// A context type owning all types exposed to Diplomat. +#[derive(Debug)] +pub struct TypeContext { + out_structs: Vec, + structs: Vec, + opaques: Vec, + enums: Vec, + traits: Vec, + functions: Vec, +} + +/// Additional features/config to support while lowering +#[non_exhaustive] +#[derive(Default, Debug, Copy, Clone)] +pub struct LoweringConfig { + /// Support references in callback params (unsafe) + pub unsafe_references_in_callbacks: bool, +} + +/// Key used to index into a [`TypeContext`] representing a struct. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct StructId(usize); + +/// Key used to index into a [`TypeContext`] representing an out struct. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct OutStructId(usize); + +/// Key used to index into a [`TypeContext`] representing a opaque. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct OpaqueId(usize); + +/// Key used to index into a [`TypeContext`] representing an enum. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct EnumId(usize); + +/// Key used to index into a [`TypeContext`] representing a trait. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct TraitId(usize); + +/// Key used to index into a [`TypeContext`] representing a function. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct FunctionId(usize); + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[non_exhaustive] +pub enum TypeId { + Struct(StructId), + OutStruct(OutStructId), + Opaque(OpaqueId), + Enum(EnumId), +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[non_exhaustive] +pub enum SymbolId { + TypeId(TypeId), + TraitId(TraitId), + FunctionId(FunctionId), +} + +enum Param<'a> { + Input(&'a str), + Return, +} + +impl Display for Param<'_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if let Param::Input(s) = *self { + write!(f, "param {s}") + } else { + write!(f, "return type") + } + } +} + +impl TypeContext { + pub fn all_types<'tcx>(&'tcx self) -> impl Iterator)> { + self.structs + .iter() + .enumerate() + .map(|(i, ty)| (TypeId::Struct(StructId(i)), TypeDef::Struct(ty))) + .chain( + self.out_structs + .iter() + .enumerate() + .map(|(i, ty)| (TypeId::OutStruct(OutStructId(i)), TypeDef::OutStruct(ty))), + ) + .chain( + self.opaques + .iter() + .enumerate() + .map(|(i, ty)| (TypeId::Opaque(OpaqueId(i)), TypeDef::Opaque(ty))), + ) + .chain( + self.enums + .iter() + .enumerate() + .map(|(i, ty)| (TypeId::Enum(EnumId(i)), TypeDef::Enum(ty))), + ) + } + + pub fn all_traits<'tcx>(&'tcx self) -> impl Iterator { + self.traits + .iter() + .enumerate() + .map(|(i, trt)| (TraitId(i), trt)) + } + + pub fn all_free_functions<'tcx>( + &'tcx self, + ) -> impl Iterator { + self.functions + .iter() + .enumerate() + .map(|(i, f)| (FunctionId(i), f)) + } + + pub fn out_structs(&self) -> &[OutStructDef] { + &self.out_structs + } + + pub fn structs(&self) -> &[StructDef] { + &self.structs + } + + pub fn opaques(&self) -> &[OpaqueDef] { + &self.opaques + } + + pub fn enums(&self) -> &[EnumDef] { + &self.enums + } + + pub fn traits(&self) -> &[TraitDef] { + &self.traits + } + + pub fn resolve_type<'tcx>(&'tcx self, id: TypeId) -> TypeDef<'tcx> { + match id { + TypeId::Struct(i) => TypeDef::Struct(self.resolve_struct(i)), + TypeId::OutStruct(i) => TypeDef::OutStruct(self.resolve_out_struct(i)), + TypeId::Opaque(i) => TypeDef::Opaque(self.resolve_opaque(i)), + TypeId::Enum(i) => TypeDef::Enum(self.resolve_enum(i)), + } + } + + /// Helper methods for resolving different IDs. + /// + /// Prefer using `resolve_type()` for simplicity. + pub fn resolve_out_struct(&self, id: OutStructId) -> &OutStructDef { + self.out_structs.index(id.0) + } + + /// Helper methods for resolving different IDs. + /// + /// Prefer using `resolve_type()` for simplicity. + pub fn resolve_struct(&self, id: StructId) -> &StructDef { + self.structs.index(id.0) + } + + /// Helper methods for resolving different IDs. + /// + /// Prefer using `resolve_type()` for simplicity. + pub fn resolve_opaque(&self, id: OpaqueId) -> &OpaqueDef { + self.opaques.index(id.0) + } + + /// Helper methods for resolving different IDs. + /// + /// Prefer using `resolve_type()` for simplicity. + pub fn resolve_enum(&self, id: EnumId) -> &EnumDef { + self.enums.index(id.0) + } + + pub fn resolve_trait(&self, id: TraitId) -> &TraitDef { + self.traits.index(id.0) + } + + pub fn resolve_function(&self, id: FunctionId) -> &Method { + self.functions.index(id.0) + } + + /// Resolve and format a named type for use in diagnostics + /// (don't apply rename rules and such) + pub fn fmt_type_name_diagnostics(&self, id: TypeId) -> Cow<'_, str> { + self.resolve_type(id).name().as_str().into() + } + + pub fn fmt_symbol_name_diagnostics(&self, id: SymbolId) -> Cow<'_, str> { + match id { + SymbolId::TypeId(id) => self.fmt_type_name_diagnostics(id), + SymbolId::TraitId(id) => self.resolve_trait(id).name.as_str().into(), + SymbolId::FunctionId(id) => self.resolve_function(id).name.as_str().into(), + } + } + + /// Lower the AST to the HIR while simultaneously performing validation. + pub fn from_syn<'ast>( + s: &'ast syn::File, + cfg: LoweringConfig, + attr_validator: impl AttributeValidator + 'static, + ) -> Result> { + let types = ast::File::from(s).all_types(); + let (mut ctx, hir) = Self::from_ast_without_validation(&types, cfg, attr_validator)?; + ctx.errors.set_item("(validation)"); + hir.validate(&mut ctx.errors); + if !ctx.errors.is_empty() { + return Err(ctx.errors.take_errors()); + } + Ok(hir) + } + + /// Lower the AST to the HIR, without validation. For testing + pub(super) fn from_ast_without_validation<'ast>( + env: &'ast Env, + cfg: LoweringConfig, + attr_validator: impl AttributeValidator + 'static, + ) -> Result<(LoweringContext<'ast>, Self), Vec> { + let mut ast_out_structs = SmallVec::<[_; 16]>::new(); + let mut ast_structs = SmallVec::<[_; 16]>::new(); + let mut ast_opaques = SmallVec::<[_; 16]>::new(); + let mut ast_enums = SmallVec::<[_; 16]>::new(); + let mut ast_traits = SmallVec::<[_; 16]>::new(); + let mut ast_functions = SmallVec::<[_; 16]>::new(); + + let mut errors = ErrorStore::default(); + + for (path, mod_env) in env.iter_modules() { + errors.set_item( + path.elements + .last() + .map(|m| m.as_str()) + .unwrap_or("root module"), + ); + let mod_attrs = Attrs::from_ast( + &mod_env.attrs, + &attr_validator, + &Default::default(), + &mut errors, + ); + let ty_attrs = mod_attrs.for_inheritance(AttrInheritContext::Type); + let method_attrs = + mod_attrs.for_inheritance(AttrInheritContext::MethodOrImplFromModule); + + for sym in mod_env.items() { + match sym { + ast::ModSymbol::CustomType(custom_type) => match custom_type { + ast::CustomType::Struct(strct) => { + let id = if strct.output_only { + TypeId::OutStruct(OutStructId(ast_out_structs.len())) + } else { + TypeId::Struct(StructId(ast_structs.len())) + }; + let item = ItemAndInfo { + item: strct, + in_path: path, + ty_parent_attrs: ty_attrs.clone(), + method_parent_attrs: method_attrs.clone(), + id: id.into(), + }; + if strct.output_only { + ast_out_structs.push(item); + } else { + ast_structs.push(item); + } + } + ast::CustomType::Opaque(opaque) => { + let item = ItemAndInfo { + item: opaque, + in_path: path, + ty_parent_attrs: ty_attrs.clone(), + method_parent_attrs: method_attrs.clone(), + id: TypeId::Opaque(OpaqueId(ast_opaques.len())).into(), + }; + ast_opaques.push(item) + } + ast::CustomType::Enum(enm) => { + let item = ItemAndInfo { + item: enm, + in_path: path, + ty_parent_attrs: ty_attrs.clone(), + method_parent_attrs: method_attrs.clone(), + id: TypeId::Enum(EnumId(ast_enums.len())).into(), + }; + ast_enums.push(item) + } + }, + ast::ModSymbol::Trait(trt) => { + let item = ItemAndInfo { + item: trt, + in_path: path, + ty_parent_attrs: ty_attrs.clone(), + method_parent_attrs: method_attrs.clone(), + id: TraitId(ast_traits.len()).into(), + }; + ast_traits.push(item) + } + ast::ModSymbol::Function(f) => { + let item = ItemAndInfo { + item: f, + in_path: path, + ty_parent_attrs: ty_attrs.clone(), + method_parent_attrs: method_attrs.clone(), + id: FunctionId(ast_functions.len()).into(), + }; + ast_functions.push(item) + } + _ => {} + } + } + } + + let lookup_id = LookupId::new( + &ast_out_structs[..], + &ast_structs[..], + &ast_opaques[..], + &ast_enums[..], + &ast_traits[..], + ); + let attr_validator = Box::new(attr_validator); + + let mut ctx = LoweringContext { + lookup_id, + env, + errors, + attr_validator, + cfg, + }; + + let out_structs = ctx.lower_all_out_structs(ast_out_structs.into_iter()); + let structs = ctx.lower_all_structs(ast_structs.into_iter()); + let opaques = ctx.lower_all_opaques(ast_opaques.into_iter()); + let enums = ctx.lower_all_enums(ast_enums.into_iter()); + let traits = ctx.lower_all_traits(ast_traits.into_iter()).unwrap(); + let functions = ctx.lower_all_functions(ast_functions.into_iter()); + + match (out_structs, structs, opaques, enums, functions) { + (Ok(out_structs), Ok(structs), Ok(opaques), Ok(enums), Ok(functions)) => { + let res = Self { + out_structs, + structs, + opaques, + enums, + traits, + functions, + }; + + if !ctx.errors.is_empty() { + return Err(ctx.errors.take_errors()); + } + Ok((ctx, res)) + } + _ => { + assert!( + !ctx.errors.is_empty(), + "Lowering failed without error messages" + ); + Err(ctx.errors.take_errors()) + } + } + } + + /// Run validation phase + /// + /// Currently validates that methods are not inheriting any transitive bounds from parameters + /// Todo: Automatically insert these bounds during HIR construction in a second phase + fn validate<'hir>(&'hir self, errors: &mut ErrorStore<'hir>) { + // Lifetime validity check + for (_id, ty) in self.all_types() { + errors.set_item(ty.name().as_str()); + + self.validate_type_def(errors, ty); + + for method in ty.methods() { + errors.set_subitem(method.name.as_str()); + + // This check must occur before validate_ty_in_method is called + // since validate_ty_in_method calls link_lifetimes which does not + // work for structs with elision + let mut failed = false; + method.output.with_contained_types(|out_ty| { + for lt in out_ty.lifetimes() { + if let MaybeStatic::NonStatic(lt) = lt { + if method.lifetime_env.get_bounds(lt).is_none() { + errors.push(LoweringError::Other( + "Found elided lifetime in return type, please explicitly specify".into(), + )); + + failed = true; + break; + } + } + } + }); + + if failed { + // link_lifetimes will fail if elision exists + continue; + } + + let mut struct_ref_lifetimes = BTreeSet::new(); + + if let Some(super::ParamSelf { + ty: super::SelfType::Struct(s), + attrs: _attrs, + }) = &method.param_self + { + if let MaybeOwn::Borrow(b) = s.owner { + if let MaybeStatic::NonStatic(ns) = b.lifetime { + struct_ref_lifetimes.insert(ns); + } + } + } + + for param in &method.params { + if let super::Type::Struct(ref st) = ¶m.ty { + if let MaybeOwn::Borrow(b) = st.owner { + if let MaybeStatic::NonStatic(ns) = b.lifetime { + struct_ref_lifetimes.insert(ns); + } + } + } + + self.validate_ty_in_method( + errors, + Param::Input(param.name.as_str()), + ¶m.ty, + method, + ) + } + + let lts = method.output.used_method_lifetimes(); + let mut intersection = lts.intersection(&struct_ref_lifetimes).peekable(); + if intersection.peek().is_some() { + errors.push(LoweringError::Other( + format!("Found lifetimes used in struct references also used in the return type: {}", intersection.map(|lt| { + format!("'{} ", method.lifetime_env.fmt_lifetime(lt)) + }).collect::()) + )); + } + + method.output.with_contained_types(|out_ty| { + self.validate_ty_in_method(errors, Param::Return, out_ty, method); + }) + } + } + + for (_id, def) in self.all_traits() { + errors.set_item(def.name.as_str()); + self.validate_trait(errors, def); + } + } + + /// Perform validation checks on any given type + /// (whether it be a struct field, a method argument, etc.) + /// Currently used to check if a given type is a slice of structs, + /// and ensure the relevant attributes are set there. + fn validate_ty(&self, errors: &mut ErrorStore, ty: &hir::Type

) { + if let hir::Type::Slice(hir::Slice::Struct(_, st)) = ty { + let st = self.resolve_type(st.id()); + match st { + TypeDef::Struct(st) => { + if !st.attrs.abi_compatible { + errors.push(LoweringError::Other(format!( + "Cannot construct a slice of {:?}. Try marking with `#[diplomat::attr(auto, abi_compatible)]`", + st.name + ))); + } + } + _ => unreachable!(), + } + } + } + + /// Ensure that a given method's input our output type does not implicitly introduce bounds that are not + /// already specified on the method + /// Also validates the type of each given parameter. + fn validate_ty_in_method( + &self, + errors: &mut ErrorStore, + param: Param, + param_ty: &hir::Type

, + method: &hir::Method, + ) { + self.validate_ty(errors, param_ty); + + let linked = match ¶m_ty { + hir::Type::Opaque(p) => p.link_lifetimes(self), + hir::Type::Struct(p) => p.link_lifetimes(self), + _ => return, + }; + + for (use_lt, def_lt) in linked.lifetimes_all() { + let MaybeStatic::NonStatic(use_lt) = use_lt else { + continue; + }; + let Some(use_bounds) = &method.lifetime_env.get_bounds(use_lt) else { + continue; + }; + let use_longer_lifetimes = &use_bounds.longer; + let anchor; + let def_longer_lifetimes = if let Some(def_lt) = def_lt { + let Some(def_bounds) = &linked.def_env().get_bounds(def_lt) else { + continue; + }; + &def_bounds.longer + } else { + anchor = linked.def_env().all_lifetimes().collect(); + &anchor + }; + + for def_longer in def_longer_lifetimes { + let MaybeStatic::NonStatic(corresponding_use) = linked.def_to_use(*def_longer) + else { + continue; + }; + + // In the case of stuff like <'a, 'a> passed to Foo<'x, 'y: 'x> the bound + // is trivially fulfilled + if corresponding_use == use_lt { + continue; + } + + if !use_longer_lifetimes.contains(&corresponding_use) { + let use_name = method.lifetime_env.fmt_lifetime(use_lt); + let use_longer_name = method.lifetime_env.fmt_lifetime(corresponding_use); + let def_cause = if let Some(def_lt) = def_lt { + let def_name = linked.def_env().fmt_lifetime(def_lt); + let def_longer_name = linked.def_env().fmt_lifetime(def_longer); + format!("comes from source type's '{def_longer_name}: '{def_name}") + } else { + // This case is technically already handled in the lifetime lowerer, we're being careful + "comes from &-ref's lifetime in parameter".into() + }; + errors.push(LoweringError::Other(format!("Method should explicitly include this \ + lifetime bound from {param}: '{use_longer_name}: '{use_name} ({def_cause})"))) + } + } + } + } + + fn validate_type_def(&self, errors: &mut ErrorStore, def: TypeDef) { + if let TypeDef::Struct(st) = def { + self.validate_struct(errors, st); + } + } + + fn validate_trait(&self, errors: &mut ErrorStore, def: &TraitDef) { + for m in &def.methods { + for p in &m.params { + self.validate_ty(errors, &p.ty); + } + + let success = match &*m.output { + hir::ReturnType::Infallible(success) | hir::ReturnType::Nullable(success) => { + success + } + hir::ReturnType::Fallible(success, fallible) => { + if let Some(f) = fallible { + self.validate_ty(errors, f); + } + success + } + }; + + if let hir::SuccessType::OutType(o) = success { + self.validate_ty(errors, o); + } + } + } + + fn validate_struct(&self, errors: &mut ErrorStore, st: &StructDef

) { + if st.attrs.abi_compatible && st.lifetimes.num_lifetimes() > 0 { + errors.push(LoweringError::Other(format!( + "Struct {:?} cannot have any lifetimes if it is marked as ABI compatible.", + st.name + ))); + } + + for f in &st.fields { + self.validate_ty(errors, &f.ty); + + if matches!(f.ty, hir::Type::Struct(..)) + && (f.ty.is_immutably_borrowed() || f.ty.is_mutably_borrowed()) + { + errors.push(LoweringError::Other(format!( + "Struct {:?} field {:?} cannot be borrowed. Structs cannot be borrowed inside of other structs, try removing the borrow and storing the struct directly.", + st.name, f.name + ))); + } + if st.attrs.abi_compatible { + match &f.ty { + hir::Type::Primitive(..) => {} + hir::Type::Struct(st_pth) => { + let ty = self.resolve_type(st_pth.id()); + match ty { + TypeDef::Struct(f_st) => { + if !f_st.attrs.abi_compatible { + errors.push(LoweringError::Other(format!( + "Struct {:?} field {:?} type {:?} must be marked with `#[diplomat::attr(auto, abi_compatible)]`.", + st.name, f.name, f_st.name + ))); + } + } + TypeDef::OutStruct(out) => { + errors.push(LoweringError::Other( + format!("Out struct {out:?} cannot be included in structs marked with #[diplomat::attr(auto, abi_compatible)].") + )); + } + _ => unreachable!(), + } + } + _ => { + errors.push(LoweringError::Other(format!( + "Cannot construct a slice of {:?} with non-primitive, non-struct field {:?}", + st.name, f.name + ))); + } + } + } + } + } +} + +/// Struct that just wraps the mapping from AST custom types to their IDs that +/// will show up in the final [`TypeContext`]. +/// +/// The entire point of this type is to reduce the number of arguments in helper +/// functions which need to look up IDs for structs. It does nothing fancy and +/// is only ever used when constructing a [`TypeContext`]. +pub(super) struct LookupId<'ast> { + out_struct_map: HashMap<&'ast ast::Struct, OutStructId>, + struct_map: HashMap<&'ast ast::Struct, StructId>, + opaque_map: HashMap<&'ast ast::OpaqueType, OpaqueId>, + enum_map: HashMap<&'ast ast::Enum, EnumId>, + trait_map: HashMap<&'ast ast::Trait, TraitId>, +} + +impl<'ast> LookupId<'ast> { + /// Returns a new [`LookupId`]. + fn new( + out_structs: &[ItemAndInfo<'ast, ast::Struct>], + structs: &[ItemAndInfo<'ast, ast::Struct>], + opaques: &[ItemAndInfo<'ast, ast::OpaqueType>], + enums: &[ItemAndInfo<'ast, ast::Enum>], + traits: &[ItemAndInfo<'ast, ast::Trait>], + ) -> Self { + Self { + out_struct_map: out_structs + .iter() + .enumerate() + .map(|(index, item)| (item.item, OutStructId(index))) + .collect(), + struct_map: structs + .iter() + .enumerate() + .map(|(index, item)| (item.item, StructId(index))) + .collect(), + opaque_map: opaques + .iter() + .enumerate() + .map(|(index, item)| (item.item, OpaqueId(index))) + .collect(), + enum_map: enums + .iter() + .enumerate() + .map(|(index, item)| (item.item, EnumId(index))) + .collect(), + trait_map: traits + .iter() + .enumerate() + .map(|(index, item)| (item.item, TraitId(index))) + .collect(), + } + } + + pub(super) fn resolve_out_struct(&self, strct: &ast::Struct) -> Option { + self.out_struct_map.get(strct).copied() + } + + pub(super) fn resolve_struct(&self, strct: &ast::Struct) -> Option { + self.struct_map.get(strct).copied() + } + + pub(super) fn resolve_opaque(&self, opaque: &ast::OpaqueType) -> Option { + self.opaque_map.get(opaque).copied() + } + + pub(super) fn resolve_enum(&self, enm: &ast::Enum) -> Option { + self.enum_map.get(enm).copied() + } + + pub(super) fn resolve_trait(&self, trt: &ast::Trait) -> Option { + self.trait_map.get(trt).copied() + } +} + +impl From for TypeId { + fn from(x: StructId) -> Self { + TypeId::Struct(x) + } +} + +impl From for TypeId { + fn from(x: OutStructId) -> Self { + TypeId::OutStruct(x) + } +} + +impl From for TypeId { + fn from(x: OpaqueId) -> Self { + TypeId::Opaque(x) + } +} + +impl From for TypeId { + fn from(x: EnumId) -> Self { + TypeId::Enum(x) + } +} + +impl From for SymbolId { + fn from(x: TypeId) -> Self { + SymbolId::TypeId(x) + } +} + +impl From for SymbolId { + fn from(x: TraitId) -> Self { + SymbolId::TraitId(x) + } +} + +impl From for SymbolId { + fn from(x: FunctionId) -> Self { + SymbolId::FunctionId(x) + } +} + +impl From for SymbolId { + fn from(x: StructId) -> Self { + SymbolId::TypeId(x.into()) + } +} + +impl From for SymbolId { + fn from(x: OutStructId) -> Self { + SymbolId::TypeId(x.into()) + } +} + +impl From for SymbolId { + fn from(x: OpaqueId) -> Self { + SymbolId::TypeId(x.into()) + } +} + +impl From for SymbolId { + fn from(x: EnumId) -> Self { + SymbolId::TypeId(x.into()) + } +} + +impl TryInto for SymbolId { + type Error = (); + fn try_into(self) -> Result { + match self { + SymbolId::TypeId(id) => Ok(id), + _ => Err(()), + } + } +} + +impl TryInto for SymbolId { + type Error = (); + fn try_into(self) -> Result { + match self { + SymbolId::TraitId(id) => Ok(id), + _ => Err(()), + } + } +} + +#[cfg(test)] +mod tests { + use crate::hir; + use std::fmt::Write; + + macro_rules! uitest_lowering { + ($($file:tt)*) => { + let parsed: syn::File = syn::parse_quote! { $($file)* }; + + let mut output = String::new(); + + let mut attr_validator = hir::BasicAttributeValidator::new("tests"); + attr_validator.support.option = true; + attr_validator.support.abi_compatibles = true; + attr_validator.support.free_functions = true; + match hir::TypeContext::from_syn(&parsed, Default::default(), attr_validator) { + Ok(_context) => (), + Err(e) => { + for (ctx, err) in e { + writeln!(&mut output, "Lowering error in {ctx}: {err}").unwrap(); + } + } + }; + insta::with_settings!({}, { + insta::assert_snapshot!(output) + }); + } + } + + #[test] + fn test_required_implied_bounds() { + uitest_lowering! { + #[diplomat::bridge] + mod ffi { + #[diplomat::opaque] + struct Foo<'a, 'b: 'a, 'c: 'b> (&'a u8, &'b u8, &'c u8); + + #[diplomat::opaque] + struct Opaque; + + + #[diplomat::opaque] + struct OneLifetime<'a>(&'a u8); + + impl Opaque { + pub fn use_foo<'x, 'y, 'z>(&self, foo: &Foo<'x, 'y, 'z>) {} + pub fn return_foo<'x, 'y, 'z>(&'x self) -> Box> {} + pub fn return_result_foo<'x, 'y, 'z>(&'x self) -> Result>, ()> {} + // This doesn't actually error since the lowerer inserts the implicit bound + pub fn implied_ref_bound<'a, 'b>(&self, one_lt: &'a OneLifetime<'b>) {} + } + } + } + } + + /// This is a buch of tests put together + #[test] + fn test_basic_lowering() { + uitest_lowering! { + #[diplomat::bridge] + mod other_ffi { + + struct Foo { + field: u8 + } + + #[diplomat::out] + struct OutStruct { + field: Box, + } + + #[diplomat::opaque] + struct OtherOpaque; + } + #[diplomat::bridge] + mod ffi { + use crate::other_ffi::{Foo, OutStruct, OtherOpaque}; + + #[diplomat::opaque] + struct Opaque; + + struct EmptyStruct; + + enum EmptyEnum {} + + struct InStructWithOutField { + field: Box, + out_struct: OutStruct, + } + + struct BadStructFields { + field1: Option, + field2: Result, + } + + impl Opaque { + pub fn use_foo_ref(&self, foo: &Foo) {} + pub fn return_foo_box(&self) -> Box {} + pub fn use_self(self) {} + pub fn return_self(self) -> Self {} + pub fn use_opaque_owned(&self, opaque: OtherOpaque) {} + pub fn return_opaque_owned(&self) -> OtherOpaque {} + pub fn use_out_as_in(&self, out: OutStruct) {} + } + + pub fn free_function(foo : &Opaque) {} + pub fn other_free_function() -> Box {} + + } + } + } + + #[test] + fn test_opaque_ffi() { + uitest_lowering! { + #[diplomat::bridge] + mod ffi { + #[diplomat::opaque] + struct MyOpaqueStruct(UnknownType); + + impl MyOpaqueStruct { + pub fn new() -> Box {} + pub fn new_broken() -> MyOpaqueStruct {} + pub fn do_thing(&self) {} + pub fn do_thing_broken(self) {} + pub fn broken_differently(&self, x: &MyOpaqueStruct) {} + } + + #[diplomat::opaque] + enum MyOpaqueEnum { + A(UnknownType), + B, + C(i32, i32, UnknownType2), + } + + impl MyOpaqueEnum { + pub fn new() -> Box {} + pub fn new_broken() -> MyOpaqueEnum {} + pub fn do_thing(&self) {} + pub fn do_thing_broken(self) {} + pub fn broken_differently(&self, x: &MyOpaqueEnum) {} + } + } + } + } + + #[test] + fn opaque_checks_with_safe_use() { + uitest_lowering! { + #[diplomat::bridge] + mod ffi { + struct NonOpaqueStruct {} + + impl NonOpaqueStruct { + pub fn new(x: i32) -> NonOpaqueStruct { + unimplemented!(); + } + } + + #[diplomat::opaque] + struct OpaqueStruct {} + + impl OpaqueStruct { + pub fn new() -> Box { + unimplemented!(); + } + + pub fn get_i32(&self) -> i32 { + unimplemented!() + } + } + } + }; + } + + #[test] + fn opaque_checks_with_error() { + uitest_lowering! { + #[diplomat::bridge] + mod ffi { + #[diplomat::opaque] + struct OpaqueStruct {} + + impl OpaqueStruct { + pub fn new() -> OpaqueStruct { + unimplemented!(); + } + + pub fn get_i32(self) -> i32 { + unimplemented!() + } + } + } + }; + } + + #[test] + fn zst_non_opaque() { + uitest_lowering! { + #[diplomat::bridge] + mod ffi { + struct NonOpaque; + + impl NonOpaque { + pub fn foo(self) {} + } + } + }; + } + + #[test] + fn option_invalid() { + uitest_lowering! { + #[diplomat::bridge] + mod ffi { + use diplomat_runtime::DiplomatResult; + struct Foo { + field: Option, + } + + impl Foo { + pub fn do_thing(opt: Option>) { + + } + + pub fn do_thing2(opt: DiplomatResult, u8>) { + + } + pub fn do_thing2(opt: Option) { + + } + + pub fn do_thing3() -> Option { + + } + } + } + }; + } + + #[test] + fn option_valid() { + uitest_lowering! { + #[diplomat::bridge] + mod ffi { + struct Foo { + field: Option>, + } + + impl Foo { + pub fn do_thing(opt: Option>) { + + } + pub fn do_thing2(opt: Option<&u32>) { + + } + } + } + }; + } + + #[test] + fn non_opaque_move() { + uitest_lowering! { + #[diplomat::bridge] + mod ffi { + struct NonOpaque { + num: u8, + } + + impl NonOpaque { + pub fn foo(&self) {} + } + + #[diplomat::opaque] + struct Opaque; + + impl Opaque { + pub fn bar<'a>(&'a self) -> &'a NonOpaque {} + pub fn baz<'a>(&'a self, x: &'a NonOpaque) {} + pub fn quux(&self) -> Box {} + } + } + }; + } + + #[test] + fn test_lifetime_in_return() { + uitest_lowering! { + #[diplomat::bridge] + mod ffi { + #[diplomat::opaque] + struct Opaque; + + struct Foo<'a> { + x: &'a Opaque, + } + + impl Opaque { + pub fn returns_self(&self) -> &Self {} + pub fn returns_foo(&self) -> Foo {} + pub fn returns_foo_ref(&self) -> &Foo {} + } + } + }; + } + #[test] + fn test_struct_forbidden() { + uitest_lowering! { + #[diplomat::bridge] + mod ffi { + struct Crimes<'a> { + slice1: &'a str, + slice1: &'a DiplomatStr, + slice2: &'a [u8], + slice3: Box, + slice3: Box, + slice4: Box<[u8]>, + } + } + }; + } + + #[test] + fn test_option() { + uitest_lowering! { + #[diplomat::bridge] + mod ffi { + use diplomat_runtime::DiplomatOption; + #[diplomat::opaque] + struct Foo {} + struct CustomStruct { + num: u8, + b: bool, + diplo_option: DiplomatOption, + } + + struct BrokenStruct { + regular_option: Option, + regular_option: Option, + } + impl Foo { + pub fn diplo_option_u8(x: DiplomatOption) -> DiplomatOption { + x + } + pub fn diplo_option_ref(x: DiplomatOption<&Foo>) -> DiplomatOption<&Foo> { + x + } + pub fn diplo_option_box() -> DiplomatOption> { + x + } + pub fn diplo_option_struct(x: DiplomatOption) -> DiplomatOption { + x + } + pub fn option_u8(x: Option) -> Option { + x + } + pub fn option_ref(x: Option<&Foo>) -> Option<&Foo> { + x + } + pub fn option_box() -> Option> { + x + } + pub fn option_struct(x: Option) -> Option { + x + } + } + } + }; + } + + #[test] + fn test_non_primitive_struct_slices_fails() { + uitest_lowering! { + #[diplomat::bridge] + mod ffi { + #[diplomat::attr(auto, abi_compatible)] + pub struct Foo<'a> { + pub x: u32, + pub y: u32, + pub z : DiplomatStrSlice<'a> + } + + impl Foo { + pub fn takes_slice(sl : &[Foo]) { + todo!() + } + } + } + } + } + + #[test] + fn test_return_struct_slice() { + uitest_lowering! { + #[diplomat::bridge] + mod ffi { + #[diplomat::attr(auto, abi_compatible)] + #[diplomat::out] + pub struct Foo { + pub x: u32, + pub y: u32 + } + + impl Foo { + pub fn returns_slice<'a>() -> &'a [Foo] { + todo!() + } + } + } + } + } + + #[test] + fn test_mut_struct() { + let parsed: syn::File = syn::parse_quote! { + #[diplomat::bridge] + mod ffi { + #[diplomat::attr(auto, abi_compatible)] + pub struct Foo { + pub x: u32, + pub y: u32 + } + + impl Foo { + pub fn takes_mut(&mut self, sl : &mut Self) { + todo!() + } + } + } + }; + + let mut output = String::new(); + + let mut attr_validator = hir::BasicAttributeValidator::new("tests"); + attr_validator.support.struct_refs = true; + attr_validator.support.abi_compatibles = true; + match hir::TypeContext::from_syn(&parsed, Default::default(), attr_validator) { + Ok(_context) => (), + Err(e) => { + for (ctx, err) in e { + writeln!(&mut output, "Lowering error in {ctx}: {err}").unwrap(); + } + } + }; + insta::with_settings!({}, { insta::assert_snapshot!(output) }); + } + + #[test] + fn test_mut_struct_fails() { + let parsed: syn::File = syn::parse_quote! { + #[diplomat::bridge] + mod ffi { + pub struct Foo { + pub x: u32, + pub y: u32 + } + + impl Foo { + pub fn takes_mut(&mut self, sl : &mut Self) -> &mut Self { + todo!() + } + } + } + }; + + let mut output = String::new(); + + let mut attr_validator = hir::BasicAttributeValidator::new("tests"); + attr_validator.support.abi_compatibles = true; + attr_validator.support.struct_refs = true; + match hir::TypeContext::from_syn(&parsed, Default::default(), attr_validator) { + Ok(_context) => (), + Err(e) => { + for (ctx, err) in e { + writeln!(&mut output, "Lowering error in {ctx}: {err}").unwrap(); + } + } + }; + insta::with_settings!({}, { insta::assert_snapshot!(output) }); + } + + #[test] + fn test_struct_ref_fails() { + let parsed: syn::File = syn::parse_quote! { + #[diplomat::bridge] + mod ffi { + pub struct Foo<'a> { + pub x: u32, + pub y: u32, + pub foo : &'a Foo<'a> + } + + #[diplomat::opaque] + pub struct Bar<'a>(&'a Foo<'a>); + + impl Foo { + pub fn out<'a>(&'a self) -> Box> {} + } + } + }; + + let mut output = String::new(); + + let mut attr_validator = hir::BasicAttributeValidator::new("tests"); + attr_validator.support.abi_compatibles = true; + attr_validator.support.struct_refs = true; + match hir::TypeContext::from_syn(&parsed, Default::default(), attr_validator) { + Ok(_context) => (), + Err(e) => { + for (ctx, err) in e { + writeln!(&mut output, "Lowering error in {ctx}: {err}").unwrap(); + } + } + }; + insta::with_settings!({}, { insta::assert_snapshot!(output) }); + } + #[test] + fn test_callback_borrowing_fails() { + // We may end up supporting this in the future, but + // we want to test that it is currently forbidden + let parsed: syn::File = syn::parse_quote! { + #[diplomat::bridge] + mod ffi { + #[diplomat::opaque] + pub struct Foo(u8); + + impl Foo { + pub fn apply_callback(&self, cb: impl FnMut(&Foo) -> &Foo) {} + } + } + }; + + let mut output = String::new(); + + let mut attr_validator = hir::BasicAttributeValidator::new("tests"); + attr_validator.support.abi_compatibles = true; + attr_validator.support.struct_refs = true; + attr_validator.support.callbacks = true; + match hir::TypeContext::from_syn(&parsed, Default::default(), attr_validator) { + Ok(_context) => (), + Err(e) => { + for (ctx, err) in e { + writeln!(&mut output, "Lowering error in {ctx}: {err}").unwrap(); + } + } + }; + insta::with_settings!({}, { insta::assert_snapshot!(output) }); + } + #[test] + fn test_callback_borrowing_fails_with_unsafe_borrows() { + // We may end up supporting this in the future, but + // we want to test that it is currently forbidden + let parsed: syn::File = syn::parse_quote! { + #[diplomat::bridge] + mod ffi { + #[diplomat::opaque] + pub struct Foo(u8); + + pub struct Bar { + x: u8, + } + + impl Foo { + // This is OK + pub fn apply_allowed_callback(&self, cb: impl FnMut(&Foo) -> &Foo) {} + // This is not + pub fn apply_callback_owned_slice(&self, cb: impl FnMut(&Foo) -> Box) {} + // Nor is this + pub fn apply_callback_borrowed_struct(&self, cb: impl FnMut(&Foo) -> &Bar) {} + } + } + }; + + let mut output = String::new(); + + let mut attr_validator = hir::BasicAttributeValidator::new("tests"); + attr_validator.support.abi_compatibles = true; + attr_validator.support.struct_refs = true; + attr_validator.support.callbacks = true; + let config = super::LoweringConfig { + unsafe_references_in_callbacks: true, + }; + match hir::TypeContext::from_syn(&parsed, config, attr_validator) { + Ok(_context) => (), + Err(e) => { + for (ctx, err) in e { + writeln!(&mut output, "Lowering error in {ctx}: {err}").unwrap(); + } + } + }; + insta::with_settings!({}, { insta::assert_snapshot!(output) }); + } +} diff --git a/deps/crates/vendor/diplomat_core/src/hir/types.rs b/deps/crates/vendor/diplomat_core/src/hir/types.rs new file mode 100644 index 00000000000000..984c32203e5373 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/hir/types.rs @@ -0,0 +1,244 @@ +//! Types that can be exposed in Diplomat APIs. + +use super::lifetimes::{Lifetime, MaybeStatic}; +use super::{ + EnumPath, Everywhere, NonOptional, OpaqueOwner, OpaquePath, Optional, OutputOnly, + PrimitiveType, StructPath, StructPathLike, TyPosition, TypeContext, TypeId, +}; +use crate::ast; +use crate::hir::MaybeOwn; +pub use ast::Mutability; +pub use ast::StringEncoding; +use either::Either; + +/// Type that can only be used as an output. +pub type OutType = Type; + +/// Type that may be used as input or output. +#[derive(Debug, Clone)] +#[non_exhaustive] +pub enum Type { + Primitive(PrimitiveType), + Opaque(OpaquePath), + Struct(P::StructPath), + ImplTrait(P::TraitPath), + Enum(EnumPath), + Slice(Slice

), + Callback(P::CallbackInstantiation), // only a Callback if P == InputOnly + /// `DiplomatOption`, for a primitive, struct, or enum `T`. + /// + /// In some cases this can be specified as `Option`, but under the hood it gets translated to + /// the DiplomatOption FFI-compatible union type. + /// + /// This is *different* from `Option<&T>` and `Option` for an opaque `T`: That is represented as + /// a nullable pointer. + /// + /// This does not get used when the user writes `-> Option` (for non-opaque T): + /// that will always use [`ReturnType::Nullable`](crate::hir::ReturnType::Nullable). + DiplomatOption(Box>), +} + +/// Type that can appear in the `self` position. +#[derive(Debug, Clone)] +#[non_exhaustive] +pub enum SelfType { + Opaque(OpaquePath), + Struct(StructPath), + Enum(EnumPath), +} + +#[derive(Copy, Clone, Debug)] +#[non_exhaustive] +pub enum Slice { + /// A string slice, e.g. `&DiplomatStr` or `Box`. + /// + /// Owned slices are useful for garbage-collected languages that have to + /// reallocate into non-gc memory anyway. For example for Dart it's more + /// efficient to accept `Box` than to accept `&str` and then + /// allocate in Rust, as Dart will have to create the `Box to + /// pass `&str` anyway. + Str(Option>, StringEncoding), + + /// A primitive slice, e.g. `&mut [u8]` or `Box<[usize]>`. + /// + /// Owned slices are useful for garbage-collected languages that have to + /// reallocate into non-gc memory anyway. For example for Dart it's more + /// efficient to accept `Box<[bool]>` than to accept `&[bool]` and then + /// allocate in Rust, as Dart will have to create the `Box<[bool]`> to + /// pass `&[bool]` anyway. + Primitive(MaybeOwn, PrimitiveType), + + /// A `&[DiplomatStrSlice]`. This type of slice always needs to be + /// allocated before passing it into Rust, as it has to conform to the + /// Rust ABI. In other languages this is the idiomatic list of string + /// views, i.e. `std::span` or `core.List`. + Strs(StringEncoding), + + /// A `&[Struct]`, where `Struct` is a structure that is only comprised of primitive types and + /// structures that only contain primitive types. Must be marked with `#[diplomat::attr(auto, allowed_in_slices)]`. + /// Currently assumes that `&[Struct]` is provided as an input only for function parameters. + /// Validated in [`super::type_context::TypeContext::validate_primitive_slice_struct`] + Struct(MaybeOwn, P::StructPath), +} + +// For now, the lifetime in not optional. This is because when you have references +// as fields of structs, the lifetime must always be present, and we want to uphold +// this invariant at the type level within the HIR. +// +// The only time when a lifetime is optional in Rust code is in function signatures, +// where implicit lifetimes are allowed. Getting this to all fit together will +// involve getting the implicit lifetime thing to be understood by Diplomat, but +// should be doable. +#[derive(Copy, Clone, Debug)] +#[non_exhaustive] +pub struct Borrow { + pub lifetime: MaybeStatic, + pub mutability: Mutability, +} + +// This is implemented on InputOnly and Everywhere types. Could be extended +// if we genericize .resolve() later. +impl> Type

{ + /// Return the number of fields and leaves that will show up in the [`LifetimeTree`] + /// returned by [`Param::lifetime_tree`] and [`ParamSelf::lifetime_tree`]. + /// + /// This method is used to calculate how much space to allocate upfront. + pub(super) fn field_leaf_lifetime_counts(&self, tcx: &TypeContext) -> (usize, usize) { + match self { + Type::Struct(ty) => ty.resolve(tcx).fields.iter().fold((1, 0), |acc, field| { + let inner = field.ty.field_leaf_lifetime_counts(tcx); + (acc.0 + inner.0, acc.1 + inner.1) + }), + Type::Opaque(_) | Type::Slice(_) | Type::Callback(_) | Type::ImplTrait(_) => (1, 1), + Type::Primitive(_) | Type::Enum(_) => (0, 0), + Type::DiplomatOption(ty) => ty.field_leaf_lifetime_counts(tcx), + } + } +} + +impl Type

{ + /// Get all lifetimes "contained" in this type + pub fn lifetimes(&self) -> impl Iterator> + '_ { + match self { + Type::Opaque(opaque) => Either::Right( + opaque + .lifetimes + .as_slice() + .iter() + .copied() + .chain(opaque.owner.lifetime()), + ), + Type::Struct(struct_) => Either::Left(struct_.lifetimes().as_slice().iter().copied()), + Type::Slice(slice) => Either::Left( + slice + .lifetime() + .map(|lt| std::slice::from_ref(lt).iter().copied()) + .unwrap_or([].iter().copied()), + ), + Type::DiplomatOption(ty) => ty.lifetimes(), + // TODO the Callback case + _ => Either::Left([].iter().copied()), + } + } + + // For custom types, get the type id + pub fn id(&self) -> Option { + Some(match self { + Self::Opaque(p) => TypeId::Opaque(p.tcx_id), + Self::Enum(p) => TypeId::Enum(p.tcx_id), + Self::Struct(p) => p.id(), + _ => return None, + }) + } + + /// Unwrap to the inner type if `self` is `DiplomatOption` + pub fn unwrap_option(&self) -> &Type

{ + match self { + Self::DiplomatOption(ref o) => o, + _ => self, + } + } + + /// Whether this type is a `DiplomatOption` or optional Opaque + pub fn is_option(&self) -> bool { + match self { + Self::DiplomatOption(..) => true, + Self::Opaque(ref o) if o.is_optional() => true, + _ => false, + } + } + /// Returns whether the self parameter is borrowed immutably. + /// + /// Curently this can only happen with opaque types. + pub fn is_immutably_borrowed(&self) -> bool { + matches!(self, Self::Opaque(opaque_path) if opaque_path.owner.mutability() == Some(Mutability::Immutable)) + || matches!(self, Self::Struct(st) if st.owner().mutability().is_immutable()) + } + /// Returns whether the self parameter is borrowed mutably. + /// + /// Curently this can only happen with opaque types. + pub fn is_mutably_borrowed(&self) -> bool { + matches!(self, Self::Opaque(opaque_path) if opaque_path.owner.mutability() == Some(Mutability::Mutable)) + || matches!(self, Self::Struct(st) if st.owner().mutability().is_immutable()) + } +} + +impl SelfType { + /// Returns whether the self parameter is borrowed immutably. + /// + /// Curently this can only happen with opaque types. + pub fn is_immutably_borrowed(&self) -> bool { + matches!(self, SelfType::Opaque(opaque_path) if opaque_path.owner.mutability == Mutability::Immutable) + || matches!(self, SelfType::Struct(st) if st.owner().mutability().is_immutable()) + } + /// Returns whether the self parameter is borrowed mutably. + /// + /// Curently this can only happen with opaque types. + pub fn is_mutably_borrowed(&self) -> bool { + matches!(self, SelfType::Opaque(opaque_path) if opaque_path.owner.mutability == Mutability::Mutable) + || matches!(self, SelfType::Struct(st) if st.owner().mutability().is_immutable()) + } + /// Returns whether the self parameter is consuming. + /// + /// Currently this can only (and must) only happen for non-opaque types. + pub fn is_consuming(&self) -> bool { + matches!(self, SelfType::Enum(_)) + || matches!(self, SelfType::Struct(st) if st.owner().is_owned()) + } +} + +impl Slice

{ + /// Returns the [`Lifetime`] contained in either the `Str` or `Primitive` + /// variant. + pub fn lifetime(&self) -> Option<&MaybeStatic> { + match self { + Slice::Str(lifetime, ..) => lifetime.as_ref(), + Slice::Primitive(MaybeOwn::Borrow(reference), ..) + | Slice::Struct(MaybeOwn::Borrow(reference), ..) => Some(&reference.lifetime), + Slice::Primitive(..) | Slice::Struct(..) => None, + Slice::Strs(..) => Some({ + const X: MaybeStatic = MaybeStatic::NonStatic(Lifetime::new(usize::MAX)); + &X + }), + } + } +} + +impl Borrow { + pub(super) fn new(lifetime: MaybeStatic, mutability: Mutability) -> Self { + Self { + lifetime, + mutability, + } + } +} + +impl From for Type { + fn from(s: SelfType) -> Type { + match s { + SelfType::Opaque(o) => Type::Opaque(o.wrap_optional()), + SelfType::Struct(s) => Type::Struct(s), + SelfType::Enum(e) => Type::Enum(e), + } + } +} diff --git a/deps/crates/vendor/diplomat_core/src/lib.rs b/deps/crates/vendor/diplomat_core/src/lib.rs new file mode 100644 index 00000000000000..84853724a0274c --- /dev/null +++ b/deps/crates/vendor/diplomat_core/src/lib.rs @@ -0,0 +1,15 @@ +//! The Diplomat core module contains common logic between +//! the macro expansion and code generation. Right now, this +//! is primarily the AST types that Diplomat generates while +//! extracting APIs. + +#![allow(clippy::needless_lifetimes)] // we use named lifetimes for clarity +#![warn(clippy::exhaustive_structs, clippy::exhaustive_enums)] + +pub mod ast; +#[cfg(feature = "hir")] +pub mod hir; + +mod environment; + +pub use environment::{Env, ModuleEnv}; diff --git a/deps/crates/vendor/displaydoc/.cargo-checksum.json b/deps/crates/vendor/displaydoc/.cargo-checksum.json new file mode 100644 index 00000000000000..ddbf7a3890d17a --- /dev/null +++ b/deps/crates/vendor/displaydoc/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"9aadbd7c8b22fa4574b2080d0baaa908f43b5ed2c320c64ec88476cbf739871b","Cargo.lock":"53ebb1c438812bf2e049126afd9bb833d02278416d49ed436d67b4c5c03f21b1","Cargo.toml":"c6f12ae2dd031cf599ec131d3b6b89fb5de66edc4416b4a8f2f06b3fda889620","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"4e230c5596f208b8b752edaa1ff3ace5b1508da61f2069129fa5a6fbda6f4834","README.tpl":"974701ae7f6d238bd325dd32104a5265841e79a9b79a595f7fdd964711c0cd19","examples/simple.rs":"bca524b36621ac56044cbe3eebf8892f7a3b398fd8f257fc67b17b26ae34bfbf","src/attr.rs":"10b31136a5d46066066ea3988f8b857b554fa62b3737988967ae7c2aaa97a58b","src/expand.rs":"6d201ddf75b065875131f437d5a911bb4b2d3e9fe385eebbfc61101d790549dd","src/fmt.rs":"9c13cbcd337066614bc26ecfd36ea9730c9b8099083a9a7ffd79f8dc17e414f1","src/lib.rs":"01b770363022045aa8de41548b20764db7278ae90add903642312eaa4408d467","tests/compile_tests.rs":"935609d68eaa52e0ce9f29b3dae649787cd1f540f9b4bbadcbefcb8a0febcfc8","tests/happy.rs":"1b4c119184ca3914684c1cafaa25a8fbb9e60ef45eb257ad7ac86b8b2d7a3856","tests/no_std/enum_prefix.rs":"386e18cd6b6d35df0a864473a820aa05872f2f7f8364793adae784203946eb82","tests/no_std/enum_prefix_missing.rs":"f60100eac4b3a0f86c57b2082ee52e94b3fa0b5029e535fd3fd55cc1aeaf308c","tests/no_std/enum_prefix_missing.stderr":"e0e98f4dfc21f8cb133519ff98f10b08d8c76219b54cfbc6436c46ba9c601ead","tests/no_std/multi_line.rs":"b0c0cdc7631234a9b7a49205bb1d6824821153001ab30ddad1948deaaaa363c3","tests/no_std/multi_line.stderr":"08cba6ace9ac1938ea8fe18ed4a536b861ad48a9f9d646b4a7ebfe4bf5da438c","tests/no_std/multi_line_allow.rs":"7f7b300db1336b5d9487f82e10deee6a22a7d749ae3698e13e45455540ed5742","tests/no_std/with.rs":"ba96ba70da11f7d5afb5b43a23d8f1d7d28b1eceda8c84c1595006145b8e15fd","tests/no_std/without.rs":"fa2d73e9d6b3bff8073bc95296aeef69e4e8c20a8e6666c239041564877cfec9","tests/no_std/without.stderr":"be00cd4dd7396f324c1cb6283d02a38ad55e3b4d2684e7a4b6bbd43ed937c7f2","tests/num_in_field.rs":"d0bc3ba7f9aea17d3abee4ac05afe6d4a0112d3527698791e1eeaa3464e2b1d4","tests/std/enum_prefix.rs":"baab2132d9468ec167423048ba5244394238e488523214b9e50adee46920f700","tests/std/enum_prefix_missing.rs":"58c8f7c9d851689ca59caf475c0e5f12674f5a58ecbb025cac232acc68eec8aa","tests/std/enum_prefix_missing.stderr":"a26fa36de033d2b032a1e6475cb8d89ee1266e15647bcfaf192931188b38445b","tests/std/multi_line.rs":"b0c0cdc7631234a9b7a49205bb1d6824821153001ab30ddad1948deaaaa363c3","tests/std/multi_line.stderr":"02ca7d07ae4f72c726457c918506ed38873b5085af53c5b60090b53cf5ae46b0","tests/std/multi_line_allow.rs":"ecacc0120aa127dc289d6333348ab357c74d6cb49851de43e7cf3984facf0abc","tests/std/multiple.rs":"b8dc9939c41b2655600ba1b698dbdbbef6e907bff533b6f2cbc315134013fc84","tests/std/without.rs":"fa2d73e9d6b3bff8073bc95296aeef69e4e8c20a8e6666c239041564877cfec9","tests/std/without.stderr":"606a9470520b99eb17c1e609e1074b3765ccd3ab4f1d0b3c3cc2bda9811884de","tests/variantless.rs":"af6930daa15f488fcc00fd2a623a2662ddb86d071ffe698bd97c13c65b9b50a3","update-readme.sh":"7885d60cba79c3dc2b779b9805d520960cc7d8b82d7f1d0c59deff4140ac857b"},"package":"97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"} \ No newline at end of file diff --git a/deps/crates/vendor/displaydoc/CHANGELOG.md b/deps/crates/vendor/displaydoc/CHANGELOG.md new file mode 100644 index 00000000000000..b4d6cad0a56f87 --- /dev/null +++ b/deps/crates/vendor/displaydoc/CHANGELOG.md @@ -0,0 +1,58 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + + +## [Unreleased] - ReleaseDate + +# [0.2.5] - 2024-06-20 + +# Changed + - Don't name the output of the const block to work around `non_local_definitions` error (#47) + - Reference the `core` crate correctly to avoid clashes with modules named `core` (#45) + - Explicitly list MSRV in Cargo.toml (#51) + - Bump edition to 2021 (#51) + +# [0.2.4] - 2022-05-02 + +## Added +- Updated `syn` dependency to 2.0 +- Support for empty enums +- Implicitly require fmt::Display on all type parameters unless overridden + +## Changed +- Bumped MSRV to 1.56 + +# [0.2.3] - 2021-07-16 +## Added +- Added `#[displaydoc("..")]` attribute for overriding a doc comment + +# [0.2.2] - 2021-07-01 +## Added +- Added prefix feature to use the doc comment from an enum and prepend it + before the error message from each variant. + +# [0.2.1] - 2021-03-26 +## Added +- Added opt in support for ignoring extra doc attributes + +# [0.2.0] - 2021-03-16 +## Changed + +- (BREAKING) disallow multiple `doc` attributes in display impl + [https://github.com/yaahc/displaydoc/pull/22]. Allowing and ignoring extra + doc attributes made it too easy to accidentally create a broken display + implementation with missing context without realizing it, this change turns + that into a hard error and directs users towards block comments if multiple + lines are needed. + + +[Unreleased]: https://github.com/yaahc/displaydoc/compare/v0.2.4...HEAD +[0.2.4]: https://github.com/yaahc/displaydoc/compare/v0.2.3...v0.2.4 +[0.2.3]: https://github.com/yaahc/displaydoc/compare/v0.2.2...v0.2.3 +[0.2.2]: https://github.com/yaahc/displaydoc/compare/v0.2.1...v0.2.2 +[0.2.1]: https://github.com/yaahc/displaydoc/compare/v0.2.0...v0.2.1 +[0.2.0]: https://github.com/yaahc/displaydoc/releases/tag/v0.2.0 diff --git a/deps/crates/vendor/displaydoc/Cargo.lock b/deps/crates/vendor/displaydoc/Cargo.lock new file mode 100644 index 00000000000000..5e313d2eec1039 --- /dev/null +++ b/deps/crates/vendor/displaydoc/Cargo.lock @@ -0,0 +1,404 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi", +] + +[[package]] +name = "ctor" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "difference" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" + +[[package]] +name = "displaydoc" +version = "0.2.5" +dependencies = [ + "libc", + "pretty_assertions", + "proc-macro2", + "quote", + "rustversion", + "static_assertions", + "syn 2.0.66", + "thiserror", + "trybuild", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "output_vt100" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" +dependencies = [ + "winapi", +] + +[[package]] +name = "pretty_assertions" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" +dependencies = [ + "ansi_term", + "ctor", + "difference", + "output_vt100", +] + +[[package]] +name = "proc-macro2" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "serde_json" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +dependencies = [ + "serde", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "toml" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "trybuild" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33a5f13f11071020bb12de7a16b925d2d58636175c20c11dc5f96cb64bb6c9b3" +dependencies = [ + "glob", + "serde", + "serde_derive", + "serde_json", + "termcolor", + "toml", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winnow" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +dependencies = [ + "memchr", +] diff --git a/deps/crates/vendor/displaydoc/Cargo.toml b/deps/crates/vendor/displaydoc/Cargo.toml new file mode 100644 index 00000000000000..0202d998578e4a --- /dev/null +++ b/deps/crates/vendor/displaydoc/Cargo.toml @@ -0,0 +1,115 @@ +# 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.56.0" +name = "displaydoc" +version = "0.2.5" +authors = ["Jane Lusby "] +description = """ +A derive macro for implementing the display Trait via a doc comment and string interpolation +""" +homepage = "https://github.com/yaahc/displaydoc" +documentation = "https://docs.rs/displaydoc" +readme = "README.md" +keywords = [ + "display", + "derive", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/yaahc/displaydoc" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[package.metadata.release] +no-dev-version = true +pre-release-hook = ["./update-readme.sh"] + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +replace = "{{version}}" +search = "Unreleased" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "src/lib.rs" +replace = "#![doc(html_root_url = \"https://docs.rs/{{crate_name}}/{{version}}\")]" +search = '#!\[doc\(html_root_url.*' + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +replace = "{{date}}" +search = "ReleaseDate" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = """ + + +# [Unreleased] - ReleaseDate""" +search = "" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = "...{{tag_name}}" +search = '\.\.\.HEAD' + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = """ + +[Unreleased]: https://github.com/yaahc/{{crate_name}}/compare/{{tag_name}}...HEAD""" +search = "" + +[lib] +path = "src/lib.rs" +proc-macro = true + +[dependencies.proc-macro2] +version = "1.0" + +[dependencies.quote] +version = "1.0" + +[dependencies.syn] +version = "2.0" + +[dev-dependencies.libc] +version = "0.2" +default-features = false + +[dev-dependencies.pretty_assertions] +version = "0.6.1" + +[dev-dependencies.rustversion] +version = "1.0.0" + +[dev-dependencies.static_assertions] +version = "1.1" + +[dev-dependencies.thiserror] +version = "1.0.24" + +[dev-dependencies.trybuild] +version = "1.0" + +[features] +default = ["std"] +std = [] diff --git a/deps/crates/vendor/displaydoc/LICENSE-APACHE b/deps/crates/vendor/displaydoc/LICENSE-APACHE new file mode 100644 index 00000000000000..16fe87b06e802f --- /dev/null +++ b/deps/crates/vendor/displaydoc/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/deps/crates/vendor/displaydoc/LICENSE-MIT b/deps/crates/vendor/displaydoc/LICENSE-MIT new file mode 100644 index 00000000000000..31aa79387f27e7 --- /dev/null +++ b/deps/crates/vendor/displaydoc/LICENSE-MIT @@ -0,0 +1,23 @@ +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/deps/crates/vendor/displaydoc/README.md b/deps/crates/vendor/displaydoc/README.md new file mode 100644 index 00000000000000..a609b0f270aced --- /dev/null +++ b/deps/crates/vendor/displaydoc/README.md @@ -0,0 +1,115 @@ +derive(Display) /// `From` +=============== + +[![Latest Version](https://img.shields.io/crates/v/displaydoc.svg)](https://crates.io/crates/displaydoc) +[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/displaydoc) + +This library provides a convenient derive macro for the standard library's +[`core::fmt::Display`] trait. + +[`core::fmt::Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html + +```toml +[dependencies] +displaydoc = "0.2" +``` + +*Compiler support: requires rustc 1.56+* + +
+ +### Example + +*Demonstration alongside the [`Error`][std::error::Error] derive macro from [`thiserror`](https://docs.rs/thiserror/1.0.25/thiserror/index.html), +to propagate source locations from [`io::Error`][std::io::Error] with the `#[source]` attribute:* +```rust +use std::io; +use displaydoc::Display; +use thiserror::Error; + +#[derive(Display, Error, Debug)] +pub enum DataStoreError { + /// data store disconnected + Disconnect(#[source] io::Error), + /// the data for key `{0}` is not available + Redaction(String), + /// invalid header (expected {expected:?}, found {found:?}) + InvalidHeader { + expected: String, + found: String, + }, + /// unknown data store error + Unknown, +} + +let error = DataStoreError::Redaction("CLASSIFIED CONTENT".to_string()); +assert!("the data for key `CLASSIFIED CONTENT` is not available" == &format!("{}", error)); +``` +*Note that although [`io::Error`][std::io::Error] implements `Display`, we do not add it to the +generated message for `DataStoreError::Disconnect`, since it is already made available via +`#[source]`. See further context on avoiding duplication in error reports at the rust blog +[here](https://github.com/yaahc/blog.rust-lang.org/blob/master/posts/inside-rust/2021-05-15-What-the-error-handling-project-group-is-working-towards.md#duplicate-information-issue).* + +
+ +### Details + +- A `fmt::Display` impl is generated for your enum if you provide + a docstring comment on each variant as shown above in the example. The + `Display` derive macro supports a shorthand for interpolating fields from + the error: + - `/// {var}` ⟶ `write!("{}", self.var)` + - `/// {0}` ⟶ `write!("{}", self.0)` + - `/// {var:?}` ⟶ `write!("{:?}", self.var)` + - `/// {0:?}` ⟶ `write!("{:?}", self.0)` +- This also works with structs and [generic types][crate::Display#generic-type-parameters]: +```rust +/// oh no, an error: {0} +#[derive(Display)] +pub struct Error(pub E); + +let error: Error<&str> = Error("muahaha i am an error"); +assert!("oh no, an error: muahaha i am an error" == &format!("{}", error)); +``` + +- Two optional attributes can be added to your types next to the derive: + + - `#[ignore_extra_doc_attributes]` makes the macro ignore any doc + comment attributes (or `///` lines) after the first. Multi-line + comments using `///` are otherwise treated as an error, so use this + attribute or consider switching to block doc comments (`/** */`). + + - `#[prefix_enum_doc_attributes]` combines the doc comment message on + your enum itself with the messages for each variant, in the format + “enum: variant”. When added to an enum, the doc comment on the enum + becomes mandatory. When added to any other type, it has no effect. + +- In case you want to have an independent doc comment, the + `#[displaydoc("...")` atrribute may be used on the variant or struct to + override it. + +
+ +### FAQ + +1. **Is this crate `no_std` compatible?** + * Yes! This crate implements the [`core::fmt::Display`] trait, not the [`std::fmt::Display`] trait, so it should work in `std` and `no_std` environments. Just add `default-features = false`. + +2. **Does this crate work with `Path` and `PathBuf` via the `Display` trait?** + * Yuuup. This crate uses @dtolnay's [autoref specialization technique](https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md) to add a special trait for types to get the display impl. It then specializes for `Path` and `PathBuf`, and when either of these types are found, it calls `self.display()` to get a `std::path::Display<'_>` type which can be used with the `Display` format specifier! + + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + diff --git a/deps/crates/vendor/displaydoc/README.tpl b/deps/crates/vendor/displaydoc/README.tpl new file mode 100644 index 00000000000000..6206a9e7e63ee6 --- /dev/null +++ b/deps/crates/vendor/displaydoc/README.tpl @@ -0,0 +1,23 @@ +derive(Display) /// `From` +=============== + +[![Latest Version](https://img.shields.io/crates/v/displaydoc.svg)](https://crates.io/crates/displaydoc) +[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/displaydoc) + +{{readme}} + + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + diff --git a/deps/crates/vendor/displaydoc/examples/simple.rs b/deps/crates/vendor/displaydoc/examples/simple.rs new file mode 100644 index 00000000000000..f4aad2131fd457 --- /dev/null +++ b/deps/crates/vendor/displaydoc/examples/simple.rs @@ -0,0 +1,36 @@ +use displaydoc::Display; + +#[derive(Debug, Display)] +pub enum DataStoreError { + /// data store disconnected + Disconnect, + /// the data for key `{0}` is not available + Redaction(String), + /// invalid header (expected {expected:?}, found {found:?}) + InvalidHeader { expected: String, found: String }, + /// unknown data store error + Unknown, +} + +fn main() { + let disconnect = DataStoreError::Disconnect; + println!( + "Enum value `Disconnect` should be printed as:\n\t{}", + disconnect + ); + + let redaction = DataStoreError::Redaction(String::from("Dummy")); + println!( + "Enum value `Redaction` should be printed as:\n\t{}", + redaction + ); + + let invalid_header = DataStoreError::InvalidHeader { + expected: String::from("https"), + found: String::from("http"), + }; + println!( + "Enum value `InvalidHeader` should be printed as:\n\t{}", + invalid_header + ); +} diff --git a/deps/crates/vendor/displaydoc/src/attr.rs b/deps/crates/vendor/displaydoc/src/attr.rs new file mode 100644 index 00000000000000..afda4b90fa61fd --- /dev/null +++ b/deps/crates/vendor/displaydoc/src/attr.rs @@ -0,0 +1,137 @@ +use proc_macro2::TokenStream; +use quote::{quote, ToTokens}; +use syn::{Attribute, LitStr, Meta, Result}; + +#[derive(Clone)] +pub(crate) struct Display { + pub(crate) fmt: LitStr, + pub(crate) args: TokenStream, +} + +pub(crate) struct VariantDisplay { + pub(crate) r#enum: Option, + pub(crate) variant: Display, +} + +impl ToTokens for Display { + fn to_tokens(&self, tokens: &mut TokenStream) { + let fmt = &self.fmt; + let args = &self.args; + tokens.extend(quote! { + write!(formatter, #fmt #args) + }); + } +} + +impl ToTokens for VariantDisplay { + fn to_tokens(&self, tokens: &mut TokenStream) { + if let Some(ref r#enum) = self.r#enum { + r#enum.to_tokens(tokens); + tokens.extend(quote! { ?; write!(formatter, ": ")?; }); + } + self.variant.to_tokens(tokens); + } +} + +pub(crate) struct AttrsHelper { + ignore_extra_doc_attributes: bool, + prefix_enum_doc_attributes: bool, +} + +impl AttrsHelper { + pub(crate) fn new(attrs: &[Attribute]) -> Self { + let ignore_extra_doc_attributes = attrs + .iter() + .any(|attr| attr.path().is_ident("ignore_extra_doc_attributes")); + let prefix_enum_doc_attributes = attrs + .iter() + .any(|attr| attr.path().is_ident("prefix_enum_doc_attributes")); + + Self { + ignore_extra_doc_attributes, + prefix_enum_doc_attributes, + } + } + + pub(crate) fn display(&self, attrs: &[Attribute]) -> Result> { + let displaydoc_attr = attrs.iter().find(|attr| attr.path().is_ident("displaydoc")); + + if let Some(displaydoc_attr) = displaydoc_attr { + let lit = displaydoc_attr + .parse_args() + .expect("#[displaydoc(\"foo\")] must contain string arguments"); + let mut display = Display { + fmt: lit, + args: TokenStream::new(), + }; + + display.expand_shorthand(); + return Ok(Some(display)); + } + + let num_doc_attrs = attrs + .iter() + .filter(|attr| attr.path().is_ident("doc")) + .count(); + + if !self.ignore_extra_doc_attributes && num_doc_attrs > 1 { + panic!("Multi-line comments are disabled by default by displaydoc. Please consider using block doc comments (/** */) or adding the #[ignore_extra_doc_attributes] attribute to your type next to the derive."); + } + + for attr in attrs { + if attr.path().is_ident("doc") { + let lit = match &attr.meta { + Meta::NameValue(syn::MetaNameValue { + value: + syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Str(lit), + .. + }), + .. + }) => lit, + _ => unimplemented!(), + }; + + // Make an attempt at cleaning up multiline doc comments. + let doc_str = lit + .value() + .lines() + .map(|line| line.trim().trim_start_matches('*').trim()) + .collect::>() + .join("\n"); + + let lit = LitStr::new(doc_str.trim(), lit.span()); + + let mut display = Display { + fmt: lit, + args: TokenStream::new(), + }; + + display.expand_shorthand(); + return Ok(Some(display)); + } + } + + Ok(None) + } + + pub(crate) fn display_with_input( + &self, + r#enum: &[Attribute], + variant: &[Attribute], + ) -> Result> { + let r#enum = if self.prefix_enum_doc_attributes { + let result = self + .display(r#enum)? + .expect("Missing doc comment on enum with #[prefix_enum_doc_attributes]. Please remove the attribute or add a doc comment to the enum itself."); + + Some(result) + } else { + None + }; + + Ok(self + .display(variant)? + .map(|variant| VariantDisplay { r#enum, variant })) + } +} diff --git a/deps/crates/vendor/displaydoc/src/expand.rs b/deps/crates/vendor/displaydoc/src/expand.rs new file mode 100644 index 00000000000000..3b146f81ecd1c2 --- /dev/null +++ b/deps/crates/vendor/displaydoc/src/expand.rs @@ -0,0 +1,409 @@ +use super::attr::AttrsHelper; +use proc_macro2::{Span, TokenStream}; +use quote::{format_ident, quote}; +use syn::{ + punctuated::Punctuated, + token::{Colon, Comma, PathSep, Plus, Where}, + Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Path, PathArguments, + PathSegment, PredicateType, Result, TraitBound, TraitBoundModifier, Type, TypeParam, + TypeParamBound, TypePath, WhereClause, WherePredicate, +}; + +use std::collections::HashMap; + +pub(crate) fn derive(input: &DeriveInput) -> Result { + let impls = match &input.data { + Data::Struct(data) => impl_struct(input, data), + Data::Enum(data) => impl_enum(input, data), + Data::Union(_) => Err(Error::new_spanned(input, "Unions are not supported")), + }?; + + let helpers = specialization(); + Ok(quote! { + #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] + const _: () = { + #helpers + #impls + }; + }) +} + +#[cfg(feature = "std")] +fn specialization() -> TokenStream { + quote! { + trait DisplayToDisplayDoc { + fn __displaydoc_display(&self) -> Self; + } + + impl DisplayToDisplayDoc for &T { + fn __displaydoc_display(&self) -> Self { + self + } + } + + // If the `std` feature gets enabled we want to ensure that any crate + // using displaydoc can still reference the std crate, which is already + // being compiled in by whoever enabled the `std` feature in + // `displaydoc`, even if the crates using displaydoc are no_std. + extern crate std; + + trait PathToDisplayDoc { + fn __displaydoc_display(&self) -> std::path::Display<'_>; + } + + impl PathToDisplayDoc for std::path::Path { + fn __displaydoc_display(&self) -> std::path::Display<'_> { + self.display() + } + } + + impl PathToDisplayDoc for std::path::PathBuf { + fn __displaydoc_display(&self) -> std::path::Display<'_> { + self.display() + } + } + } +} + +#[cfg(not(feature = "std"))] +fn specialization() -> TokenStream { + quote! {} +} + +fn impl_struct(input: &DeriveInput, data: &DataStruct) -> Result { + let ty = &input.ident; + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + let where_clause = generate_where_clause(&input.generics, where_clause); + + let helper = AttrsHelper::new(&input.attrs); + + let display = helper.display(&input.attrs)?.map(|display| { + let pat = match &data.fields { + Fields::Named(fields) => { + let var = fields.named.iter().map(|field| &field.ident); + quote!(Self { #(#var),* }) + } + Fields::Unnamed(fields) => { + let var = (0..fields.unnamed.len()).map(|i| format_ident!("_{}", i)); + quote!(Self(#(#var),*)) + } + Fields::Unit => quote!(_), + }; + quote! { + impl #impl_generics ::core::fmt::Display for #ty #ty_generics #where_clause { + fn fmt(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + // NB: This destructures the fields of `self` into named variables (for unnamed + // fields, it uses _0, _1, etc as above). The `#[allow(unused_variables)]` + // section means it doesn't have to parse the individual field references out of + // the docstring. + #[allow(unused_variables)] + let #pat = self; + #display + } + } + } + }); + + Ok(quote! { #display }) +} + +/// Create a `where` predicate for `ident`, without any [bound][TypeParamBound]s yet. +fn new_empty_where_type_predicate(ident: Ident) -> PredicateType { + let mut path_segments = Punctuated::::new(); + path_segments.push_value(PathSegment { + ident, + arguments: PathArguments::None, + }); + PredicateType { + lifetimes: None, + bounded_ty: Type::Path(TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: path_segments, + }, + }), + colon_token: Colon { + spans: [Span::call_site()], + }, + bounds: Punctuated::::new(), + } +} + +/// Create a `where` clause that we can add [WherePredicate]s to. +fn new_empty_where_clause() -> WhereClause { + WhereClause { + where_token: Where { + span: Span::call_site(), + }, + predicates: Punctuated::::new(), + } +} + +enum UseGlobalPrefix { + LeadingColon, + #[allow(dead_code)] + NoLeadingColon, +} + +/// Create a path with segments composed of [Idents] *without* any [PathArguments]. +fn join_paths(name_segments: &[&str], use_global_prefix: UseGlobalPrefix) -> Path { + let mut segments = Punctuated::::new(); + assert!(!name_segments.is_empty()); + segments.push_value(PathSegment { + ident: Ident::new(name_segments[0], Span::call_site()), + arguments: PathArguments::None, + }); + for name in name_segments[1..].iter() { + segments.push_punct(PathSep { + spans: [Span::call_site(), Span::mixed_site()], + }); + segments.push_value(PathSegment { + ident: Ident::new(name, Span::call_site()), + arguments: PathArguments::None, + }); + } + Path { + leading_colon: match use_global_prefix { + UseGlobalPrefix::LeadingColon => Some(PathSep { + spans: [Span::call_site(), Span::mixed_site()], + }), + UseGlobalPrefix::NoLeadingColon => None, + }, + segments, + } +} + +/// Push `new_type_predicate` onto the end of `where_clause`. +fn append_where_clause_type_predicate( + where_clause: &mut WhereClause, + new_type_predicate: PredicateType, +) { + // Push a comma at the end if there are already any `where` predicates. + if !where_clause.predicates.is_empty() { + where_clause.predicates.push_punct(Comma { + spans: [Span::call_site()], + }); + } + where_clause + .predicates + .push_value(WherePredicate::Type(new_type_predicate)); +} + +/// Add a requirement for [core::fmt::Display] to a `where` predicate for some type. +fn add_display_constraint_to_type_predicate( + predicate_that_needs_a_display_impl: &mut PredicateType, +) { + // Create a `Path` of `::core::fmt::Display`. + let display_path = join_paths(&["core", "fmt", "Display"], UseGlobalPrefix::LeadingColon); + + let display_bound = TypeParamBound::Trait(TraitBound { + paren_token: None, + modifier: TraitBoundModifier::None, + lifetimes: None, + path: display_path, + }); + if !predicate_that_needs_a_display_impl.bounds.is_empty() { + predicate_that_needs_a_display_impl.bounds.push_punct(Plus { + spans: [Span::call_site()], + }); + } + + predicate_that_needs_a_display_impl + .bounds + .push_value(display_bound); +} + +/// Map each declared generic type parameter to the set of all trait boundaries declared on it. +/// +/// These boundaries may come from the declaration site: +/// pub enum E { ... } +/// or a `where` clause after the parameter declarations: +/// pub enum E where T: MyTrait { ... } +/// This method will return the boundaries from both of those cases. +fn extract_trait_constraints_from_source( + where_clause: &WhereClause, + type_params: &[&TypeParam], +) -> HashMap> { + // Add trait bounds provided at the declaration site of type parameters for the struct/enum. + let mut param_constraint_mapping: HashMap> = type_params + .iter() + .map(|type_param| { + let trait_bounds: Vec = type_param + .bounds + .iter() + .flat_map(|bound| match bound { + TypeParamBound::Trait(trait_bound) => Some(trait_bound), + _ => None, + }) + .cloned() + .collect(); + (type_param.ident.clone(), trait_bounds) + }) + .collect(); + + // Add trait bounds from `where` clauses, which may be type parameters or types containing + // those parameters. + for predicate in where_clause.predicates.iter() { + // We only care about type and not lifetime constraints here. + if let WherePredicate::Type(ref pred_ty) = predicate { + let ident = match &pred_ty.bounded_ty { + Type::Path(TypePath { path, qself: None }) => match path.get_ident() { + None => continue, + Some(ident) => ident, + }, + _ => continue, + }; + // We ignore any type constraints that aren't direct references to type + // parameters of the current enum of struct definition. No types can be + // constrained in a `where` clause unless they are a type parameter or a generic + // type instantiated with one of the type parameters, so by only allowing single + // identifiers, we can be sure that the constrained type is a type parameter + // that is contained in `param_constraint_mapping`. + if let Some((_, ref mut known_bounds)) = param_constraint_mapping + .iter_mut() + .find(|(id, _)| *id == ident) + { + for bound in pred_ty.bounds.iter() { + // We only care about trait bounds here. + if let TypeParamBound::Trait(ref bound) = bound { + known_bounds.push(bound.clone()); + } + } + } + } + } + + param_constraint_mapping +} + +/// Hygienically add `where _: Display` to the set of [TypeParamBound]s for `ident`, creating such +/// a set if necessary. +fn ensure_display_in_where_clause_for_type(where_clause: &mut WhereClause, ident: Ident) { + for pred_ty in where_clause + .predicates + .iter_mut() + // Find the `where` predicate constraining the current type param, if it exists. + .flat_map(|predicate| match predicate { + WherePredicate::Type(pred_ty) => Some(pred_ty), + // We're looking through type constraints, not lifetime constraints. + _ => None, + }) + { + // Do a complicated destructuring in order to check if the type being constrained in this + // `where` clause is the type we're looking for, so we can use the mutable reference to + // `pred_ty` if so. + let matches_desired_type = matches!( + &pred_ty.bounded_ty, + Type::Path(TypePath { path, .. }) if Some(&ident) == path.get_ident()); + if matches_desired_type { + add_display_constraint_to_type_predicate(pred_ty); + return; + } + } + + // If there is no `where` predicate for the current type param, we will construct one. + let mut new_type_predicate = new_empty_where_type_predicate(ident); + add_display_constraint_to_type_predicate(&mut new_type_predicate); + append_where_clause_type_predicate(where_clause, new_type_predicate); +} + +/// For all declared type parameters, add a [core::fmt::Display] constraint, unless the type +/// parameter already has any type constraint. +fn ensure_where_clause_has_display_for_all_unconstrained_members( + where_clause: &mut WhereClause, + type_params: &[&TypeParam], +) { + let param_constraint_mapping = extract_trait_constraints_from_source(where_clause, type_params); + + for (ident, known_bounds) in param_constraint_mapping.into_iter() { + // If the type parameter has any constraints already, we don't want to touch it, to avoid + // breaking use cases where a type parameter only needs to impl `Debug`, for example. + if known_bounds.is_empty() { + ensure_display_in_where_clause_for_type(where_clause, ident); + } + } +} + +/// Generate a `where` clause that ensures all generic type parameters `impl` +/// [core::fmt::Display] unless already constrained. +/// +/// This approach allows struct/enum definitions deriving [crate::Display] to avoid hardcoding +/// a [core::fmt::Display] constraint into every type parameter. +/// +/// If the type parameter isn't already constrained, we add a `where _: Display` clause to our +/// display implementation to expect to be able to format every enum case or struct member. +/// +/// In fact, we would preferably only require `where _: Display` or `where _: Debug` where the +/// format string actually requires it. However, while [`std::fmt` defines a formal syntax for +/// `format!()`][format syntax], it *doesn't* expose the actual logic to parse the format string, +/// which appears to live in [`rustc_parse_format`]. While we use the [`syn`] crate to parse rust +/// syntax, it also doesn't currently provide any method to introspect a `format!()` string. It +/// would be nice to contribute this upstream in [`syn`]. +/// +/// [format syntax]: std::fmt#syntax +/// [`rustc_parse_format`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse_format/index.html +fn generate_where_clause(generics: &Generics, where_clause: Option<&WhereClause>) -> WhereClause { + let mut where_clause = where_clause.cloned().unwrap_or_else(new_empty_where_clause); + let type_params: Vec<&TypeParam> = generics.type_params().collect(); + ensure_where_clause_has_display_for_all_unconstrained_members(&mut where_clause, &type_params); + where_clause +} + +fn impl_enum(input: &DeriveInput, data: &DataEnum) -> Result { + let ty = &input.ident; + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + let where_clause = generate_where_clause(&input.generics, where_clause); + + let helper = AttrsHelper::new(&input.attrs); + + let displays = data + .variants + .iter() + .map(|variant| helper.display_with_input(&input.attrs, &variant.attrs)) + .collect::>>()?; + + if data.variants.is_empty() { + Ok(quote! { + impl #impl_generics ::core::fmt::Display for #ty #ty_generics #where_clause { + fn fmt(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + unreachable!("empty enums cannot be instantiated and thus cannot be printed") + } + } + }) + } else if displays.iter().any(Option::is_some) { + let arms = data + .variants + .iter() + .zip(displays) + .map(|(variant, display)| { + let display = + display.ok_or_else(|| Error::new_spanned(variant, "missing doc comment"))?; + let ident = &variant.ident; + Ok(match &variant.fields { + Fields::Named(fields) => { + let var = fields.named.iter().map(|field| &field.ident); + quote!(Self::#ident { #(#var),* } => { #display }) + } + Fields::Unnamed(fields) => { + let var = (0..fields.unnamed.len()).map(|i| format_ident!("_{}", i)); + quote!(Self::#ident(#(#var),*) => { #display }) + } + Fields::Unit => quote!(Self::#ident => { #display }), + }) + }) + .collect::>>()?; + Ok(quote! { + impl #impl_generics ::core::fmt::Display for #ty #ty_generics #where_clause { + fn fmt(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + #[allow(unused_variables)] + match self { + #(#arms,)* + } + } + } + }) + } else { + Err(Error::new_spanned(input, "Missing doc comments")) + } +} diff --git a/deps/crates/vendor/displaydoc/src/fmt.rs b/deps/crates/vendor/displaydoc/src/fmt.rs new file mode 100644 index 00000000000000..5848557ea43875 --- /dev/null +++ b/deps/crates/vendor/displaydoc/src/fmt.rs @@ -0,0 +1,159 @@ +use crate::attr::Display; +use proc_macro2::TokenStream; +use quote::quote_spanned; +use syn::{Ident, LitStr}; + +macro_rules! peek_next { + ($read:ident) => { + match $read.chars().next() { + Some(next) => next, + None => return, + } + }; +} + +impl Display { + // Transform `"error {var}"` to `"error {}", var`. + pub(crate) fn expand_shorthand(&mut self) { + let span = self.fmt.span(); + let fmt = self.fmt.value(); + let mut read = fmt.as_str(); + let mut out = String::new(); + let mut args = TokenStream::new(); + + while let Some(brace) = read.find('{') { + out += &read[..=brace]; + read = &read[brace + 1..]; + + // skip cases where we find a {{ + if read.starts_with('{') { + out.push('{'); + read = &read[1..]; + continue; + } + + let next = peek_next!(read); + + let var = match next { + '0'..='9' => take_int(&mut read), + 'a'..='z' | 'A'..='Z' | '_' => take_ident(&mut read), + _ => return, + }; + + let ident = Ident::new(&var, span); + + let next = peek_next!(read); + + let arg = if cfg!(feature = "std") && next == '}' { + quote_spanned!(span=> , #ident.__displaydoc_display()) + } else { + quote_spanned!(span=> , #ident) + }; + + args.extend(arg); + } + + out += read; + self.fmt = LitStr::new(&out, self.fmt.span()); + self.args = args; + } +} + +fn take_int(read: &mut &str) -> String { + let mut int = String::new(); + int.push('_'); + for (i, ch) in read.char_indices() { + match ch { + '0'..='9' => int.push(ch), + _ => { + *read = &read[i..]; + break; + } + } + } + int +} + +fn take_ident(read: &mut &str) -> String { + let mut ident = String::new(); + for (i, ch) in read.char_indices() { + match ch { + 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => ident.push(ch), + _ => { + *read = &read[i..]; + break; + } + } + } + ident +} + +#[cfg(test)] +mod tests { + use super::*; + use pretty_assertions::assert_eq; + use proc_macro2::Span; + + fn assert(input: &str, fmt: &str, args: &str) { + let mut display = Display { + fmt: LitStr::new(input, Span::call_site()), + args: TokenStream::new(), + }; + display.expand_shorthand(); + assert_eq!(fmt, display.fmt.value()); + assert_eq!(args, display.args.to_string()); + } + + #[test] + fn test_expand() { + assert("fn main() {{ }}", "fn main() {{ }}", ""); + } + + #[test] + #[cfg_attr(not(feature = "std"), ignore)] + fn test_std_expand() { + assert( + "{v} {v:?} {0} {0:?}", + "{} {:?} {} {:?}", + ", v . __displaydoc_display () , v , _0 . __displaydoc_display () , _0", + ); + assert("error {var}", "error {}", ", var . __displaydoc_display ()"); + + assert( + "error {var1}", + "error {}", + ", var1 . __displaydoc_display ()", + ); + + assert( + "error {var1var}", + "error {}", + ", var1var . __displaydoc_display ()", + ); + + assert( + "The path {0}", + "The path {}", + ", _0 . __displaydoc_display ()", + ); + assert("The path {0:?}", "The path {:?}", ", _0"); + } + + #[test] + #[cfg_attr(feature = "std", ignore)] + fn test_nostd_expand() { + assert( + "{v} {v:?} {0} {0:?}", + "{} {:?} {} {:?}", + ", v , v , _0 , _0", + ); + assert("error {var}", "error {}", ", var"); + + assert("The path {0}", "The path {}", ", _0"); + assert("The path {0:?}", "The path {:?}", ", _0"); + + assert("error {var1}", "error {}", ", var1"); + + assert("error {var1var}", "error {}", ", var1var"); + } +} diff --git a/deps/crates/vendor/displaydoc/src/lib.rs b/deps/crates/vendor/displaydoc/src/lib.rs new file mode 100644 index 00000000000000..8824ff05ba8c85 --- /dev/null +++ b/deps/crates/vendor/displaydoc/src/lib.rs @@ -0,0 +1,186 @@ +//! This library provides a convenient derive macro for the standard library's +//! [`core::fmt::Display`] trait. +//! +//! [`core::fmt::Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html +//! +//! ```toml +//! [dependencies] +//! displaydoc = "0.2" +//! ``` +//! +//! *Compiler support: requires rustc 1.56+* +//! +//!
+//! +//! ## Example +//! +//! *Demonstration alongside the [`Error`][std::error::Error] derive macro from [`thiserror`](https://docs.rs/thiserror/1.0.25/thiserror/index.html), +//! to propagate source locations from [`io::Error`][std::io::Error] with the `#[source]` attribute:* +//! ```rust +//! use std::io; +//! use displaydoc::Display; +//! use thiserror::Error; +//! +//! #[derive(Display, Error, Debug)] +//! pub enum DataStoreError { +//! /// data store disconnected +//! Disconnect(#[source] io::Error), +//! /// the data for key `{0}` is not available +//! Redaction(String), +//! /// invalid header (expected {expected:?}, found {found:?}) +//! InvalidHeader { +//! expected: String, +//! found: String, +//! }, +//! /// unknown data store error +//! Unknown, +//! } +//! +//! let error = DataStoreError::Redaction("CLASSIFIED CONTENT".to_string()); +//! assert!("the data for key `CLASSIFIED CONTENT` is not available" == &format!("{}", error)); +//! ``` +//! *Note that although [`io::Error`][std::io::Error] implements `Display`, we do not add it to the +//! generated message for `DataStoreError::Disconnect`, since it is already made available via +//! `#[source]`. See further context on avoiding duplication in error reports at the rust blog +//! [here](https://github.com/yaahc/blog.rust-lang.org/blob/master/posts/inside-rust/2021-05-15-What-the-error-handling-project-group-is-working-towards.md#duplicate-information-issue).* +//! +//!
+//! +//! ## Details +//! +//! - A `fmt::Display` impl is generated for your enum if you provide +//! a docstring comment on each variant as shown above in the example. The +//! `Display` derive macro supports a shorthand for interpolating fields from +//! the error: +//! - `/// {var}` ⟶ `write!("{}", self.var)` +//! - `/// {0}` ⟶ `write!("{}", self.0)` +//! - `/// {var:?}` ⟶ `write!("{:?}", self.var)` +//! - `/// {0:?}` ⟶ `write!("{:?}", self.0)` +//! - This also works with structs and [generic types][crate::Display#generic-type-parameters]: +//! ```rust +//! # use displaydoc::Display; +//! /// oh no, an error: {0} +//! #[derive(Display)] +//! pub struct Error(pub E); +//! +//! let error: Error<&str> = Error("muahaha i am an error"); +//! assert!("oh no, an error: muahaha i am an error" == &format!("{}", error)); +//! ``` +//! +//! - Two optional attributes can be added to your types next to the derive: +//! +//! - `#[ignore_extra_doc_attributes]` makes the macro ignore any doc +//! comment attributes (or `///` lines) after the first. Multi-line +//! comments using `///` are otherwise treated as an error, so use this +//! attribute or consider switching to block doc comments (`/** */`). +//! +//! - `#[prefix_enum_doc_attributes]` combines the doc comment message on +//! your enum itself with the messages for each variant, in the format +//! “enum: variant”. When added to an enum, the doc comment on the enum +//! becomes mandatory. When added to any other type, it has no effect. +//! +//! - In case you want to have an independent doc comment, the +//! `#[displaydoc("...")` atrribute may be used on the variant or struct to +//! override it. +//! +//!
+//! +//! ## FAQ +//! +//! 1. **Is this crate `no_std` compatible?** +//! * Yes! This crate implements the [`core::fmt::Display`] trait, not the [`std::fmt::Display`] trait, so it should work in `std` and `no_std` environments. Just add `default-features = false`. +//! +//! 2. **Does this crate work with `Path` and `PathBuf` via the `Display` trait?** +//! * Yuuup. This crate uses @dtolnay's [autoref specialization technique](https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md) to add a special trait for types to get the display impl. It then specializes for `Path` and `PathBuf`, and when either of these types are found, it calls `self.display()` to get a `std::path::Display<'_>` type which can be used with the `Display` format specifier! +#![doc(html_root_url = "https://docs.rs/displaydoc/0.2.3")] +#![cfg_attr(docsrs, feature(doc_cfg))] +#![warn( + rust_2018_idioms, + unreachable_pub, + bad_style, + dead_code, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + unconditional_recursion, + unused, + unused_allocation, + unused_comparisons, + unused_parens, + while_true +)] +#![allow(clippy::try_err)] + +#[allow(unused_extern_crates)] +extern crate proc_macro; + +mod attr; +mod expand; +mod fmt; + +use proc_macro::TokenStream; +use syn::{parse_macro_input, DeriveInput}; + +/// [Custom `#[derive(...)]` macro](https://doc.rust-lang.org/edition-guide/rust-2018/macros/custom-derive.html) +/// for implementing [`fmt::Display`][core::fmt::Display] via doc comment attributes. +/// +/// ### Generic Type Parameters +/// +/// Type parameters to an enum or struct using this macro should *not* need to +/// have an explicit `Display` constraint at the struct or enum definition +/// site. A `Display` implementation for the `derive`d struct or enum is +/// generated assuming each type parameter implements `Display`, but that should +/// be possible without adding the constraint to the struct definition itself: +/// ```rust +/// use displaydoc::Display; +/// +/// /// oh no, an error: {0} +/// #[derive(Display)] +/// pub struct Error(pub E); +/// +/// // No need to require `E: Display`, since `displaydoc::Display` adds that implicitly. +/// fn generate_error(e: E) -> Error { Error(e) } +/// +/// assert!("oh no, an error: muahaha" == &format!("{}", generate_error("muahaha"))); +/// ``` +/// +/// ### Using [`Debug`][core::fmt::Debug] Implementations with Type Parameters +/// However, if a type parameter must instead be constrained with the +/// [`Debug`][core::fmt::Debug] trait so that some field may be printed with +/// `{:?}`, that constraint must currently still also be specified redundantly +/// at the struct or enum definition site. If a struct or enum field is being +/// formatted with `{:?}` via [`displaydoc`][crate], and a generic type +/// parameter must implement `Debug` to do that, then that struct or enum +/// definition will need to propagate the `Debug` constraint to every type +/// parameter it's instantiated with: +/// ```rust +/// use core::fmt::Debug; +/// use displaydoc::Display; +/// +/// /// oh no, an error: {0:?} +/// #[derive(Display)] +/// pub struct Error(pub E); +/// +/// // `E: Debug` now has to propagate to callers. +/// fn generate_error(e: E) -> Error { Error(e) } +/// +/// assert!("oh no, an error: \"cool\"" == &format!("{}", generate_error("cool"))); +/// +/// // Try this with a struct that doesn't impl `Display` at all, unlike `str`. +/// #[derive(Debug)] +/// pub struct Oh; +/// assert!("oh no, an error: Oh" == &format!("{}", generate_error(Oh))); +/// ``` +#[proc_macro_derive( + Display, + attributes(ignore_extra_doc_attributes, prefix_enum_doc_attributes, displaydoc) +)] +pub fn derive_error(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + expand::derive(&input) + .unwrap_or_else(|err| err.to_compile_error()) + .into() +} diff --git a/deps/crates/vendor/displaydoc/tests/compile_tests.rs b/deps/crates/vendor/displaydoc/tests/compile_tests.rs new file mode 100644 index 00000000000000..29c72a862147ca --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/compile_tests.rs @@ -0,0 +1,29 @@ +#[allow(unused_attributes)] +#[rustversion::attr(not(nightly), ignore)] +#[test] +fn no_std() { + let t = trybuild::TestCases::new(); + #[cfg(not(feature = "std"))] + t.compile_fail("tests/no_std/without.rs"); + #[cfg(not(feature = "std"))] + t.compile_fail("tests/no_std/multi_line.rs"); + #[cfg(not(feature = "std"))] + t.pass("tests/no_std/multi_line_allow.rs"); + #[cfg(not(feature = "std"))] + t.compile_fail("tests/no_std/enum_prefix_missing.rs"); + #[cfg(not(feature = "std"))] + t.pass("tests/no_std/enum_prefix.rs"); + #[cfg(feature = "std")] + t.compile_fail("tests/std/without.rs"); + #[cfg(feature = "std")] + t.compile_fail("tests/std/multi_line.rs"); + #[cfg(feature = "std")] + t.pass("tests/std/multi_line_allow.rs"); + #[cfg(feature = "std")] + t.compile_fail("tests/std/enum_prefix_missing.rs"); + #[cfg(feature = "std")] + t.pass("tests/std/enum_prefix.rs"); + #[cfg(feature = "std")] + t.pass("tests/std/multiple.rs"); + t.pass("tests/no_std/with.rs"); +} diff --git a/deps/crates/vendor/displaydoc/tests/happy.rs b/deps/crates/vendor/displaydoc/tests/happy.rs new file mode 100644 index 00000000000000..85aa78f1379741 --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/happy.rs @@ -0,0 +1,152 @@ +use displaydoc::Display; + +#[cfg(feature = "std")] +use std::path::PathBuf; + +#[derive(Display)] +/// Just a basic struct {thing} +struct HappyStruct { + thing: &'static str, +} + +#[derive(Display)] +#[ignore_extra_doc_attributes] +/// Just a basic struct {thing} +/// and this line should get ignored +struct HappyStruct2 { + thing: &'static str, +} + +#[derive(Display)] +enum Happy { + /// I really like Variant1 + Variant1, + /// Variant2 is pretty swell 2 + Variant2, + /// Variant3 is okay {sometimes} + Variant3 { sometimes: &'static str }, + /** + * Variant4 wants to have a lot of lines + * + * Lets see how this works out for it + */ + Variant4, + /// Variant5 has a parameter {0} and some regular comments + // A regular comment that won't get picked + Variant5(u32), + + /// The path {0} + #[cfg(feature = "std")] + Variant6(PathBuf), + + /// These docs are ignored + #[displaydoc("Variant7 has a parameter {0} and uses #[displaydoc]")] + /// These docs are also ignored + Variant7(u32), +} + +// Used for testing indented doc comments +mod inner_mod { + use super::Display; + + #[derive(Display)] + pub enum InnerHappy { + /// I really like Variant1 + Variant1, + /// Variant2 is pretty swell 2 + Variant2, + /// Variant3 is okay {sometimes} + Variant3 { sometimes: &'static str }, + /** + * Variant4 wants to have a lot of lines + * + * Lets see how this works out for it + */ + Variant4, + /// Variant5 has a parameter {0} and some regular comments + // A regular comment that won't get picked + Variant5(u32), + + /** what happens if we + * put text on the first line? + */ + Variant6, + + /** + what happens if we don't use *? + */ + Variant7, + + /** + * + * what about extra new lines? + */ + Variant8, + } +} + +fn assert_display(input: T, expected: &'static str) { + let out = format!("{}", input); + assert_eq!(expected, out); +} + +#[test] +fn does_it_print() { + assert_display(Happy::Variant1, "I really like Variant1"); + assert_display(Happy::Variant2, "Variant2 is pretty swell 2"); + assert_display(Happy::Variant3 { sometimes: "hi" }, "Variant3 is okay hi"); + assert_display( + Happy::Variant4, + "Variant4 wants to have a lot of lines\n\nLets see how this works out for it", + ); + assert_display( + Happy::Variant5(2), + "Variant5 has a parameter 2 and some regular comments", + ); + assert_display( + Happy::Variant7(2), + "Variant7 has a parameter 2 and uses #[displaydoc]", + ); + assert_display(HappyStruct { thing: "hi" }, "Just a basic struct hi"); + + assert_display(HappyStruct2 { thing: "hi2" }, "Just a basic struct hi2"); + + assert_display(inner_mod::InnerHappy::Variant1, "I really like Variant1"); + assert_display( + inner_mod::InnerHappy::Variant2, + "Variant2 is pretty swell 2", + ); + assert_display( + inner_mod::InnerHappy::Variant3 { sometimes: "hi" }, + "Variant3 is okay hi", + ); + assert_display( + inner_mod::InnerHappy::Variant4, + "Variant4 wants to have a lot of lines\n\nLets see how this works out for it", + ); + assert_display( + inner_mod::InnerHappy::Variant5(2), + "Variant5 has a parameter 2 and some regular comments", + ); + assert_display( + inner_mod::InnerHappy::Variant6, + "what happens if we\nput text on the first line?", + ); + assert_display( + inner_mod::InnerHappy::Variant7, + "what happens if we don\'t use *?", + ); + assert_display( + inner_mod::InnerHappy::Variant8, + "what about extra new lines?", + ); +} + +#[test] +#[cfg(feature = "std")] +fn does_it_print_path() { + assert_display( + Happy::Variant6(PathBuf::from("/var/log/happy")), + "The path /var/log/happy", + ); +} diff --git a/deps/crates/vendor/displaydoc/tests/no_std/enum_prefix.rs b/deps/crates/vendor/displaydoc/tests/no_std/enum_prefix.rs new file mode 100644 index 00000000000000..5538e2751aa324 --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/no_std/enum_prefix.rs @@ -0,0 +1,36 @@ +#![cfg_attr(not(feature = "std"), allow(internal_features), feature(lang_items, start))] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg_attr(not(feature = "std"), start)] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +#[lang = "eh_personality"] +#[no_mangle] +#[cfg(not(feature = "std"))] +pub extern "C" fn rust_eh_personality() {} +#[panic_handler] +#[cfg(not(feature = "std"))] +fn panic(_info: &core::panic::PanicInfo) -> ! { + unsafe { + libc::abort(); + } +} + +use displaydoc::Display; + +/// this type is pretty swell +#[derive(Display)] +#[prefix_enum_doc_attributes] +enum TestType { + /// this variant is too + Variant1, + + /// this variant is two + Variant2, +} + +static_assertions::assert_impl_all!(TestType: core::fmt::Display); + +#[cfg(feature = "std")] +fn main() {} diff --git a/deps/crates/vendor/displaydoc/tests/no_std/enum_prefix_missing.rs b/deps/crates/vendor/displaydoc/tests/no_std/enum_prefix_missing.rs new file mode 100644 index 00000000000000..71710726f3ba3a --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/no_std/enum_prefix_missing.rs @@ -0,0 +1,35 @@ +#![cfg_attr(not(feature = "std"), allow(internal_features), feature(lang_items, start))] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg_attr(not(feature = "std"), start)] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +#[lang = "eh_personality"] +#[no_mangle] +#[cfg(not(feature = "std"))] +pub extern "C" fn rust_eh_personality() {} +#[panic_handler] +#[cfg(not(feature = "std"))] +fn panic(_info: &core::panic::PanicInfo) -> ! { + unsafe { + libc::abort(); + } +} + +use displaydoc::Display; + +#[derive(Display)] +#[prefix_enum_doc_attributes] +enum TestType { + /// this variant is too + Variant1, + + /// this variant is two + Variant2, +} + +static_assertions::assert_impl_all!(TestType: core::fmt::Display); + +#[cfg(feature = "std")] +fn main() {} diff --git a/deps/crates/vendor/displaydoc/tests/no_std/enum_prefix_missing.stderr b/deps/crates/vendor/displaydoc/tests/no_std/enum_prefix_missing.stderr new file mode 100644 index 00000000000000..8cf7993271bddc --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/no_std/enum_prefix_missing.stderr @@ -0,0 +1,22 @@ +error: proc-macro derive panicked + --> $DIR/enum_prefix_missing.rs:22:10 + | +22 | #[derive(Display)] + | ^^^^^^^ + | + = help: message: Missing doc comment on enum with #[prefix_enum_doc_attributes]. Please remove the attribute or add a doc comment to the enum itself. + +error[E0277]: `TestType` doesn't implement `Display` + --> $DIR/enum_prefix_missing.rs:32:37 + | +32 | static_assertions::assert_impl_all!(TestType: core::fmt::Display); + | ^^^^^^^^ `TestType` cannot be formatted with the default formatter + | + = help: the trait `Display` is not implemented for `TestType` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `assert_impl_all` + --> $DIR/enum_prefix_missing.rs:32:1 + | +32 | static_assertions::assert_impl_all!(TestType: core::fmt::Display); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the macro `static_assertions::assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/deps/crates/vendor/displaydoc/tests/no_std/multi_line.rs b/deps/crates/vendor/displaydoc/tests/no_std/multi_line.rs new file mode 100644 index 00000000000000..ca4215cdc3cb05 --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/no_std/multi_line.rs @@ -0,0 +1,37 @@ +#![cfg_attr(not(feature = "std"), allow(internal_features), feature(lang_items, start))] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg_attr(not(feature = "std"), start)] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +#[lang = "eh_personality"] +#[no_mangle] +#[cfg(not(feature = "std"))] +pub extern "C" fn rust_eh_personality() {} +#[panic_handler] +#[cfg(not(feature = "std"))] +fn panic(_info: &core::panic::PanicInfo) -> ! { + unsafe { + libc::abort(); + } +} + +use displaydoc::Display; + +/// this type is pretty swell +#[derive(Display)] +enum TestType { + /// This one is okay + Variant1, + + /// Multi + /// line + /// doc. + Variant2, +} + +static_assertions::assert_impl_all!(TestType: core::fmt::Display); + +#[cfg(feature = "std")] +fn main() {} diff --git a/deps/crates/vendor/displaydoc/tests/no_std/multi_line.stderr b/deps/crates/vendor/displaydoc/tests/no_std/multi_line.stderr new file mode 100644 index 00000000000000..f3d77b9e4b9747 --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/no_std/multi_line.stderr @@ -0,0 +1,22 @@ +error: proc-macro derive panicked + --> $DIR/multi_line.rs:23:10 + | +23 | #[derive(Display)] + | ^^^^^^^ + | + = help: message: Multi-line comments are disabled by default by displaydoc. Please consider using block doc comments (/** */) or adding the #[ignore_extra_doc_attributes] attribute to your type next to the derive. + +error[E0277]: `TestType` doesn't implement `Display` + --> $DIR/multi_line.rs:34:37 + | +34 | static_assertions::assert_impl_all!(TestType: core::fmt::Display); + | ^^^^^^^^ `TestType` cannot be formatted with the default formatter + | + = help: the trait `Display` is not implemented for `TestType` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `assert_impl_all` + --> $DIR/multi_line.rs:34:1 + | +34 | static_assertions::assert_impl_all!(TestType: core::fmt::Display); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the macro `static_assertions::assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/deps/crates/vendor/displaydoc/tests/no_std/multi_line_allow.rs b/deps/crates/vendor/displaydoc/tests/no_std/multi_line_allow.rs new file mode 100644 index 00000000000000..84676817ea72e2 --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/no_std/multi_line_allow.rs @@ -0,0 +1,38 @@ +#![cfg_attr(not(feature = "std"), allow(internal_features), feature(lang_items, start))] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg_attr(not(feature = "std"), start)] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +#[lang = "eh_personality"] +#[no_mangle] +#[cfg(not(feature = "std"))] +pub extern "C" fn rust_eh_personality() {} +#[panic_handler] +#[cfg(not(feature = "std"))] +fn panic(_info: &core::panic::PanicInfo) -> ! { + unsafe { + libc::abort(); + } +} + +use displaydoc::Display; + +/// this type is pretty swell +#[derive(Display)] +#[ignore_extra_doc_attributes] +enum TestType { + /// This one is okay + Variant1, + + /// Multi + /// line + /// doc. + Variant2, +} + +static_assertions::assert_impl_all!(TestType: core::fmt::Display); + +#[cfg(feature = "std")] +fn main() {} diff --git a/deps/crates/vendor/displaydoc/tests/no_std/with.rs b/deps/crates/vendor/displaydoc/tests/no_std/with.rs new file mode 100644 index 00000000000000..67aef473aa4c6b --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/no_std/with.rs @@ -0,0 +1,32 @@ +#![feature(lang_items, start)] +#![no_std] + +#[start] +#[cfg(not(feature = "std"))] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} + +#[lang = "eh_personality"] +#[no_mangle] +#[cfg(not(feature = "std"))] +pub extern "C" fn rust_eh_personality() {} + +#[panic_handler] +#[cfg(not(feature = "std"))] +fn panic(_info: &core::panic::PanicInfo) -> ! { + unsafe { + libc::abort(); + } +} + +#[cfg(feature = "std")] +fn main() {} + +use displaydoc::Display; + +/// this type is pretty swell +#[derive(Display)] +struct FakeType; + +static_assertions::assert_impl_all!(FakeType: core::fmt::Display); diff --git a/deps/crates/vendor/displaydoc/tests/no_std/without.rs b/deps/crates/vendor/displaydoc/tests/no_std/without.rs new file mode 100644 index 00000000000000..04d4b8fa695edb --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/no_std/without.rs @@ -0,0 +1,28 @@ +#![cfg_attr(not(feature = "std"), allow(internal_features), feature(lang_items, start))] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg_attr(not(feature = "std"), start)] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +#[lang = "eh_personality"] +#[no_mangle] +#[cfg(not(feature = "std"))] +pub extern "C" fn rust_eh_personality() {} +#[panic_handler] +#[cfg(not(feature = "std"))] +fn panic(_info: &core::panic::PanicInfo) -> ! { + unsafe { + libc::abort(); + } +} + +use displaydoc::Display; + +/// this type is pretty swell +struct FakeType; + +static_assertions::assert_impl_all!(FakeType: core::fmt::Display); + +#[cfg(feature = "std")] +fn main() {} diff --git a/deps/crates/vendor/displaydoc/tests/no_std/without.stderr b/deps/crates/vendor/displaydoc/tests/no_std/without.stderr new file mode 100644 index 00000000000000..a12edc4a38415b --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/no_std/without.stderr @@ -0,0 +1,22 @@ +warning: unused import: `displaydoc::Display` + --> $DIR/without.rs:20:5 + | +20 | use displaydoc::Display; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + +error[E0277]: `FakeType` doesn't implement `Display` + --> $DIR/without.rs:25:37 + | +25 | static_assertions::assert_impl_all!(FakeType: core::fmt::Display); + | ^^^^^^^^ `FakeType` cannot be formatted with the default formatter + | + = help: the trait `Display` is not implemented for `FakeType` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `assert_impl_all` + --> $DIR/without.rs:25:1 + | +25 | static_assertions::assert_impl_all!(FakeType: core::fmt::Display); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the macro `static_assertions::assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/deps/crates/vendor/displaydoc/tests/num_in_field.rs b/deps/crates/vendor/displaydoc/tests/num_in_field.rs new file mode 100644 index 00000000000000..9510f8206bd469 --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/num_in_field.rs @@ -0,0 +1,22 @@ +/// {foo1} {foo2} +#[derive(displaydoc::Display)] +pub struct Test { + foo1: String, + foo2: String, +} + +fn assert_display(input: T, expected: &'static str) { + let out = format!("{}", input); + assert_eq!(expected, out); +} + +#[test] +fn does_it_print() { + assert_display( + Test { + foo1: "hi".into(), + foo2: "hello".into(), + }, + "hi hello", + ); +} diff --git a/deps/crates/vendor/displaydoc/tests/std/enum_prefix.rs b/deps/crates/vendor/displaydoc/tests/std/enum_prefix.rs new file mode 100644 index 00000000000000..7e6abcce8f652d --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/std/enum_prefix.rs @@ -0,0 +1,36 @@ +#![cfg_attr(not(feature = "std"), feature(lang_items, start))] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg_attr(not(feature = "std"), start)] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +#[lang = "eh_personality"] +#[no_mangle] +#[cfg(not(feature = "std"))] +pub extern "C" fn rust_eh_personality() {} +#[panic_handler] +#[cfg(not(feature = "std"))] +fn panic(_info: &core::panic::PanicInfo) -> ! { + unsafe { + libc::abort(); + } +} + +use displaydoc::Display; + +/// this type is pretty swell +#[derive(Display)] +#[prefix_enum_doc_attributes] +enum TestType { + /// this variant is too + Variant1, + + /// this variant is two + Variant2, +} + +static_assertions::assert_impl_all!(TestType: core::fmt::Display); + +#[cfg(feature = "std")] +fn main() {} diff --git a/deps/crates/vendor/displaydoc/tests/std/enum_prefix_missing.rs b/deps/crates/vendor/displaydoc/tests/std/enum_prefix_missing.rs new file mode 100644 index 00000000000000..45c312b7e25804 --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/std/enum_prefix_missing.rs @@ -0,0 +1,35 @@ +#![cfg_attr(not(feature = "std"), feature(lang_items, start))] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg_attr(not(feature = "std"), start)] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +#[lang = "eh_personality"] +#[no_mangle] +#[cfg(not(feature = "std"))] +pub extern "C" fn rust_eh_personality() {} +#[panic_handler] +#[cfg(not(feature = "std"))] +fn panic(_info: &core::panic::PanicInfo) -> ! { + unsafe { + libc::abort(); + } +} + +use displaydoc::Display; + +#[derive(Display)] +#[prefix_enum_doc_attributes] +enum TestType { + /// this variant is too + Variant1, + + /// this variant is two + Variant2, +} + +static_assertions::assert_impl_all!(TestType: core::fmt::Display); + +#[cfg(feature = "std")] +fn main() {} diff --git a/deps/crates/vendor/displaydoc/tests/std/enum_prefix_missing.stderr b/deps/crates/vendor/displaydoc/tests/std/enum_prefix_missing.stderr new file mode 100644 index 00000000000000..09e1db68b4e8f5 --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/std/enum_prefix_missing.stderr @@ -0,0 +1,22 @@ +error: proc-macro derive panicked + --> $DIR/enum_prefix_missing.rs:22:10 + | +22 | #[derive(Display)] + | ^^^^^^^ + | + = help: message: Missing doc comment on enum with #[prefix_enum_doc_attributes]. Please remove the attribute or add a doc comment to the enum itself. + +error[E0277]: `TestType` doesn't implement `std::fmt::Display` + --> $DIR/enum_prefix_missing.rs:32:37 + | +32 | static_assertions::assert_impl_all!(TestType: core::fmt::Display); + | ^^^^^^^^ `TestType` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `TestType` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `assert_impl_all` + --> $DIR/enum_prefix_missing.rs:32:1 + | +32 | static_assertions::assert_impl_all!(TestType: core::fmt::Display); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the macro `static_assertions::assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/deps/crates/vendor/displaydoc/tests/std/multi_line.rs b/deps/crates/vendor/displaydoc/tests/std/multi_line.rs new file mode 100644 index 00000000000000..ca4215cdc3cb05 --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/std/multi_line.rs @@ -0,0 +1,37 @@ +#![cfg_attr(not(feature = "std"), allow(internal_features), feature(lang_items, start))] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg_attr(not(feature = "std"), start)] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +#[lang = "eh_personality"] +#[no_mangle] +#[cfg(not(feature = "std"))] +pub extern "C" fn rust_eh_personality() {} +#[panic_handler] +#[cfg(not(feature = "std"))] +fn panic(_info: &core::panic::PanicInfo) -> ! { + unsafe { + libc::abort(); + } +} + +use displaydoc::Display; + +/// this type is pretty swell +#[derive(Display)] +enum TestType { + /// This one is okay + Variant1, + + /// Multi + /// line + /// doc. + Variant2, +} + +static_assertions::assert_impl_all!(TestType: core::fmt::Display); + +#[cfg(feature = "std")] +fn main() {} diff --git a/deps/crates/vendor/displaydoc/tests/std/multi_line.stderr b/deps/crates/vendor/displaydoc/tests/std/multi_line.stderr new file mode 100644 index 00000000000000..c36a75db2a1000 --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/std/multi_line.stderr @@ -0,0 +1,22 @@ +error: proc-macro derive panicked + --> $DIR/multi_line.rs:23:10 + | +23 | #[derive(Display)] + | ^^^^^^^ + | + = help: message: Multi-line comments are disabled by default by displaydoc. Please consider using block doc comments (/** */) or adding the #[ignore_extra_doc_attributes] attribute to your type next to the derive. + +error[E0277]: `TestType` doesn't implement `std::fmt::Display` + --> $DIR/multi_line.rs:34:37 + | +34 | static_assertions::assert_impl_all!(TestType: core::fmt::Display); + | ^^^^^^^^ `TestType` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `TestType` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `assert_impl_all` + --> $DIR/multi_line.rs:34:1 + | +34 | static_assertions::assert_impl_all!(TestType: core::fmt::Display); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the macro `static_assertions::assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/deps/crates/vendor/displaydoc/tests/std/multi_line_allow.rs b/deps/crates/vendor/displaydoc/tests/std/multi_line_allow.rs new file mode 100644 index 00000000000000..e09e8fcf2cc9f1 --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/std/multi_line_allow.rs @@ -0,0 +1,38 @@ +#![cfg_attr(not(feature = "std"), feature(lang_items, start))] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg_attr(not(feature = "std"), start)] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +#[lang = "eh_personality"] +#[no_mangle] +#[cfg(not(feature = "std"))] +pub extern "C" fn rust_eh_personality() {} +#[panic_handler] +#[cfg(not(feature = "std"))] +fn panic(_info: &core::panic::PanicInfo) -> ! { + unsafe { + libc::abort(); + } +} + +use displaydoc::Display; + +/// this type is pretty swell +#[derive(Display)] +#[ignore_extra_doc_attributes] +enum TestType { + /// This one is okay + Variant1, + + /// Multi + /// line + /// doc. + Variant2, +} + +static_assertions::assert_impl_all!(TestType: core::fmt::Display); + +#[cfg(feature = "std")] +fn main() {} diff --git a/deps/crates/vendor/displaydoc/tests/std/multiple.rs b/deps/crates/vendor/displaydoc/tests/std/multiple.rs new file mode 100644 index 00000000000000..66d59b76903bb3 --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/std/multiple.rs @@ -0,0 +1,38 @@ +#![feature(lang_items, start)] +#![no_std] + +#[start] +#[cfg(not(feature = "std"))] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} + +#[lang = "eh_personality"] +#[no_mangle] +#[cfg(not(feature = "std"))] +pub extern "C" fn rust_eh_personality() {} + +#[panic_handler] +#[cfg(not(feature = "std"))] +fn panic(_info: &core::panic::PanicInfo) -> ! { + unsafe { + libc::abort(); + } +} + +#[cfg(feature = "std")] +fn main() {} + +use displaydoc::Display; + +/// this type is pretty swell +#[derive(Display)] +struct FakeType; + +static_assertions::assert_impl_all!(FakeType: core::fmt::Display); + +/// this type is pretty swell2 +#[derive(Display)] +struct FakeType2; + +static_assertions::assert_impl_all!(FakeType2: core::fmt::Display); diff --git a/deps/crates/vendor/displaydoc/tests/std/without.rs b/deps/crates/vendor/displaydoc/tests/std/without.rs new file mode 100644 index 00000000000000..04d4b8fa695edb --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/std/without.rs @@ -0,0 +1,28 @@ +#![cfg_attr(not(feature = "std"), allow(internal_features), feature(lang_items, start))] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg_attr(not(feature = "std"), start)] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +#[lang = "eh_personality"] +#[no_mangle] +#[cfg(not(feature = "std"))] +pub extern "C" fn rust_eh_personality() {} +#[panic_handler] +#[cfg(not(feature = "std"))] +fn panic(_info: &core::panic::PanicInfo) -> ! { + unsafe { + libc::abort(); + } +} + +use displaydoc::Display; + +/// this type is pretty swell +struct FakeType; + +static_assertions::assert_impl_all!(FakeType: core::fmt::Display); + +#[cfg(feature = "std")] +fn main() {} diff --git a/deps/crates/vendor/displaydoc/tests/std/without.stderr b/deps/crates/vendor/displaydoc/tests/std/without.stderr new file mode 100644 index 00000000000000..4f0d71316c95b5 --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/std/without.stderr @@ -0,0 +1,22 @@ +warning: unused import: `displaydoc::Display` + --> $DIR/without.rs:20:5 + | +20 | use displaydoc::Display; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + +error[E0277]: `FakeType` doesn't implement `std::fmt::Display` + --> $DIR/without.rs:25:37 + | +25 | static_assertions::assert_impl_all!(FakeType: core::fmt::Display); + | ^^^^^^^^ `FakeType` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `FakeType` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `assert_impl_all` + --> $DIR/without.rs:25:1 + | +25 | static_assertions::assert_impl_all!(FakeType: core::fmt::Display); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` + = note: this error originates in the macro `static_assertions::assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/deps/crates/vendor/displaydoc/tests/variantless.rs b/deps/crates/vendor/displaydoc/tests/variantless.rs new file mode 100644 index 00000000000000..7511bc7f0f11a1 --- /dev/null +++ b/deps/crates/vendor/displaydoc/tests/variantless.rs @@ -0,0 +1,6 @@ +use displaydoc::Display; + +#[derive(Display)] +enum EmptyInside {} + +static_assertions::assert_impl_all!(EmptyInside: core::fmt::Display); diff --git a/deps/crates/vendor/displaydoc/update-readme.sh b/deps/crates/vendor/displaydoc/update-readme.sh new file mode 100755 index 00000000000000..f67bfd566b6032 --- /dev/null +++ b/deps/crates/vendor/displaydoc/update-readme.sh @@ -0,0 +1,5 @@ +#! /usr/bin/env bash + +cargo readme > ./README.md +git add ./README.md +git commit -m "Update readme" || true diff --git a/deps/crates/vendor/icu_calendar/.cargo-checksum.json b/deps/crates/vendor/icu_calendar/.cargo-checksum.json new file mode 100644 index 00000000000000..24c90d80a0e937 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"133164f2c7c66053988a55b15ca4364f8ae03ae52836f2094630cde3eaf9351c","LICENSE":"f367c1b8e1aa262435251e442901da4607b4650e0e63a026f5044473ecfb90f2","README.md":"c51a6704a477876d2ebe131267a2a8023d3deaa3a2f208b9895dda192a2ff880","benches/convert.rs":"e266633d7a07629f1ab716084ee17aa8a919d9729ca482246406925a4e333369","benches/date.rs":"c614ace643c9121d92a742b03cd4748004fc99e708d012c0f49cc00994a294cd","benches/fixtures/datetimes.json":"ad8db74905ad8837b5e75ddc0bb51c1f277a8aa20e486d6927438a8fc7f094a6","benches/fixtures/mod.rs":"c927a527009af7d29bb16fdb893704178ac577ec2688baffa924f24da7f6b040","src/any_calendar.rs":"9437638ef54108b3aab83702eeb60ba02da17f18938787c9997cd60de766ab97","src/cal/buddhist.rs":"eac3e9ad36e24fdfc96b90775f7ef0e0ab3453f0c1ca4eb15559432910f275cf","src/cal/chinese.rs":"fb195492ca130c4264067b49a9b4145a32de6a33671cc66e4040daedde0e8949","src/cal/chinese_based.rs":"cd2d806da42fd9507109f5f8438d61f11a3a0cbbc94c0334afe60135f83fa879","src/cal/coptic.rs":"2462e5f644e3dbeeef8f907f35cb4768ec629360783e327b584bbc1f34d6a5ff","src/cal/dangi.rs":"a4e9e6f20f32b4e6900333ce5067301df0894892866ae035372b7c007fd58fc2","src/cal/ethiopian.rs":"34a9116c624c649909ff75dfe1920ea409d30b6d3ec7582ecce8f495abd66ed7","src/cal/gregorian.rs":"0f17844e2e5e7b6e318f1ab45c0dea9115826a3234a137861f8ef3938bf7287a","src/cal/hebrew.rs":"6d19e5219dd63e2ba7bac805653710b0cd84df758e7a85ab1944a8bef519e550","src/cal/hijri.rs":"a80e7c07c3fe8bced24716ef55e993f29f3ed191d93a44ee9d60b38329d9a164","src/cal/hijri/ummalqura_data.rs":"9e489ef9fd0fc7205213ca3c7ed1edb5523d8cf89d66d7e626a859b49dcbbe30","src/cal/indian.rs":"3d93134cd78b1e49c264eb0d345038e6448bf9ced1d0e1d3067b9cb6c4d8550a","src/cal/iso.rs":"101b81918a873cb58cdca2e98fa4349ca04c88b2cb6401c56244c7df44bebba9","src/cal/japanese.rs":"80ae17bb05141e2d91065f49b2aa8a41d37f6ecafed676ed94fa6b047fc44bc2","src/cal/julian.rs":"f5191def5442543bae6c1ae6a443ffd8ccd69c87361e21c035da52c190fac3d7","src/cal/mod.rs":"77450c6949e36e8496350d3664bd35aead278f4898ba543acfd8b1ca90ce848d","src/cal/persian.rs":"90b27551fe24de57d859c732ee034cc2cc4a60581472dc2ece174fa62f3deaef","src/cal/roc.rs":"c82aca51e24dd038cdc7a1b36d86b5c058f92753df20db8aac7282c057d6a079","src/calendar.rs":"976ef558a0574c717d214cb4d1464885ed79d0fc1f3668d775106f8eb66870be","src/calendar_arithmetic.rs":"f22cd14476b67e59c9b18d211c79bc2b9f0a5e9904d88add497cccd624c8d855","src/date.rs":"91a3b142b48783d6fd4e508bc9bf07026c668ec72f795c269379324507d230d3","src/duration.rs":"65bde57c0af6bd8b146b92bb45bb14f661c918defe6bd388b51569503ec8bd33","src/error.rs":"c01e5adebd4be2b6287173a02623a2ff20afa2269d9e2ba4ecc01b643c7189cf","src/ixdtf.rs":"691dd80767b1d9f4f5aa2202303b49df38f2cf6699c6976ba44d5aae74fa3073","src/lib.rs":"2a10cdd624c9dbce2d8490acaf7f115ce96219bf659dfcc0d6181c132968ed19","src/provider.rs":"89aabfc8fdae13f8e1d7ebfa14f54c9f0249cc17c4436ba24766873a5f4ad128","src/provider/chinese_based.rs":"75fa2be19454674c892b2ac4e54c2b08fbb7fdfcad091ae338c30a8693be9396","src/provider/hijri.rs":"bc2d77aae6c347ba2700381eb64abf1c8118a81a2ccd6f66be6eb5b8f4c10a7c","src/tests/continuity_test.rs":"d3c97c72efc0b23d0cdf55e2911f4962fa0f55e8261019a929f2fc7d8c6a680b","src/tests/mod.rs":"0925663ff594ebac9892d652d3576a9bc1ed938b2e4ee7a6d23a641899e8bf5a","src/types.rs":"fced40c1477ca7d66edbea8597c21bf233deb7d3fe0e72addbff03a6291862fc","src/week.rs":"803b68991584f3cee05bf051db601c0207f266b9139fa27731d0bc55b1cae88d"},"package":"362941891d17750e05cd8fdfca4a89a86552825d625a937020ee1a65580da1f9"} \ No newline at end of file diff --git a/deps/crates/vendor/icu_calendar/Cargo.toml b/deps/crates/vendor/icu_calendar/Cargo.toml new file mode 100644 index 00000000000000..79be24ad34b964 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/Cargo.toml @@ -0,0 +1,168 @@ +# 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.82" +name = "icu_calendar" +version = "2.0.6" +authors = ["The ICU4X Project Developers"] +build = false +include = [ + "data/**/*", + "src/**/*", + "examples/**/*", + "benches/**/*", + "tests/**/*", + "Cargo.toml", + "LICENSE", + "README.md", + "build.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Date APIs for Gregorian and non-Gregorian calendars" +homepage = "https://icu4x.unicode.org" +readme = "README.md" +categories = ["internationalization"] +license = "Unicode-3.0" +repository = "https://github.com/unicode-org/icu4x" + +[package.metadata.docs.rs] +all-features = true + +[features] +alloc = [] +compiled_data = [ + "dep:icu_calendar_data", + "dep:icu_locale", + "icu_locale?/compiled_data", + "icu_provider/baked", +] +datagen = [ + "serde", + "dep:databake", + "zerovec/databake", + "tinystr/databake", + "alloc", + "icu_provider/export", +] +default = [ + "compiled_data", + "ixdtf", +] +ixdtf = ["dep:ixdtf"] +logging = ["calendrical_calculations/logging"] +serde = [ + "dep:serde", + "zerovec/serde", + "tinystr/serde", + "icu_provider/serde", +] + +[lib] +name = "icu_calendar" +path = "src/lib.rs" + +[[bench]] +name = "convert" +path = "benches/convert.rs" +harness = false + +[[bench]] +name = "date" +path = "benches/date.rs" +harness = false + +[dependencies.calendrical_calculations] +version = "0.2.2" +default-features = false + +[dependencies.databake] +version = "0.2.0" +features = ["derive"] +optional = true +default-features = false + +[dependencies.displaydoc] +version = "0.2.3" +default-features = false + +[dependencies.icu_calendar_data] +version = "~2.0.0" +optional = true +default-features = false + +[dependencies.icu_locale] +version = "~2.0.0" +optional = true +default-features = false + +[dependencies.icu_locale_core] +version = "2.0.0" +features = ["alloc"] +default-features = false + +[dependencies.icu_provider] +version = "2.0.0" +features = ["alloc"] +default-features = false + +[dependencies.ixdtf] +version = "0.5.0" +optional = true +default-features = false + +[dependencies.serde] +version = "1.0.110" +features = [ + "derive", + "alloc", +] +optional = true +default-features = false + +[dependencies.tinystr] +version = "0.8.0" +features = [ + "alloc", + "zerovec", +] +default-features = false + +[dependencies.writeable] +version = "0.6.0" +default-features = false + +[dependencies.zerovec] +version = "0.11.1" +features = ["derive"] +default-features = false + +[dev-dependencies.serde] +version = "1.0.110" +features = [ + "derive", + "alloc", +] +default-features = false + +[dev-dependencies.serde_json] +version = "1.0.45" + +[dev-dependencies.simple_logger] +version = "5.0.0" + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies.criterion] +version = "0.5.0" diff --git a/deps/crates/vendor/icu_calendar/LICENSE b/deps/crates/vendor/icu_calendar/LICENSE new file mode 100644 index 00000000000000..c9be6012c53792 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/LICENSE @@ -0,0 +1,46 @@ +UNICODE LICENSE V3 + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 2020-2024 Unicode, Inc. + +NOTICE TO USER: Carefully read the following legal agreement. BY +DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR +SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT +DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of data files and any associated documentation (the "Data Files") or +software and any associated documentation (the "Software") to deal in the +Data Files or Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, and/or sell +copies of the Data Files or Software, and to permit persons to whom the +Data Files or Software are furnished to do so, provided that either (a) +this copyright and permission notice appear with all copies of the Data +Files or Software, or (b) this copyright and permission notice appear in +associated Documentation. + +THE DATA FILES AND SOFTWARE ARE 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 OF +THIRD PARTY RIGHTS. + +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE +BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA +FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in these Data Files or Software without prior written +authorization of the copyright holder. + +SPDX-License-Identifier: Unicode-3.0 + +— + +Portions of ICU4X may have been adapted from ICU4C and/or ICU4J. +ICU 1.8.1 to ICU 57.1 © 1995-2016 International Business Machines Corporation and others. diff --git a/deps/crates/vendor/icu_calendar/README.md b/deps/crates/vendor/icu_calendar/README.md new file mode 100644 index 00000000000000..fa2e1d6fd5eb93 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/README.md @@ -0,0 +1,79 @@ +# icu_calendar [![crates.io](https://img.shields.io/crates/v/icu_calendar)](https://crates.io/crates/icu_calendar) + + + +Types for dealing with dates and custom calendars. + +This module is published as its own crate ([`icu_calendar`](https://docs.rs/icu_calendar/latest/icu_calendar/)) +and as part of the [`icu`](https://docs.rs/icu/latest/icu/) crate. See the latter for more details on the ICU4X project. +The [`types`] module has a lot of common types for dealing with dates. + +[`Calendar`] is a trait that allows one to define custom calendars, and [`Date`] +can represent dates for arbitrary calendars. + +The [`Iso`] and [`Gregorian`] types are implementations for the ISO and +Gregorian calendars respectively. Further calendars can be found in the [`cal`] module. + +Most interaction with this crate will be done via the [`Date`] type. + +Some of the algorithms implemented here are based on +Dershowitz, Nachum, and Edward M. Reingold. _Calendrical calculations_. Cambridge University Press, 2008. +with associated Lisp code found at . + +## Examples + +Examples of date manipulation using `Date` object. `Date` objects are useful +for working with dates, encompassing information about the day, month, year, +as well as the calendar type. + +```rust +use icu::calendar::{types::Weekday, Date}; + +// Creating ISO date: 1992-09-02. +let mut date_iso = Date::try_new_iso(1992, 9, 2) + .expect("Failed to initialize ISO Date instance."); + +assert_eq!(date_iso.day_of_week(), Weekday::Wednesday); +assert_eq!(date_iso.era_year().year, 1992); +assert_eq!(date_iso.month().ordinal, 9); +assert_eq!(date_iso.day_of_month().0, 2); + +// Answering questions about days in month and year. +assert_eq!(date_iso.days_in_year(), 366); +assert_eq!(date_iso.days_in_month(), 30); +``` + +Example of converting an ISO date across Indian and Buddhist calendars. + +```rust +use icu::calendar::cal::{Buddhist, Indian}; +use icu::calendar::Date; + +// Creating ISO date: 1992-09-02. +let mut date_iso = Date::try_new_iso(1992, 9, 2) + .expect("Failed to initialize ISO Date instance."); + +assert_eq!(date_iso.era_year().year, 1992); +assert_eq!(date_iso.month().ordinal, 9); +assert_eq!(date_iso.day_of_month().0, 2); + +// Conversion into Indian calendar: 1914-08-02. +let date_indian = date_iso.to_calendar(Indian); +assert_eq!(date_indian.era_year().year, 1914); +assert_eq!(date_indian.month().ordinal, 6); +assert_eq!(date_indian.day_of_month().0, 11); + +// Conversion into Buddhist calendar: 2535-09-02. +let date_buddhist = date_iso.to_calendar(Buddhist); +assert_eq!(date_buddhist.era_year().year, 2535); +assert_eq!(date_buddhist.month().ordinal, 9); +assert_eq!(date_buddhist.day_of_month().0, 2); +``` + +[`ICU4X`]: ../icu/index.html + + + +## More Information + +For more information on development, authorship, contributing etc. please visit [`ICU4X home page`](https://github.com/unicode-org/icu4x). diff --git a/deps/crates/vendor/icu_calendar/benches/convert.rs b/deps/crates/vendor/icu_calendar/benches/convert.rs new file mode 100644 index 00000000000000..90b18f256cc8d6 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/benches/convert.rs @@ -0,0 +1,106 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +mod fixtures; + +use criterion::{ + black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, +}; +use icu_calendar::{Calendar, Date, Ref}; + +fn bench_calendar( + group: &mut BenchmarkGroup, + name: &str, + calendar: C, +) { + let iso = Date::try_new_iso(2023, 8, 16).unwrap(); + group.bench_function(name, |b| { + b.iter(|| { + let converted = black_box(iso).to_calendar(Ref(&calendar)); + let year = black_box(converted.year()); + let month = black_box(converted.month()); + let day = black_box(converted.day_of_month()); + black_box((converted, year, month, day)) + }) + }); +} + +fn convert_benches(c: &mut Criterion) { + let mut group = c.benchmark_group("convert"); + + bench_calendar(&mut group, "calendar/iso", icu::calendar::cal::Iso); + + bench_calendar( + &mut group, + "calendar/buddhist", + icu::calendar::cal::Buddhist, + ); + + bench_calendar(&mut group, "calendar/coptic", icu::calendar::cal::Coptic); + + bench_calendar( + &mut group, + "calendar/ethiopic", + icu::calendar::cal::Ethiopian::new(), + ); + + bench_calendar(&mut group, "calendar/indian", icu::calendar::cal::Indian); + + bench_calendar(&mut group, "calendar/julian", icu::calendar::cal::Julian); + + bench_calendar( + &mut group, + "calendar/chinese_calculating", + icu::calendar::cal::Chinese::new_always_calculating(), + ); + + bench_calendar( + &mut group, + "calendar/chinese_cached", + icu::calendar::cal::Chinese::new(), + ); + + bench_calendar( + &mut group, + "calendar/gregorian", + icu::calendar::cal::Gregorian, + ); + + bench_calendar(&mut group, "calendar/hebrew", icu::calendar::cal::Hebrew); + + bench_calendar( + &mut group, + "calendar/islamic/observational", + icu::calendar::cal::HijriSimulated::new_mecca_always_calculating(), + ); + + bench_calendar( + &mut group, + "calendar/islamic/civil", + icu::calendar::cal::HijriTabular::new( + icu::calendar::cal::HijriTabularLeapYears::TypeII, + icu::calendar::cal::HijriTabularEpoch::Friday, + ), + ); + + bench_calendar( + &mut group, + "calendar/islamic/ummalqura", + icu::calendar::cal::HijriUmmAlQura::new(), + ); + + bench_calendar( + &mut group, + "calendar/islamic/tabular", + icu::calendar::cal::HijriTabular::new( + icu::calendar::cal::HijriTabularLeapYears::TypeII, + icu::calendar::cal::HijriTabularEpoch::Thursday, + ), + ); + + group.finish(); +} + +criterion_group!(benches, convert_benches); +criterion_main!(benches); diff --git a/deps/crates/vendor/icu_calendar/benches/date.rs b/deps/crates/vendor/icu_calendar/benches/date.rs new file mode 100644 index 00000000000000..4cd5e5fecd22b9 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/benches/date.rs @@ -0,0 +1,268 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +mod fixtures; + +use criterion::{ + black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, +}; +use fixtures::DateFixture; +use icu_calendar::{AsCalendar, Calendar, Date, DateDuration}; + +fn bench_date(date: &mut Date) { + // black_box used to avoid compiler optimization. + // Arithmetic + date.add(DateDuration::new( + black_box(1), + black_box(2), + black_box(3), + black_box(4), + )); + + // Retrieving vals + let _ = black_box(date.year()); + let _ = black_box(date.month()); + let _ = black_box(date.day_of_month()); + + // Conversion to ISO. + let _ = black_box(date.to_iso()); +} + +fn bench_calendar( + group: &mut BenchmarkGroup, + name: &str, + fxs: &DateFixture, + calendar: C, + calendar_date_init: impl Fn(i32, u8, u8) -> Date, +) { + group.bench_function(name, |b| { + b.iter(|| { + for fx in &fxs.0 { + // Instantion from int + let mut instantiated_date_calendar = calendar_date_init(fx.year, fx.month, fx.day); + + // Conversion from ISO + let date_iso = Date::try_new_iso(fx.year, fx.month, fx.day).unwrap(); + let mut converted_date_calendar = Date::new_from_iso(date_iso, calendar.clone()); + + bench_date(&mut instantiated_date_calendar); + bench_date(&mut converted_date_calendar); + } + }) + }); +} + +fn date_benches(c: &mut Criterion) { + let mut group = c.benchmark_group("date"); + let fxs = serde_json::from_str::(include_str!("fixtures/datetimes.json")).unwrap(); + + bench_calendar( + &mut group, + "calendar/overview", + &fxs, + icu::calendar::cal::Iso, + |y, m, d| Date::try_new_iso(y, m, d).unwrap(), + ); + + bench_calendar( + &mut group, + "calendar/buddhist", + &fxs, + icu::calendar::cal::Buddhist, + |y, m, d| Date::try_new_buddhist(y, m, d).unwrap(), + ); + + bench_calendar( + &mut group, + "calendar/coptic", + &fxs, + icu::calendar::cal::Coptic, + |y, m, d| Date::try_new_coptic(y, m, d).unwrap(), + ); + + bench_calendar( + &mut group, + "calendar/ethiopic", + &fxs, + icu::calendar::cal::Ethiopian::new(), + |y, m, d| { + Date::try_new_ethiopian(icu::calendar::cal::EthiopianEraStyle::AmeteMihret, y, m, d) + .unwrap() + }, + ); + + bench_calendar( + &mut group, + "calendar/indian", + &fxs, + icu::calendar::cal::Indian, + |y, m, d| Date::try_new_indian(y, m, d).unwrap(), + ); + + bench_calendar( + &mut group, + "calendar/persian", + &fxs, + icu::calendar::cal::Persian, + |y, m, d| Date::try_new_persian(y, m, d).unwrap(), + ); + + bench_calendar( + &mut group, + "calendar/roc", + &fxs, + icu::calendar::cal::Roc, + |y, m, d| Date::try_new_roc(y, m, d).unwrap(), + ); + + bench_calendar( + &mut group, + "calendar/julian", + &fxs, + icu::calendar::cal::Julian, + |y, m, d| Date::try_new_julian(y, m, d).unwrap(), + ); + + bench_calendar( + &mut group, + "calendar/chinese_calculating", + &fxs, + icu::calendar::cal::Chinese::new_always_calculating(), + |y, m, d| { + Date::try_new_chinese_with_calendar( + y, + m, + d, + icu::calendar::cal::Chinese::new_always_calculating(), + ) + .unwrap() + }, + ); + + bench_calendar( + &mut group, + "calendar/chinese_cached", + &fxs, + icu::calendar::cal::Chinese::new(), + |y, m, d| { + Date::try_new_chinese_with_calendar(y, m, d, icu::calendar::cal::Chinese::new()) + .unwrap() + }, + ); + + bench_calendar( + &mut group, + "calendar/dangi_calculating", + &fxs, + icu::calendar::cal::Dangi::new_always_calculating(), + |y, m, d| { + Date::try_new_dangi_with_calendar( + y, + m, + d, + icu::calendar::cal::Dangi::new_always_calculating(), + ) + .unwrap() + }, + ); + + bench_calendar( + &mut group, + "calendar/dangi_cached", + &fxs, + icu::calendar::cal::Dangi::new(), + |y, m, d| { + Date::try_new_dangi_with_calendar(y, m, d, icu::calendar::cal::Dangi::new()).unwrap() + }, + ); + + bench_calendar( + &mut group, + "calendar/hebrew", + &fxs, + icu::calendar::cal::Hebrew, + |y, m, d| Date::try_new_hebrew(y, m, d).unwrap(), + ); + + bench_calendar( + &mut group, + "calendar/gregorian", + &fxs, + icu::calendar::cal::Gregorian, + |y, m, d| Date::try_new_gregorian(y, m, d).unwrap(), + ); + + bench_calendar( + &mut group, + "calendar/islamic/civil", + &fxs, + icu::calendar::cal::HijriTabular::new( + icu::calendar::cal::HijriTabularLeapYears::TypeII, + icu::calendar::cal::HijriTabularEpoch::Friday, + ), + |y, m, d| { + Date::try_new_hijri_tabular_with_calendar( + y, + m, + d, + icu::calendar::cal::HijriTabular::new( + icu::calendar::cal::HijriTabularLeapYears::TypeII, + icu::calendar::cal::HijriTabularEpoch::Friday, + ), + ) + .unwrap() + }, + ); + + bench_calendar( + &mut group, + "calendar/islamic/tabular", + &fxs, + icu::calendar::cal::HijriTabular::new( + icu::calendar::cal::HijriTabularLeapYears::TypeII, + icu::calendar::cal::HijriTabularEpoch::Thursday, + ), + |y, m, d| { + Date::try_new_hijri_tabular_with_calendar( + y, + m, + d, + icu::calendar::cal::HijriTabular::new( + icu::calendar::cal::HijriTabularLeapYears::TypeII, + icu::calendar::cal::HijriTabularEpoch::Thursday, + ), + ) + .unwrap() + }, + ); + + bench_calendar( + &mut group, + "calendar/islamic/ummalqura", + &fxs, + icu::calendar::cal::HijriUmmAlQura::new(), + |y, m, d| Date::try_new_ummalqura(y, m, d).unwrap(), + ); + + bench_calendar( + &mut group, + "calendar/islamic/observational", + &fxs, + icu::calendar::cal::HijriSimulated::new_mecca_always_calculating(), + |y, m, d| { + Date::try_new_simulated_hijri_with_calendar( + y, + m, + d, + icu::calendar::cal::HijriSimulated::new_mecca_always_calculating(), + ) + .unwrap() + }, + ); + + group.finish(); +} + +criterion_group!(benches, date_benches); +criterion_main!(benches); diff --git a/deps/crates/vendor/icu_calendar/benches/fixtures/datetimes.json b/deps/crates/vendor/icu_calendar/benches/fixtures/datetimes.json new file mode 100644 index 00000000000000..08378b4dc4be3f --- /dev/null +++ b/deps/crates/vendor/icu_calendar/benches/fixtures/datetimes.json @@ -0,0 +1,82 @@ +[ + { + "year": 1990, + "month": 1, + "day": 20, + "hour": 14, + "minute": 12, + "second": 1 + }, + { + "year": 1996, + "month": 3, + "day": 20, + "hour": 2, + "minute": 55, + "second": 12 + }, + { + "year": 2000, + "month": 3, + "day": 23, + "hour": 1, + "minute": 34, + "second": 35 + }, + { + "year": 2010, + "month": 5, + "day": 10, + "hour": 9, + "minute": 31, + "second": 12 + }, + { + "year": 2020, + "month": 6, + "day": 13, + "hour": 23, + "minute": 1, + "second": 12 + }, + { + "year": 1881, + "month": 6, + "day": 10, + "hour": 3, + "minute": 27, + "second": 59 + }, + { + "year": 1720, + "month": 2, + "day": 1, + "hour": 13, + "minute": 24, + "second": 13 + }, + { + "year": 1630, + "month": 3, + "day": 4, + "hour": 3, + "minute": 1, + "second": 1 + }, + { + "year": 1540, + "month": 3, + "day": 4, + "hour": 3, + "minute": 2, + "second": 12 + }, + { + "year": 1024, + "month": 5, + "day": 10, + "hour": 19, + "minute": 31, + "second": 2 + } +] \ No newline at end of file diff --git a/deps/crates/vendor/icu_calendar/benches/fixtures/mod.rs b/deps/crates/vendor/icu_calendar/benches/fixtures/mod.rs new file mode 100644 index 00000000000000..c4bc9336ea0aee --- /dev/null +++ b/deps/crates/vendor/icu_calendar/benches/fixtures/mod.rs @@ -0,0 +1,18 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct DateFixture(pub Vec); + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Test { + pub year: i32, + pub month: u8, + pub day: u8, + pub hour: u8, + pub minute: u8, + pub second: u8, +} diff --git a/deps/crates/vendor/icu_calendar/src/any_calendar.rs b/deps/crates/vendor/icu_calendar/src/any_calendar.rs new file mode 100644 index 00000000000000..6ce6ed1164e6bd --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/any_calendar.rs @@ -0,0 +1,1992 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! Module for working with multiple calendars at once + +use crate::cal::hijri::HijriSimulatedLocation; +use crate::cal::iso::IsoDateInner; +use crate::cal::{ + Buddhist, Chinese, Coptic, Dangi, Ethiopian, EthiopianEraStyle, Gregorian, Hebrew, + HijriSimulated, HijriTabular, HijriTabularEpoch, HijriTabularLeapYears, HijriUmmAlQura, Indian, + Iso, Japanese, JapaneseExtended, Persian, Roc, +}; +use crate::error::DateError; +use crate::types::YearInfo; +use crate::{types, AsCalendar, Calendar, Date, DateDuration, DateDurationUnit, Ref}; + +use crate::preferences::{CalendarAlgorithm, HijriCalendarAlgorithm}; +use icu_locale_core::preferences::define_preferences; +use icu_locale_core::subtags::region; +use icu_provider::prelude::*; + +use core::fmt; + +define_preferences!( + /// The preferences for calendars formatting. + [Copy] + CalendarPreferences, + { + /// The user's preferred calendar system. + calendar_algorithm: CalendarAlgorithm + } +); + +/// This is a calendar that encompasses all formattable calendars supported by this crate +/// +/// This allows for the construction of [`Date`] objects that have their calendar known at runtime. +/// +/// This can be constructed by calling `.into()` on a concrete calendar type if the calendar type is known at +/// compile time. When the type is known at runtime, the [`AnyCalendar::new()`] and sibling methods may be used. +/// +/// [`Date`] can also be converted to [`AnyCalendar`]-compatible ones +/// via [`Date::to_any()`](crate::Date::to_any()). +/// +/// There are many ways of constructing an AnyCalendar'd date: +/// ``` +/// use icu::calendar::{AnyCalendar, AnyCalendarKind, Date, cal::Japanese, types::MonthCode}; +/// use icu::locale::locale; +/// use tinystr::tinystr; +/// # use std::rc::Rc; +/// +/// let locale = locale!("en-u-ca-japanese"); // English with the Japanese calendar +/// +/// let calendar = AnyCalendar::new(AnyCalendarKind::new(locale.into())); +/// let calendar = Rc::new(calendar); // Avoid cloning it each time +/// // If everything is a local reference, you may use icu::calendar::Ref instead. +/// +/// // construct from era code, year, month code, day, and a calendar +/// // This is March 28, 15 Heisei +/// let manual_date = Date::try_new_from_codes(Some("heisei"), 15, MonthCode(tinystr!(4, "M03")), 28, calendar.clone()) +/// .expect("Failed to construct Date manually"); +/// +/// +/// // construct another date by converting from ISO +/// let iso_date = Date::try_new_iso(2020, 9, 1) +/// .expect("Failed to construct ISO Date."); +/// let iso_converted = iso_date.to_calendar(calendar); +/// +/// // Construct a date in the appropriate typed calendar and convert +/// let japanese_calendar = Japanese::new(); +/// let japanese_date = Date::try_new_japanese_with_calendar("heisei", 15, 3, 28, +/// japanese_calendar).unwrap(); +/// // This is a Date +/// let any_japanese_date = japanese_date.to_any(); +/// ``` +#[derive(Debug, Clone)] +#[non_exhaustive] +pub enum AnyCalendar { + /// A [`Buddhist`] calendar + Buddhist(Buddhist), + /// A [`Chinese`] calendar + Chinese(Chinese), + /// A [`Coptic`] calendar + Coptic(Coptic), + /// A [`Dangi`] calendar + Dangi(Dangi), + /// An [`Ethiopian`] calendar + Ethiopian(Ethiopian), + /// A [`Gregorian`] calendar + Gregorian(Gregorian), + /// A [`Hebrew`] calendar + Hebrew(Hebrew), + /// An [`Indian`] calendar + Indian(Indian), + /// A [`HijriTabular`] calendar + HijriTabular(HijriTabular), + /// A [`HijriSimulated`] calendar + HijriSimulated(HijriSimulated), + /// A [`HijriUmmAlQura`] calendar + HijriUmmAlQura(HijriUmmAlQura), + /// An [`Iso`] calendar + Iso(Iso), + /// A [`Japanese`] calendar + Japanese(Japanese), + /// A [`JapaneseExtended`] calendar + JapaneseExtended(JapaneseExtended), + /// A [`Persian`] calendar + Persian(Persian), + /// A [`Roc`] calendar + Roc(Roc), +} + +// TODO(#3469): Decide on the best way to implement Ord. +/// The inner date type for [`AnyCalendar`] +#[derive(Clone, PartialEq, Eq, Debug, Copy)] +#[non_exhaustive] +pub enum AnyDateInner { + /// A date for a [`Buddhist`] calendar + Buddhist(::DateInner), + /// A date for a [`Chinese`] calendar + Chinese(::DateInner), + /// A date for a [`Coptic`] calendar + Coptic(::DateInner), + /// A date for a [`Dangi`] calendar + Dangi(::DateInner), + /// A date for an [`Ethiopian`] calendar + Ethiopian(::DateInner), + /// A date for a [`Gregorian`] calendar + Gregorian(::DateInner), + /// A date for a [`Hebrew`] calendar + Hebrew(::DateInner), + /// A date for an [`Indian`] calendar + Indian(::DateInner), + /// A date for a [`HijriTabular`] calendar + HijriTabular( + ::DateInner, + HijriTabularLeapYears, + HijriTabularEpoch, + ), + /// A date for a [`HijriSimulated`] calendar + HijriSimulated(::DateInner), + /// A date for a [`HijriUmmAlQura`] calendar + HijriUmmAlQura(::DateInner), + /// A date for an [`Iso`] calendar + Iso(::DateInner), + /// A date for a [`Japanese`] calendar + Japanese(::DateInner), + /// A date for a [`JapaneseExtended`] calendar + JapaneseExtended(::DateInner), + /// A date for a [`Persian`] calendar + Persian(::DateInner), + /// A date for a [`Roc`] calendar + Roc(::DateInner), +} + +macro_rules! match_cal_and_date { + (match ($cal:ident, $date:ident): ($cal_matched:ident, $date_matched:ident) => $e:expr) => { + match ($cal, $date) { + (&Self::Buddhist(ref $cal_matched), &AnyDateInner::Buddhist(ref $date_matched)) => $e, + (&Self::Chinese(ref $cal_matched), &AnyDateInner::Chinese(ref $date_matched)) => $e, + (&Self::Coptic(ref $cal_matched), &AnyDateInner::Coptic(ref $date_matched)) => $e, + (&Self::Dangi(ref $cal_matched), &AnyDateInner::Dangi(ref $date_matched)) => $e, + (&Self::Ethiopian(ref $cal_matched), &AnyDateInner::Ethiopian(ref $date_matched)) => $e, + (&Self::Gregorian(ref $cal_matched), &AnyDateInner::Gregorian(ref $date_matched)) => $e, + (&Self::Hebrew(ref $cal_matched), &AnyDateInner::Hebrew(ref $date_matched)) => $e, + (&Self::Indian(ref $cal_matched), &AnyDateInner::Indian(ref $date_matched)) => $e, + ( + &Self::HijriTabular(ref $cal_matched), + &AnyDateInner::HijriTabular(ref $date_matched, leap_years, epoch), + ) if $cal_matched.epoch == epoch && $cal_matched.leap_years == leap_years => $e, + ( + &Self::HijriSimulated(ref $cal_matched), + &AnyDateInner::HijriSimulated(ref $date_matched), + ) => $e, + ( + &Self::HijriUmmAlQura(ref $cal_matched), + &AnyDateInner::HijriUmmAlQura(ref $date_matched), + ) => $e, + (&Self::Iso(ref $cal_matched), &AnyDateInner::Iso(ref $date_matched)) => $e, + (&Self::Japanese(ref $cal_matched), &AnyDateInner::Japanese(ref $date_matched)) => $e, + ( + &Self::JapaneseExtended(ref $cal_matched), + &AnyDateInner::JapaneseExtended(ref $date_matched), + ) => $e, + (&Self::Persian(ref $cal_matched), &AnyDateInner::Persian(ref $date_matched)) => $e, + (&Self::Roc(ref $cal_matched), &AnyDateInner::Roc(ref $date_matched)) => $e, + _ => panic!( + "Found AnyCalendar with mixed calendar type {:?} and date type {:?}!", + $cal.kind().debug_name(), + $date.kind().debug_name() + ), + } + }; +} + +macro_rules! match_cal { + (match $cal:ident: ($cal_matched:ident) => $e:expr) => { + match $cal { + &Self::Buddhist(ref $cal_matched) => AnyDateInner::Buddhist($e), + &Self::Chinese(ref $cal_matched) => AnyDateInner::Chinese($e), + &Self::Coptic(ref $cal_matched) => AnyDateInner::Coptic($e), + &Self::Dangi(ref $cal_matched) => AnyDateInner::Dangi($e), + &Self::Ethiopian(ref $cal_matched) => AnyDateInner::Ethiopian($e), + &Self::Gregorian(ref $cal_matched) => AnyDateInner::Gregorian($e), + &Self::Hebrew(ref $cal_matched) => AnyDateInner::Hebrew($e), + &Self::Indian(ref $cal_matched) => AnyDateInner::Indian($e), + &Self::HijriSimulated(ref $cal_matched) => AnyDateInner::HijriSimulated($e), + &Self::HijriTabular(ref $cal_matched) => { + AnyDateInner::HijriTabular($e, $cal_matched.leap_years, $cal_matched.epoch) + } + &Self::HijriUmmAlQura(ref $cal_matched) => AnyDateInner::HijriUmmAlQura($e), + &Self::Iso(ref $cal_matched) => AnyDateInner::Iso($e), + &Self::Japanese(ref $cal_matched) => AnyDateInner::Japanese($e), + &Self::JapaneseExtended(ref $cal_matched) => AnyDateInner::JapaneseExtended($e), + &Self::Persian(ref $cal_matched) => AnyDateInner::Persian($e), + &Self::Roc(ref $cal_matched) => AnyDateInner::Roc($e), + } + }; +} + +impl crate::cal::scaffold::UnstableSealed for AnyCalendar {} +impl Calendar for AnyCalendar { + type DateInner = AnyDateInner; + type Year = YearInfo; + + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + Ok(match_cal!(match self: (c) => c.from_codes(era, year, month_code, day)?)) + } + + fn from_iso(&self, iso: IsoDateInner) -> AnyDateInner { + match_cal!(match self: (c) => c.from_iso(iso)) + } + + fn from_rata_die(&self, rd: calendrical_calculations::rata_die::RataDie) -> Self::DateInner { + match_cal!(match self: (c) => c.from_rata_die(rd)) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> calendrical_calculations::rata_die::RataDie { + match_cal_and_date!(match (self, date): (c, d) => c.to_rata_die(d)) + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + match_cal_and_date!(match (self, date): (c, d) => c.to_iso(d)) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + match_cal_and_date!(match (self, date): (c, d) => c.months_in_year(d)) + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + match_cal_and_date!(match (self, date): (c, d) => c.days_in_year(d)) + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + match_cal_and_date!(match (self, date): (c, d) => c.days_in_month(d)) + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + match (self, date) { + (Self::Buddhist(c), AnyDateInner::Buddhist(ref mut d)) => { + c.offset_date(d, offset.cast_unit()) + } + (Self::Chinese(c), AnyDateInner::Chinese(ref mut d)) => { + c.offset_date(d, offset.cast_unit()) + } + (Self::Coptic(c), AnyDateInner::Coptic(ref mut d)) => { + c.offset_date(d, offset.cast_unit()) + } + (Self::Dangi(c), AnyDateInner::Dangi(ref mut d)) => { + c.offset_date(d, offset.cast_unit()) + } + (Self::Ethiopian(c), AnyDateInner::Ethiopian(ref mut d)) => { + c.offset_date(d, offset.cast_unit()) + } + (Self::Gregorian(c), AnyDateInner::Gregorian(ref mut d)) => { + c.offset_date(d, offset.cast_unit()) + } + (Self::Hebrew(c), AnyDateInner::Hebrew(ref mut d)) => { + c.offset_date(d, offset.cast_unit()) + } + (Self::Indian(c), AnyDateInner::Indian(ref mut d)) => { + c.offset_date(d, offset.cast_unit()) + } + ( + Self::HijriTabular(c), + &mut AnyDateInner::HijriTabular(ref mut d, leap_years, epoch), + ) if c.epoch == epoch && c.leap_years == leap_years => { + c.offset_date(d, offset.cast_unit()) + } + (Self::HijriSimulated(c), AnyDateInner::HijriSimulated(ref mut d)) => { + c.offset_date(d, offset.cast_unit()) + } + (Self::HijriUmmAlQura(c), AnyDateInner::HijriUmmAlQura(ref mut d)) => { + c.offset_date(d, offset.cast_unit()) + } + (Self::Iso(c), AnyDateInner::Iso(ref mut d)) => c.offset_date(d, offset.cast_unit()), + (Self::Japanese(c), AnyDateInner::Japanese(ref mut d)) => { + c.offset_date(d, offset.cast_unit()) + } + (Self::JapaneseExtended(c), AnyDateInner::JapaneseExtended(ref mut d)) => { + c.offset_date(d, offset.cast_unit()) + } + (Self::Persian(c), AnyDateInner::Persian(ref mut d)) => { + c.offset_date(d, offset.cast_unit()) + } + (Self::Roc(c), AnyDateInner::Roc(ref mut d)) => c.offset_date(d, offset.cast_unit()), + // This is only reached from misuse of from_raw, a semi-internal api + #[allow(clippy::panic)] + (_, d) => panic!( + "Found AnyCalendar with mixed calendar type {} and date type {}!", + self.kind().debug_name(), + d.kind().debug_name() + ), + } + } + + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + calendar2: &Self, + largest_unit: DateDurationUnit, + smallest_unit: DateDurationUnit, + ) -> DateDuration { + match (self, calendar2, date1, date2) { + ( + Self::Buddhist(c1), + Self::Buddhist(c2), + AnyDateInner::Buddhist(d1), + AnyDateInner::Buddhist(d2), + ) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + ( + Self::Chinese(c1), + Self::Chinese(c2), + AnyDateInner::Chinese(d1), + AnyDateInner::Chinese(d2), + ) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + ( + Self::Coptic(c1), + Self::Coptic(c2), + AnyDateInner::Coptic(d1), + AnyDateInner::Coptic(d2), + ) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + ( + Self::Dangi(c1), + Self::Dangi(c2), + AnyDateInner::Dangi(d1), + AnyDateInner::Dangi(d2), + ) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + ( + Self::Ethiopian(c1), + Self::Ethiopian(c2), + AnyDateInner::Ethiopian(d1), + AnyDateInner::Ethiopian(d2), + ) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + ( + Self::Gregorian(c1), + Self::Gregorian(c2), + AnyDateInner::Gregorian(d1), + AnyDateInner::Gregorian(d2), + ) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + ( + Self::Hebrew(c1), + Self::Hebrew(c2), + AnyDateInner::Hebrew(d1), + AnyDateInner::Hebrew(d2), + ) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + ( + Self::Indian(c1), + Self::Indian(c2), + AnyDateInner::Indian(d1), + AnyDateInner::Indian(d2), + ) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + ( + Self::HijriTabular(c1), + Self::HijriTabular(c2), + &AnyDateInner::HijriTabular(ref d1, l1, e1), + &AnyDateInner::HijriTabular(ref d2, l2, e2), + ) if c1.epoch == c2.epoch + && c2.epoch == e1 + && e1 == e2 + && c1.leap_years == c2.leap_years + && c2.leap_years == l1 + && l1 == l2 => + { + c1.until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit() + } + ( + Self::HijriSimulated(c1), + Self::HijriSimulated(c2), + AnyDateInner::HijriSimulated(d1), + AnyDateInner::HijriSimulated(d2), + ) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + ( + Self::HijriUmmAlQura(c1), + Self::HijriUmmAlQura(c2), + AnyDateInner::HijriUmmAlQura(d1), + AnyDateInner::HijriUmmAlQura(d2), + ) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + (Self::Iso(c1), Self::Iso(c2), AnyDateInner::Iso(d1), AnyDateInner::Iso(d2)) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + ( + Self::Japanese(c1), + Self::Japanese(c2), + AnyDateInner::Japanese(d1), + AnyDateInner::Japanese(d2), + ) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + ( + Self::JapaneseExtended(c1), + Self::JapaneseExtended(c2), + AnyDateInner::JapaneseExtended(d1), + AnyDateInner::JapaneseExtended(d2), + ) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + ( + Self::Persian(c1), + Self::Persian(c2), + AnyDateInner::Persian(d1), + AnyDateInner::Persian(d2), + ) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + (Self::Roc(c1), Self::Roc(c2), AnyDateInner::Roc(d1), AnyDateInner::Roc(d2)) => c1 + .until(d1, d2, c2, largest_unit, smallest_unit) + .cast_unit(), + _ => { + // attempt to convert + let iso = calendar2.to_iso(date2); + + match_cal_and_date!(match (self, date1): + (c1, d1) => { + let d2 = c1.from_iso(iso); + let until = c1.until(d1, &d2, c1, largest_unit, smallest_unit); + until.cast_unit::() + } + ) + } + } + } + + fn year_info(&self, date: &Self::DateInner) -> types::YearInfo { + match_cal_and_date!(match (self, date): (c, d) => c.year_info(d).into()) + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + match_cal_and_date!(match (self, date): (c, d) => c.extended_year(d)) + } + + /// The calendar-specific check if `date` is in a leap year + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + match_cal_and_date!(match (self, date): (c, d) => c.is_in_leap_year(d)) + } + + /// The calendar-specific month represented by `date` + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + match_cal_and_date!(match (self, date): (c, d) => c.month(d)) + } + + /// The calendar-specific day-of-month represented by `date` + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + match_cal_and_date!(match (self, date): (c, d) => c.day_of_month(d)) + } + + /// Information of the day of the year + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + match_cal_and_date!(match (self, date): (c, d) => c.day_of_year(d)) + } + + fn debug_name(&self) -> &'static str { + match self.kind() { + AnyCalendarKind::Buddhist => "AnyCalendar (Buddhist)", + AnyCalendarKind::Chinese => "AnyCalendar (Chinese)", + AnyCalendarKind::Coptic => "AnyCalendar (Coptic)", + AnyCalendarKind::Dangi => "AnyCalendar (Dangi)", + AnyCalendarKind::Ethiopian => "AnyCalendar (Ethiopian, Amete Miret)", + AnyCalendarKind::EthiopianAmeteAlem => "AnyCalendar (Ethiopian, Amete Alem)", + AnyCalendarKind::Gregorian => "AnyCalendar (Gregorian)", + AnyCalendarKind::Hebrew => "AnyCalendar (Hebrew)", + AnyCalendarKind::Indian => "AnyCalendar (Indian)", + AnyCalendarKind::HijriTabularTypeIIFriday => { + "AnyCalendar (Hijri, tabular, type II leap years, Friday epoch)" + } + AnyCalendarKind::HijriTabularTypeIIThursday => { + "AnyCalendar (Hijri, tabular, type II leap years, Thursday epoch)" + } + AnyCalendarKind::HijriSimulatedMecca => "AnyCalendar (Hijri, simulated Mecca)", + AnyCalendarKind::HijriUmmAlQura => "AnyCalendar (Hijri, Umm al-Qura)", + AnyCalendarKind::Iso => "AnyCalendar (Iso)", + AnyCalendarKind::Japanese => "AnyCalendar (Japanese)", + AnyCalendarKind::JapaneseExtended => "AnyCalendar (Japanese, historical era data)", + AnyCalendarKind::Persian => "AnyCalendar (Persian)", + AnyCalendarKind::Roc => "AnyCalendar (Roc)", + } + } + + fn calendar_algorithm(&self) -> Option { + match self { + Self::Buddhist(ref c) => c.calendar_algorithm(), + Self::Chinese(ref c) => c.calendar_algorithm(), + Self::Coptic(ref c) => c.calendar_algorithm(), + Self::Dangi(ref c) => c.calendar_algorithm(), + Self::Ethiopian(ref c) => c.calendar_algorithm(), + Self::Gregorian(ref c) => c.calendar_algorithm(), + Self::Hebrew(ref c) => c.calendar_algorithm(), + Self::Indian(ref c) => c.calendar_algorithm(), + Self::HijriSimulated(ref c) => c.calendar_algorithm(), + Self::HijriTabular(ref c) => c.calendar_algorithm(), + Self::HijriUmmAlQura(ref c) => c.calendar_algorithm(), + Self::Iso(ref c) => c.calendar_algorithm(), + Self::Japanese(ref c) => c.calendar_algorithm(), + Self::JapaneseExtended(ref c) => c.calendar_algorithm(), + Self::Persian(ref c) => c.calendar_algorithm(), + Self::Roc(ref c) => c.calendar_algorithm(), + } + } +} + +impl AnyCalendar { + /// Constructs an AnyCalendar for a given calendar kind from compiled data. + /// + /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + #[cfg(feature = "compiled_data")] + pub const fn new(kind: AnyCalendarKind) -> Self { + match kind { + AnyCalendarKind::Buddhist => AnyCalendar::Buddhist(Buddhist), + AnyCalendarKind::Chinese => AnyCalendar::Chinese(Chinese::new()), + AnyCalendarKind::Coptic => AnyCalendar::Coptic(Coptic), + AnyCalendarKind::Dangi => AnyCalendar::Dangi(Dangi::new()), + AnyCalendarKind::Ethiopian => AnyCalendar::Ethiopian(Ethiopian::new_with_era_style( + EthiopianEraStyle::AmeteMihret, + )), + AnyCalendarKind::EthiopianAmeteAlem => { + AnyCalendar::Ethiopian(Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteAlem)) + } + AnyCalendarKind::Gregorian => AnyCalendar::Gregorian(Gregorian), + AnyCalendarKind::Hebrew => AnyCalendar::Hebrew(Hebrew), + AnyCalendarKind::Indian => AnyCalendar::Indian(Indian), + AnyCalendarKind::HijriTabularTypeIIFriday => { + AnyCalendar::HijriTabular(HijriTabular::new( + crate::cal::hijri::HijriTabularLeapYears::TypeII, + HijriTabularEpoch::Friday, + )) + } + AnyCalendarKind::HijriSimulatedMecca => { + AnyCalendar::HijriSimulated(HijriSimulated::new_mecca()) + } + AnyCalendarKind::HijriTabularTypeIIThursday => { + AnyCalendar::HijriTabular(HijriTabular::new( + crate::cal::hijri::HijriTabularLeapYears::TypeII, + HijriTabularEpoch::Thursday, + )) + } + AnyCalendarKind::HijriUmmAlQura => AnyCalendar::HijriUmmAlQura(HijriUmmAlQura::new()), + AnyCalendarKind::Iso => AnyCalendar::Iso(Iso), + AnyCalendarKind::Japanese => AnyCalendar::Japanese(Japanese::new()), + AnyCalendarKind::JapaneseExtended => { + AnyCalendar::JapaneseExtended(JapaneseExtended::new()) + } + AnyCalendarKind::Persian => AnyCalendar::Persian(Persian), + AnyCalendarKind::Roc => AnyCalendar::Roc(Roc), + } + } + + #[cfg(feature = "serde")] + #[doc = icu_provider::gen_buffer_unstable_docs!(BUFFER, Self::new)] + pub fn try_new_with_buffer_provider

( + provider: &P, + kind: AnyCalendarKind, + ) -> Result + where + P: BufferProvider + ?Sized, + { + Ok(match kind { + AnyCalendarKind::Buddhist => AnyCalendar::Buddhist(Buddhist), + AnyCalendarKind::Chinese => { + AnyCalendar::Chinese(Chinese::try_new_with_buffer_provider(provider)?) + } + AnyCalendarKind::Coptic => AnyCalendar::Coptic(Coptic), + AnyCalendarKind::Dangi => { + AnyCalendar::Dangi(Dangi::try_new_with_buffer_provider(provider)?) + } + AnyCalendarKind::Ethiopian => AnyCalendar::Ethiopian(Ethiopian::new_with_era_style( + EthiopianEraStyle::AmeteMihret, + )), + AnyCalendarKind::EthiopianAmeteAlem => { + AnyCalendar::Ethiopian(Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteAlem)) + } + AnyCalendarKind::Gregorian => AnyCalendar::Gregorian(Gregorian), + AnyCalendarKind::Hebrew => AnyCalendar::Hebrew(Hebrew), + AnyCalendarKind::Indian => AnyCalendar::Indian(Indian), + AnyCalendarKind::HijriTabularTypeIIFriday => { + AnyCalendar::HijriTabular(HijriTabular::new( + crate::cal::hijri::HijriTabularLeapYears::TypeII, + HijriTabularEpoch::Friday, + )) + } + AnyCalendarKind::HijriSimulatedMecca => AnyCalendar::HijriSimulated( + HijriSimulated::try_new_mecca_with_buffer_provider(provider)?, + ), + AnyCalendarKind::HijriTabularTypeIIThursday => { + AnyCalendar::HijriTabular(HijriTabular::new( + crate::cal::hijri::HijriTabularLeapYears::TypeII, + HijriTabularEpoch::Thursday, + )) + } + AnyCalendarKind::HijriUmmAlQura => AnyCalendar::HijriUmmAlQura(HijriUmmAlQura::new()), + AnyCalendarKind::Iso => AnyCalendar::Iso(Iso), + AnyCalendarKind::Japanese => { + AnyCalendar::Japanese(Japanese::try_new_with_buffer_provider(provider)?) + } + AnyCalendarKind::JapaneseExtended => AnyCalendar::JapaneseExtended( + JapaneseExtended::try_new_with_buffer_provider(provider)?, + ), + AnyCalendarKind::Persian => AnyCalendar::Persian(Persian), + AnyCalendarKind::Roc => AnyCalendar::Roc(Roc), + }) + } + + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new)] + pub fn try_new_unstable

(provider: &P, kind: AnyCalendarKind) -> Result + where + P: DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + ?Sized, + { + Ok(match kind { + AnyCalendarKind::Buddhist => AnyCalendar::Buddhist(Buddhist), + AnyCalendarKind::Chinese => AnyCalendar::Chinese(Chinese::try_new_unstable(provider)?), + AnyCalendarKind::Coptic => AnyCalendar::Coptic(Coptic), + AnyCalendarKind::Dangi => AnyCalendar::Dangi(Dangi::try_new_unstable(provider)?), + AnyCalendarKind::Ethiopian => AnyCalendar::Ethiopian(Ethiopian::new_with_era_style( + EthiopianEraStyle::AmeteMihret, + )), + AnyCalendarKind::EthiopianAmeteAlem => { + AnyCalendar::Ethiopian(Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteAlem)) + } + AnyCalendarKind::Gregorian => AnyCalendar::Gregorian(Gregorian), + AnyCalendarKind::Hebrew => AnyCalendar::Hebrew(Hebrew), + AnyCalendarKind::Indian => AnyCalendar::Indian(Indian), + AnyCalendarKind::HijriTabularTypeIIFriday => { + AnyCalendar::HijriTabular(HijriTabular::new( + crate::cal::hijri::HijriTabularLeapYears::TypeII, + HijriTabularEpoch::Friday, + )) + } + AnyCalendarKind::HijriSimulatedMecca => { + AnyCalendar::HijriSimulated(HijriSimulated::try_new_mecca_unstable(provider)?) + } + AnyCalendarKind::HijriTabularTypeIIThursday => { + AnyCalendar::HijriTabular(HijriTabular::new( + crate::cal::hijri::HijriTabularLeapYears::TypeII, + HijriTabularEpoch::Thursday, + )) + } + AnyCalendarKind::HijriUmmAlQura => AnyCalendar::HijriUmmAlQura(HijriUmmAlQura::new()), + AnyCalendarKind::Iso => AnyCalendar::Iso(Iso), + AnyCalendarKind::Japanese => { + AnyCalendar::Japanese(Japanese::try_new_unstable(provider)?) + } + AnyCalendarKind::JapaneseExtended => { + AnyCalendar::JapaneseExtended(JapaneseExtended::try_new_unstable(provider)?) + } + AnyCalendarKind::Persian => AnyCalendar::Persian(Persian), + AnyCalendarKind::Roc => AnyCalendar::Roc(Roc), + }) + } + + /// The [`AnyCalendarKind`] corresponding to the calendar this contains + pub fn kind(&self) -> AnyCalendarKind { + match *self { + Self::Buddhist(_) => AnyCalendarKind::Buddhist, + Self::Chinese(_) => AnyCalendarKind::Chinese, + Self::Coptic(_) => AnyCalendarKind::Coptic, + Self::Dangi(_) => AnyCalendarKind::Dangi, + Self::Ethiopian(ref e) => IntoAnyCalendar::kind(e), + Self::Gregorian(_) => AnyCalendarKind::Gregorian, + Self::Hebrew(_) => AnyCalendarKind::Hebrew, + Self::Indian(_) => AnyCalendarKind::Indian, + Self::HijriTabular(ref h) => IntoAnyCalendar::kind(h), + Self::HijriSimulated(ref h) => IntoAnyCalendar::kind(h), + Self::HijriUmmAlQura(_) => AnyCalendarKind::HijriUmmAlQura, + Self::Iso(_) => AnyCalendarKind::Iso, + Self::Japanese(_) => AnyCalendarKind::Japanese, + Self::JapaneseExtended(_) => AnyCalendarKind::JapaneseExtended, + Self::Persian(_) => AnyCalendarKind::Persian, + Self::Roc(_) => AnyCalendarKind::Roc, + } + } +} + +impl> Date { + /// Convert this `Date` to another `AnyCalendar`, if conversion is needed + pub fn convert_any<'a>(&self, calendar: &'a AnyCalendar) -> Date> { + if calendar.kind() != self.calendar.as_calendar().kind() { + Date::new_from_iso(self.to_iso(), Ref(calendar)) + } else { + Date { + inner: self.inner, + calendar: Ref(calendar), + } + } + } +} + +impl AnyDateInner { + fn kind(&self) -> AnyCalendarKind { + match *self { + AnyDateInner::Buddhist(_) => AnyCalendarKind::Buddhist, + AnyDateInner::Chinese(_) => AnyCalendarKind::Chinese, + AnyDateInner::Coptic(_) => AnyCalendarKind::Coptic, + AnyDateInner::Dangi(_) => AnyCalendarKind::Dangi, + AnyDateInner::Ethiopian(_) => AnyCalendarKind::Ethiopian, + AnyDateInner::Gregorian(_) => AnyCalendarKind::Gregorian, + AnyDateInner::Hebrew(_) => AnyCalendarKind::Hebrew, + AnyDateInner::Indian(_) => AnyCalendarKind::Indian, + AnyDateInner::HijriTabular( + _, + HijriTabularLeapYears::TypeII, + HijriTabularEpoch::Friday, + ) => AnyCalendarKind::HijriTabularTypeIIFriday, + AnyDateInner::HijriSimulated(_) => AnyCalendarKind::HijriSimulatedMecca, + AnyDateInner::HijriTabular( + _, + HijriTabularLeapYears::TypeII, + HijriTabularEpoch::Thursday, + ) => AnyCalendarKind::HijriTabularTypeIIThursday, + AnyDateInner::HijriUmmAlQura(_) => AnyCalendarKind::HijriUmmAlQura, + AnyDateInner::Iso(_) => AnyCalendarKind::Iso, + AnyDateInner::Japanese(_) => AnyCalendarKind::Japanese, + AnyDateInner::JapaneseExtended(_) => AnyCalendarKind::JapaneseExtended, + AnyDateInner::Persian(_) => AnyCalendarKind::Persian, + AnyDateInner::Roc(_) => AnyCalendarKind::Roc, + } + } +} + +/// Convenient type for selecting the kind of AnyCalendar to construct +#[non_exhaustive] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] +pub enum AnyCalendarKind { + /// The kind of a [`Buddhist`] calendar + Buddhist, + /// The kind of a [`Chinese`] calendar + Chinese, + /// The kind of a [`Coptic`] calendar + Coptic, + /// The kind of a [`Dangi`] calendar + Dangi, + /// The kind of an [`Ethiopian`] calendar, with Amete Mihret era + Ethiopian, + /// The kind of an [`Ethiopian`] calendar, with Amete Alem era + EthiopianAmeteAlem, + /// The kind of a [`Gregorian`] calendar + Gregorian, + /// The kind of a [`Hebrew`] calendar + Hebrew, + /// The kind of a [`Indian`] calendar + Indian, + /// The kind of an [`HijriTabular`] calendar using [`HijriTabularLeapYears::TypeII`] and [`HijriTabularEpoch::Friday`] + HijriTabularTypeIIFriday, + /// The kind of an [`HijriSimulated`], Mecca calendar + HijriSimulatedMecca, + /// The kind of an [`HijriTabular`] calendar using [`HijriTabularLeapYears::TypeII`] and [`HijriTabularEpoch::Thursday`] + HijriTabularTypeIIThursday, + /// The kind of an [`HijriUmmAlQura`] calendar + HijriUmmAlQura, + /// The kind of an [`Iso`] calendar + Iso, + /// The kind of a [`Japanese`] calendar + Japanese, + /// The kind of a [`JapaneseExtended`] calendar + JapaneseExtended, + /// The kind of a [`Persian`] calendar + Persian, + /// The kind of a [`Roc`] calendar + Roc, +} + +impl AnyCalendarKind { + /// Selects the [`AnyCalendarKind`] appropriate for the given [`CalendarPreferences`]. + pub fn new(prefs: CalendarPreferences) -> Self { + let algo = prefs.calendar_algorithm; + let region = prefs.locale_preferences.region(); + if let Some(kind) = algo.and_then(|a| a.try_into().ok()) { + return kind; + } + if region == Some(region!("TH")) { + AnyCalendarKind::Buddhist + } else if region == Some(region!("AF")) || region == Some(region!("IR")) { + AnyCalendarKind::Persian + } else if region == Some(region!("SA")) && algo == Some(CalendarAlgorithm::Hijri(None)) { + AnyCalendarKind::HijriSimulatedMecca + } else { + AnyCalendarKind::Gregorian + } + } + + fn debug_name(self) -> &'static str { + match self { + AnyCalendarKind::Buddhist => Buddhist.debug_name(), + AnyCalendarKind::Chinese => Chinese::DEBUG_NAME, + AnyCalendarKind::Coptic => Coptic.debug_name(), + AnyCalendarKind::Dangi => Dangi::DEBUG_NAME, + AnyCalendarKind::Ethiopian => Ethiopian(false).debug_name(), + AnyCalendarKind::EthiopianAmeteAlem => Ethiopian(true).debug_name(), + AnyCalendarKind::Gregorian => Gregorian.debug_name(), + AnyCalendarKind::Hebrew => Hebrew.debug_name(), + AnyCalendarKind::Indian => Indian.debug_name(), + AnyCalendarKind::HijriTabularTypeIIFriday => HijriTabular::new( + crate::cal::hijri::HijriTabularLeapYears::TypeII, + HijriTabularEpoch::Friday, + ) + .debug_name(), + AnyCalendarKind::HijriSimulatedMecca => HijriSimulated::DEBUG_NAME, + AnyCalendarKind::HijriTabularTypeIIThursday => HijriTabular::new( + crate::cal::hijri::HijriTabularLeapYears::TypeII, + HijriTabularEpoch::Thursday, + ) + .debug_name(), + AnyCalendarKind::HijriUmmAlQura => HijriUmmAlQura::DEBUG_NAME, + AnyCalendarKind::Iso => Iso.debug_name(), + AnyCalendarKind::Japanese => Japanese::DEBUG_NAME, + AnyCalendarKind::JapaneseExtended => JapaneseExtended::DEBUG_NAME, + AnyCalendarKind::Persian => Persian.debug_name(), + AnyCalendarKind::Roc => Roc.debug_name(), + } + } +} + +impl TryFrom for AnyCalendarKind { + type Error = (); + fn try_from(v: CalendarAlgorithm) -> Result { + use CalendarAlgorithm::*; + match v { + Buddhist => Ok(AnyCalendarKind::Buddhist), + Chinese => Ok(AnyCalendarKind::Chinese), + Coptic => Ok(AnyCalendarKind::Coptic), + Dangi => Ok(AnyCalendarKind::Dangi), + Ethioaa => Ok(AnyCalendarKind::EthiopianAmeteAlem), + Ethiopic => Ok(AnyCalendarKind::Ethiopian), + Gregory => Ok(AnyCalendarKind::Gregorian), + Hebrew => Ok(AnyCalendarKind::Hebrew), + Indian => Ok(AnyCalendarKind::Indian), + Hijri(None) => Err(()), + Hijri(Some(HijriCalendarAlgorithm::Umalqura)) => Ok(AnyCalendarKind::HijriUmmAlQura), + Hijri(Some(HijriCalendarAlgorithm::Tbla)) => { + Ok(AnyCalendarKind::HijriTabularTypeIIThursday) + } + Hijri(Some(HijriCalendarAlgorithm::Civil)) => { + Ok(AnyCalendarKind::HijriTabularTypeIIFriday) + } + Hijri(Some(HijriCalendarAlgorithm::Rgsa)) => Ok(AnyCalendarKind::HijriSimulatedMecca), + Iso8601 => Ok(AnyCalendarKind::Iso), + Japanese => Ok(AnyCalendarKind::Japanese), + Persian => Ok(AnyCalendarKind::Persian), + Roc => Ok(AnyCalendarKind::Roc), + _ => { + debug_assert!(false, "unknown calendar algorithm {v:?}"); + Err(()) + } + } + } +} + +impl fmt::Display for AnyCalendarKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self, f) + } +} + +/// Trait for calendars that may be converted to [`AnyCalendar`] +pub trait IntoAnyCalendar: Calendar + Sized { + /// Convert this calendar into an [`AnyCalendar`], moving it + /// + /// You should not need to call this method directly + fn to_any(self) -> AnyCalendar; + + /// The [`AnyCalendarKind`] enum variant associated with this calendar + fn kind(&self) -> AnyCalendarKind; + + /// Move an [`AnyCalendar`] into a `Self`, or returning it as an error + /// if the types do not match. + /// + /// You should not need to call this method directly + fn from_any(any: AnyCalendar) -> Result; + + /// Convert an [`AnyCalendar`] reference into a `Self` reference. + /// + /// You should not need to call this method directly + fn from_any_ref(any: &AnyCalendar) -> Option<&Self>; + + /// Convert a date for this calendar into an `AnyDateInner` + /// + /// You should not need to call this method directly + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner; +} + +impl IntoAnyCalendar for AnyCalendar { + #[inline] + fn to_any(self) -> AnyCalendar { + self + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + self.kind() + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + Ok(any) + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + Some(any) + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + *d + } +} + +impl IntoAnyCalendar for Buddhist { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::Buddhist(Buddhist) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + AnyCalendarKind::Buddhist + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::Buddhist(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::Buddhist(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::Buddhist(*d) + } +} + +impl From for AnyCalendar { + fn from(value: Buddhist) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for Chinese { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::Chinese(self) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + AnyCalendarKind::Chinese + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::Chinese(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::Chinese(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::Chinese(*d) + } +} + +impl From for AnyCalendar { + fn from(value: Chinese) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for Coptic { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::Coptic(Coptic) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + AnyCalendarKind::Coptic + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::Coptic(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::Coptic(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::Coptic(*d) + } +} + +impl From for AnyCalendar { + fn from(value: Coptic) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for Dangi { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::Dangi(self) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + AnyCalendarKind::Dangi + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::Dangi(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::Dangi(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::Dangi(*d) + } +} + +impl From for AnyCalendar { + fn from(value: Dangi) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for Ethiopian { + // Amete Mihret calendars are the default + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::Ethiopian(self) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + if self.0 { + AnyCalendarKind::EthiopianAmeteAlem + } else { + AnyCalendarKind::Ethiopian + } + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::Ethiopian(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::Ethiopian(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::Ethiopian(*d) + } +} + +impl From for AnyCalendar { + fn from(value: Ethiopian) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for Gregorian { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::Gregorian(Gregorian) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + AnyCalendarKind::Gregorian + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::Gregorian(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::Gregorian(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::Gregorian(*d) + } +} + +impl From for AnyCalendar { + fn from(value: Gregorian) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for Hebrew { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::Hebrew(Hebrew) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + AnyCalendarKind::Hebrew + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::Hebrew(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::Hebrew(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::Hebrew(*d) + } +} + +impl From for AnyCalendar { + fn from(value: Hebrew) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for Indian { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::Indian(Indian) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + AnyCalendarKind::Indian + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::Indian(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::Indian(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::Indian(*d) + } +} + +impl From for AnyCalendar { + fn from(value: Indian) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for HijriTabular { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::HijriTabular(self) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + match (self.leap_years, self.epoch) { + (HijriTabularLeapYears::TypeII, HijriTabularEpoch::Friday) => { + AnyCalendarKind::HijriTabularTypeIIFriday + } + (HijriTabularLeapYears::TypeII, HijriTabularEpoch::Thursday) => { + AnyCalendarKind::HijriTabularTypeIIThursday + } + } + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::HijriTabular(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::HijriTabular(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::HijriTabular(*d, self.leap_years, self.epoch) + } +} + +impl From for AnyCalendar { + fn from(value: HijriTabular) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for HijriSimulated { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::HijriSimulated(self) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + match self.location { + HijriSimulatedLocation::Mecca => AnyCalendarKind::HijriSimulatedMecca, + } + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::HijriSimulated(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::HijriSimulated(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::HijriSimulated(*d) + } +} + +impl From for AnyCalendar { + fn from(value: HijriSimulated) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for HijriUmmAlQura { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::HijriUmmAlQura(self) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + AnyCalendarKind::HijriUmmAlQura + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::HijriUmmAlQura(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::HijriUmmAlQura(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::HijriUmmAlQura(*d) + } +} + +impl From for AnyCalendar { + fn from(value: HijriUmmAlQura) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for Iso { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::Iso(Iso) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + AnyCalendarKind::Iso + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::Iso(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::Iso(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::Iso(*d) + } +} + +impl From for AnyCalendar { + fn from(value: Iso) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for Japanese { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::Japanese(self) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + AnyCalendarKind::Japanese + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::Japanese(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::Japanese(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::Japanese(*d) + } +} + +impl From for AnyCalendar { + fn from(value: Japanese) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for JapaneseExtended { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::JapaneseExtended(self) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + AnyCalendarKind::JapaneseExtended + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::JapaneseExtended(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::JapaneseExtended(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::JapaneseExtended(*d) + } +} + +impl From for AnyCalendar { + fn from(value: JapaneseExtended) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for Persian { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::Persian(Persian) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + AnyCalendarKind::Persian + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::Persian(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::Persian(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::Persian(*d) + } +} + +impl From for AnyCalendar { + fn from(value: Persian) -> AnyCalendar { + value.to_any() + } +} + +impl IntoAnyCalendar for Roc { + #[inline] + fn to_any(self) -> AnyCalendar { + AnyCalendar::Roc(Roc) + } + #[inline] + fn kind(&self) -> AnyCalendarKind { + AnyCalendarKind::Roc + } + #[inline] + fn from_any(any: AnyCalendar) -> Result { + if let AnyCalendar::Roc(cal) = any { + Ok(cal) + } else { + Err(any) + } + } + #[inline] + fn from_any_ref(any: &AnyCalendar) -> Option<&Self> { + if let AnyCalendar::Roc(cal) = any { + Some(cal) + } else { + None + } + } + #[inline] + fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { + AnyDateInner::Roc(*d) + } +} + +impl From for AnyCalendar { + fn from(value: Roc) -> AnyCalendar { + value.to_any() + } +} + +#[cfg(test)] +mod tests { + use tinystr::tinystr; + use types::MonthCode; + + use super::*; + use crate::Ref; + + #[track_caller] + fn single_test_roundtrip( + calendar: Ref, + era: Option<(&str, Option)>, + year: i32, + month_code: &str, + day: u8, + ) { + let month = types::MonthCode(month_code.parse().expect("month code must parse")); + + let date = Date::try_new_from_codes(era.map(|x| x.0), year, month, day, calendar) + .unwrap_or_else(|e| { + panic!( + "Failed to construct date for {} with {era:?}, {year}, {month}, {day}: {e:?}", + calendar.debug_name(), + ) + }); + + let roundtrip_year = date.year(); + // FIXME: these APIs should be improved + let roundtrip_year = roundtrip_year.era_year_or_related_iso(); + let roundtrip_month = date.month().standard_code; + let roundtrip_day = date.day_of_month().0; + + assert_eq!( + (year, month, day), + (roundtrip_year, roundtrip_month, roundtrip_day), + "Failed to roundtrip for calendar {}", + calendar.debug_name() + ); + + if let Some((era_code, era_index)) = era { + let roundtrip_era_year = date.year().era().expect("year type should be era"); + assert_eq!( + (era_code, era_index), + ( + roundtrip_era_year.era.as_str(), + roundtrip_era_year.era_index + ), + "Failed to roundtrip era for calendar {}", + calendar.debug_name() + ) + } + + let iso = date.to_iso(); + let reconstructed = Date::new_from_iso(iso, calendar); + assert_eq!( + date, reconstructed, + "Failed to roundtrip via iso with {era:?}, {year}, {month}, {day}" + ) + } + + #[track_caller] + fn single_test_error( + calendar: Ref, + era: Option<(&str, Option)>, + year: i32, + month_code: &str, + day: u8, + error: DateError, + ) { + let month = types::MonthCode(month_code.parse().expect("month code must parse")); + + let date = Date::try_new_from_codes(era.map(|x| x.0), year, month, day, calendar); + assert_eq!( + date, + Err(error), + "Construction with {era:?}, {year}, {month}, {day} did not return {error:?}" + ) + } + + #[test] + fn test_any_construction() { + let buddhist = AnyCalendar::new(AnyCalendarKind::Buddhist); + let chinese = AnyCalendar::new(AnyCalendarKind::Chinese); + let coptic = AnyCalendar::new(AnyCalendarKind::Coptic); + let dangi = AnyCalendar::new(AnyCalendarKind::Dangi); + let ethioaa = AnyCalendar::new(AnyCalendarKind::EthiopianAmeteAlem); + let ethiopian = AnyCalendar::new(AnyCalendarKind::Ethiopian); + let gregorian = AnyCalendar::new(AnyCalendarKind::Gregorian); + let hebrew = AnyCalendar::new(AnyCalendarKind::Hebrew); + let indian = AnyCalendar::new(AnyCalendarKind::Indian); + let hijri_civil: AnyCalendar = AnyCalendar::new(AnyCalendarKind::HijriTabularTypeIIFriday); + let hijri_simulated: AnyCalendar = AnyCalendar::new(AnyCalendarKind::HijriSimulatedMecca); + let hijri_astronomical: AnyCalendar = + AnyCalendar::new(AnyCalendarKind::HijriTabularTypeIIThursday); + let hijri_umm_al_qura: AnyCalendar = AnyCalendar::new(AnyCalendarKind::HijriUmmAlQura); + let japanese = AnyCalendar::new(AnyCalendarKind::Japanese); + let japanext = AnyCalendar::new(AnyCalendarKind::JapaneseExtended); + let persian = AnyCalendar::new(AnyCalendarKind::Persian); + let roc = AnyCalendar::new(AnyCalendarKind::Roc); + let buddhist = Ref(&buddhist); + let chinese = Ref(&chinese); + let coptic = Ref(&coptic); + let dangi = Ref(&dangi); + let ethioaa = Ref(ðioaa); + let ethiopian = Ref(ðiopian); + let gregorian = Ref(&gregorian); + let hebrew = Ref(&hebrew); + let indian = Ref(&indian); + let hijri_civil = Ref(&hijri_civil); + let hijri_simulated = Ref(&hijri_simulated); + let hijri_astronomical = Ref(&hijri_astronomical); + let hijri_umm_al_qura = Ref(&hijri_umm_al_qura); + let japanese = Ref(&japanese); + let japanext = Ref(&japanext); + let persian = Ref(&persian); + let roc = Ref(&roc); + + single_test_roundtrip(buddhist, Some(("be", Some(0))), 100, "M03", 1); + single_test_roundtrip(buddhist, None, 2000, "M03", 1); + single_test_roundtrip(buddhist, Some(("be", Some(0))), -100, "M03", 1); + single_test_error( + buddhist, + Some(("be", Some(0))), + 100, + "M13", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M13"))), + ); + + single_test_roundtrip(coptic, Some(("am", Some(0))), 100, "M03", 1); + single_test_roundtrip(coptic, None, 2000, "M03", 1); + single_test_roundtrip(coptic, Some(("am", Some(0))), -99, "M03", 1); + single_test_roundtrip(coptic, Some(("am", Some(0))), 100, "M13", 1); + single_test_error( + coptic, + Some(("am", Some(0))), + 100, + "M14", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M14"))), + ); + + single_test_roundtrip(ethiopian, Some(("am", Some(1))), 100, "M03", 1); + single_test_roundtrip(ethiopian, None, 2000, "M03", 1); + single_test_roundtrip(ethiopian, Some(("am", Some(1))), 2000, "M13", 1); + single_test_roundtrip(ethiopian, Some(("aa", Some(0))), 5400, "M03", 1); + single_test_error( + ethiopian, + Some(("am", Some(0))), + 0, + "M03", + 1, + DateError::Range { + field: "year", + value: 0, + min: 1, + max: i32::MAX, + }, + ); + single_test_error( + ethiopian, + Some(("aa", Some(0))), + 5600, + "M03", + 1, + DateError::Range { + field: "year", + value: 5600, + min: i32::MIN, + max: 5500, + }, + ); + single_test_error( + ethiopian, + Some(("am", Some(0))), + 100, + "M14", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M14"))), + ); + + single_test_roundtrip(ethioaa, Some(("aa", Some(0))), 7000, "M13", 1); + single_test_roundtrip(ethioaa, None, 7000, "M13", 1); + single_test_roundtrip(ethioaa, Some(("aa", Some(0))), 100, "M03", 1); + single_test_error( + ethiopian, + Some(("aa", Some(0))), + 100, + "M14", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M14"))), + ); + + single_test_roundtrip(gregorian, Some(("ce", Some(1))), 100, "M03", 1); + single_test_roundtrip(gregorian, None, 2000, "M03", 1); + single_test_roundtrip(gregorian, Some(("bce", Some(0))), 100, "M03", 1); + single_test_error( + gregorian, + Some(("ce", Some(1))), + 0, + "M03", + 1, + DateError::Range { + field: "year", + value: 0, + min: 1, + max: i32::MAX, + }, + ); + single_test_error( + gregorian, + Some(("bce", Some(0))), + 0, + "M03", + 1, + DateError::Range { + field: "year", + value: 0, + min: 1, + max: i32::MAX, + }, + ); + + single_test_error( + gregorian, + Some(("bce", Some(0))), + 100, + "M13", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M13"))), + ); + + single_test_roundtrip(indian, Some(("shaka", Some(0))), 100, "M03", 1); + single_test_roundtrip(indian, None, 2000, "M12", 1); + single_test_roundtrip(indian, None, -100, "M03", 1); + single_test_roundtrip(indian, Some(("shaka", Some(0))), 0, "M03", 1); + single_test_error( + indian, + Some(("shaka", Some(0))), + 100, + "M13", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M13"))), + ); + + single_test_roundtrip(chinese, None, 400, "M02", 5); + single_test_roundtrip(chinese, None, 4660, "M07", 29); + single_test_roundtrip(chinese, None, -100, "M11", 12); + single_test_error( + chinese, + None, + 4658, + "M13", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M13"))), + ); + + single_test_roundtrip(dangi, None, 400, "M02", 5); + single_test_roundtrip(dangi, None, 4660, "M08", 29); + single_test_roundtrip(dangi, None, -1300, "M11", 12); + single_test_error( + dangi, + None, + 10393, + "M00L", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M00L"))), + ); + + single_test_roundtrip(japanese, Some(("reiwa", None)), 3, "M03", 1); + single_test_roundtrip(japanese, Some(("heisei", None)), 6, "M12", 1); + single_test_roundtrip(japanese, Some(("meiji", None)), 10, "M03", 1); + single_test_roundtrip(japanese, Some(("ce", None)), 1000, "M03", 1); + single_test_roundtrip(japanese, None, 1000, "M03", 1); + single_test_roundtrip(japanese, Some(("bce", None)), 10, "M03", 1); + single_test_error( + japanese, + Some(("ce", None)), + 0, + "M03", + 1, + DateError::Range { + field: "year", + value: 0, + min: 1, + max: i32::MAX, + }, + ); + single_test_error( + japanese, + Some(("bce", Some(0))), + 0, + "M03", + 1, + DateError::Range { + field: "year", + value: 0, + min: 1, + max: i32::MAX, + }, + ); + + single_test_error( + japanese, + Some(("reiwa", None)), + 2, + "M13", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M13"))), + ); + + single_test_roundtrip(japanext, Some(("reiwa", None)), 3, "M03", 1); + single_test_roundtrip(japanext, Some(("heisei", None)), 6, "M12", 1); + single_test_roundtrip(japanext, Some(("meiji", None)), 10, "M03", 1); + single_test_roundtrip(japanext, Some(("tenpyokampo-749", None)), 1, "M04", 20); + single_test_roundtrip(japanext, Some(("ce", None)), 100, "M03", 1); + single_test_roundtrip(japanext, Some(("bce", None)), 10, "M03", 1); + single_test_error( + japanext, + Some(("ce", None)), + 0, + "M03", + 1, + DateError::Range { + field: "year", + value: 0, + min: 1, + max: i32::MAX, + }, + ); + single_test_error( + japanext, + Some(("bce", Some(0))), + 0, + "M03", + 1, + DateError::Range { + field: "year", + value: 0, + min: 1, + max: i32::MAX, + }, + ); + + single_test_error( + japanext, + Some(("reiwa", None)), + 2, + "M13", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M13"))), + ); + + single_test_roundtrip(persian, Some(("ap", Some(0))), 477, "M03", 1); + single_test_roundtrip(persian, None, 2083, "M07", 21); + single_test_roundtrip(persian, Some(("ap", Some(0))), 1600, "M12", 20); + single_test_error( + persian, + Some(("ap", Some(0))), + 100, + "M9", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M9"))), + ); + + single_test_roundtrip(hebrew, Some(("am", Some(0))), 5773, "M03", 1); + single_test_roundtrip(hebrew, None, 4993, "M07", 21); + single_test_roundtrip(hebrew, Some(("am", Some(0))), 5012, "M12", 20); + single_test_error( + hebrew, + Some(("am", Some(0))), + 100, + "M9", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M9"))), + ); + + single_test_roundtrip(roc, Some(("roc", Some(1))), 10, "M05", 3); + single_test_roundtrip(roc, Some(("broc", Some(0))), 15, "M01", 10); + single_test_roundtrip(roc, None, 100, "M10", 30); + + single_test_roundtrip(hijri_simulated, Some(("ah", Some(0))), 477, "M03", 1); + single_test_roundtrip(hijri_simulated, None, 2083, "M07", 21); + single_test_roundtrip(hijri_simulated, Some(("ah", Some(0))), 1600, "M12", 20); + single_test_error( + hijri_simulated, + Some(("ah", Some(0))), + 100, + "M9", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M9"))), + ); + + single_test_roundtrip(hijri_civil, Some(("ah", Some(0))), 477, "M03", 1); + single_test_roundtrip(hijri_civil, None, 2083, "M07", 21); + single_test_roundtrip(hijri_civil, Some(("ah", Some(0))), 1600, "M12", 20); + single_test_error( + hijri_civil, + Some(("ah", Some(0))), + 100, + "M9", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M9"))), + ); + + single_test_roundtrip(hijri_umm_al_qura, Some(("ah", Some(0))), 477, "M03", 1); + single_test_roundtrip(hijri_umm_al_qura, None, 2083, "M07", 21); + single_test_roundtrip(hijri_umm_al_qura, Some(("ah", Some(0))), 1600, "M12", 20); + single_test_error( + hijri_umm_al_qura, + Some(("ah", Some(0))), + 100, + "M9", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M9"))), + ); + + single_test_roundtrip(hijri_astronomical, Some(("ah", Some(0))), 477, "M03", 1); + single_test_roundtrip(hijri_astronomical, None, 2083, "M07", 21); + single_test_roundtrip(hijri_astronomical, Some(("ah", Some(0))), 1600, "M12", 20); + single_test_error( + hijri_astronomical, + Some(("ah", Some(0))), + 100, + "M9", + 1, + DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M9"))), + ); + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/buddhist.rs b/deps/crates/vendor/icu_calendar/src/cal/buddhist.rs new file mode 100644 index 00000000000000..0e56b890d1eee9 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/buddhist.rs @@ -0,0 +1,435 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and implementations for the Buddhist calendar. +//! +//! ```rust +//! use icu::calendar::{cal::Buddhist, Date}; +//! +//! let date_iso = Date::try_new_iso(1970, 1, 2) +//! .expect("Failed to initialize ISO Date instance."); +//! let date_buddhist = Date::new_from_iso(date_iso, Buddhist); +//! +//! assert_eq!(date_buddhist.era_year().year, 2513); +//! assert_eq!(date_buddhist.month().ordinal, 1); +//! assert_eq!(date_buddhist.day_of_month().0, 2); +//! ``` + +use crate::cal::iso::{Iso, IsoDateInner}; +use crate::calendar_arithmetic::ArithmeticDate; +use crate::error::DateError; +use crate::{types, Calendar, Date, DateDuration, DateDurationUnit, RangeError}; +use calendrical_calculations::rata_die::RataDie; +use tinystr::tinystr; + +/// The number of years the Buddhist Era is ahead of C.E. by +/// +/// (1 AD = 544 BE) +const BUDDHIST_ERA_OFFSET: i32 = 543; + +#[derive(Copy, Clone, Debug, Default)] +/// The [Thai Solar Buddhist Calendar][cal] +/// +/// The [Thai Solar Buddhist Calendar][cal] is a solar calendar used in Thailand, with twelve months. +/// The months and days are identical to that of the Gregorian calendar, however the years are counted +/// differently using the Buddhist Era. +/// +/// This type can be used with [`Date`] to represent dates in this calendar. +/// +/// [cal]: https://en.wikipedia.org/wiki/Thai_solar_calendar +/// +/// # Era codes +/// +/// This calendar uses a single era code `be`, with 1 Buddhist Era being 543 BCE. Dates before this era use negative years. +/// +/// # Month codes +/// +/// This calendar supports 12 solar month codes (`"M01" - "M12"`) +#[allow(clippy::exhaustive_structs)] // this type is stable +pub struct Buddhist; + +impl crate::cal::scaffold::UnstableSealed for Buddhist {} +impl Calendar for Buddhist { + type DateInner = IsoDateInner; + type Year = types::EraYear; + + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + match era { + Some("be") | None => {} + _ => return Err(DateError::UnknownEra), + } + let year = year - BUDDHIST_ERA_OFFSET; + + ArithmeticDate::new_from_codes(self, year, month_code, day).map(IsoDateInner) + } + + fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner { + iso + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + *date + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + Iso.from_rata_die(rd) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + Iso.to_rata_die(date) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + Iso.months_in_year(date) + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + Iso.days_in_year(date) + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + Iso.days_in_month(date) + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + Iso.offset_date(date, offset.cast_unit()) + } + + #[allow(clippy::field_reassign_with_default)] // it's more clear this way + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + largest_unit: DateDurationUnit, + smallest_unit: DateDurationUnit, + ) -> DateDuration { + Iso.until(date1, date2, &Iso, largest_unit, smallest_unit) + .cast_unit() + } + + /// The calendar-specific year represented by `date` + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + types::EraYear { + era: tinystr!(16, "be"), + era_index: Some(0), + year: self.extended_year(date), + ambiguity: types::YearAmbiguity::CenturyRequired, + } + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + Iso.extended_year(date) + BUDDHIST_ERA_OFFSET + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Iso.is_in_leap_year(date) + } + + /// The calendar-specific month represented by `date` + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + Iso.month(date) + } + + /// The calendar-specific day-of-month represented by `date` + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + Iso.day_of_month(date) + } + + /// Information of the day of the year + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + Iso.day_of_year(date) + } + + fn debug_name(&self) -> &'static str { + "Buddhist" + } + + fn calendar_algorithm(&self) -> Option { + Some(crate::preferences::CalendarAlgorithm::Buddhist) + } +} + +impl Date { + /// Construct a new Buddhist Date. + /// + /// Years are specified as BE years. + /// + /// ```rust + /// use icu::calendar::Date; + /// + /// let date_buddhist = Date::try_new_buddhist(1970, 1, 2) + /// .expect("Failed to initialize Buddhist Date instance."); + /// + /// assert_eq!(date_buddhist.era_year().year, 1970); + /// assert_eq!(date_buddhist.month().ordinal, 1); + /// assert_eq!(date_buddhist.day_of_month().0, 2); + /// ``` + pub fn try_new_buddhist(year: i32, month: u8, day: u8) -> Result, RangeError> { + Date::try_new_iso(year - BUDDHIST_ERA_OFFSET, month, day) + .map(|d| Date::new_from_iso(d, Buddhist)) + } +} + +#[cfg(test)] +mod test { + use calendrical_calculations::rata_die::RataDie; + + use super::*; + + #[test] + fn test_buddhist_roundtrip_near_rd_zero() { + for i in -10000..=10000 { + let rd = RataDie::new(i); + let iso1 = Date::from_rata_die(rd, Iso); + let buddhist = iso1.to_calendar(Buddhist); + let iso2 = buddhist.to_calendar(Iso); + let result = iso2.to_rata_die(); + assert_eq!(rd, result); + } + } + + #[test] + fn test_buddhist_roundtrip_near_epoch() { + // Buddhist epoch start RD: -198326 + for i in -208326..=-188326 { + let rd = RataDie::new(i); + let iso1 = Date::from_rata_die(rd, Iso); + let buddhist = iso1.to_calendar(Buddhist); + let iso2 = buddhist.to_calendar(Iso); + let result = iso2.to_rata_die(); + assert_eq!(rd, result); + } + } + + #[test] + fn test_buddhist_directionality_near_rd_zero() { + for i in -100..=100 { + for j in -100..=100 { + let iso_i = Date::from_rata_die(RataDie::new(i), Iso); + let iso_j = Date::from_rata_die(RataDie::new(j), Iso); + + let buddhist_i = Date::new_from_iso(iso_i, Buddhist); + let buddhist_j = Date::new_from_iso(iso_j, Buddhist); + + assert_eq!( + i.cmp(&j), + iso_i.cmp(&iso_j), + "ISO directionality inconsistent with directionality for i: {i}, j: {j}" + ); + + assert_eq!( + i.cmp(&j), + buddhist_i.cmp(&buddhist_j), + "Buddhist directionality inconsistent with directionality for i: {i}, j: {j}" + ); + } + } + } + + #[test] + fn test_buddhist_directionality_near_epoch() { + // Buddhist epoch start RD: -198326 + for i in -198426..=-198226 { + for j in -198426..=-198226 { + let iso_i = Date::from_rata_die(RataDie::new(i), Iso); + let iso_j = Date::from_rata_die(RataDie::new(j), Iso); + + let buddhist_i = Date::new_from_iso(iso_i, Buddhist); + let buddhist_j = Date::new_from_iso(iso_j, Buddhist); + + assert_eq!( + i.cmp(&j), + iso_i.cmp(&iso_j), + "ISO directionality inconsistent with directionality for i: {i}, j: {j}" + ); + + assert_eq!( + i.cmp(&j), + buddhist_i.cmp(&buddhist_j), + "Buddhist directionality inconsistent with directionality for i: {i}, j: {j}" + ); + } + } + } + + #[derive(Debug)] + struct TestCase { + iso_year: i32, + iso_month: u8, + iso_day: u8, + buddhist_year: i32, + buddhist_month: u8, + buddhist_day: u8, + } + + fn check_test_case(case: TestCase) { + let iso_year = case.iso_year; + let iso_month = case.iso_month; + let iso_day = case.iso_day; + let buddhist_year = case.buddhist_year; + let buddhist_month = case.buddhist_month; + let buddhist_day = case.buddhist_day; + + let iso1 = Date::try_new_iso(iso_year, iso_month, iso_day).unwrap(); + let buddhist1 = iso1.to_calendar(Buddhist); + assert_eq!( + buddhist1.era_year().year, + buddhist_year, + "Iso -> Buddhist year check failed for case: {case:?}" + ); + assert_eq!( + buddhist1.month().ordinal, + buddhist_month, + "Iso -> Buddhist month check failed for case: {case:?}" + ); + assert_eq!( + buddhist1.day_of_month().0, + buddhist_day, + "Iso -> Buddhist day check failed for case: {case:?}" + ); + + let buddhist2 = + Date::try_new_buddhist(buddhist_year, buddhist_month, buddhist_day).unwrap(); + let iso2 = buddhist2.to_calendar(Iso); + assert_eq!( + iso2.era_year().year, + iso_year, + "Buddhist -> Iso year check failed for case: {case:?}" + ); + assert_eq!( + iso2.month().ordinal, + iso_month, + "Buddhist -> Iso month check failed for case: {case:?}" + ); + assert_eq!( + iso2.day_of_month().0, + iso_day, + "Buddhist -> Iso day check failed for case: {case:?}" + ); + } + + #[test] + fn test_buddhist_cases_near_rd_zero() { + let cases = [ + TestCase { + iso_year: -100, + iso_month: 2, + iso_day: 15, + buddhist_year: 443, + buddhist_month: 2, + buddhist_day: 15, + }, + TestCase { + iso_year: -3, + iso_month: 10, + iso_day: 29, + buddhist_year: 540, + buddhist_month: 10, + buddhist_day: 29, + }, + TestCase { + iso_year: 0, + iso_month: 12, + iso_day: 31, + buddhist_year: 543, + buddhist_month: 12, + buddhist_day: 31, + }, + TestCase { + iso_year: 1, + iso_month: 1, + iso_day: 1, + buddhist_year: 544, + buddhist_month: 1, + buddhist_day: 1, + }, + TestCase { + iso_year: 4, + iso_month: 2, + iso_day: 29, + buddhist_year: 547, + buddhist_month: 2, + buddhist_day: 29, + }, + ]; + + for case in cases { + check_test_case(case); + } + } + + #[test] + fn test_buddhist_cases_near_epoch() { + // 1 BE = 543 BCE = -542 ISO + let cases = [ + TestCase { + iso_year: -554, + iso_month: 12, + iso_day: 31, + buddhist_year: -11, + buddhist_month: 12, + buddhist_day: 31, + }, + TestCase { + iso_year: -553, + iso_month: 1, + iso_day: 1, + buddhist_year: -10, + buddhist_month: 1, + buddhist_day: 1, + }, + TestCase { + iso_year: -544, + iso_month: 8, + iso_day: 31, + buddhist_year: -1, + buddhist_month: 8, + buddhist_day: 31, + }, + TestCase { + iso_year: -543, + iso_month: 5, + iso_day: 12, + buddhist_year: 0, + buddhist_month: 5, + buddhist_day: 12, + }, + TestCase { + iso_year: -543, + iso_month: 12, + iso_day: 31, + buddhist_year: 0, + buddhist_month: 12, + buddhist_day: 31, + }, + TestCase { + iso_year: -542, + iso_month: 1, + iso_day: 1, + buddhist_year: 1, + buddhist_month: 1, + buddhist_day: 1, + }, + TestCase { + iso_year: -541, + iso_month: 7, + iso_day: 9, + buddhist_year: 2, + buddhist_month: 7, + buddhist_day: 9, + }, + ]; + + for case in cases { + check_test_case(case); + } + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/chinese.rs b/deps/crates/vendor/icu_calendar/src/cal/chinese.rs new file mode 100644 index 00000000000000..43ec385369438a --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/chinese.rs @@ -0,0 +1,1039 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and implementations for the Chinese calendar. +//! +//! ```rust +//! use icu::calendar::{cal::Chinese, Date}; +//! +//! let chinese = Chinese::new(); +//! let chinese_date = Date::try_new_chinese_with_calendar(2023, 6, 6, chinese) +//! .expect("Failed to initialize Chinese Date instance."); +//! +//! assert_eq!(chinese_date.cyclic_year().related_iso, 2023); +//! assert_eq!(chinese_date.cyclic_year().year, 40); +//! assert_eq!(chinese_date.month().ordinal, 6); +//! assert_eq!(chinese_date.day_of_month().0, 6); +//! ``` + +use crate::cal::chinese_based::{ChineseBasedPrecomputedData, ChineseBasedWithDataLoading}; +use crate::cal::iso::{Iso, IsoDateInner}; +use crate::calendar_arithmetic::PrecomputedDataSource; +use crate::calendar_arithmetic::{ArithmeticDate, CalendarArithmetic}; +use crate::error::DateError; +use crate::provider::chinese_based::CalendarChineseV1; +use crate::AsCalendar; +use crate::{types, Calendar, Date, DateDuration, DateDurationUnit}; +use calendrical_calculations::chinese_based; +use calendrical_calculations::rata_die::RataDie; +use core::cmp::Ordering; +use icu_provider::prelude::*; + +/// The [Chinese Calendar](https://en.wikipedia.org/wiki/Chinese_calendar) +/// +/// The Chinese Calendar is a lunisolar calendar used traditionally in China as well as in other +/// countries particularly in, but not limited to, East Asia. It is often used today to track important +/// cultural events and holidays like the Chinese Lunar New Year. +/// +/// This type can be used with [`Date`] to represent dates in the Chinese calendar. +/// +/// # Months +/// +/// The Chinese calendar is an astronomical calendar which uses the phases of the moon to track months. +/// Each month starts on the date of the new moon as observed from China, meaning that months last 29 +/// or 30 days. +/// +/// One year in the Chinese calendar is typically 12 lunar months; however, because 12 lunar months does +/// not line up to one solar year, the Chinese calendar will add an intercalary leap month approximately +/// every three years to keep Chinese calendar months in line with the solar year. +/// +/// Leap months can happen after any month; the month in which a leap month occurs is based on the alignment +/// of months with 24 solar terms into which the solar year is divided. +/// +/// # Year and Era codes +/// +/// Unlike the Gregorian calendar, the Chinese calendar does not traditionally count years in an infinitely +/// increasing sequence. Instead, 10 "celestial stems" and 12 "terrestrial branches" are combined to form a +/// cycle of year names which repeats every 60 years. However, for the purposes of calendar calculations and +/// conversions, this calendar also counts years based on the ISO (Gregorian) calendar. This "related ISO year" +/// marks the ISO year in which a Chinese year begins. +/// +/// Because the Chinese calendar does not traditionally count years, era codes are not used in this calendar. +/// +/// For more information, suggested reading materials include: +/// * _Calendrical Calculations_ by Reingold & Dershowitz +/// * _The Mathematics of the Chinese Calendar_ by Helmer Aslaksen +/// * Wikipedia: +/// +/// # Month codes +/// +/// This calendar is a lunisolar calendar. It supports regular month codes `"M01" - "M12"` as well +/// as leap month codes `"M01L" - "M12L"`. +/// +/// This calendar is currently in a preview state: formatting for this calendar is not +/// going to be perfect. +#[derive(Clone, Debug, Default)] +pub struct Chinese { + data: Option>, +} + +/// The inner date type used for representing [`Date`]s of [`Chinese`]. See [`Date`] and [`Chinese`] for more details. +#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)] +pub struct ChineseDateInner(ArithmeticDate); + +// we want these impls without the `C: Copy/Clone` bounds +impl Copy for ChineseDateInner {} +impl Clone for ChineseDateInner { + fn clone(&self) -> Self { + *self + } +} + +// These impls just make custom derives on types containing C +// work. They're basically no-ops +impl PartialEq for Chinese { + fn eq(&self, _: &Self) -> bool { + true + } +} +impl Eq for Chinese {} +#[allow(clippy::non_canonical_partial_ord_impl)] // this is intentional +impl PartialOrd for Chinese { + fn partial_cmp(&self, _: &Self) -> Option { + Some(Ordering::Equal) + } +} + +impl Ord for Chinese { + fn cmp(&self, _: &Self) -> Ordering { + Ordering::Equal + } +} + +impl Chinese { + /// Creates a new [`Chinese`] with some precomputed calendrical calculations. + /// + /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + #[cfg(feature = "compiled_data")] + pub const fn new() -> Self { + Self { + data: Some(DataPayload::from_static_ref( + crate::provider::Baked::SINGLETON_CALENDAR_CHINESE_V1, + )), + } + } + + icu_provider::gen_buffer_data_constructors!(() -> error: DataError, + functions: [ + new: skip, + try_new_with_buffer_provider, + try_new_unstable, + Self, + ]); + + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new)] + pub fn try_new_unstable + ?Sized>( + provider: &D, + ) -> Result { + Ok(Self { + data: Some(provider.load(Default::default())?.payload), + }) + } + + /// Construct a new [`Chinese`] without any precomputed calendrical calculations. + pub fn new_always_calculating() -> Self { + Chinese { data: None } + } + + pub(crate) const DEBUG_NAME: &'static str = "Chinese"; +} + +impl crate::cal::scaffold::UnstableSealed for Chinese {} +impl Calendar for Chinese { + type DateInner = ChineseDateInner; + type Year = types::CyclicYear; + + // Construct a date from era/month codes and fields + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + match era { + None => {} + _ => return Err(DateError::UnknownEra), + } + + let year = self.get_precomputed_data().load_or_compute_info(year); + + let Some(month) = year.parse_month_code(month_code) else { + return Err(DateError::UnknownMonthCode(month_code)); + }; + + year.validate_md(month, day)?; + + Ok(ChineseDateInner(ArithmeticDate::new_unchecked( + year, month, day, + ))) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + let iso = Iso.from_rata_die(rd); + let y = self + .get_precomputed_data() + .load_or_compute_info_for_rd(rd, iso.0); + let (m, d) = y.md_from_rd(rd); + ChineseDateInner(ArithmeticDate::new_unchecked(y, m, d)) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + date.0.year.rd_from_md(date.0.month, date.0.day) + } + + fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner { + let rd = Iso.to_rata_die(&iso); + let y = self + .get_precomputed_data() + .load_or_compute_info_for_rd(rd, iso.0); + let (m, d) = y.md_from_rd(rd); + ChineseDateInner(ArithmeticDate::new_unchecked(y, m, d)) + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + Iso.from_rata_die(self.to_rata_die(date)) + } + + // Count the number of months in a given year, specified by providing a date + // from that year + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + date.0.days_in_year() + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + date.0.days_in_month() + } + + #[doc(hidden)] // unstable + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + date.0.offset_date(offset, &self.get_precomputed_data()); + } + + #[doc(hidden)] // unstable + #[allow(clippy::field_reassign_with_default)] + /// Calculate `date2 - date` as a duration + /// + /// `calendar2` is the calendar object associated with `date2`. In case the specific calendar objects + /// differ on date, the date for the first calendar is used, and `date2` may be converted if necessary. + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + _largest_unit: DateDurationUnit, + _smallest_unit: DateDurationUnit, + ) -> DateDuration { + date1.0.until(date2.0, _largest_unit, _smallest_unit) + } + + /// Obtain a name for the calendar for debug printing + fn debug_name(&self) -> &'static str { + Self::DEBUG_NAME + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + let year = date.0.year; + types::CyclicYear { + year: (year.related_iso - 4).rem_euclid(60) as u8 + 1, + related_iso: year.related_iso, + } + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + chinese_based::extended_from_iso::(date.0.year.related_iso) + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Self::provided_year_is_leap(date.0.year) + } + + /// The calendar-specific month code represented by `date`; + /// since the Chinese calendar has leap months, an "L" is appended to the month code for + /// leap months. For example, in a year where an intercalary month is added after the second + /// month, the month codes for ordinal months 1, 2, 3, 4, 5 would be "M01", "M02", "M02L", "M03", "M04". + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + date.0.year.month(date.0.month) + } + + /// The calendar-specific day-of-month represented by `date` + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + date.0.day_of_month() + } + + /// Information of the day of the year + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + types::DayOfYear(date.0.year.day_of_year(date.0.month, date.0.day)) + } + + fn calendar_algorithm(&self) -> Option { + Some(crate::preferences::CalendarAlgorithm::Chinese) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + date.0.months_in_year() + } +} + +impl> Date { + /// Construct a new Chinese date from a `year`, `month`, and `day`. + /// `year` represents the [ISO](crate::Iso) year that roughly matches the Chinese year; + /// `month` represents the month of the year ordinally (ex. if it is a leap year, the last month will be 13, not 12); + /// `day` indicates the day of month + /// + /// This date will not use any precomputed calendrical calculations, + /// one that loads such data from a provider will be added in the future (#3933) + /// + /// ```rust + /// use icu::calendar::{cal::Chinese, Date}; + /// + /// let chinese = Chinese::new_always_calculating(); + /// + /// let date_chinese = + /// Date::try_new_chinese_with_calendar(2023, 6, 11, chinese) + /// .expect("Failed to initialize Chinese Date instance."); + /// + /// assert_eq!(date_chinese.cyclic_year().related_iso, 2023); + /// assert_eq!(date_chinese.cyclic_year().year, 40); + /// assert_eq!(date_chinese.month().ordinal, 6); + /// assert_eq!(date_chinese.day_of_month().0, 11); + /// ``` + pub fn try_new_chinese_with_calendar( + related_iso_year: i32, + month: u8, + day: u8, + calendar: A, + ) -> Result, DateError> { + let year = calendar + .as_calendar() + .get_precomputed_data() + .load_or_compute_info(related_iso_year); + year.validate_md(month, day)?; + Ok(Date::from_raw( + ChineseDateInner(ArithmeticDate::new_unchecked(year, month, day)), + calendar, + )) + } +} + +type ChineseCB = calendrical_calculations::chinese_based::Chinese; +impl ChineseBasedWithDataLoading for Chinese { + type CB = ChineseCB; + fn get_precomputed_data(&self) -> ChineseBasedPrecomputedData { + ChineseBasedPrecomputedData::new(self.data.as_ref().map(|d| d.get())) + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::types::MonthCode; + use calendrical_calculations::{iso::fixed_from_iso, rata_die::RataDie}; + use tinystr::tinystr; + + /// Run a test twice, with two calendars + fn do_twice( + chinese_calculating: &Chinese, + chinese_cached: &Chinese, + test: impl Fn(crate::Ref, &'static str), + ) { + test(crate::Ref(chinese_calculating), "calculating"); + test(crate::Ref(chinese_cached), "cached"); + } + + #[test] + fn test_chinese_from_rd() { + #[derive(Debug)] + struct TestCase { + rd: i64, + expected_year: i32, + expected_month: u8, + expected_day: u8, + } + + let cases = [ + TestCase { + rd: -964192, + expected_year: -2, + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: -963838, + expected_year: -1, + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: -963129, + expected_year: 0, + expected_month: 13, + expected_day: 1, + }, + TestCase { + rd: -963100, + expected_year: 0, + expected_month: 13, + expected_day: 30, + }, + TestCase { + rd: -963099, + expected_year: 1, + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: 738700, + expected_year: 4660, + expected_month: 6, + expected_day: 12, + }, + TestCase { + rd: fixed_from_iso(2319, 2, 20).to_i64_date(), + expected_year: 2319 + 2636, + expected_month: 13, + expected_day: 30, + }, + TestCase { + rd: fixed_from_iso(2319, 2, 21).to_i64_date(), + expected_year: 2319 + 2636 + 1, + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: 738718, + expected_year: 4660, + expected_month: 6, + expected_day: 30, + }, + TestCase { + rd: 738747, + expected_year: 4660, + expected_month: 7, + expected_day: 29, + }, + TestCase { + rd: 738748, + expected_year: 4660, + expected_month: 8, + expected_day: 1, + }, + TestCase { + rd: 738865, + expected_year: 4660, + expected_month: 11, + expected_day: 29, + }, + TestCase { + rd: 738895, + expected_year: 4660, + expected_month: 12, + expected_day: 29, + }, + TestCase { + rd: 738925, + expected_year: 4660, + expected_month: 13, + expected_day: 30, + }, + ]; + + let chinese_calculating = Chinese::new_always_calculating(); + let chinese_cached = Chinese::new(); + for case in cases { + let rata_die = RataDie::new(case.rd); + + do_twice( + &chinese_calculating, + &chinese_cached, + |chinese, calendar_type| { + let chinese = Date::from_rata_die(rata_die, chinese); + assert_eq!( + case.expected_year, + chinese.extended_year(), + "[{calendar_type}] Chinese from RD failed, case: {case:?}" + ); + assert_eq!( + case.expected_month, + chinese.month().ordinal, + "[{calendar_type}] Chinese from RD failed, case: {case:?}" + ); + assert_eq!( + case.expected_day, + chinese.day_of_month().0, + "[{calendar_type}] Chinese from RD failed, case: {case:?}" + ); + }, + ); + } + } + + #[test] + fn test_rd_from_chinese() { + #[derive(Debug)] + struct TestCase { + year: i32, + month: u8, + day: u8, + expected: i64, + } + + let cases = [ + TestCase { + year: 2023, + month: 6, + day: 6, + // June 23 2023 + expected: 738694, + }, + TestCase { + year: -2636, + month: 1, + day: 1, + expected: -963099, + }, + ]; + + let chinese_calculating = Chinese::new_always_calculating(); + let chinese_cached = Chinese::new(); + for case in cases { + do_twice( + &chinese_calculating, + &chinese_cached, + |chinese, calendar_type| { + let date = Date::try_new_chinese_with_calendar( + case.year, case.month, case.day, chinese, + ) + .unwrap(); + let rd = date.to_rata_die().to_i64_date(); + let expected = case.expected; + assert_eq!(rd, expected, "[{calendar_type}] RD from Chinese failed, with expected: {expected} and calculated: {rd}, for test case: {case:?}"); + }, + ); + } + } + + #[test] + fn test_rd_chinese_roundtrip() { + let mut rd = -1963020; + let max_rd = 1963020; + let mut iters = 0; + let max_iters = 560; + let chinese_calculating = Chinese::new_always_calculating(); + let chinese_cached = Chinese::new(); + while rd < max_rd && iters < max_iters { + let rata_die = RataDie::new(rd); + + do_twice( + &chinese_calculating, + &chinese_cached, + |chinese, calendar_type| { + let chinese = Date::from_rata_die(rata_die, chinese); + let result = chinese.to_rata_die(); + assert_eq!(result, rata_die, "[{calendar_type}] Failed roundtrip RD -> Chinese -> RD for RD: {rata_die:?}, with calculated: {result:?} from Chinese date:\n{chinese:?}"); + }, + ); + rd += 7043; + iters += 1; + } + } + + #[test] + fn test_chinese_epoch() { + let iso = Date::try_new_iso(-2636, 2, 15).unwrap(); + + do_twice( + &Chinese::new_always_calculating(), + &Chinese::new(), + |chinese, _calendar_type| { + let chinese = iso.to_calendar(chinese); + + assert_eq!(chinese.cyclic_year().related_iso, -2636); + assert_eq!(chinese.month().ordinal, 1); + assert_eq!(chinese.month().standard_code.0, "M01"); + assert_eq!(chinese.day_of_month().0, 1); + assert_eq!(chinese.cyclic_year().year, 1); + assert_eq!(chinese.cyclic_year().related_iso, -2636); + }, + ) + } + + #[test] + fn test_iso_to_chinese_negative_years() { + #[derive(Debug)] + struct TestCase { + iso_year: i32, + iso_month: u8, + iso_day: u8, + expected_year: i32, + expected_month: u8, + expected_day: u8, + } + + let cases = [ + TestCase { + iso_year: -2636, + iso_month: 2, + iso_day: 14, + expected_year: -2637, + expected_month: 13, + expected_day: 30, + }, + TestCase { + iso_year: -2636, + iso_month: 1, + iso_day: 15, + expected_year: -2637, + expected_month: 12, + expected_day: 30, + }, + ]; + + let chinese_calculating = Chinese::new_always_calculating(); + let chinese_cached = Chinese::new(); + + for case in cases { + let iso = Date::try_new_iso(case.iso_year, case.iso_month, case.iso_day).unwrap(); + do_twice( + &chinese_calculating, + &chinese_cached, + |chinese, calendar_type| { + let chinese = iso.to_calendar(chinese); + assert_eq!( + case.expected_year, + chinese.cyclic_year().related_iso, + "[{calendar_type}] ISO to Chinese failed for case: {case:?}" + ); + assert_eq!( + case.expected_month, + chinese.month().ordinal, + "[{calendar_type}] ISO to Chinese failed for case: {case:?}" + ); + assert_eq!( + case.expected_day, + chinese.day_of_month().0, + "[{calendar_type}] ISO to Chinese failed for case: {case:?}" + ); + }, + ); + } + } + + #[test] + fn test_chinese_leap_months() { + let expected = [ + (1933, 6), + (1938, 8), + (1984, 11), + (2009, 6), + (2017, 7), + (2028, 6), + ]; + let chinese_calculating = Chinese::new_always_calculating(); + let chinese_cached = Chinese::new(); + + for case in expected { + let year = case.0; + let expected_month = case.1; + let iso = Date::try_new_iso(year, 6, 1).unwrap(); + do_twice( + &chinese_calculating, + &chinese_cached, + |chinese, calendar_type| { + let chinese_date = iso.to_calendar(chinese); + assert!( + chinese_date.is_in_leap_year(), + "[{calendar_type}] {year} should be a leap year" + ); + let new_year = chinese_date.inner.0.year.new_year(); + assert_eq!( + expected_month, + calendrical_calculations::chinese_based::get_leap_month_from_new_year::< + calendrical_calculations::chinese_based::Chinese, + >(new_year), + "[{calendar_type}] {year} have leap month {expected_month}" + ); + }, + ); + } + } + + #[test] + fn test_month_days() { + let year = + ChineseBasedPrecomputedData::<::CB>::default() + .load_or_compute_info(2023); + let cases = [ + (1, 29), + (2, 30), + (3, 29), + (4, 29), + (5, 30), + (6, 30), + (7, 29), + (8, 30), + (9, 30), + (10, 29), + (11, 30), + (12, 29), + (13, 30), + ]; + for case in cases { + let days_in_month = Chinese::days_in_provided_month(year, case.0); + assert_eq!( + case.1, days_in_month, + "month_days test failed for case: {case:?}" + ); + } + } + + #[test] + fn test_ordinal_to_month_code() { + #[derive(Debug)] + struct TestCase { + year: i32, + month: u8, + day: u8, + expected_code: &'static str, + } + + let cases = [ + TestCase { + year: 2023, + month: 1, + day: 9, + expected_code: "M12", + }, + TestCase { + year: 2023, + month: 2, + day: 9, + expected_code: "M01", + }, + TestCase { + year: 2023, + month: 3, + day: 9, + expected_code: "M02", + }, + TestCase { + year: 2023, + month: 4, + day: 9, + expected_code: "M02L", + }, + TestCase { + year: 2023, + month: 5, + day: 9, + expected_code: "M03", + }, + TestCase { + year: 2023, + month: 6, + day: 9, + expected_code: "M04", + }, + TestCase { + year: 2023, + month: 7, + day: 9, + expected_code: "M05", + }, + TestCase { + year: 2023, + month: 8, + day: 9, + expected_code: "M06", + }, + TestCase { + year: 2023, + month: 9, + day: 9, + expected_code: "M07", + }, + TestCase { + year: 2023, + month: 10, + day: 9, + expected_code: "M08", + }, + TestCase { + year: 2023, + month: 11, + day: 9, + expected_code: "M09", + }, + TestCase { + year: 2023, + month: 12, + day: 9, + expected_code: "M10", + }, + TestCase { + year: 2024, + month: 1, + day: 9, + expected_code: "M11", + }, + TestCase { + year: 2024, + month: 2, + day: 9, + expected_code: "M12", + }, + TestCase { + year: 2024, + month: 2, + day: 10, + expected_code: "M01", + }, + ]; + + let chinese_calculating = Chinese::new_always_calculating(); + let chinese_cached = Chinese::new(); + + for case in cases { + let iso = Date::try_new_iso(case.year, case.month, case.day).unwrap(); + do_twice( + &chinese_calculating, + &chinese_cached, + |chinese, calendar_type| { + let chinese = iso.to_calendar(chinese); + let result_code = chinese.month().standard_code.0; + let expected_code = case.expected_code.to_string(); + assert_eq!( + expected_code, result_code, + "[{calendar_type}] Month codes did not match for test case: {case:?}" + ); + }, + ); + } + } + + #[test] + fn test_month_code_to_ordinal() { + // construct using ::default() to force recomputation + let year = + ChineseBasedPrecomputedData::<::CB>::default() + .load_or_compute_info(2023); + let codes = [ + (1, tinystr!(4, "M01")), + (2, tinystr!(4, "M02")), + (3, tinystr!(4, "M02L")), + (4, tinystr!(4, "M03")), + (5, tinystr!(4, "M04")), + (6, tinystr!(4, "M05")), + (7, tinystr!(4, "M06")), + (8, tinystr!(4, "M07")), + (9, tinystr!(4, "M08")), + (10, tinystr!(4, "M09")), + (11, tinystr!(4, "M10")), + (12, tinystr!(4, "M11")), + (13, tinystr!(4, "M12")), + ]; + for ordinal_code_pair in codes { + let code = MonthCode(ordinal_code_pair.1); + let ordinal = year.parse_month_code(code); + assert_eq!( + ordinal, + Some(ordinal_code_pair.0), + "Code to ordinal failed for year: {}, code: {code}", + year.related_iso + ); + } + } + + #[test] + fn check_invalid_month_code_to_ordinal() { + let non_leap_year = 4659; + let leap_year = 4660; + let invalid_codes = [ + (non_leap_year, tinystr!(4, "M2")), + (leap_year, tinystr!(4, "M0")), + (non_leap_year, tinystr!(4, "J01")), + (leap_year, tinystr!(4, "3M")), + (non_leap_year, tinystr!(4, "M04L")), + (leap_year, tinystr!(4, "M04L")), + (non_leap_year, tinystr!(4, "M13")), + (leap_year, tinystr!(4, "M13")), + ]; + for (year, code) in invalid_codes { + // construct using ::default() to force recomputation + let year = ChineseBasedPrecomputedData::< + ::CB, + >::default() + .load_or_compute_info(year); + let code = MonthCode(code); + let ordinal = year.parse_month_code(code); + assert_eq!( + ordinal, None, + "Invalid month code failed for year: {}, code: {code}", + year.related_iso + ); + } + } + + #[test] + fn test_iso_chinese_roundtrip() { + let chinese_calculating = Chinese::new_always_calculating(); + let chinese_cached = Chinese::new(); + + for i in -1000..=1000 { + let year = i; + let month = i as u8 % 12 + 1; + let day = i as u8 % 28 + 1; + let iso = Date::try_new_iso(year, month, day).unwrap(); + do_twice( + &chinese_calculating, + &chinese_cached, + |chinese, calendar_type| { + let chinese = iso.to_calendar(chinese); + let result = chinese.to_calendar(Iso); + assert_eq!(iso, result, "[{calendar_type}] ISO to Chinese roundtrip failed!\nIso: {iso:?}\nChinese: {chinese:?}\nResult: {result:?}"); + }, + ); + } + } + + #[test] + fn test_consistent_with_icu() { + #[derive(Debug)] + struct TestCase { + iso_year: i32, + iso_month: u8, + iso_day: u8, + expected_rel_iso: i32, + expected_cyclic: u8, + expected_month: u8, + expected_day: u8, + } + + let cases = [ + TestCase { + iso_year: -2332, + iso_month: 3, + iso_day: 1, + expected_rel_iso: -2332, + expected_cyclic: 5, + expected_month: 1, + expected_day: 16, + }, + TestCase { + iso_year: -2332, + iso_month: 2, + iso_day: 15, + expected_rel_iso: -2332, + expected_cyclic: 5, + expected_month: 1, + expected_day: 1, + }, + TestCase { + // This test case fails to match ICU + iso_year: -2332, + iso_month: 2, + iso_day: 14, + expected_rel_iso: -2333, + expected_cyclic: 4, + expected_month: 13, + expected_day: 30, + }, + TestCase { + // This test case fails to match ICU + iso_year: -2332, + iso_month: 1, + iso_day: 17, + expected_rel_iso: -2333, + expected_cyclic: 4, + expected_month: 13, + expected_day: 2, + }, + TestCase { + // This test case fails to match ICU + iso_year: -2332, + iso_month: 1, + iso_day: 16, + expected_rel_iso: -2333, + expected_cyclic: 4, + expected_month: 13, + expected_day: 1, + }, + TestCase { + iso_year: -2332, + iso_month: 1, + iso_day: 15, + expected_rel_iso: -2333, + expected_cyclic: 4, + expected_month: 12, + expected_day: 29, + }, + TestCase { + iso_year: -2332, + iso_month: 1, + iso_day: 1, + expected_rel_iso: -2333, + expected_cyclic: 4, + expected_month: 12, + expected_day: 15, + }, + TestCase { + iso_year: -2333, + iso_month: 1, + iso_day: 16, + expected_rel_iso: -2334, + expected_cyclic: 3, + expected_month: 12, + expected_day: 19, + }, + ]; + + let chinese_calculating = Chinese::new_always_calculating(); + let chinese_cached = Chinese::new(); + + for case in cases { + let iso = Date::try_new_iso(case.iso_year, case.iso_month, case.iso_day).unwrap(); + + do_twice( + &chinese_calculating, + &chinese_cached, + |chinese, calendar_type| { + let chinese = iso.to_calendar(chinese); + let chinese_rel_iso = chinese.cyclic_year().related_iso; + let chinese_cyclic = chinese.cyclic_year().year; + let chinese_month = chinese.month().ordinal; + let chinese_day = chinese.day_of_month().0; + + assert_eq!( + chinese_rel_iso, case.expected_rel_iso, + "[{calendar_type}] Related ISO failed for test case: {case:?}" + ); + assert_eq!( + chinese_cyclic, case.expected_cyclic, + "[{calendar_type}] Cyclic year failed for test case: {case:?}" + ); + assert_eq!( + chinese_month, case.expected_month, + "[{calendar_type}] Month failed for test case: {case:?}" + ); + assert_eq!( + chinese_day, case.expected_day, + "[{calendar_type}] Day failed for test case: {case:?}" + ); + }, + ); + } + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/chinese_based.rs b/deps/crates/vendor/icu_calendar/src/cal/chinese_based.rs new file mode 100644 index 00000000000000..08ca5c81620104 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/chinese_based.rs @@ -0,0 +1,446 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and traits for use in the Chinese traditional lunar calendar, +//! as well as in related and derived calendars such as the Korean and Vietnamese lunar calendars. + +use crate::{ + calendar_arithmetic::{ArithmeticDate, CalendarArithmetic, PrecomputedDataSource}, + error::DateError, + provider::chinese_based::{ChineseBasedCache, PackedChineseBasedYearInfo}, + types::{MonthCode, MonthInfo}, + Calendar, Iso, +}; + +use calendrical_calculations::chinese_based::{self, ChineseBased, YearBounds}; +use calendrical_calculations::rata_die::RataDie; +use core::marker::PhantomData; +use tinystr::tinystr; + +/// The trait ChineseBased is used by Chinese-based calendars to perform computations shared by such calendar. +/// +/// For an example of how to use this trait, see `impl ChineseBasedWithDataLoading for Chinese` in [`Chinese`]. +pub(crate) trait ChineseBasedWithDataLoading: Calendar { + type CB: ChineseBased; + /// Get the compiled const data for a ChineseBased calendar; can return `None` if the given year + /// does not correspond to any compiled data. + fn get_precomputed_data(&self) -> ChineseBasedPrecomputedData<'_, Self::CB>; +} + +/// Contains any loaded precomputed data. If constructed with Default, will +/// *not* contain any extra data and will always compute stuff from scratch +#[derive(Default)] +pub(crate) struct ChineseBasedPrecomputedData<'a, CB: ChineseBased> { + data: Option<&'a ChineseBasedCache<'a>>, + _cb: PhantomData, +} + +impl PrecomputedDataSource + for ChineseBasedPrecomputedData<'_, CB> +{ + fn load_or_compute_info(&self, related_iso: i32) -> ChineseBasedYearInfo { + self.data + .and_then(|d| { + Some(ChineseBasedYearInfo { + packed_data: d + .data + .get(usize::try_from(related_iso - d.first_related_iso_year).ok()?)?, + related_iso, + }) + }) + .unwrap_or_else(|| ChineseBasedYearInfo::compute::(related_iso)) + } +} + +impl<'b, CB: ChineseBased> ChineseBasedPrecomputedData<'b, CB> { + pub(crate) fn new(data: Option<&'b ChineseBasedCache<'b>>) -> Self { + Self { + data, + _cb: PhantomData, + } + } + + /// Given an ISO date (in both ArithmeticDate and R.D. format), returns the ChineseBasedYearInfo and extended year for that date, loading + /// from cache or computing. + pub(crate) fn load_or_compute_info_for_rd( + &self, + rd: RataDie, + iso: ArithmeticDate, + ) -> ChineseBasedYearInfo { + if let Some(cached) = self.data.and_then(|d| { + let delta = usize::try_from(iso.year - d.first_related_iso_year).ok()?; + if delta == 0 { + return None; + } + + let packed_data = d.data.get(delta)?; + if iso.day_of_year().0 > packed_data.ny_offset() as u16 { + Some(ChineseBasedYearInfo { + packed_data, + related_iso: iso.year, + }) + } else { + // We're dealing with an ISO day in the beginning of the year, before Chinese New Year. + // Return data for the previous Chinese year instead. + if delta <= 1 { + return None; + } + Some(ChineseBasedYearInfo { + packed_data: d.data.get(delta - 1)?, + related_iso: iso.year - 1, + }) + } + }) { + return cached; + }; + // compute + + let mid_year = calendrical_calculations::iso::fixed_from_iso(iso.year, 7, 1); + let year_bounds = YearBounds::compute::(mid_year); + let YearBounds { new_year, .. } = year_bounds; + if rd >= new_year { + ChineseBasedYearInfo::compute_with_yb::(iso.year, year_bounds) + } else { + ChineseBasedYearInfo::compute::(iso.year - 1) + } + } +} + +/// A data struct used to load and use information for a set of ChineseBasedDates +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +// TODO(#3933): potentially make this smaller +pub(crate) struct ChineseBasedYearInfo { + /// Contains: + /// - length of each month in the year + /// - whether or not there is a leap month, and which month it is + /// - the date of Chinese New Year in the related ISO year + packed_data: PackedChineseBasedYearInfo, + pub(crate) related_iso: i32, +} + +impl From for i32 { + fn from(value: ChineseBasedYearInfo) -> Self { + value.related_iso + } +} + +impl ChineseBasedYearInfo { + /// Compute ChineseBasedYearInfo for a given extended year + fn compute(related_iso: i32) -> Self { + let mid_year = calendrical_calculations::iso::fixed_from_iso(related_iso, 7, 1); + let year_bounds = YearBounds::compute::(mid_year); + Self::compute_with_yb::(related_iso, year_bounds) + } + + /// Compute ChineseBasedYearInfo for a given extended year, for which you have already computed the YearBounds + fn compute_with_yb(related_iso: i32, year_bounds: YearBounds) -> Self { + let YearBounds { + new_year, + next_new_year, + .. + } = year_bounds; + let (month_lengths, leap_month) = + chinese_based::month_structure_for_year::(new_year, next_new_year); + + let ny_offset = new_year - calendrical_calculations::iso::fixed_from_iso(related_iso, 1, 1); + Self { + packed_data: PackedChineseBasedYearInfo::new(month_lengths, leap_month, ny_offset), + related_iso, + } + } + + /// Get the new year R.D. + pub(crate) fn new_year(self) -> RataDie { + calendrical_calculations::iso::fixed_from_iso(self.related_iso, 1, 1) + + self.packed_data.ny_offset() as i64 + } + + /// Get the next new year R.D. + fn next_new_year(self) -> RataDie { + self.new_year() + i64::from(self.days_in_year()) + } + + /// Get which month is the leap month. This produces the month *number* + /// that is the leap month (not the ordinal month). In other words, for + /// a year with an M05L, this will return Some(5). Note that the regular month precedes + /// the leap month. + fn leap_month(self) -> Option { + self.packed_data.leap_month() + } + + /// The last day of year in the previous month. + /// `month` is 1-indexed, and the returned value is also + /// a 1-indexed day of year + /// + /// Will be zero for the first month as the last day of the previous month + /// is not in this year + fn last_day_of_previous_month(self, month: u8) -> u16 { + debug_assert!((1..=13).contains(&month), "Month out of bounds!"); + // Get the last day of the previous month. + // Since `month` is 1-indexed, this needs to check if the month is 1 for the zero case + if month == 1 { + 0 + } else { + self.packed_data.last_day_of_month(month - 1) + } + } + + fn days_in_year(self) -> u16 { + self.last_day_of_month(self.months_in_year()) + } + + /// Return the number of months in a given year, which is 13 in a leap year, and 12 in a common year. + fn months_in_year(self) -> u8 { + if self.leap_month().is_some() { + 13 + } else { + 12 + } + } + + /// The last day of year in the current month. + /// `month` is 1-indexed, and the returned value is also + /// a 1-indexed day of year + /// + /// Will be zero for the first month as the last day of the previous month + /// is not in this year + fn last_day_of_month(self, month: u8) -> u16 { + debug_assert!((1..=13).contains(&month), "Month out of bounds!"); + self.packed_data.last_day_of_month(month) + } + + fn days_in_month(self, month: u8) -> u8 { + if self.packed_data.month_has_30_days(month) { + 30 + } else { + 29 + } + } + + pub(crate) fn md_from_rd(self, rd: RataDie) -> (u8, u8) { + debug_assert!( + rd < self.next_new_year(), + "Stored date {rd:?} out of bounds!" + ); + // 1-indexed day of year + let day_of_year = u16::try_from(rd - self.new_year() + 1); + debug_assert!(day_of_year.is_ok(), "Somehow got a very large year in data"); + let day_of_year = day_of_year.unwrap_or(1); + let mut month = 1; + // TODO(#3933) perhaps use a binary search + for iter_month in 1..=13 { + month = iter_month; + if self.last_day_of_month(iter_month) >= day_of_year { + break; + } + } + + debug_assert!((1..=13).contains(&month), "Month out of bounds!"); + + debug_assert!( + month < 13 || self.leap_month().is_some(), + "Cannot have 13 months in a non-leap year!" + ); + let day_before_month_start = self.last_day_of_previous_month(month); + let day_of_month = day_of_year - day_before_month_start; + let day_of_month = u8::try_from(day_of_month); + debug_assert!(day_of_month.is_ok(), "Month too big!"); + let day_of_month = day_of_month.unwrap_or(1); + + (month, day_of_month) + } + + pub(crate) fn rd_from_md(self, month: u8, day: u8) -> RataDie { + self.new_year() + self.day_of_year(month, day) as i64 - 1 + } + + /// Calculate the number of days in the year so far for a ChineseBasedDate; + /// similar to `CalendarArithmetic::day_of_year` + pub(crate) fn day_of_year(self, month: u8, day: u8) -> u16 { + self.last_day_of_previous_month(month) + day as u16 + } + + /// The calendar-specific month code represented by `month`; + /// since the Chinese calendar has leap months, an "L" is appended to the month code for + /// leap months. For example, in a year where an intercalary month is added after the second + /// month, the month codes for ordinal months 1, 2, 3, 4, 5 would be "M01", "M02", "M02L", "M03", "M04". + pub(crate) fn month(self, month: u8) -> MonthInfo { + // 1 indexed leap month name. This is also the ordinal for the leap month + // in the year (e.g. in `M01, M01L, M02, ..`, the leap month is for month 1, and it is also + // ordinally `month 2`, zero-indexed) + // 14 is a sentinel value + let leap_month = self.leap_month().unwrap_or(14); + let code_inner = if leap_month == month { + // Month cannot be 1 because a year cannot have a leap month before the first actual month, + // and the maximum num of months ina leap year is 13. + debug_assert!((2..=13).contains(&month)); + match month { + 2 => tinystr!(4, "M01L"), + 3 => tinystr!(4, "M02L"), + 4 => tinystr!(4, "M03L"), + 5 => tinystr!(4, "M04L"), + 6 => tinystr!(4, "M05L"), + 7 => tinystr!(4, "M06L"), + 8 => tinystr!(4, "M07L"), + 9 => tinystr!(4, "M08L"), + 10 => tinystr!(4, "M09L"), + 11 => tinystr!(4, "M10L"), + 12 => tinystr!(4, "M11L"), + 13 => tinystr!(4, "M12L"), + _ => tinystr!(4, "und"), + } + } else { + let mut adjusted_ordinal = month; + if month > leap_month { + // Before adjusting for leap month, if ordinal > leap_month, + // the month cannot be 1 because this implies the leap month is < 1, which is impossible; + // cannot be 2 because that implies the leap month is = 1, which is impossible, + // and cannot be more than 13 because max number of months in a year is 13. + debug_assert!((2..=13).contains(&month)); + adjusted_ordinal -= 1; + } + debug_assert!((1..=12).contains(&adjusted_ordinal)); + match adjusted_ordinal { + 1 => tinystr!(4, "M01"), + 2 => tinystr!(4, "M02"), + 3 => tinystr!(4, "M03"), + 4 => tinystr!(4, "M04"), + 5 => tinystr!(4, "M05"), + 6 => tinystr!(4, "M06"), + 7 => tinystr!(4, "M07"), + 8 => tinystr!(4, "M08"), + 9 => tinystr!(4, "M09"), + 10 => tinystr!(4, "M10"), + 11 => tinystr!(4, "M11"), + 12 => tinystr!(4, "M12"), + _ => tinystr!(4, "und"), + } + }; + let code = MonthCode(code_inner); + MonthInfo { + ordinal: month, + standard_code: code, + formatting_code: code, + } + } + + /// Create a new arithmetic date from a year, month ordinal, and day with bounds checking; returns the + /// result of creating this arithmetic date, as well as a ChineseBasedYearInfo - either the one passed in + /// optionally as an argument, or a new ChineseBasedYearInfo for the given year, month, and day args. + pub(crate) fn validate_md(self, month: u8, day: u8) -> Result<(), DateError> { + let max_month = self.months_in_year(); + if month == 0 || !(1..=max_month).contains(&month) { + return Err(DateError::Range { + field: "month", + value: month as i32, + min: 1, + max: max_month as i32, + }); + } + + let max_day = self.days_in_month(month); + if day == 0 || day > max_day { + return Err(DateError::Range { + field: "day", + value: day as i32, + min: 1, + max: max_day as i32, + }); + } + Ok(()) + } + + /// Get the ordinal lunar month from a code for chinese-based calendars. + pub(crate) fn parse_month_code(self, code: MonthCode) -> Option { + // 14 is a sentinel value, greater than all other months, for the purpose of computation only; + // it is impossible to actually have 14 months in a year. + let leap_month = self.leap_month().unwrap_or(14); + + if code.0.len() < 3 { + return None; + } + let bytes = code.0.all_bytes(); + if bytes[0] != b'M' { + return None; + } + if code.0.len() == 4 && bytes[3] != b'L' { + return None; + } + // Unadjusted is zero-indexed month index, must add one to it to use + let mut unadjusted = 0; + if bytes[1] == b'0' { + if bytes[2] >= b'1' && bytes[2] <= b'9' { + unadjusted = bytes[2] - b'0'; + } + } else if bytes[1] == b'1' && bytes[2] >= b'0' && bytes[2] <= b'2' { + unadjusted = 10 + bytes[2] - b'0'; + } + if bytes[3] == b'L' { + // Asked for a leap month that doesn't exist + if unadjusted + 1 != leap_month { + return None; + } else { + // The leap month occurs after the regular month of the same name + return Some(unadjusted + 1); + } + } + if unadjusted != 0 { + // If the month has an index greater than that of the leap month, + // bump it up by one + if unadjusted + 1 > leap_month { + return Some(unadjusted + 1); + } else { + return Some(unadjusted); + } + } + None + } +} + +impl CalendarArithmetic for C { + type YearInfo = ChineseBasedYearInfo; + + fn days_in_provided_month(year: ChineseBasedYearInfo, month: u8) -> u8 { + year.days_in_month(month) + } + + /// Returns the number of months in a given year, which is 13 in a leap year, and 12 in a common year. + fn months_in_provided_year(year: ChineseBasedYearInfo) -> u8 { + year.months_in_year() + } + + /// Returns true if the given year is a leap year, and false if not. + fn provided_year_is_leap(year: ChineseBasedYearInfo) -> bool { + year.leap_month().is_some() + } + + /// Returns the (month, day) of the last day in a Chinese year (the day before Chinese New Year). + /// The last month in a year will always be 12 in a common year or 13 in a leap year. The day is + /// determined by finding the day immediately before the next new year and calculating the number + /// of days since the last new moon (beginning of the last month in the year). + fn last_month_day_in_provided_year(year: ChineseBasedYearInfo) -> (u8, u8) { + if year.leap_month().is_some() { + (13, year.days_in_month(13)) + } else { + (12, year.days_in_month(12)) + } + } + + fn days_in_provided_year(year: ChineseBasedYearInfo) -> u16 { + year.days_in_year() + } +} + +#[cfg(feature = "datagen")] +impl ChineseBasedCache<'_> { + /// Compute this data for a range of years + pub fn compute_for(related_isos: core::ops::Range) -> Self { + ChineseBasedCache { + first_related_iso_year: related_isos.start, + data: related_isos + .map(|related_iso| ChineseBasedYearInfo::compute::(related_iso).packed_data) + .collect(), + } + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/coptic.rs b/deps/crates/vendor/icu_calendar/src/cal/coptic.rs new file mode 100644 index 00000000000000..4eb8bd7f148909 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/coptic.rs @@ -0,0 +1,234 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and implementations for the Coptic calendar. +//! +//! ```rust +//! use icu::calendar::{cal::Coptic, Date}; +//! +//! let date_iso = Date::try_new_iso(1970, 1, 2) +//! .expect("Failed to initialize ISO Date instance."); +//! let date_coptic = Date::new_from_iso(date_iso, Coptic); +//! +//! assert_eq!(date_coptic.era_year().year, 1686); +//! assert_eq!(date_coptic.month().ordinal, 4); +//! assert_eq!(date_coptic.day_of_month().0, 24); +//! ``` + +use crate::cal::iso::{Iso, IsoDateInner}; +use crate::calendar_arithmetic::{ArithmeticDate, CalendarArithmetic}; +use crate::error::DateError; +use crate::{types, Calendar, Date, DateDuration, DateDurationUnit, RangeError}; +use calendrical_calculations::helpers::I32CastError; +use calendrical_calculations::rata_die::RataDie; +use tinystr::tinystr; + +/// The [Coptic Calendar] +/// +/// The [Coptic calendar] is a solar calendar used by the Coptic Orthodox Church, with twelve normal months +/// and a thirteenth small epagomenal month. +/// +/// This type can be used with [`Date`] to represent dates in this calendar. +/// +/// [Coptic calendar]: https://en.wikipedia.org/wiki/Coptic_calendar +/// +/// # Era codes +/// +/// This calendar uses a single code: `am`, corresponding to the After Diocletian/Anno Martyrum +/// era. 1 A.M. is equivalent to 284 C.E. +/// +/// # Month codes +/// +/// This calendar supports 13 solar month codes (`"M01" - "M13"`), with `"M13"` being used for the short epagomenal month +/// at the end of the year. +#[derive(Copy, Clone, Debug, Hash, Default, Eq, PartialEq, PartialOrd, Ord)] +#[allow(clippy::exhaustive_structs)] // this type is stable +pub struct Coptic; + +/// The inner date type used for representing [`Date`]s of [`Coptic`]. See [`Date`] and [`Coptic`] for more details. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +pub struct CopticDateInner(pub(crate) ArithmeticDate); + +impl CalendarArithmetic for Coptic { + type YearInfo = i32; + + fn days_in_provided_month(year: i32, month: u8) -> u8 { + if (1..=12).contains(&month) { + 30 + } else if month == 13 { + if Self::provided_year_is_leap(year) { + 6 + } else { + 5 + } + } else { + 0 + } + } + + fn months_in_provided_year(_: i32) -> u8 { + 13 + } + + fn provided_year_is_leap(year: i32) -> bool { + year.rem_euclid(4) == 3 + } + + fn last_month_day_in_provided_year(year: i32) -> (u8, u8) { + if Self::provided_year_is_leap(year) { + (13, 6) + } else { + (13, 5) + } + } + + fn days_in_provided_year(year: i32) -> u16 { + if Self::provided_year_is_leap(year) { + 366 + } else { + 365 + } + } +} + +impl crate::cal::scaffold::UnstableSealed for Coptic {} +impl Calendar for Coptic { + type DateInner = CopticDateInner; + type Year = types::EraYear; + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + let year = match era { + Some("am") | None => year, + Some(_) => return Err(DateError::UnknownEra), + }; + + ArithmeticDate::new_from_codes(self, year, month_code, day).map(CopticDateInner) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + CopticDateInner( + match calendrical_calculations::coptic::coptic_from_fixed(rd) { + Err(I32CastError::BelowMin) => ArithmeticDate::min_date(), + Err(I32CastError::AboveMax) => ArithmeticDate::max_date(), + Ok((year, month, day)) => ArithmeticDate::new_unchecked(year, month, day), + }, + ) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + calendrical_calculations::coptic::fixed_from_coptic(date.0.year, date.0.month, date.0.day) + } + + fn from_iso(&self, iso: IsoDateInner) -> CopticDateInner { + self.from_rata_die(Iso.to_rata_die(&iso)) + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + Iso.from_rata_die(self.to_rata_die(date)) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + date.0.months_in_year() + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + date.0.days_in_year() + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + date.0.days_in_month() + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + date.0.offset_date(offset, &()); + } + + #[allow(clippy::field_reassign_with_default)] + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + _largest_unit: DateDurationUnit, + _smallest_unit: DateDurationUnit, + ) -> DateDuration { + date1.0.until(date2.0, _largest_unit, _smallest_unit) + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + let year = self.extended_year(date); + types::EraYear { + era: tinystr!(16, "am"), + era_index: Some(0), + year, + ambiguity: types::YearAmbiguity::CenturyRequired, + } + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + date.0.extended_year() + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Self::provided_year_is_leap(date.0.year) + } + + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + date.0.month() + } + + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + date.0.day_of_month() + } + + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + date.0.day_of_year() + } + + fn debug_name(&self) -> &'static str { + "Coptic" + } + + fn calendar_algorithm(&self) -> Option { + Some(crate::preferences::CalendarAlgorithm::Coptic) + } +} + +impl Date { + /// Construct new Coptic Date. + /// + /// ```rust + /// use icu::calendar::Date; + /// + /// let date_coptic = Date::try_new_coptic(1686, 5, 6) + /// .expect("Failed to initialize Coptic Date instance."); + /// + /// assert_eq!(date_coptic.era_year().year, 1686); + /// assert_eq!(date_coptic.month().ordinal, 5); + /// assert_eq!(date_coptic.day_of_month().0, 6); + /// ``` + pub fn try_new_coptic(year: i32, month: u8, day: u8) -> Result, RangeError> { + ArithmeticDate::new_from_ordinals(year, month, day) + .map(CopticDateInner) + .map(|inner| Date::from_raw(inner, Coptic)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_coptic_regression() { + // https://github.com/unicode-org/icu4x/issues/2254 + let iso_date = Date::try_new_iso(-100, 3, 3).unwrap(); + let coptic = iso_date.to_calendar(Coptic); + let recovered_iso = coptic.to_iso(); + assert_eq!(iso_date, recovered_iso); + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/dangi.rs b/deps/crates/vendor/icu_calendar/src/cal/dangi.rs new file mode 100644 index 00000000000000..e0eef839a53d85 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/dangi.rs @@ -0,0 +1,932 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and implementations for the Korean Dangi calendar. +//! +//! ```rust +//! use icu::calendar::cal::Dangi; +//! use icu::calendar::Date; +//! +//! let dangi = Dangi::new(); +//! let dangi_date = Date::try_new_dangi_with_calendar(2023, 6, 6, dangi) +//! .expect("Failed to initialize Dangi Date instance."); +//! +//! assert_eq!(dangi_date.cyclic_year().related_iso, 2023); +//! assert_eq!(dangi_date.cyclic_year().year, 40); +//! assert_eq!(dangi_date.month().ordinal, 6); +//! assert_eq!(dangi_date.day_of_month().0, 6); +//! ``` + +use crate::cal::chinese_based::{ChineseBasedPrecomputedData, ChineseBasedWithDataLoading}; +use crate::cal::iso::{Iso, IsoDateInner}; +use crate::calendar_arithmetic::PrecomputedDataSource; +use crate::calendar_arithmetic::{ArithmeticDate, CalendarArithmetic}; +use crate::error::DateError; +use crate::provider::chinese_based::CalendarDangiV1; +use crate::types::CyclicYear; +use crate::AsCalendar; +use crate::{types, Calendar, Date}; +use calendrical_calculations::chinese_based; +use calendrical_calculations::rata_die::RataDie; +use core::cmp::Ordering; +use icu_provider::prelude::*; + +/// The [Traditional Korean (Dangi) Calendar](https://en.wikipedia.org/wiki/Korean_calendar) +/// +/// The Dangi Calendar is a lunisolar calendar used traditionally in North and South Korea. +/// It is often used today to track important cultural events and holidays like Seollal +/// (Korean lunar new year). It is similar to the Chinese lunar calendar (see [`Chinese`](super::Chinese)), +/// except that observations are based in Korea (currently UTC+9) rather than China (UTC+8). +/// This can cause some differences; for example, 2012 was a leap year, but in the Dangi +/// calendar the leap month was 3, while in the Chinese calendar the leap month was 4. +/// +/// This calendar is currently in a preview state: formatting for this calendar is not +/// going to be perfect. +/// +/// ```rust +/// use icu::calendar::cal::{Chinese, Dangi}; +/// use icu::calendar::Date; +/// use tinystr::tinystr; +/// +/// let iso_a = Date::try_new_iso(2012, 4, 23).unwrap(); +/// let dangi_a = iso_a.to_calendar(Dangi::new()); +/// let chinese_a = iso_a.to_calendar(Chinese::new()); +/// +/// assert_eq!(dangi_a.month().standard_code.0, tinystr!(4, "M03L")); +/// assert_eq!(chinese_a.month().standard_code.0, tinystr!(4, "M04")); +/// +/// let iso_b = Date::try_new_iso(2012, 5, 23).unwrap(); +/// let dangi_b = iso_b.to_calendar(Dangi::new()); +/// let chinese_b = iso_b.to_calendar(Chinese::new()); +/// +/// assert_eq!(dangi_b.month().standard_code.0, tinystr!(4, "M04")); +/// assert_eq!(chinese_b.month().standard_code.0, tinystr!(4, "M04L")); +/// ``` +/// # Era codes +/// +/// This calendar does not use era codes. +/// +/// # Month codes +/// +/// This calendar is a lunisolar calendar. It supports regular month codes `"M01" - "M12"` as well +/// as leap month codes `"M01L" - "M12L"`. +#[derive(Clone, Debug, Default)] +pub struct Dangi { + data: Option>, +} + +/// The inner date type used for representing [`Date`]s of [`Dangi`]. See [`Date`] and [`Dangi`] for more detail. +#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)] +pub struct DangiDateInner(ArithmeticDate); + +// we want these impls without the `C: Copy/Clone` bounds +impl Copy for DangiDateInner {} +impl Clone for DangiDateInner { + fn clone(&self) -> Self { + *self + } +} + +// These impls just make custom derives on types containing C +// work. They're basically no-ops +impl PartialEq for Dangi { + fn eq(&self, _: &Self) -> bool { + true + } +} +impl Eq for Dangi {} +#[allow(clippy::non_canonical_partial_ord_impl)] // this is intentional +impl PartialOrd for Dangi { + fn partial_cmp(&self, _: &Self) -> Option { + Some(Ordering::Equal) + } +} + +impl Ord for Dangi { + fn cmp(&self, _: &Self) -> Ordering { + Ordering::Equal + } +} + +impl Dangi { + /// Creates a new [`Dangi`] with some precomputed calendrical calculations. + /// + /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + #[cfg(feature = "compiled_data")] + pub const fn new() -> Self { + Self { + data: Some(DataPayload::from_static_ref( + crate::provider::Baked::SINGLETON_CALENDAR_DANGI_V1, + )), + } + } + + icu_provider::gen_buffer_data_constructors!(() -> error: DataError, + functions: [ + new: skip, + try_new_with_buffer_provider, + try_new_unstable, + Self, + ]); + + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new)] + pub fn try_new_unstable + ?Sized>( + provider: &D, + ) -> Result { + Ok(Self { + data: Some(provider.load(Default::default())?.payload), + }) + } + + /// Construct a new [`Dangi`] without any precomputed calendrical calculations. + pub fn new_always_calculating() -> Self { + Dangi { data: None } + } + + pub(crate) const DEBUG_NAME: &'static str = "Dangi"; +} + +impl crate::cal::scaffold::UnstableSealed for Dangi {} +impl Calendar for Dangi { + type DateInner = DangiDateInner; + type Year = CyclicYear; + + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: crate::types::MonthCode, + day: u8, + ) -> Result { + match era { + None => {} + _ => return Err(DateError::UnknownEra), + } + + let year = self.get_precomputed_data().load_or_compute_info(year); + + let Some(month) = year.parse_month_code(month_code) else { + return Err(DateError::UnknownMonthCode(month_code)); + }; + + year.validate_md(month, day)?; + + Ok(DangiDateInner(ArithmeticDate::new_unchecked( + year, month, day, + ))) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + let iso = Iso.from_rata_die(rd); + let y = self + .get_precomputed_data() + .load_or_compute_info_for_rd(rd, iso.0); + let (m, d) = y.md_from_rd(rd); + DangiDateInner(ArithmeticDate::new_unchecked(y, m, d)) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + date.0.year.rd_from_md(date.0.month, date.0.day) + } + + fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner { + let rd = Iso.to_rata_die(&iso); + let y = self + .get_precomputed_data() + .load_or_compute_info_for_rd(rd, iso.0); + let (m, d) = y.md_from_rd(rd); + DangiDateInner(ArithmeticDate::new_unchecked(y, m, d)) + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + Iso.from_rata_die(self.to_rata_die(date)) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + date.0.months_in_year() + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + date.0.days_in_year() + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + date.0.days_in_month() + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: crate::DateDuration) { + date.0.offset_date(offset, &self.get_precomputed_data()); + } + + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + largest_unit: crate::DateDurationUnit, + smallest_unit: crate::DateDurationUnit, + ) -> crate::DateDuration { + date1.0.until(date2.0, largest_unit, smallest_unit) + } + + fn debug_name(&self) -> &'static str { + Self::DEBUG_NAME + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + let year = date.0.year; + CyclicYear { + year: (year.related_iso as i64 - 4).rem_euclid(60) as u8 + 1, + related_iso: year.related_iso, + } + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + chinese_based::extended_from_iso::(date.0.year.related_iso) + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Self::provided_year_is_leap(date.0.year) + } + + fn month(&self, date: &Self::DateInner) -> crate::types::MonthInfo { + date.0.year.month(date.0.month) + } + + fn day_of_month(&self, date: &Self::DateInner) -> crate::types::DayOfMonth { + date.0.day_of_month() + } + + fn day_of_year(&self, date: &Self::DateInner) -> crate::types::DayOfYear { + types::DayOfYear(date.0.year.day_of_year(date.0.month, date.0.day)) + } + + fn calendar_algorithm(&self) -> Option { + Some(crate::preferences::CalendarAlgorithm::Dangi) + } +} + +impl> Date { + /// Construct a new Dangi date from a `year`, `month`, and `day`. + /// `year` represents the [ISO](crate::Iso) year that roughly matches the Dangi year; + /// `month` represents the month of the year ordinally (ex. if it is a leap year, the last month will be 13, not 12); + /// `day` indicates day of month. + /// + /// This date will not use any precomputed calendrical calculations, + /// one that loads such data from a provider will be added in the future (#3933) + /// + /// ```rust + /// use icu::calendar::cal::Dangi; + /// use icu::calendar::Date; + /// + /// let dangi = Dangi::new(); + /// + /// let date_dangi = Date::try_new_dangi_with_calendar(2023, 6, 18, dangi) + /// .expect("Failed to initialize Dangi Date instance."); + /// + /// assert_eq!(date_dangi.cyclic_year().related_iso, 2023); + /// assert_eq!(date_dangi.cyclic_year().year, 40); + /// assert_eq!(date_dangi.month().ordinal, 6); + /// assert_eq!(date_dangi.day_of_month().0, 18); + /// ``` + pub fn try_new_dangi_with_calendar( + related_iso_year: i32, + month: u8, + day: u8, + calendar: A, + ) -> Result, DateError> { + let year = calendar + .as_calendar() + .get_precomputed_data() + .load_or_compute_info(related_iso_year); + year.validate_md(month, day)?; + Ok(Date::from_raw( + DangiDateInner(ArithmeticDate::new_unchecked(year, month, day)), + calendar, + )) + } +} + +impl ChineseBasedWithDataLoading for Dangi { + type CB = calendrical_calculations::chinese_based::Dangi; + fn get_precomputed_data(&self) -> ChineseBasedPrecomputedData { + ChineseBasedPrecomputedData::new(self.data.as_ref().map(|d| d.get())) + } +} + +#[cfg(test)] +mod test { + + use super::*; + use crate::cal::Chinese; + use calendrical_calculations::rata_die::RataDie; + + /// Run a test twice, with two calendars + fn do_twice( + dangi_calculating: &Dangi, + dangi_cached: &Dangi, + test: impl Fn(crate::Ref, &'static str), + ) { + test(crate::Ref(dangi_calculating), "calculating"); + test(crate::Ref(dangi_cached), "cached"); + } + + fn check_cyclic_and_rel_iso(year: i32) { + let iso = Date::try_new_iso(year, 6, 6).unwrap(); + let chinese = iso.to_calendar(Chinese::new_always_calculating()); + let dangi = iso.to_calendar(Dangi::new_always_calculating()); + let chinese_year = chinese.cyclic_year(); + let korean_year = dangi.cyclic_year(); + assert_eq!( + chinese_year, korean_year, + "Cyclic year failed for year: {year}" + ); + let chinese_rel_iso = chinese_year.related_iso; + let korean_rel_iso = korean_year.related_iso; + assert_eq!( + chinese_rel_iso, korean_rel_iso, + "Rel. ISO year equality failed for year: {year}" + ); + assert_eq!(korean_rel_iso, year, "Dangi Rel. ISO failed!"); + } + + #[test] + fn test_cyclic_same_as_chinese_near_present_day() { + for year in 1923..=2123 { + check_cyclic_and_rel_iso(year); + } + } + + #[test] + fn test_cyclic_same_as_chinese_near_rd_zero() { + for year in -100..=100 { + check_cyclic_and_rel_iso(year); + } + } + + #[test] + fn test_iso_to_dangi_roundtrip() { + let mut rd = -1963020; + let max_rd = 1963020; + let mut iters = 0; + let max_iters = 560; + let dangi_calculating = Dangi::new_always_calculating(); + let dangi_cached = Dangi::new(); + while rd < max_rd && iters < max_iters { + let rata_die = RataDie::new(rd); + let iso = Date::from_rata_die(rata_die, Iso); + do_twice(&dangi_calculating, &dangi_cached, |dangi, calendar_type| { + let korean = iso.to_calendar(dangi); + let result = korean.to_calendar(Iso); + assert_eq!( + iso, result, + "[{calendar_type}] Failed roundtrip ISO -> Dangi -> ISO for RD: {rd}" + ); + }); + + rd += 7043; + iters += 1; + } + } + + #[test] + fn test_dangi_consistent_with_icu() { + // Test cases for this test are derived from existing ICU Intl.DateTimeFormat. If there is a bug in ICU, + // these test cases may be affected, and this calendar's output may not be entirely valid. + + // There are a number of test cases which do not match ICU for dates very far in the past or future, + // see #3709. + + #[derive(Debug)] + struct TestCase { + iso_year: i32, + iso_month: u8, + iso_day: u8, + expected_rel_iso: i32, + expected_cyclic: u8, + expected_month: u8, + expected_day: u8, + } + + let cases = [ + TestCase { + // #3709: This test case fails to match ICU + iso_year: 4321, + iso_month: 1, + iso_day: 23, + expected_rel_iso: 4320, + expected_cyclic: 57, + expected_month: 13, + expected_day: 12, + }, + TestCase { + iso_year: 3649, + iso_month: 9, + iso_day: 20, + expected_rel_iso: 3649, + expected_cyclic: 46, + expected_month: 9, + expected_day: 1, + }, + TestCase { + iso_year: 3333, + iso_month: 3, + iso_day: 3, + expected_rel_iso: 3333, + expected_cyclic: 30, + expected_month: 1, + expected_day: 25, + }, + TestCase { + iso_year: 3000, + iso_month: 3, + iso_day: 30, + expected_rel_iso: 3000, + expected_cyclic: 57, + expected_month: 3, + expected_day: 3, + }, + TestCase { + iso_year: 2772, + iso_month: 7, + iso_day: 27, + expected_rel_iso: 2772, + expected_cyclic: 9, + expected_month: 7, + expected_day: 5, + }, + TestCase { + iso_year: 2525, + iso_month: 2, + iso_day: 25, + expected_rel_iso: 2525, + expected_cyclic: 2, + expected_month: 2, + expected_day: 3, + }, + TestCase { + iso_year: 2345, + iso_month: 3, + iso_day: 21, + expected_rel_iso: 2345, + expected_cyclic: 2, + expected_month: 2, + expected_day: 17, + }, + TestCase { + iso_year: 2222, + iso_month: 2, + iso_day: 22, + expected_rel_iso: 2222, + expected_cyclic: 59, + expected_month: 1, + expected_day: 11, + }, + TestCase { + iso_year: 2167, + iso_month: 6, + iso_day: 22, + expected_rel_iso: 2167, + expected_cyclic: 4, + expected_month: 5, + expected_day: 6, + }, + TestCase { + iso_year: 2121, + iso_month: 2, + iso_day: 12, + expected_rel_iso: 2120, + expected_cyclic: 17, + expected_month: 13, + expected_day: 25, + }, + TestCase { + iso_year: 2080, + iso_month: 12, + iso_day: 31, + expected_rel_iso: 2080, + expected_cyclic: 37, + expected_month: 12, + expected_day: 21, + }, + TestCase { + iso_year: 2030, + iso_month: 3, + iso_day: 20, + expected_rel_iso: 2030, + expected_cyclic: 47, + expected_month: 2, + expected_day: 17, + }, + TestCase { + iso_year: 2027, + iso_month: 2, + iso_day: 7, + expected_rel_iso: 2027, + expected_cyclic: 44, + expected_month: 1, + expected_day: 1, + }, + TestCase { + iso_year: 2023, + iso_month: 7, + iso_day: 1, + expected_rel_iso: 2023, + expected_cyclic: 40, + expected_month: 6, + expected_day: 14, + }, + TestCase { + iso_year: 2022, + iso_month: 3, + iso_day: 1, + expected_rel_iso: 2022, + expected_cyclic: 39, + expected_month: 1, + expected_day: 29, + }, + TestCase { + iso_year: 2021, + iso_month: 2, + iso_day: 1, + expected_rel_iso: 2020, + expected_cyclic: 37, + expected_month: 13, + expected_day: 20, + }, + TestCase { + iso_year: 2016, + iso_month: 3, + iso_day: 30, + expected_rel_iso: 2016, + expected_cyclic: 33, + expected_month: 2, + expected_day: 22, + }, + TestCase { + iso_year: 2016, + iso_month: 7, + iso_day: 30, + expected_rel_iso: 2016, + expected_cyclic: 33, + expected_month: 6, + expected_day: 27, + }, + TestCase { + iso_year: 2015, + iso_month: 9, + iso_day: 22, + expected_rel_iso: 2015, + expected_cyclic: 32, + expected_month: 8, + expected_day: 10, + }, + TestCase { + iso_year: 2013, + iso_month: 10, + iso_day: 1, + expected_rel_iso: 2013, + expected_cyclic: 30, + expected_month: 8, + expected_day: 27, + }, + TestCase { + iso_year: 2010, + iso_month: 2, + iso_day: 1, + expected_rel_iso: 2009, + expected_cyclic: 26, + expected_month: 13, + expected_day: 18, + }, + TestCase { + iso_year: 2000, + iso_month: 8, + iso_day: 30, + expected_rel_iso: 2000, + expected_cyclic: 17, + expected_month: 8, + expected_day: 2, + }, + TestCase { + iso_year: 1990, + iso_month: 11, + iso_day: 11, + expected_rel_iso: 1990, + expected_cyclic: 7, + expected_month: 10, + expected_day: 24, + }, + TestCase { + iso_year: 1970, + iso_month: 6, + iso_day: 10, + expected_rel_iso: 1970, + expected_cyclic: 47, + expected_month: 5, + expected_day: 7, + }, + TestCase { + iso_year: 1970, + iso_month: 1, + iso_day: 1, + expected_rel_iso: 1969, + expected_cyclic: 46, + expected_month: 11, + expected_day: 24, + }, + TestCase { + iso_year: 1941, + iso_month: 12, + iso_day: 7, + expected_rel_iso: 1941, + expected_cyclic: 18, + expected_month: 11, + expected_day: 19, + }, + TestCase { + iso_year: 1812, + iso_month: 5, + iso_day: 4, + expected_rel_iso: 1812, + expected_cyclic: 9, + expected_month: 3, + expected_day: 24, + }, + TestCase { + iso_year: 1655, + iso_month: 6, + iso_day: 15, + expected_rel_iso: 1655, + expected_cyclic: 32, + expected_month: 5, + expected_day: 12, + }, + TestCase { + iso_year: 1333, + iso_month: 3, + iso_day: 10, + expected_rel_iso: 1333, + expected_cyclic: 10, + expected_month: 2, + expected_day: 16, + }, + TestCase { + iso_year: 1000, + iso_month: 10, + iso_day: 10, + expected_rel_iso: 1000, + expected_cyclic: 37, + expected_month: 9, + expected_day: 5, + }, + TestCase { + iso_year: 842, + iso_month: 2, + iso_day: 15, + expected_rel_iso: 841, + expected_cyclic: 58, + expected_month: 13, + expected_day: 28, + }, + TestCase { + iso_year: 101, + iso_month: 1, + iso_day: 10, + expected_rel_iso: 100, + expected_cyclic: 37, + expected_month: 12, + expected_day: 24, + }, + TestCase { + iso_year: -1, + iso_month: 3, + iso_day: 28, + expected_rel_iso: -1, + expected_cyclic: 56, + expected_month: 2, + expected_day: 25, + }, + TestCase { + iso_year: -3, + iso_month: 2, + iso_day: 28, + expected_rel_iso: -3, + expected_cyclic: 54, + expected_month: 2, + expected_day: 5, + }, + TestCase { + iso_year: -365, + iso_month: 7, + iso_day: 24, + expected_rel_iso: -365, + expected_cyclic: 52, + expected_month: 6, + expected_day: 24, + }, + TestCase { + iso_year: -999, + iso_month: 9, + iso_day: 9, + expected_rel_iso: -999, + expected_cyclic: 18, + expected_month: 7, + expected_day: 27, + }, + TestCase { + iso_year: -1500, + iso_month: 1, + iso_day: 5, + expected_rel_iso: -1501, + expected_cyclic: 56, + expected_month: 12, + expected_day: 2, + }, + TestCase { + iso_year: -2332, + iso_month: 3, + iso_day: 1, + expected_rel_iso: -2332, + expected_cyclic: 5, + expected_month: 1, + expected_day: 16, + }, + TestCase { + iso_year: -2332, + iso_month: 2, + iso_day: 15, + expected_rel_iso: -2332, + expected_cyclic: 5, + expected_month: 1, + expected_day: 1, + }, + TestCase { + // #3709: This test case fails to match ICU + iso_year: -2332, + iso_month: 2, + iso_day: 14, + expected_rel_iso: -2333, + expected_cyclic: 4, + expected_month: 13, + expected_day: 30, + }, + TestCase { + // #3709: This test case fails to match ICU + iso_year: -2332, + iso_month: 1, + iso_day: 17, + expected_rel_iso: -2333, + expected_cyclic: 4, + expected_month: 13, + expected_day: 2, + }, + TestCase { + // #3709: This test case fails to match ICU + iso_year: -2332, + iso_month: 1, + iso_day: 16, + expected_rel_iso: -2333, + expected_cyclic: 4, + expected_month: 13, + expected_day: 1, + }, + TestCase { + iso_year: -2332, + iso_month: 1, + iso_day: 15, + expected_rel_iso: -2333, + expected_cyclic: 4, + expected_month: 12, + expected_day: 29, + }, + TestCase { + iso_year: -2332, + iso_month: 1, + iso_day: 1, + expected_rel_iso: -2333, + expected_cyclic: 4, + expected_month: 12, + expected_day: 15, + }, + TestCase { + iso_year: -2333, + iso_month: 1, + iso_day: 16, + expected_rel_iso: -2334, + expected_cyclic: 3, + expected_month: 12, + expected_day: 19, + }, + TestCase { + iso_year: -2333, + iso_month: 1, + iso_day: 27, + expected_rel_iso: -2333, + expected_cyclic: 4, + expected_month: 1, + expected_day: 1, + }, + TestCase { + iso_year: -2333, + iso_month: 1, + iso_day: 26, + expected_rel_iso: -2334, + expected_cyclic: 3, + expected_month: 12, + expected_day: 29, + }, + TestCase { + iso_year: -2600, + iso_month: 9, + iso_day: 16, + expected_rel_iso: -2600, + expected_cyclic: 37, + expected_month: 8, + expected_day: 16, + }, + TestCase { + iso_year: -2855, + iso_month: 2, + iso_day: 3, + expected_rel_iso: -2856, + expected_cyclic: 21, + expected_month: 12, + expected_day: 30, + }, + TestCase { + // #3709: This test case fails to match ICU + iso_year: -3000, + iso_month: 5, + iso_day: 15, + expected_rel_iso: -3000, + expected_cyclic: 57, + expected_month: 4, + expected_day: 1, + }, + TestCase { + // #3709: This test case fails to match ICU + iso_year: -3649, + iso_month: 9, + iso_day: 20, + expected_rel_iso: -3649, + expected_cyclic: 8, + expected_month: 8, + expected_day: 10, + }, + TestCase { + // #3709: This test case fails to match ICU + iso_year: -3649, + iso_month: 3, + iso_day: 30, + expected_rel_iso: -3649, + expected_cyclic: 8, + expected_month: 2, + expected_day: 14, + }, + TestCase { + // #3709: This test case fails to match ICU + iso_year: -3650, + iso_month: 3, + iso_day: 30, + expected_rel_iso: -3650, + expected_cyclic: 7, + expected_month: 3, + expected_day: 3, + }, + ]; + + let dangi_calculating = Dangi::new_always_calculating(); + let dangi_cached = Dangi::new(); + + for case in cases { + let iso = Date::try_new_iso(case.iso_year, case.iso_month, case.iso_day).unwrap(); + do_twice(&dangi_calculating, &dangi_cached, |dangi, calendar_type| { + let dangi = iso.to_calendar(dangi); + let dangi_cyclic = dangi.cyclic_year(); + let dangi_month = dangi.month().ordinal; + let dangi_day = dangi.day_of_month().0; + + assert_eq!( + dangi_cyclic.related_iso, case.expected_rel_iso, + "[{calendar_type}] Related ISO failed for test case: {case:?}" + ); + assert_eq!( + dangi_cyclic.year, case.expected_cyclic, + "[{calendar_type}] Cyclic year failed for test case: {case:?}" + ); + assert_eq!( + dangi_month, case.expected_month, + "[{calendar_type}] Month failed for test case: {case:?}" + ); + assert_eq!( + dangi_day, case.expected_day, + "[{calendar_type}] Day failed for test case: {case:?}" + ); + }); + } + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/ethiopian.rs b/deps/crates/vendor/icu_calendar/src/cal/ethiopian.rs new file mode 100644 index 00000000000000..3fd0cb96a07b58 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/ethiopian.rs @@ -0,0 +1,394 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and implementations for the Ethiopian calendar. +//! +//! ```rust +//! use icu::calendar::{cal::Ethiopian, Date}; +//! +//! let date_iso = Date::try_new_iso(1970, 1, 2) +//! .expect("Failed to initialize ISO Date instance."); +//! let date_ethiopian = Date::new_from_iso(date_iso, Ethiopian::new()); +//! +//! assert_eq!(date_ethiopian.era_year().year, 1962); +//! assert_eq!(date_ethiopian.month().ordinal, 4); +//! assert_eq!(date_ethiopian.day_of_month().0, 24); +//! ``` + +use crate::cal::iso::{Iso, IsoDateInner}; +use crate::calendar_arithmetic::{ArithmeticDate, CalendarArithmetic}; +use crate::error::{year_check, DateError}; +use crate::{types, Calendar, Date, DateDuration, DateDurationUnit, RangeError}; +use calendrical_calculations::helpers::I32CastError; +use calendrical_calculations::rata_die::RataDie; +use tinystr::tinystr; + +/// The number of years the Amete Alem epoch precedes the Amete Mihret epoch +const INCARNATION_OFFSET: i32 = 5500; + +/// Which era style the ethiopian calendar uses +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[non_exhaustive] +pub enum EthiopianEraStyle { + /// Use the Anno Mundi era, anchored at the date of Creation, followed by the + /// Incarnation era, anchored at the date of the Incarnation of Jesus + AmeteMihret, + /// Use the single Anno Mundi era, anchored at the date of Creation + AmeteAlem, +} + +/// The [Ethiopian Calendar] +/// +/// The [Ethiopian calendar] is a solar calendar used by the Coptic Orthodox Church, with twelve normal months +/// and a thirteenth small epagomenal month. +/// +/// This type can be used with [`Date`] to represent dates in this calendar. +/// +/// It can be constructed in two modes: using the Amete Alem era scheme, or the Amete Mihret era scheme (the default), +/// see [`EthiopianEraStyle`] for more info. +/// +/// [Ethiopian calendar]: https://en.wikipedia.org/wiki/Ethiopian_calendar +/// +/// # Era codes +/// +/// This calendar always uses the `aa` era, where 1 Amete Alem is 5493 BCE. Dates before this era use negative years. +/// Dates before that use negative year numbers. +/// In the Amete Mihret scheme it uses the additional `am` era, 1 Amete Mihret is 9 CE. +/// +/// # Month codes +/// +/// This calendar supports 13 solar month codes (`"M01" - "M13"`), with `"M13"` being used for the short epagomenal month +/// at the end of the year. +// The bool specifies whether dates should be in the Amete Alem era scheme +#[derive(Copy, Clone, Debug, Hash, Default, Eq, PartialEq, PartialOrd, Ord)] +pub struct Ethiopian(pub(crate) bool); + +/// The inner date type used for representing [`Date`]s of [`Ethiopian`]. See [`Date`] and [`Ethiopian`] for more details. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +pub struct EthiopianDateInner(ArithmeticDate); + +impl CalendarArithmetic for Ethiopian { + type YearInfo = i32; + + fn days_in_provided_month(year: i32, month: u8) -> u8 { + if (1..=12).contains(&month) { + 30 + } else if month == 13 { + if Self::provided_year_is_leap(year) { + 6 + } else { + 5 + } + } else { + 0 + } + } + + fn months_in_provided_year(_: i32) -> u8 { + 13 + } + + fn provided_year_is_leap(year: i32) -> bool { + year.rem_euclid(4) == 3 + } + + fn last_month_day_in_provided_year(year: i32) -> (u8, u8) { + if Self::provided_year_is_leap(year) { + (13, 6) + } else { + (13, 5) + } + } + + fn days_in_provided_year(year: i32) -> u16 { + if Self::provided_year_is_leap(year) { + 366 + } else { + 365 + } + } +} + +impl crate::cal::scaffold::UnstableSealed for Ethiopian {} +impl Calendar for Ethiopian { + type DateInner = EthiopianDateInner; + type Year = types::EraYear; + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + let year = match (self.era_style(), era) { + (EthiopianEraStyle::AmeteMihret, Some("am") | None) => { + year_check(year, 1..)? + INCARNATION_OFFSET + } + (EthiopianEraStyle::AmeteMihret, Some("aa")) => { + year_check(year, ..=INCARNATION_OFFSET)? + } + (EthiopianEraStyle::AmeteAlem, Some("aa") | None) => year, + (_, Some(_)) => { + return Err(DateError::UnknownEra); + } + }; + ArithmeticDate::new_from_codes(self, year, month_code, day).map(EthiopianDateInner) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + EthiopianDateInner( + match calendrical_calculations::ethiopian::ethiopian_from_fixed(rd) { + Err(I32CastError::BelowMin) => ArithmeticDate::min_date(), + Err(I32CastError::AboveMax) => ArithmeticDate::max_date(), + Ok((year, month, day)) => ArithmeticDate::new_unchecked( + // calendrical calculations returns years in the Incarnation era + year + INCARNATION_OFFSET, + month, + day, + ), + }, + ) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + // calendrical calculations expects years in the Incarnation era + calendrical_calculations::ethiopian::fixed_from_ethiopian( + date.0.year - INCARNATION_OFFSET, + date.0.month, + date.0.day, + ) + } + + fn from_iso(&self, iso: IsoDateInner) -> EthiopianDateInner { + self.from_rata_die(Iso.to_rata_die(&iso)) + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + Iso.from_rata_die(self.to_rata_die(date)) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + date.0.months_in_year() + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + date.0.days_in_year() + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + date.0.days_in_month() + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + date.0.offset_date(offset, &()); + } + + #[allow(clippy::field_reassign_with_default)] + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + _largest_unit: DateDurationUnit, + _smallest_unit: DateDurationUnit, + ) -> DateDuration { + date1.0.until(date2.0, _largest_unit, _smallest_unit) + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + let year = date.0.year; + if self.0 || year <= INCARNATION_OFFSET { + types::EraYear { + era: tinystr!(16, "aa"), + era_index: Some(0), + year, + ambiguity: types::YearAmbiguity::CenturyRequired, + } + } else { + types::EraYear { + era: tinystr!(16, "am"), + era_index: Some(1), + year: year - INCARNATION_OFFSET, + ambiguity: types::YearAmbiguity::CenturyRequired, + } + } + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + let year = date.0.extended_year(); + if self.0 { + year + } else { + year - INCARNATION_OFFSET + } + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Self::provided_year_is_leap(date.0.year) + } + + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + date.0.month() + } + + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + date.0.day_of_month() + } + + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + date.0.day_of_year() + } + + fn debug_name(&self) -> &'static str { + "Ethiopian" + } + + fn calendar_algorithm(&self) -> Option { + Some(crate::preferences::CalendarAlgorithm::Ethiopic) + } +} + +impl Ethiopian { + /// Construct a new Ethiopian Calendar for the Amete Mihret era naming scheme + pub const fn new() -> Self { + Self(false) + } + /// Construct a new Ethiopian Calendar with a value specifying whether or not it is Amete Alem + pub const fn new_with_era_style(era_style: EthiopianEraStyle) -> Self { + Self(matches!(era_style, EthiopianEraStyle::AmeteAlem)) + } + + /// Returns whether this has the Amete Alem era + pub fn era_style(&self) -> EthiopianEraStyle { + if self.0 { + EthiopianEraStyle::AmeteAlem + } else { + EthiopianEraStyle::AmeteMihret + } + } +} + +impl Date { + /// Construct new Ethiopian Date. + /// + /// ```rust + /// use icu::calendar::cal::EthiopianEraStyle; + /// use icu::calendar::Date; + /// + /// let date_ethiopian = + /// Date::try_new_ethiopian(EthiopianEraStyle::AmeteMihret, 2014, 8, 25) + /// .expect("Failed to initialize Ethopic Date instance."); + /// + /// assert_eq!(date_ethiopian.era_year().year, 2014); + /// assert_eq!(date_ethiopian.month().ordinal, 8); + /// assert_eq!(date_ethiopian.day_of_month().0, 25); + /// ``` + pub fn try_new_ethiopian( + era_style: EthiopianEraStyle, + mut year: i32, + month: u8, + day: u8, + ) -> Result, RangeError> { + if era_style == EthiopianEraStyle::AmeteAlem { + year -= INCARNATION_OFFSET; + } + ArithmeticDate::new_from_ordinals(year, month, day) + .map(EthiopianDateInner) + .map(|inner| Date::from_raw(inner, Ethiopian::new_with_era_style(era_style))) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_leap_year() { + // 11th September 2023 in gregorian is 6/13/2015 in ethiopian + let iso_date = Date::try_new_iso(2023, 9, 11).unwrap(); + let date_ethiopian = Date::new_from_iso(iso_date, Ethiopian::new()); + assert_eq!(date_ethiopian.extended_year(), 2015); + assert_eq!(date_ethiopian.month().ordinal, 13); + assert_eq!(date_ethiopian.day_of_month().0, 6); + } + + #[test] + fn test_iso_to_ethiopian_conversion_and_back() { + let iso_date = Date::try_new_iso(1970, 1, 2).unwrap(); + let date_ethiopian = Date::new_from_iso(iso_date, Ethiopian::new()); + + assert_eq!(date_ethiopian.extended_year(), 1962); + assert_eq!(date_ethiopian.month().ordinal, 4); + assert_eq!(date_ethiopian.day_of_month().0, 24); + + assert_eq!( + date_ethiopian.to_iso(), + Date::try_new_iso(1970, 1, 2).unwrap() + ); + } + + #[test] + fn test_iso_to_ethiopian_aa_conversion_and_back() { + let iso_date = Date::try_new_iso(1970, 1, 2).unwrap(); + let date_ethiopian = Date::new_from_iso( + iso_date, + Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteAlem), + ); + + assert_eq!(date_ethiopian.extended_year(), 7462); + assert_eq!(date_ethiopian.month().ordinal, 4); + assert_eq!(date_ethiopian.day_of_month().0, 24); + + assert_eq!( + date_ethiopian.to_iso(), + Date::try_new_iso(1970, 1, 2).unwrap() + ); + } + + #[test] + fn test_roundtrip_negative() { + // https://github.com/unicode-org/icu4x/issues/2254 + let iso_date = Date::try_new_iso(-1000, 3, 3).unwrap(); + let ethiopian = iso_date.to_calendar(Ethiopian::new()); + let recovered_iso = ethiopian.to_iso(); + assert_eq!(iso_date, recovered_iso); + } + + #[test] + fn extended_year() { + assert_eq!( + Date::new_from_iso( + Date::try_new_iso(-5500 + 9, 1, 1).unwrap(), + Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteAlem) + ) + .extended_year(), + 1 + ); + assert_eq!( + Date::new_from_iso( + Date::try_new_iso(9, 1, 1).unwrap(), + Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteAlem) + ) + .extended_year(), + 5501 + ); + + assert_eq!( + Date::new_from_iso( + Date::try_new_iso(-5500 + 9, 1, 1).unwrap(), + Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteMihret) + ) + .extended_year(), + -5499 + ); + assert_eq!( + Date::new_from_iso( + Date::try_new_iso(9, 1, 1).unwrap(), + Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteMihret) + ) + .extended_year(), + 1 + ); + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/gregorian.rs b/deps/crates/vendor/icu_calendar/src/cal/gregorian.rs new file mode 100644 index 00000000000000..0466be71743ba5 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/gregorian.rs @@ -0,0 +1,389 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and implementations for the Gregorian calendar. +//! +//! ```rust +//! use icu::calendar::{cal::Gregorian, Date}; +//! +//! let date_iso = Date::try_new_iso(1970, 1, 2) +//! .expect("Failed to initialize ISO Date instance."); +//! let date_gregorian = Date::new_from_iso(date_iso, Gregorian); +//! +//! assert_eq!(date_gregorian.era_year().year, 1970); +//! assert_eq!(date_gregorian.month().ordinal, 1); +//! assert_eq!(date_gregorian.day_of_month().0, 2); +//! ``` + +use crate::cal::iso::{Iso, IsoDateInner}; +use crate::calendar_arithmetic::ArithmeticDate; +use crate::error::{year_check, DateError}; +use crate::{types, Calendar, Date, DateDuration, DateDurationUnit, RangeError}; +use calendrical_calculations::rata_die::RataDie; +use tinystr::tinystr; + +/// The [(proleptic) Gregorian Calendar](https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar) +/// +/// The Gregorian calendar is a solar calendar used by most of the world, with twelve months. +/// +/// This type can be used with [`Date`] to represent dates in this calendar. +/// +/// # Era codes +/// +/// This calendar uses two era codes: `bce` (alias `bc`), and `ce` (alias `ad`), corresponding to the BCE and CE eras. +/// +/// # Month codes +/// +/// This calendar supports 12 solar month codes (`"M01" - "M12"`) +#[derive(Copy, Clone, Debug, Default)] +#[allow(clippy::exhaustive_structs)] // this type is stable +pub struct Gregorian; + +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +/// The inner date type used for representing [`Date`]s of [`Gregorian`]. See [`Date`] and [`Gregorian`] for more details. +pub struct GregorianDateInner(pub(crate) IsoDateInner); + +impl crate::cal::scaffold::UnstableSealed for Gregorian {} +impl Calendar for Gregorian { + type DateInner = GregorianDateInner; + type Year = types::EraYear; + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + let year = match era { + Some("bce" | "bc") => 1 - year_check(year, 1..)?, + Some("ad" | "ce") | None => year_check(year, 1..)?, + Some(_) => return Err(DateError::UnknownEra), + }; + + ArithmeticDate::new_from_codes(self, year, month_code, day) + .map(IsoDateInner) + .map(GregorianDateInner) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + GregorianDateInner(Iso.from_rata_die(rd)) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + Iso.to_rata_die(&date.0) + } + + fn from_iso(&self, iso: IsoDateInner) -> GregorianDateInner { + GregorianDateInner(iso) + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + date.0 + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + Iso.months_in_year(&date.0) + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + Iso.days_in_year(&date.0) + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + Iso.days_in_month(&date.0) + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + Iso.offset_date(&mut date.0, offset.cast_unit()) + } + + #[allow(clippy::field_reassign_with_default)] // it's more clear this way + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + largest_unit: DateDurationUnit, + smallest_unit: DateDurationUnit, + ) -> DateDuration { + Iso.until(&date1.0, &date2.0, &Iso, largest_unit, smallest_unit) + .cast_unit() + } + /// The calendar-specific year represented by `date` + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + let extended_year = self.extended_year(date); + if extended_year > 0 { + types::EraYear { + era: tinystr!(16, "ce"), + era_index: Some(1), + year: extended_year, + ambiguity: match extended_year { + ..=999 => types::YearAmbiguity::EraAndCenturyRequired, + 1000..=1949 => types::YearAmbiguity::CenturyRequired, + 1950..=2049 => types::YearAmbiguity::Unambiguous, + 2050.. => types::YearAmbiguity::CenturyRequired, + }, + } + } else { + types::EraYear { + era: tinystr!(16, "bce"), + era_index: Some(0), + year: 1_i32.saturating_sub(extended_year), + ambiguity: types::YearAmbiguity::EraAndCenturyRequired, + } + } + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + Iso.extended_year(&date.0) + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Iso.is_in_leap_year(&date.0) + } + + /// The calendar-specific month represented by `date` + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + Iso.month(&date.0) + } + + /// The calendar-specific day-of-month represented by `date` + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + Iso.day_of_month(&date.0) + } + + /// Information of the day of the year + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + date.0 .0.day_of_year() + } + + fn debug_name(&self) -> &'static str { + "Gregorian" + } + + fn calendar_algorithm(&self) -> Option { + Some(crate::preferences::CalendarAlgorithm::Gregory) + } +} + +impl Date { + /// Construct a new Gregorian Date. + /// + /// Years are specified as ISO years. + /// + /// ```rust + /// use icu::calendar::Date; + /// + /// // Conversion from ISO to Gregorian + /// let date_gregorian = Date::try_new_gregorian(1970, 1, 2) + /// .expect("Failed to initialize Gregorian Date instance."); + /// + /// assert_eq!(date_gregorian.era_year().year, 1970); + /// assert_eq!(date_gregorian.month().ordinal, 1); + /// assert_eq!(date_gregorian.day_of_month().0, 2); + /// ``` + pub fn try_new_gregorian(year: i32, month: u8, day: u8) -> Result, RangeError> { + Date::try_new_iso(year, month, day).map(|d| Date::new_from_iso(d, Gregorian)) + } +} + +#[cfg(test)] +mod test { + use calendrical_calculations::rata_die::RataDie; + + use super::*; + + #[derive(Debug)] + struct TestCase { + rd: RataDie, + iso_year: i32, + iso_month: u8, + iso_day: u8, + expected_year: i32, + expected_era: &'static str, + expected_month: u8, + expected_day: u8, + } + + fn check_test_case(case: TestCase) { + let iso_from_rd = Date::from_rata_die(case.rd, Iso); + let greg_date_from_rd = Date::from_rata_die(case.rd, Gregorian); + assert_eq!(greg_date_from_rd.era_year().year, case.expected_year, + "Failed year check from RD: {case:?}\nISO: {iso_from_rd:?}\nGreg: {greg_date_from_rd:?}"); + assert_eq!( + greg_date_from_rd.era_year().era, + case.expected_era, + "Failed era check from RD: {case:?}\nISO: {iso_from_rd:?}\nGreg: {greg_date_from_rd:?}" + ); + assert_eq!(greg_date_from_rd.month().ordinal, case.expected_month, + "Failed month check from RD: {case:?}\nISO: {iso_from_rd:?}\nGreg: {greg_date_from_rd:?}"); + assert_eq!( + greg_date_from_rd.day_of_month().0, + case.expected_day, + "Failed day check from RD: {case:?}\nISO: {iso_from_rd:?}\nGreg: {greg_date_from_rd:?}" + ); + + let iso_date_man: Date = + Date::try_new_iso(case.iso_year, case.iso_month, case.iso_day) + .expect("Failed to initialize ISO date for {case:?}"); + let greg_date_man: Date = Date::new_from_iso(iso_date_man, Gregorian); + assert_eq!(iso_from_rd, iso_date_man, + "ISO from RD not equal to ISO generated from manually-input ymd\nCase: {case:?}\nRD: {iso_from_rd:?}\nMan: {iso_date_man:?}"); + assert_eq!(greg_date_from_rd, greg_date_man, + "Greg. date from RD not equal to Greg. generated from manually-input ymd\nCase: {case:?}\nRD: {greg_date_from_rd:?}\nMan: {greg_date_man:?}"); + } + + #[test] + fn test_gregorian_ce() { + // Tests that the Gregorian calendar gives the correct expected + // day, month, and year for positive years (AD/CE/gregory era) + + let cases = [ + TestCase { + rd: RataDie::new(1), + iso_year: 1, + iso_month: 1, + iso_day: 1, + expected_year: 1, + expected_era: "ce", + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: RataDie::new(181), + iso_year: 1, + iso_month: 6, + iso_day: 30, + expected_year: 1, + expected_era: "ce", + expected_month: 6, + expected_day: 30, + }, + TestCase { + rd: RataDie::new(1155), + iso_year: 4, + iso_month: 2, + iso_day: 29, + expected_year: 4, + expected_era: "ce", + expected_month: 2, + expected_day: 29, + }, + TestCase { + rd: RataDie::new(1344), + iso_year: 4, + iso_month: 9, + iso_day: 5, + expected_year: 4, + expected_era: "ce", + expected_month: 9, + expected_day: 5, + }, + TestCase { + rd: RataDie::new(36219), + iso_year: 100, + iso_month: 3, + iso_day: 1, + expected_year: 100, + expected_era: "ce", + expected_month: 3, + expected_day: 1, + }, + ]; + + for case in cases { + check_test_case(case); + } + } + + #[test] + fn test_gregorian_bce() { + // Tests that the Gregorian calendar gives the correct expected + // day, month, and year for negative years (BC/BCE era) + + let cases = [ + TestCase { + rd: RataDie::new(0), + iso_year: 0, + iso_month: 12, + iso_day: 31, + expected_year: 1, + expected_era: "bce", + expected_month: 12, + expected_day: 31, + }, + TestCase { + rd: RataDie::new(-365), // This is a leap year + iso_year: 0, + iso_month: 1, + iso_day: 1, + expected_year: 1, + expected_era: "bce", + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: RataDie::new(-366), + iso_year: -1, + iso_month: 12, + iso_day: 31, + expected_year: 2, + expected_era: "bce", + expected_month: 12, + expected_day: 31, + }, + TestCase { + rd: RataDie::new(-1461), + iso_year: -4, + iso_month: 12, + iso_day: 31, + expected_year: 5, + expected_era: "bce", + expected_month: 12, + expected_day: 31, + }, + TestCase { + rd: RataDie::new(-1826), + iso_year: -4, + iso_month: 1, + iso_day: 1, + expected_year: 5, + expected_era: "bce", + expected_month: 1, + expected_day: 1, + }, + ]; + + for case in cases { + check_test_case(case); + } + } + + #[test] + fn check_gregorian_directionality() { + // Tests that for a large range of RDs, if a RD + // is less than another, the corresponding YMD should also be less + // than the other, without exception. + for i in -100..100 { + for j in -100..100 { + let iso_i = Date::from_rata_die(RataDie::new(i), Iso); + let iso_j = Date::from_rata_die(RataDie::new(j), Iso); + + let greg_i = iso_i.to_calendar(Gregorian); + let greg_j = iso_j.to_calendar(Gregorian); + + assert_eq!( + i.cmp(&j), + iso_i.cmp(&iso_j), + "ISO directionality inconsistent with directionality for i: {i}, j: {j}" + ); + assert_eq!( + i.cmp(&j), + greg_i.cmp(&greg_j), + "Gregorian directionality inconsistent with directionality for i: {i}, j: {j}" + ); + } + } + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/hebrew.rs b/deps/crates/vendor/icu_calendar/src/cal/hebrew.rs new file mode 100644 index 00000000000000..e0464a2c1af691 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/hebrew.rs @@ -0,0 +1,516 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and implementations for the Hebrew calendar. +//! +//! ```rust +//! use icu::calendar::Date; +//! +//! let hebrew_date = Date::try_new_hebrew(3425, 10, 11) +//! .expect("Failed to initialize hebrew Date instance."); +//! +//! assert_eq!(hebrew_date.era_year().year, 3425); +//! assert_eq!(hebrew_date.month().ordinal, 10); +//! assert_eq!(hebrew_date.day_of_month().0, 11); +//! ``` + +use crate::cal::iso::{Iso, IsoDateInner}; +use crate::calendar_arithmetic::PrecomputedDataSource; +use crate::calendar_arithmetic::{ArithmeticDate, CalendarArithmetic}; +use crate::error::DateError; +use crate::types::MonthInfo; +use crate::RangeError; +use crate::{types, Calendar, Date, DateDuration, DateDurationUnit}; +use ::tinystr::tinystr; +use calendrical_calculations::hebrew_keviyah::{Keviyah, YearInfo}; +use calendrical_calculations::rata_die::RataDie; + +/// The [Hebrew Calendar](https://en.wikipedia.org/wiki/Hebrew_calendar) +/// +/// The Hebrew calendar is a lunisolar calendar used as the Jewish liturgical calendar +/// as well as an official calendar in Israel. +/// +/// This calendar is the _civil_ Hebrew calendar, with the year starting at in the month of Tishrei. +/// +/// # Era codes +/// +/// This calendar uses a single era code `am`, Anno Mundi. Dates before this era use negative years. +/// +/// # Month codes +/// +/// This calendar is a lunisolar calendar and thus has a leap month. It supports codes `"M01"-"M12"` +/// for regular months, and the leap month Adar I being coded as `"M05L"`. +/// +/// [`MonthInfo`] has slightly divergent behavior: because the regular month Adar is formatted +/// as "Adar II" in a leap year, this calendar will produce the special code `"M06L"` in any [`MonthInfo`] +/// objects it creates. +#[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Default)] +#[allow(clippy::exhaustive_structs)] // unit struct +pub struct Hebrew; + +/// The inner date type used for representing [`Date`]s of [`Hebrew`]. See [`Date`] and [`Hebrew`] for more details. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +pub struct HebrewDateInner(ArithmeticDate); + +impl Hebrew { + /// Construct a new [`Hebrew`] + pub fn new() -> Self { + Hebrew + } +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub(crate) struct HebrewYearInfo { + keviyah: Keviyah, + prev_keviyah: Keviyah, + value: i32, +} + +impl From for i32 { + fn from(value: HebrewYearInfo) -> Self { + value.value + } +} + +impl HebrewYearInfo { + /// Convenience method to compute for a given year. Don't use this if you actually need + /// a YearInfo that you want to call .new_year() on. + /// + /// This can potentially be optimized with adjacent-year knowledge, but it's complex + #[inline] + fn compute(h_year: i32) -> Self { + let keviyah = YearInfo::compute_for(h_year).keviyah; + Self::compute_with_keviyah(keviyah, h_year) + } + /// Compute for a given year when the keviyah is already known + #[inline] + fn compute_with_keviyah(keviyah: Keviyah, h_year: i32) -> Self { + let prev_keviyah = YearInfo::compute_for(h_year - 1).keviyah; + Self { + keviyah, + prev_keviyah, + value: h_year, + } + } +} +// HEBREW CALENDAR + +impl CalendarArithmetic for Hebrew { + type YearInfo = HebrewYearInfo; + + fn days_in_provided_month(info: HebrewYearInfo, ordinal_month: u8) -> u8 { + info.keviyah.month_len(ordinal_month) + } + + fn months_in_provided_year(info: HebrewYearInfo) -> u8 { + if info.keviyah.is_leap() { + 13 + } else { + 12 + } + } + + fn days_in_provided_year(info: HebrewYearInfo) -> u16 { + info.keviyah.year_length() + } + + fn provided_year_is_leap(info: HebrewYearInfo) -> bool { + info.keviyah.is_leap() + } + + fn last_month_day_in_provided_year(info: HebrewYearInfo) -> (u8, u8) { + info.keviyah.last_month_day_in_year() + } +} + +impl PrecomputedDataSource for () { + fn load_or_compute_info(&self, h_year: i32) -> HebrewYearInfo { + HebrewYearInfo::compute(h_year) + } +} + +impl crate::cal::scaffold::UnstableSealed for Hebrew {} +impl Calendar for Hebrew { + type DateInner = HebrewDateInner; + type Year = types::EraYear; + + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + match era { + Some("am") | None => {} + _ => return Err(DateError::UnknownEra), + } + + let year = HebrewYearInfo::compute(year); + + let is_leap_year = year.keviyah.is_leap(); + + let month_code_str = month_code.0.as_str(); + + let month_ordinal = if is_leap_year { + match month_code_str { + "M01" => 1, + "M02" => 2, + "M03" => 3, + "M04" => 4, + "M05" => 5, + "M05L" => 6, + // M06L is the formatting era code used for Adar II + "M06" | "M06L" => 7, + "M07" => 8, + "M08" => 9, + "M09" => 10, + "M10" => 11, + "M11" => 12, + "M12" => 13, + _ => { + return Err(DateError::UnknownMonthCode(month_code)); + } + } + } else { + match month_code_str { + "M01" => 1, + "M02" => 2, + "M03" => 3, + "M04" => 4, + "M05" => 5, + "M06" => 6, + "M07" => 7, + "M08" => 8, + "M09" => 9, + "M10" => 10, + "M11" => 11, + "M12" => 12, + _ => { + return Err(DateError::UnknownMonthCode(month_code)); + } + } + }; + + Ok(HebrewDateInner(ArithmeticDate::new_from_ordinals( + year, + month_ordinal, + day, + )?)) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + let (year, h_year) = YearInfo::year_containing_rd(rd); + // Obtaining a 1-indexed day-in-year value + let day = rd - year.new_year() + 1; + let day = u16::try_from(day).unwrap_or(u16::MAX); + + let year = HebrewYearInfo::compute_with_keviyah(year.keviyah, h_year); + let (month, day) = year.keviyah.month_day_for(day); + HebrewDateInner(ArithmeticDate::new_unchecked(year, month, day)) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + let year = date.0.year.keviyah.year_info(date.0.year.value); + + let ny = year.new_year(); + let days_preceding = year.keviyah.days_preceding(date.0.month); + + // Need to subtract 1 since the new year is itself in this year + ny + i64::from(days_preceding) + i64::from(date.0.day) - 1 + } + + fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner { + self.from_rata_die(Iso.to_rata_die(&iso)) + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + Iso.from_rata_die(self.to_rata_die(date)) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + date.0.months_in_year() + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + date.0.days_in_year() + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + date.0.days_in_month() + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + date.0.offset_date(offset, &()) + } + + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + _largest_unit: DateDurationUnit, + _smallest_unit: DateDurationUnit, + ) -> DateDuration { + date1.0.until(date2.0, _largest_unit, _smallest_unit) + } + + fn debug_name(&self) -> &'static str { + "Hebrew" + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + types::EraYear { + era_index: Some(0), + era: tinystr!(16, "am"), + year: self.extended_year(date), + ambiguity: types::YearAmbiguity::CenturyRequired, + } + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + date.0.extended_year() + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Self::provided_year_is_leap(date.0.year) + } + + fn month(&self, date: &Self::DateInner) -> MonthInfo { + let mut ordinal = date.0.month; + let is_leap_year = Self::provided_year_is_leap(date.0.year); + + if is_leap_year { + if ordinal == 6 { + return types::MonthInfo { + ordinal, + standard_code: types::MonthCode(tinystr!(4, "M05L")), + formatting_code: types::MonthCode(tinystr!(4, "M05L")), + }; + } else if ordinal == 7 { + return types::MonthInfo { + ordinal, + // Adar II is the same as Adar and has the same code + standard_code: types::MonthCode(tinystr!(4, "M06")), + formatting_code: types::MonthCode(tinystr!(4, "M06L")), + }; + } + } + + if is_leap_year && ordinal > 6 { + ordinal -= 1; + } + + let code = match ordinal { + 1 => tinystr!(4, "M01"), + 2 => tinystr!(4, "M02"), + 3 => tinystr!(4, "M03"), + 4 => tinystr!(4, "M04"), + 5 => tinystr!(4, "M05"), + 6 => tinystr!(4, "M06"), + 7 => tinystr!(4, "M07"), + 8 => tinystr!(4, "M08"), + 9 => tinystr!(4, "M09"), + 10 => tinystr!(4, "M10"), + 11 => tinystr!(4, "M11"), + 12 => tinystr!(4, "M12"), + _ => tinystr!(4, "und"), + }; + + types::MonthInfo { + ordinal: date.0.month, + standard_code: types::MonthCode(code), + formatting_code: types::MonthCode(code), + } + } + + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + date.0.day_of_month() + } + + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + date.0.day_of_year() + } + + fn calendar_algorithm(&self) -> Option { + Some(crate::preferences::CalendarAlgorithm::Hebrew) + } +} + +impl Date { + /// Construct new Hebrew Date. + /// + /// This date will not use any precomputed calendrical calculations, + /// one that loads such data from a provider will be added in the future (#3933) + /// + /// + /// ```rust + /// use icu::calendar::Date; + /// + /// let date_hebrew = Date::try_new_hebrew(3425, 4, 25) + /// .expect("Failed to initialize Hebrew Date instance."); + /// + /// assert_eq!(date_hebrew.era_year().year, 3425); + /// assert_eq!(date_hebrew.month().ordinal, 4); + /// assert_eq!(date_hebrew.day_of_month().0, 25); + /// ``` + pub fn try_new_hebrew(year: i32, month: u8, day: u8) -> Result, RangeError> { + let year = HebrewYearInfo::compute(year); + + ArithmeticDate::new_from_ordinals(year, month, day) + .map(HebrewDateInner) + .map(|inner| Date::from_raw(inner, Hebrew)) + } +} + +#[cfg(test)] +mod tests { + + use super::*; + use crate::types::MonthCode; + use calendrical_calculations::hebrew_keviyah::*; + + // Sentinel value for Adar I + // We're using normalized month values here so that we can use constants. These do not + // distinguish between the different Adars. We add an out-of-range sentinel value of 13 to + // specifically talk about Adar I in a leap year + const ADARI: u8 = 13; + + /// The leap years used in the tests below + const LEAP_YEARS_IN_TESTS: [i32; 1] = [5782]; + /// (iso, hebrew) pairs of testcases. If any of the years here + /// are leap years please add them to LEAP_YEARS_IN_TESTS (we have this manually + /// so we don't end up exercising potentially buggy codepaths to test this) + #[allow(clippy::type_complexity)] + const ISO_HEBREW_DATE_PAIRS: [((i32, u8, u8), (i32, u8, u8)); 48] = [ + ((2021, 1, 10), (5781, TEVET, 26)), + ((2021, 1, 25), (5781, SHEVAT, 12)), + ((2021, 2, 10), (5781, SHEVAT, 28)), + ((2021, 2, 25), (5781, ADAR, 13)), + ((2021, 3, 10), (5781, ADAR, 26)), + ((2021, 3, 25), (5781, NISAN, 12)), + ((2021, 4, 10), (5781, NISAN, 28)), + ((2021, 4, 25), (5781, IYYAR, 13)), + ((2021, 5, 10), (5781, IYYAR, 28)), + ((2021, 5, 25), (5781, SIVAN, 14)), + ((2021, 6, 10), (5781, SIVAN, 30)), + ((2021, 6, 25), (5781, TAMMUZ, 15)), + ((2021, 7, 10), (5781, AV, 1)), + ((2021, 7, 25), (5781, AV, 16)), + ((2021, 8, 10), (5781, ELUL, 2)), + ((2021, 8, 25), (5781, ELUL, 17)), + ((2021, 9, 10), (5782, TISHREI, 4)), + ((2021, 9, 25), (5782, TISHREI, 19)), + ((2021, 10, 10), (5782, ḤESHVAN, 4)), + ((2021, 10, 25), (5782, ḤESHVAN, 19)), + ((2021, 11, 10), (5782, KISLEV, 6)), + ((2021, 11, 25), (5782, KISLEV, 21)), + ((2021, 12, 10), (5782, TEVET, 6)), + ((2021, 12, 25), (5782, TEVET, 21)), + ((2022, 1, 10), (5782, SHEVAT, 8)), + ((2022, 1, 25), (5782, SHEVAT, 23)), + ((2022, 2, 10), (5782, ADARI, 9)), + ((2022, 2, 25), (5782, ADARI, 24)), + ((2022, 3, 10), (5782, ADAR, 7)), + ((2022, 3, 25), (5782, ADAR, 22)), + ((2022, 4, 10), (5782, NISAN, 9)), + ((2022, 4, 25), (5782, NISAN, 24)), + ((2022, 5, 10), (5782, IYYAR, 9)), + ((2022, 5, 25), (5782, IYYAR, 24)), + ((2022, 6, 10), (5782, SIVAN, 11)), + ((2022, 6, 25), (5782, SIVAN, 26)), + ((2022, 7, 10), (5782, TAMMUZ, 11)), + ((2022, 7, 25), (5782, TAMMUZ, 26)), + ((2022, 8, 10), (5782, AV, 13)), + ((2022, 8, 25), (5782, AV, 28)), + ((2022, 9, 10), (5782, ELUL, 14)), + ((2022, 9, 25), (5782, ELUL, 29)), + ((2022, 10, 10), (5783, TISHREI, 15)), + ((2022, 10, 25), (5783, TISHREI, 30)), + ((2022, 11, 10), (5783, ḤESHVAN, 16)), + ((2022, 11, 25), (5783, KISLEV, 1)), + ((2022, 12, 10), (5783, KISLEV, 16)), + ((2022, 12, 25), (5783, TEVET, 1)), + ]; + + #[test] + fn test_conversions() { + for ((iso_y, iso_m, iso_d), (y, m, d)) in ISO_HEBREW_DATE_PAIRS.into_iter() { + let iso_date = Date::try_new_iso(iso_y, iso_m, iso_d).unwrap(); + let month_code = if m == ADARI { + MonthCode(tinystr!(4, "M05L")) + } else { + MonthCode::new_normal(m).unwrap() + }; + let hebrew_date = Date::try_new_from_codes(Some("am"), y, month_code, d, Hebrew) + .expect("Date should parse"); + + let iso_to_hebrew = iso_date.to_calendar(Hebrew); + + let hebrew_to_iso = hebrew_date.to_calendar(Iso); + + assert_eq!( + hebrew_to_iso, iso_date, + "Failed comparing to-ISO value for {hebrew_date:?} => {iso_date:?}" + ); + assert_eq!( + iso_to_hebrew, hebrew_date, + "Failed comparing to-hebrew value for {iso_date:?} => {hebrew_date:?}" + ); + + let ordinal_month = if LEAP_YEARS_IN_TESTS.contains(&y) { + if m == ADARI { + ADAR + } else if m >= ADAR { + m + 1 + } else { + m + } + } else { + assert!(m != ADARI); + m + }; + + let ordinal_hebrew_date = Date::try_new_hebrew(y, ordinal_month, d) + .expect("Construction of date must succeed"); + + assert_eq!(ordinal_hebrew_date, hebrew_date, "Hebrew date construction from codes and ordinals should work the same for {hebrew_date:?}"); + } + } + + #[test] + fn test_icu_bug_22441() { + let yi = YearInfo::compute_for(88369); + assert_eq!(yi.keviyah.year_length(), 383); + } + + #[test] + fn test_negative_era_years() { + let greg_date = Date::try_new_gregorian(-5000, 1, 1).unwrap(); + let greg_year = greg_date.era_year(); + assert_eq!(greg_date.inner.0 .0.year, -5000); + assert_eq!(greg_year.era, "bce"); + // In Gregorian, era year is 1 - extended year + assert_eq!(greg_year.year, 5001); + let hebr_date = greg_date.to_calendar(Hebrew); + let hebr_year = hebr_date.era_year(); + assert_eq!(hebr_date.inner.0.year.value, -1240); + assert_eq!(hebr_year.era, "am"); + // In Hebrew, there is no inverse era, so negative extended years are negative era years + assert_eq!(hebr_year.year, -1240); + } + + #[test] + fn test_weekdays() { + // https://github.com/unicode-org/icu4x/issues/4893 + let cal = Hebrew::new(); + let era = "am"; + let month_code = MonthCode(tinystr!(4, "M01")); + let dt = Date::try_new_from_codes(Some(era), 3760, month_code, 1, cal).unwrap(); + + // Should be Saturday per: + // https://www.hebcal.com/converter?hd=1&hm=Tishrei&hy=3760&h2g=1 + assert_eq!(6, dt.day_of_week() as usize); + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/hijri.rs b/deps/crates/vendor/icu_calendar/src/cal/hijri.rs new file mode 100644 index 00000000000000..02a5d920269fa7 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/hijri.rs @@ -0,0 +1,2050 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and implementations for the Hijri calendars. +//! +//! ```rust +//! use icu::calendar::cal::HijriSimulated; +//! use icu::calendar::Date; +//! +//! let hijri = HijriSimulated::new_mecca_always_calculating(); +//! let hijri_date = +//! Date::try_new_simulated_hijri_with_calendar(1348, 10, 11, hijri) +//! .expect("Failed to initialize Hijri Date instance."); +//! +//! assert_eq!(hijri_date.era_year().year, 1348); +//! assert_eq!(hijri_date.month().ordinal, 10); +//! assert_eq!(hijri_date.day_of_month().0, 11); +//! ``` + +use crate::cal::iso::{Iso, IsoDateInner}; +use crate::calendar_arithmetic::PrecomputedDataSource; +use crate::calendar_arithmetic::{ArithmeticDate, CalendarArithmetic}; +use crate::error::{year_check, DateError}; +use crate::provider::hijri::PackedHijriYearInfo; +use crate::provider::hijri::{CalendarHijriSimulatedMeccaV1, HijriData}; +use crate::types::EraYear; +use crate::{types, Calendar, Date, DateDuration, DateDurationUnit}; +use crate::{AsCalendar, RangeError}; +use calendrical_calculations::islamic::{ISLAMIC_EPOCH_FRIDAY, ISLAMIC_EPOCH_THURSDAY}; +use calendrical_calculations::rata_die::RataDie; +use icu_provider::marker::ErasedMarker; +use icu_provider::prelude::*; +use tinystr::tinystr; +use ummalqura_data::{UMMALQURA_DATA, UMMALQURA_DATA_STARTING_YEAR}; + +mod ummalqura_data; + +fn era_year(year: i32) -> EraYear { + if year > 0 { + types::EraYear { + era: tinystr!(16, "ah"), + era_index: Some(0), + year, + ambiguity: types::YearAmbiguity::CenturyRequired, + } + } else { + types::EraYear { + era: tinystr!(16, "bh"), + era_index: Some(1), + year: 1 - year, + ambiguity: types::YearAmbiguity::CenturyRequired, + } + } +} + +/// The [simulated Hijri Calendar](https://en.wikipedia.org/wiki/Islamic_calendar) +/// +/// # Era codes +/// +/// This calendar uses two era codes: `ah`, and `bh`, corresponding to the Anno Hegirae and Before Hijrah eras +/// +/// # Month codes +/// +/// This calendar is a pure lunar calendar with no leap months. It uses month codes +/// `"M01" - "M12"`. +#[derive(Clone, Debug)] +pub struct HijriSimulated { + pub(crate) location: HijriSimulatedLocation, + data: Option>>>, +} + +#[derive(Clone, Debug, Copy, PartialEq)] +pub(crate) enum HijriSimulatedLocation { + Mecca, +} + +impl HijriSimulatedLocation { + fn location(self) -> calendrical_calculations::islamic::Location { + match self { + Self::Mecca => calendrical_calculations::islamic::MECCA, + } + } +} + +/// The [Umm al-Qura Hijri Calendar](https://en.wikipedia.org/wiki/Islamic_calendar#Saudi_Arabia's_Umm_al-Qura_calendar) +/// +/// This calendar is the official calendar in Saudi Arabia. +/// +/// # Era codes +/// +/// This calendar uses two era codes: `ah`, and `bh`, corresponding to the Anno Hegirae and Before Hijrah eras +/// +/// # Month codes +/// +/// This calendar is a pure lunar calendar with no leap months. It uses month codes +/// `"M01" - "M12"`. +#[derive(Clone, Debug, Default)] +#[non_exhaustive] +pub struct HijriUmmAlQura; + +/// The [tabular Hijri Calendar](https://en.wikipedia.org/wiki/Tabular_Islamic_calendar). +/// +/// See [`HijriTabularEpoch`] and [`HijriTabularLeapYears`] for customization. +/// +/// The most common version of this calendar uses [`HijriTabularEpoch::Friday`] and [`HijriTabularLeapYears::TypeII`]. +/// +/// # Era codes +/// +/// This calendar uses two era codes: `ah`, and `bh`, corresponding to the Anno Hegirae and Before Hijrah eras +/// +/// # Month codes +/// +/// This calendar is a pure lunar calendar with no leap months. It uses month codes +/// `"M01" - "M12"`. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +pub struct HijriTabular { + pub(crate) leap_years: HijriTabularLeapYears, + pub(crate) epoch: HijriTabularEpoch, +} + +impl HijriSimulated { + /// Creates a new [`HijriSimulated`] for reference location Mecca, with some compiled data containing precomputed calendrical calculations. + /// + /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + #[cfg(feature = "compiled_data")] + pub const fn new_mecca() -> Self { + Self { + location: HijriSimulatedLocation::Mecca, + data: Some(DataPayload::from_static_ref( + crate::provider::Baked::SINGLETON_CALENDAR_HIJRI_SIMULATED_MECCA_V1, + )), + } + } + + icu_provider::gen_buffer_data_constructors!(() -> error: DataError, + functions: [ + new: skip, + try_new_mecca_with_buffer_provider, + try_new_mecca_unstable, + Self, + ]); + + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new_mecca)] + pub fn try_new_mecca_unstable + ?Sized>( + provider: &D, + ) -> Result { + Ok(Self { + location: HijriSimulatedLocation::Mecca, + data: Some(provider.load(Default::default())?.payload.cast()), + }) + } + + /// Construct a new [`HijriSimulated`] for reference location Mecca, without any precomputed calendrical calculations. + pub const fn new_mecca_always_calculating() -> Self { + Self { + location: HijriSimulatedLocation::Mecca, + data: None, + } + } + + /// Compute a cache for this calendar + #[cfg(feature = "datagen")] + pub fn build_cache(&self, extended_years: core::ops::Range) -> HijriData<'static> { + let data = extended_years + .clone() + .map(|year| self.location.compute_year_info(year).pack()) + .collect(); + HijriData { + first_extended_year: extended_years.start, + data, + } + } +} + +impl HijriUmmAlQura { + /// Creates a new [`HijriUmmAlQura`]. + pub const fn new() -> Self { + Self + } +} + +/// The epoch for the [`HijriTabular`] calendar. +#[non_exhaustive] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +pub enum HijriTabularEpoch { + /// Thusday July 15, 622 AD (0622-07-18 ISO) + Thursday, + /// Friday July 16, 622 AD (0622-07-19 ISO) + Friday, +} + +impl HijriTabularEpoch { + fn rata_die(self) -> RataDie { + match self { + Self::Thursday => ISLAMIC_EPOCH_THURSDAY, + Self::Friday => ISLAMIC_EPOCH_FRIDAY, + } + } +} + +/// The leap year rule for the [`HijriTabular`] calendar. +/// +/// This specifies which years of a 30-year cycle have an additional day at +/// the end of the year. +#[non_exhaustive] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +pub enum HijriTabularLeapYears { + /// Leap years 2, 5, 7, 10, 13, 16, 18, 21, 24, 26, 29 + TypeII, +} + +impl HijriTabular { + /// Construct a new [`HijriTabular`] with the given leap year rule and epoch. + pub const fn new(leap_years: HijriTabularLeapYears, epoch: HijriTabularEpoch) -> Self { + Self { epoch, leap_years } + } +} + +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub(crate) struct HijriYearInfo { + month_lengths: [bool; 12], + start_day: RataDie, + value: i32, +} + +impl From for i32 { + fn from(value: HijriYearInfo) -> Self { + value.value + } +} + +impl HijriData<'_> { + /// Get the cached data for a given extended year + fn get(&self, extended_year: i32) -> Option { + Some(HijriYearInfo::unpack( + extended_year, + self.data + .get(usize::try_from(extended_year - self.first_extended_year).ok()?)?, + )) + } +} + +const LONG_YEAR_LEN: u16 = 355; +const SHORT_YEAR_LEN: u16 = 354; + +impl HijriYearInfo { + #[cfg(feature = "datagen")] + fn pack(&self) -> PackedHijriYearInfo { + PackedHijriYearInfo::new(self.value, self.month_lengths, self.start_day) + } + + fn unpack(extended_year: i32, packed: PackedHijriYearInfo) -> Self { + let (month_lengths, start_day) = packed.unpack(extended_year); + + HijriYearInfo { + month_lengths, + start_day, + value: extended_year, + } + } + + /// The number of days in a given 1-indexed month + fn days_in_month(self, month: u8) -> u8 { + let Some(zero_month) = month.checked_sub(1) else { + return 29; + }; + + if self.month_lengths.get(zero_month as usize) == Some(&true) { + 30 + } else { + 29 + } + } + + fn days_in_year(self) -> u16 { + self.last_day_of_month(12) + } + + /// Get the date's R.D. given (m, d) in this info's year + fn md_to_rd(self, month: u8, day: u8) -> RataDie { + let month_offset = if month == 1 { + 0 + } else { + self.last_day_of_month(month - 1) + }; + self.start_day + month_offset as i64 + (day - 1) as i64 + } + + fn md_from_rd(self, rd: RataDie) -> (u8, u8) { + let day_of_year = (rd - self.start_day) as u16; + debug_assert!(day_of_year < 360); + // We divide by 30, not 29, to account for the case where all months before this + // were length 30 (possible near the beginning of the year) + let mut month = (day_of_year / 30) as u8 + 1; + + let day_of_year = day_of_year + 1; + let mut last_day_of_month = self.last_day_of_month(month); + let mut last_day_of_prev_month = if month == 1 { + 0 + } else { + self.last_day_of_month(month - 1) + }; + + while day_of_year > last_day_of_month && month <= 12 { + month += 1; + last_day_of_prev_month = last_day_of_month; + last_day_of_month = self.last_day_of_month(month); + } + debug_assert!( + day_of_year - last_day_of_prev_month <= 30, + "Found day {} that doesn't fit in month!", + day_of_year - last_day_of_prev_month + ); + let day = (day_of_year - last_day_of_prev_month) as u8; + (month, day) + } + + // Which day of year is the last day of a month (month is 1-indexed) + fn last_day_of_month(self, month: u8) -> u16 { + 29 * month as u16 + + self + .month_lengths + .get(..month as usize) + .unwrap_or_default() + .iter() + .filter(|&&x| x) + .count() as u16 + } +} + +impl PrecomputedDataSource for HijriSimulated { + fn load_or_compute_info(&self, extended_year: i32) -> HijriYearInfo { + self.data + .as_ref() + .and_then(|d| d.get().get(extended_year)) + .unwrap_or_else(|| self.location.compute_year_info(extended_year)) + } +} + +/// The inner date type used for representing [`Date`]s of [`HijriSimulated`]. See [`Date`] and [`HijriSimulated`] for more details. + +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +pub struct HijriSimulatedDateInner(ArithmeticDate); + +impl CalendarArithmetic for HijriSimulated { + type YearInfo = HijriYearInfo; + + fn days_in_provided_month(year: Self::YearInfo, month: u8) -> u8 { + year.days_in_month(month) + } + + fn months_in_provided_year(_year: Self::YearInfo) -> u8 { + 12 + } + + fn days_in_provided_year(year: Self::YearInfo) -> u16 { + year.days_in_year() + } + + // As an true lunar calendar, it does not have leap years. + fn provided_year_is_leap(year: Self::YearInfo) -> bool { + year.days_in_year() != SHORT_YEAR_LEN + } + + fn last_month_day_in_provided_year(year: Self::YearInfo) -> (u8, u8) { + let days = Self::days_in_provided_month(year, 12); + + (12, days) + } +} + +impl crate::cal::scaffold::UnstableSealed for HijriSimulated {} +impl Calendar for HijriSimulated { + type DateInner = HijriSimulatedDateInner; + type Year = types::EraYear; + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + let year = match era { + Some("ah") | None => year_check(year, 1..)?, + Some("bh") => 1 - year_check(year, 1..)?, + Some(_) => return Err(DateError::UnknownEra), + }; + let Some((month, false)) = month_code.parsed() else { + return Err(DateError::UnknownMonthCode(month_code)); + }; + Ok(HijriSimulatedDateInner(ArithmeticDate::new_from_ordinals( + self.load_or_compute_info(year), + month, + day, + )?)) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + // +1 because the epoch is new year of year 1 + // truncating instead of flooring does not matter, as this is well-defined for + // positive years only + let extended_year = ((rd - calendrical_calculations::islamic::ISLAMIC_EPOCH_FRIDAY) as f64 + / calendrical_calculations::islamic::MEAN_YEAR_LENGTH) + as i32 + + 1; + + let year = self.load_or_compute_info(extended_year); + + let y = if rd < year.start_day { + self.load_or_compute_info(extended_year - 1) + } else { + let next_year = self.load_or_compute_info(extended_year + 1); + if rd < next_year.start_day { + year + } else { + next_year + } + }; + let (m, d) = y.md_from_rd(rd); + HijriSimulatedDateInner(ArithmeticDate::new_unchecked(y, m, d)) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + date.0.year.md_to_rd(date.0.month, date.0.day) + } + + fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner { + self.from_rata_die(Iso.to_rata_die(&iso)) + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + Iso.from_rata_die(self.to_rata_die(date)) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + date.0.months_in_year() + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + date.0.days_in_year() + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + date.0.days_in_month() + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + date.0.offset_date(offset, self) + } + + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + _largest_unit: DateDurationUnit, + _smallest_unit: DateDurationUnit, + ) -> DateDuration { + date1.0.until(date2.0, _largest_unit, _smallest_unit) + } + + fn debug_name(&self) -> &'static str { + Self::DEBUG_NAME + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + era_year(self.extended_year(date)) + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + date.0.extended_year() + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Self::provided_year_is_leap(date.0.year) + } + + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + date.0.month() + } + + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + date.0.day_of_month() + } + + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + date.0.day_of_year() + } + + fn calendar_algorithm(&self) -> Option { + Some(match self.location { + crate::cal::hijri::HijriSimulatedLocation::Mecca => { + crate::preferences::CalendarAlgorithm::Hijri(Some( + crate::preferences::HijriCalendarAlgorithm::Rgsa, + )) + } + }) + } +} + +impl HijriSimulatedLocation { + fn compute_year_info(self, extended_year: i32) -> HijriYearInfo { + let start_day = calendrical_calculations::islamic::fixed_from_observational_islamic( + extended_year, + 1, + 1, + self.location(), + ); + let next_start_day = calendrical_calculations::islamic::fixed_from_observational_islamic( + extended_year + 1, + 1, + 1, + self.location(), + ); + match (next_start_day - start_day) as u16 { + LONG_YEAR_LEN | SHORT_YEAR_LEN => (), + 353 => { + icu_provider::log::trace!( + "({}) Found year {extended_year} AH with length {}. See ", + HijriSimulated::DEBUG_NAME, + next_start_day - start_day + ); + } + other => { + debug_assert!( + false, + "({}) Found year {extended_year} AH with length {}!", + HijriSimulated::DEBUG_NAME, + other + ) + } + } + + let month_lengths = { + let mut excess_days = 0; + let mut month_lengths = core::array::from_fn(|month_idx| { + let days_in_month = + calendrical_calculations::islamic::observational_islamic_month_days( + extended_year, + month_idx as u8 + 1, + self.location(), + ); + match days_in_month { + 29 => false, + 30 => true, + 31 => { + icu_provider::log::trace!( + "({}) Found year {extended_year} AH with month length {days_in_month} for month {}.", + HijriSimulated::DEBUG_NAME, + month_idx + 1 + ); + excess_days += 1; + true + } + _ => { + debug_assert!( + false, + "({}) Found year {extended_year} AH with month length {days_in_month} for month {}!", + HijriSimulated::DEBUG_NAME, + month_idx + 1 + ); + false + } + } + }); + // To maintain invariants for calendar arithmetic, if astronomy finds + // a 31-day month, "move" the day to the first 29-day month in the + // same year to maintain all months at 29 or 30 days. + if excess_days != 0 { + debug_assert_eq!( + excess_days, + 1, + "({}) Found year {extended_year} AH with more than one excess day!", + HijriSimulated::DEBUG_NAME + ); + if let Some(l) = month_lengths.iter_mut().find(|l| !(**l)) { + *l = true; + } + } + month_lengths + }; + HijriYearInfo { + month_lengths, + start_day, + value: extended_year, + } + } +} + +impl HijriSimulated { + pub(crate) const DEBUG_NAME: &'static str = "Hijri (simulated)"; +} + +impl> Date { + /// Construct new simulated Hijri Date. + /// + /// ```rust + /// use icu::calendar::cal::HijriSimulated; + /// use icu::calendar::Date; + /// + /// let hijri = HijriSimulated::new_mecca_always_calculating(); + /// + /// let date_hijri = + /// Date::try_new_simulated_hijri_with_calendar(1392, 4, 25, hijri) + /// .expect("Failed to initialize Hijri Date instance."); + /// + /// assert_eq!(date_hijri.era_year().year, 1392); + /// assert_eq!(date_hijri.month().ordinal, 4); + /// assert_eq!(date_hijri.day_of_month().0, 25); + /// ``` + pub fn try_new_simulated_hijri_with_calendar( + year: i32, + month: u8, + day: u8, + calendar: A, + ) -> Result, RangeError> { + let y = calendar.as_calendar().load_or_compute_info(year); + ArithmeticDate::new_from_ordinals(y, month, day) + .map(HijriSimulatedDateInner) + .map(|inner| Date::from_raw(inner, calendar)) + } +} + +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +/// The inner date type used for representing [`Date`]s of [`HijriUmmAlQura`]. See [`Date`] and [`HijriUmmAlQura`] for more details. +pub struct HijriUmmAlQuraDateInner(ArithmeticDate); + +impl CalendarArithmetic for HijriUmmAlQura { + type YearInfo = HijriYearInfo; + + fn days_in_provided_month(year: Self::YearInfo, month: u8) -> u8 { + year.days_in_month(month) + } + + fn months_in_provided_year(_year: HijriYearInfo) -> u8 { + 12 + } + + fn days_in_provided_year(year: Self::YearInfo) -> u16 { + year.days_in_year() + } + + // As an true lunar calendar, it does not have leap years. + fn provided_year_is_leap(year: Self::YearInfo) -> bool { + year.days_in_year() != SHORT_YEAR_LEN + } + + fn last_month_day_in_provided_year(year: HijriYearInfo) -> (u8, u8) { + let days = Self::days_in_provided_month(year, 12); + + (12, days) + } +} + +impl crate::cal::scaffold::UnstableSealed for HijriUmmAlQura {} +impl Calendar for HijriUmmAlQura { + type DateInner = HijriUmmAlQuraDateInner; + type Year = types::EraYear; + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + let year = match era { + Some("ah") | None => year_check(year, 1..)?, + Some("bh") => 1 - year_check(year, 1..)?, + Some(_) => return Err(DateError::UnknownEra), + }; + let Some((month, false)) = month_code.parsed() else { + return Err(DateError::UnknownMonthCode(month_code)); + }; + Ok(HijriUmmAlQuraDateInner(ArithmeticDate::new_from_ordinals( + self.load_or_compute_info(year), + month, + day, + )?)) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + // +1 because the epoch is new year of year 1 + // truncating instead of flooring does not matter, as this is well-defined for + // positive years only + let extended_year = ((rd - calendrical_calculations::islamic::ISLAMIC_EPOCH_FRIDAY) as f64 + / calendrical_calculations::islamic::MEAN_YEAR_LENGTH) + as i32 + + 1; + + let year = self.load_or_compute_info(extended_year); + + let y = if rd < year.start_day { + self.load_or_compute_info(extended_year - 1) + } else { + let next_year = self.load_or_compute_info(extended_year + 1); + if rd < next_year.start_day { + year + } else { + next_year + } + }; + let (m, d) = y.md_from_rd(rd); + HijriUmmAlQuraDateInner(ArithmeticDate::new_unchecked(y, m, d)) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + date.0.year.md_to_rd(date.0.month, date.0.day) + } + + fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner { + self.from_rata_die(Iso.to_rata_die(&iso)) + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + Iso.from_rata_die(self.to_rata_die(date)) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + date.0.months_in_year() + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + date.0.days_in_year() + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + date.0.days_in_month() + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + date.0.offset_date(offset, &HijriUmmAlQura) + } + + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + _largest_unit: DateDurationUnit, + _smallest_unit: DateDurationUnit, + ) -> DateDuration { + date1.0.until(date2.0, _largest_unit, _smallest_unit) + } + + fn debug_name(&self) -> &'static str { + Self::DEBUG_NAME + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + era_year(self.extended_year(date)) + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + date.0.extended_year() + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Self::provided_year_is_leap(date.0.year) + } + + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + date.0.month() + } + + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + date.0.day_of_month() + } + + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + date.0.day_of_year() + } + + fn calendar_algorithm(&self) -> Option { + let expected_calendar = crate::preferences::CalendarAlgorithm::Hijri(Some( + crate::preferences::HijriCalendarAlgorithm::Umalqura, + )); + Some(expected_calendar) + } +} + +impl PrecomputedDataSource for HijriUmmAlQura { + fn load_or_compute_info(&self, year: i32) -> HijriYearInfo { + if let Some(&packed) = usize::try_from(year - UMMALQURA_DATA_STARTING_YEAR) + .ok() + .and_then(|i| UMMALQURA_DATA.get(i)) + { + HijriYearInfo::unpack(year, packed) + } else { + HijriYearInfo { + value: year, + month_lengths: core::array::from_fn(|i| { + HijriTabular::days_in_provided_month(year, i as u8 + 1) == 30 + }), + start_day: calendrical_calculations::islamic::fixed_from_tabular_islamic( + year, + 1, + 1, + ISLAMIC_EPOCH_FRIDAY, + ), + } + } + } +} + +impl HijriUmmAlQura { + pub(crate) const DEBUG_NAME: &'static str = "Hijri (Umm al-Qura)"; +} + +impl Date { + /// Construct new Hijri Umm al-Qura Date. + /// + /// ```rust + /// use icu::calendar::cal::HijriUmmAlQura; + /// use icu::calendar::Date; + /// + /// let date_hijri = Date::try_new_ummalqura(1392, 4, 25) + /// .expect("Failed to initialize Hijri Date instance."); + /// + /// assert_eq!(date_hijri.era_year().year, 1392); + /// assert_eq!(date_hijri.month().ordinal, 4); + /// assert_eq!(date_hijri.day_of_month().0, 25); + /// ``` + pub fn try_new_ummalqura( + year: i32, + month: u8, + day: u8, + ) -> Result, RangeError> { + let y = HijriUmmAlQura.load_or_compute_info(year); + Ok(Date::from_raw( + HijriUmmAlQuraDateInner(ArithmeticDate::new_from_ordinals(y, month, day)?), + HijriUmmAlQura, + )) + } +} + +/// The inner date type used for representing [`Date`]s of [`HijriTabular`]. See [`Date`] and [`HijriTabular`] for more details. + +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +pub struct HijriTabularDateInner(ArithmeticDate); + +impl CalendarArithmetic for HijriTabular { + type YearInfo = i32; + + fn days_in_provided_month(year: i32, month: u8) -> u8 { + match month { + 1 | 3 | 5 | 7 | 9 | 11 => 30, + 2 | 4 | 6 | 8 | 10 => 29, + 12 if Self::provided_year_is_leap(year) => 30, + 12 => 29, + _ => 0, + } + } + + fn months_in_provided_year(_year: Self::YearInfo) -> u8 { + 12 + } + + fn days_in_provided_year(year: i32) -> u16 { + if Self::provided_year_is_leap(year) { + LONG_YEAR_LEN + } else { + SHORT_YEAR_LEN + } + } + + fn provided_year_is_leap(year: i32) -> bool { + (14 + 11 * year).rem_euclid(30) < 11 + } + + fn last_month_day_in_provided_year(year: i32) -> (u8, u8) { + if Self::provided_year_is_leap(year) { + (12, 30) + } else { + (12, 29) + } + } +} + +impl crate::cal::scaffold::UnstableSealed for HijriTabular {} +impl Calendar for HijriTabular { + type DateInner = HijriTabularDateInner; + type Year = types::EraYear; + + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + let year = match era { + Some("ah") | None => year_check(year, 1..)?, + Some("bh") => 1 - year_check(year, 1..)?, + Some(_) => return Err(DateError::UnknownEra), + }; + + ArithmeticDate::new_from_codes(self, year, month_code, day).map(HijriTabularDateInner) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + let (y, m, d) = match self.leap_years { + HijriTabularLeapYears::TypeII => { + calendrical_calculations::islamic::tabular_islamic_from_fixed( + rd, + self.epoch.rata_die(), + ) + } + }; + + debug_assert!(Date::try_new_hijri_tabular_with_calendar(y, m, d, crate::Ref(self)).is_ok()); + HijriTabularDateInner(ArithmeticDate::new_unchecked(y, m, d)) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + match self.leap_years { + HijriTabularLeapYears::TypeII => { + calendrical_calculations::islamic::fixed_from_tabular_islamic( + date.0.year, + date.0.month, + date.0.day, + self.epoch.rata_die(), + ) + } + } + } + + fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner { + self.from_rata_die(Iso.to_rata_die(&iso)) + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + Iso.from_rata_die(self.to_rata_die(date)) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + date.0.months_in_year() + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + date.0.days_in_year() + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + date.0.days_in_month() + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + date.0.offset_date(offset, &()) + } + + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + _largest_unit: DateDurationUnit, + _smallest_unit: DateDurationUnit, + ) -> DateDuration { + date1.0.until(date2.0, _largest_unit, _smallest_unit) + } + + fn debug_name(&self) -> &'static str { + match self.epoch { + HijriTabularEpoch::Friday => "Hijri (civil)", + HijriTabularEpoch::Thursday => "Hijri (astronomical)", + } + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + era_year(self.extended_year(date)) + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + date.0.extended_year() + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Self::provided_year_is_leap(date.0.year) + } + + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + date.0.month() + } + + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + date.0.day_of_month() + } + + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + date.0.day_of_year() + } + + fn calendar_algorithm(&self) -> Option { + let expected_calendar = match (self.epoch, self.leap_years) { + (crate::cal::HijriTabularEpoch::Friday, crate::cal::HijriTabularLeapYears::TypeII) => { + crate::preferences::CalendarAlgorithm::Hijri(Some( + crate::preferences::HijriCalendarAlgorithm::Civil, + )) + } + ( + crate::cal::HijriTabularEpoch::Thursday, + crate::cal::HijriTabularLeapYears::TypeII, + ) => crate::preferences::CalendarAlgorithm::Hijri(Some( + crate::preferences::HijriCalendarAlgorithm::Tbla, + )), + }; + Some(expected_calendar) + } +} + +impl> Date { + /// Construct new Tabular Hijri Date. + /// + /// ```rust + /// use icu::calendar::cal::{ + /// HijriTabular, HijriTabularEpoch, HijriTabularLeapYears, + /// }; + /// use icu::calendar::Date; + /// + /// let hijri = HijriTabular::new( + /// HijriTabularLeapYears::TypeII, + /// HijriTabularEpoch::Thursday, + /// ); + /// + /// let date_hijri = + /// Date::try_new_hijri_tabular_with_calendar(1392, 4, 25, hijri) + /// .expect("Failed to initialize Hijri Date instance."); + /// + /// assert_eq!(date_hijri.era_year().year, 1392); + /// assert_eq!(date_hijri.month().ordinal, 4); + /// assert_eq!(date_hijri.day_of_month().0, 25); + /// ``` + pub fn try_new_hijri_tabular_with_calendar( + year: i32, + month: u8, + day: u8, + calendar: A, + ) -> Result, RangeError> { + ArithmeticDate::new_from_ordinals(year, month, day) + .map(HijriTabularDateInner) + .map(|inner| Date::from_raw(inner, calendar)) + } +} + +#[cfg(test)] +mod test { + use types::MonthCode; + + use super::*; + use crate::Ref; + + const START_YEAR: i32 = -1245; + const END_YEAR: i32 = 1518; + + #[derive(Debug)] + struct DateCase { + year: i32, + month: u8, + day: u8, + } + + static TEST_RD: [i64; 33] = [ + -214193, -61387, 25469, 49217, 171307, 210155, 253427, 369740, 400085, 434355, 452605, + 470160, 473837, 507850, 524156, 544676, 567118, 569477, 601716, 613424, 626596, 645554, + 664224, 671401, 694799, 704424, 708842, 709409, 709580, 727274, 728714, 744313, 764652, + ]; + + static UMMALQURA_CASES: [DateCase; 33] = [ + DateCase { + year: -1245, + month: 12, + day: 9, + }, + DateCase { + year: -813, + month: 2, + day: 23, + }, + DateCase { + year: -568, + month: 4, + day: 1, + }, + DateCase { + year: -501, + month: 4, + day: 6, + }, + DateCase { + year: -157, + month: 10, + day: 17, + }, + DateCase { + year: -47, + month: 6, + day: 3, + }, + DateCase { + year: 75, + month: 7, + day: 13, + }, + DateCase { + year: 403, + month: 10, + day: 5, + }, + DateCase { + year: 489, + month: 5, + day: 22, + }, + DateCase { + year: 586, + month: 2, + day: 7, + }, + DateCase { + year: 637, + month: 8, + day: 7, + }, + DateCase { + year: 687, + month: 2, + day: 20, + }, + DateCase { + year: 697, + month: 7, + day: 7, + }, + DateCase { + year: 793, + month: 7, + day: 1, + }, + DateCase { + year: 839, + month: 7, + day: 6, + }, + DateCase { + year: 897, + month: 6, + day: 1, + }, + DateCase { + year: 960, + month: 9, + day: 30, + }, + DateCase { + year: 967, + month: 5, + day: 27, + }, + DateCase { + year: 1058, + month: 5, + day: 18, + }, + DateCase { + year: 1091, + month: 6, + day: 2, + }, + DateCase { + year: 1128, + month: 8, + day: 4, + }, + DateCase { + year: 1182, + month: 2, + day: 3, + }, + DateCase { + year: 1234, + month: 10, + day: 10, + }, + DateCase { + year: 1255, + month: 1, + day: 11, + }, + DateCase { + year: 1321, + month: 1, + day: 21, + }, + DateCase { + year: 1348, + month: 3, + day: 20, + }, + DateCase { + year: 1360, + month: 9, + day: 7, + }, + DateCase { + year: 1362, + month: 4, + day: 14, + }, + DateCase { + year: 1362, + month: 10, + day: 7, + }, + DateCase { + year: 1412, + month: 9, + day: 12, + }, + DateCase { + year: 1416, + month: 10, + day: 6, + }, + DateCase { + year: 1460, + month: 10, + day: 13, + }, + DateCase { + year: 1518, + month: 3, + day: 5, + }, + ]; + + static SIMULATED_CASES: [DateCase; 33] = [ + DateCase { + year: -1245, + month: 12, + day: 10, + }, + DateCase { + year: -813, + month: 2, + day: 25, + }, + DateCase { + year: -568, + month: 4, + day: 2, + }, + DateCase { + year: -501, + month: 4, + day: 7, + }, + DateCase { + year: -157, + month: 10, + day: 18, + }, + DateCase { + year: -47, + month: 6, + day: 3, + }, + DateCase { + year: 75, + month: 7, + day: 13, + }, + DateCase { + year: 403, + month: 10, + day: 5, + }, + DateCase { + year: 489, + month: 5, + day: 22, + }, + DateCase { + year: 586, + month: 2, + day: 7, + }, + DateCase { + year: 637, + month: 8, + day: 7, + }, + DateCase { + year: 687, + month: 2, + day: 21, + }, + DateCase { + year: 697, + month: 7, + day: 7, + }, + DateCase { + year: 793, + month: 6, + day: 29, + }, + DateCase { + year: 839, + month: 7, + day: 6, + }, + DateCase { + year: 897, + month: 6, + day: 2, + }, + DateCase { + year: 960, + month: 9, + day: 30, + }, + DateCase { + year: 967, + month: 5, + day: 27, + }, + DateCase { + year: 1058, + month: 5, + day: 18, + }, + DateCase { + year: 1091, + month: 6, + day: 3, + }, + DateCase { + year: 1128, + month: 8, + day: 4, + }, + DateCase { + year: 1182, + month: 2, + day: 4, + }, + DateCase { + year: 1234, + month: 10, + day: 10, + }, + DateCase { + year: 1255, + month: 1, + day: 11, + }, + DateCase { + year: 1321, + month: 1, + day: 20, + }, + DateCase { + year: 1348, + month: 3, + day: 19, + }, + DateCase { + year: 1360, + month: 9, + day: 7, + }, + DateCase { + year: 1362, + month: 4, + day: 13, + }, + DateCase { + year: 1362, + month: 10, + day: 7, + }, + DateCase { + year: 1412, + month: 9, + day: 12, + }, + DateCase { + year: 1416, + month: 10, + day: 5, + }, + DateCase { + year: 1460, + month: 10, + day: 12, + }, + DateCase { + year: 1518, + month: 3, + day: 5, + }, + ]; + + static ARITHMETIC_CASES: [DateCase; 33] = [ + DateCase { + year: -1245, + month: 12, + day: 9, + }, + DateCase { + year: -813, + month: 2, + day: 23, + }, + DateCase { + year: -568, + month: 4, + day: 1, + }, + DateCase { + year: -501, + month: 4, + day: 6, + }, + DateCase { + year: -157, + month: 10, + day: 17, + }, + DateCase { + year: -47, + month: 6, + day: 3, + }, + DateCase { + year: 75, + month: 7, + day: 13, + }, + DateCase { + year: 403, + month: 10, + day: 5, + }, + DateCase { + year: 489, + month: 5, + day: 22, + }, + DateCase { + year: 586, + month: 2, + day: 7, + }, + DateCase { + year: 637, + month: 8, + day: 7, + }, + DateCase { + year: 687, + month: 2, + day: 20, + }, + DateCase { + year: 697, + month: 7, + day: 7, + }, + DateCase { + year: 793, + month: 7, + day: 1, + }, + DateCase { + year: 839, + month: 7, + day: 6, + }, + DateCase { + year: 897, + month: 6, + day: 1, + }, + DateCase { + year: 960, + month: 9, + day: 30, + }, + DateCase { + year: 967, + month: 5, + day: 27, + }, + DateCase { + year: 1058, + month: 5, + day: 18, + }, + DateCase { + year: 1091, + month: 6, + day: 2, + }, + DateCase { + year: 1128, + month: 8, + day: 4, + }, + DateCase { + year: 1182, + month: 2, + day: 3, + }, + DateCase { + year: 1234, + month: 10, + day: 10, + }, + DateCase { + year: 1255, + month: 1, + day: 11, + }, + DateCase { + year: 1321, + month: 1, + day: 21, + }, + DateCase { + year: 1348, + month: 3, + day: 19, + }, + DateCase { + year: 1360, + month: 9, + day: 8, + }, + DateCase { + year: 1362, + month: 4, + day: 13, + }, + DateCase { + year: 1362, + month: 10, + day: 7, + }, + DateCase { + year: 1412, + month: 9, + day: 13, + }, + DateCase { + year: 1416, + month: 10, + day: 5, + }, + DateCase { + year: 1460, + month: 10, + day: 12, + }, + DateCase { + year: 1518, + month: 3, + day: 5, + }, + ]; + + static ASTRONOMICAL_CASES: [DateCase; 33] = [ + DateCase { + year: -1245, + month: 12, + day: 10, + }, + DateCase { + year: -813, + month: 2, + day: 24, + }, + DateCase { + year: -568, + month: 4, + day: 2, + }, + DateCase { + year: -501, + month: 4, + day: 7, + }, + DateCase { + year: -157, + month: 10, + day: 18, + }, + DateCase { + year: -47, + month: 6, + day: 4, + }, + DateCase { + year: 75, + month: 7, + day: 14, + }, + DateCase { + year: 403, + month: 10, + day: 6, + }, + DateCase { + year: 489, + month: 5, + day: 23, + }, + DateCase { + year: 586, + month: 2, + day: 8, + }, + DateCase { + year: 637, + month: 8, + day: 8, + }, + DateCase { + year: 687, + month: 2, + day: 21, + }, + DateCase { + year: 697, + month: 7, + day: 8, + }, + DateCase { + year: 793, + month: 7, + day: 2, + }, + DateCase { + year: 839, + month: 7, + day: 7, + }, + DateCase { + year: 897, + month: 6, + day: 2, + }, + DateCase { + year: 960, + month: 10, + day: 1, + }, + DateCase { + year: 967, + month: 5, + day: 28, + }, + DateCase { + year: 1058, + month: 5, + day: 19, + }, + DateCase { + year: 1091, + month: 6, + day: 3, + }, + DateCase { + year: 1128, + month: 8, + day: 5, + }, + DateCase { + year: 1182, + month: 2, + day: 4, + }, + DateCase { + year: 1234, + month: 10, + day: 11, + }, + DateCase { + year: 1255, + month: 1, + day: 12, + }, + DateCase { + year: 1321, + month: 1, + day: 22, + }, + DateCase { + year: 1348, + month: 3, + day: 20, + }, + DateCase { + year: 1360, + month: 9, + day: 9, + }, + DateCase { + year: 1362, + month: 4, + day: 14, + }, + DateCase { + year: 1362, + month: 10, + day: 8, + }, + DateCase { + year: 1412, + month: 9, + day: 14, + }, + DateCase { + year: 1416, + month: 10, + day: 6, + }, + DateCase { + year: 1460, + month: 10, + day: 13, + }, + DateCase { + year: 1518, + month: 3, + day: 6, + }, + ]; + + #[test] + fn test_simulated_hijri_from_rd() { + let calendar = HijriSimulated::new_mecca(); + let calendar = Ref(&calendar); + for (case, f_date) in SIMULATED_CASES.iter().zip(TEST_RD.iter()) { + let date = Date::try_new_simulated_hijri_with_calendar( + case.year, case.month, case.day, calendar, + ) + .unwrap(); + let iso = Date::from_rata_die(RataDie::new(*f_date), Iso); + + assert_eq!(iso.to_calendar(calendar).inner, date.inner, "{case:?}"); + } + } + + #[test] + fn test_rd_from_simulated_hijri() { + let calendar = HijriSimulated::new_mecca(); + let calendar = Ref(&calendar); + for (case, f_date) in SIMULATED_CASES.iter().zip(TEST_RD.iter()) { + let date = Date::try_new_simulated_hijri_with_calendar( + case.year, case.month, case.day, calendar, + ) + .unwrap(); + assert_eq!(date.to_rata_die(), RataDie::new(*f_date), "{case:?}"); + } + } + + #[test] + fn test_rd_from_hijri() { + let calendar = HijriTabular::new(HijriTabularLeapYears::TypeII, HijriTabularEpoch::Friday); + let calendar = Ref(&calendar); + for (case, f_date) in ARITHMETIC_CASES.iter().zip(TEST_RD.iter()) { + let date = Date::try_new_hijri_tabular_with_calendar( + case.year, case.month, case.day, calendar, + ) + .unwrap(); + assert_eq!(date.to_rata_die(), RataDie::new(*f_date), "{case:?}"); + } + } + + #[test] + fn test_hijri_from_rd() { + let calendar = HijriTabular::new(HijriTabularLeapYears::TypeII, HijriTabularEpoch::Friday); + let calendar = Ref(&calendar); + for (case, f_date) in ARITHMETIC_CASES.iter().zip(TEST_RD.iter()) { + let date = Date::try_new_hijri_tabular_with_calendar( + case.year, case.month, case.day, calendar, + ) + .unwrap(); + let date_rd = Date::from_rata_die(RataDie::new(*f_date), calendar); + + assert_eq!(date, date_rd, "{case:?}"); + } + } + + #[test] + fn test_rd_from_hijri_tbla() { + let calendar = + HijriTabular::new(HijriTabularLeapYears::TypeII, HijriTabularEpoch::Thursday); + let calendar = Ref(&calendar); + for (case, f_date) in ASTRONOMICAL_CASES.iter().zip(TEST_RD.iter()) { + let date = Date::try_new_hijri_tabular_with_calendar( + case.year, case.month, case.day, calendar, + ) + .unwrap(); + assert_eq!(date.to_rata_die(), RataDie::new(*f_date), "{case:?}"); + } + } + + #[test] + fn test_hijri_tbla_from_rd() { + let calendar = + HijriTabular::new(HijriTabularLeapYears::TypeII, HijriTabularEpoch::Thursday); + let calendar = Ref(&calendar); + for (case, f_date) in ASTRONOMICAL_CASES.iter().zip(TEST_RD.iter()) { + let date = Date::try_new_hijri_tabular_with_calendar( + case.year, case.month, case.day, calendar, + ) + .unwrap(); + let date_rd = Date::from_rata_die(RataDie::new(*f_date), calendar); + + assert_eq!(date, date_rd, "{case:?}"); + } + } + + #[test] + fn test_saudi_hijri_from_rd() { + let calendar = HijriUmmAlQura::new(); + let calendar = Ref(&calendar); + for (case, f_date) in UMMALQURA_CASES.iter().zip(TEST_RD.iter()) { + let date = Date::try_new_ummalqura(case.year, case.month, case.day).unwrap(); + let date_rd = Date::from_rata_die(RataDie::new(*f_date), calendar); + + assert_eq!(date, date_rd, "{case:?}"); + } + } + + #[test] + fn test_rd_from_saudi_hijri() { + for (case, f_date) in UMMALQURA_CASES.iter().zip(TEST_RD.iter()) { + let date = Date::try_new_ummalqura(case.year, case.month, case.day).unwrap(); + assert_eq!(date.to_rata_die(), RataDie::new(*f_date), "{case:?}"); + } + } + + #[ignore] // slow + #[test] + fn test_days_in_provided_year_simulated() { + let calendar = HijriSimulated::new_mecca(); + let calendar = Ref(&calendar); + // -1245 1 1 = -214526 (R.D Date) + // 1518 1 1 = 764589 (R.D Date) + let sum_days_in_year: i64 = (START_YEAR..END_YEAR) + .map(|year| { + HijriSimulated::days_in_provided_year( + HijriSimulatedLocation::Mecca.compute_year_info(year), + ) as i64 + }) + .sum(); + let expected_number_of_days = + Date::try_new_simulated_hijri_with_calendar(END_YEAR, 1, 1, calendar) + .unwrap() + .to_rata_die() + - Date::try_new_simulated_hijri_with_calendar(START_YEAR, 1, 1, calendar) + .unwrap() + .to_rata_die(); // The number of days between Hijri years -1245 and 1518 + let tolerance = 1; // One day tolerance (See Astronomical::month_length for more context) + + assert!( + (sum_days_in_year - expected_number_of_days).abs() <= tolerance, + "Difference between sum_days_in_year and expected_number_of_days is more than the tolerance" + ); + } + + #[ignore] // slow + #[test] + fn test_days_in_provided_year_ummalqura() { + // -1245 1 1 = -214528 (R.D Date) + // 1518 1 1 = 764588 (R.D Date) + let sum_days_in_year: i64 = (START_YEAR..END_YEAR) + .map(|year| { + HijriUmmAlQura::days_in_provided_year(HijriUmmAlQura.load_or_compute_info(year)) + as i64 + }) + .sum(); + let expected_number_of_days = Date::try_new_ummalqura(END_YEAR, 1, 1) + .unwrap() + .to_rata_die() + - (Date::try_new_ummalqura(START_YEAR, 1, 1).unwrap()).to_rata_die(); // The number of days between Umm al-Qura Hijri years -1245 and 1518 + + assert_eq!(sum_days_in_year, expected_number_of_days); + } + + #[test] + fn test_regression_3868() { + // This date used to panic on creation + let iso = Date::try_new_iso(2011, 4, 4).unwrap(); + let hijri = iso.to_calendar(HijriUmmAlQura::new()); + // Data from https://www.ummulqura.org.sa/Index.aspx + assert_eq!(hijri.day_of_month().0, 30); + assert_eq!(hijri.month().ordinal, 4); + assert_eq!(hijri.era_year().year, 1432); + } + + #[test] + fn test_regression_4914() { + // https://github.com/unicode-org/icu4x/issues/4914 + let dt = HijriUmmAlQura::new() + .from_codes(Some("bh"), 6824, MonthCode::new_normal(1).unwrap(), 1) + .unwrap(); + assert_eq!(dt.0.day, 1); + assert_eq!(dt.0.month, 1); + assert_eq!(dt.0.year.value, -6823); + } + + #[test] + fn test_regression_5069_uaq() { + let cached = HijriUmmAlQura::new(); + + let cached = crate::Ref(&cached); + + let dt_cached = Date::try_new_ummalqura(1391, 1, 29).unwrap(); + + assert_eq!(dt_cached.to_iso().to_calendar(cached), dt_cached); + } + + #[test] + fn test_regression_5069_obs() { + let cached = HijriSimulated::new_mecca(); + let comp = HijriSimulated::new_mecca_always_calculating(); + + let cached = crate::Ref(&cached); + let comp = crate::Ref(&comp); + + let dt_cached = Date::try_new_simulated_hijri_with_calendar(1390, 1, 30, cached).unwrap(); + let dt_comp = Date::try_new_simulated_hijri_with_calendar(1390, 1, 30, comp).unwrap(); + + assert_eq!(dt_cached.to_iso(), dt_comp.to_iso()); + + assert_eq!(dt_comp.to_iso().to_calendar(comp), dt_comp); + assert_eq!(dt_cached.to_iso().to_calendar(cached), dt_cached); + + let dt = Date::try_new_iso(2000, 5, 5).unwrap(); + + assert!(dt.to_calendar(comp).day_of_month().0 > 0); + assert!(dt.to_calendar(cached).day_of_month().0 > 0); + } + + #[test] + fn test_regression_6197() { + let cached = HijriUmmAlQura::new(); + + let cached = crate::Ref(&cached); + + let iso = Date::try_new_iso(2025, 2, 26).unwrap(); + + let cached = iso.to_calendar(cached); + + // Data from https://www.ummulqura.org.sa/ + assert_eq!( + ( + cached.day_of_month().0, + cached.month().ordinal, + cached.era_year().year + ), + (27, 8, 1446) + ); + } + + #[test] + fn test_uaq_icu4c_agreement() { + // From https://github.com/unicode-org/icu/blob/1bf6bf774dbc8c6c2051963a81100ea1114b497f/icu4c/source/i18n/islamcal.cpp#L87 + const ICU4C_ENCODED_MONTH_LENGTHS: [u16; 1601 - 1300] = [ + 0x0AAA, 0x0D54, 0x0EC9, 0x06D4, 0x06EA, 0x036C, 0x0AAD, 0x0555, 0x06A9, 0x0792, 0x0BA9, + 0x05D4, 0x0ADA, 0x055C, 0x0D2D, 0x0695, 0x074A, 0x0B54, 0x0B6A, 0x05AD, 0x04AE, 0x0A4F, + 0x0517, 0x068B, 0x06A5, 0x0AD5, 0x02D6, 0x095B, 0x049D, 0x0A4D, 0x0D26, 0x0D95, 0x05AC, + 0x09B6, 0x02BA, 0x0A5B, 0x052B, 0x0A95, 0x06CA, 0x0AE9, 0x02F4, 0x0976, 0x02B6, 0x0956, + 0x0ACA, 0x0BA4, 0x0BD2, 0x05D9, 0x02DC, 0x096D, 0x054D, 0x0AA5, 0x0B52, 0x0BA5, 0x05B4, + 0x09B6, 0x0557, 0x0297, 0x054B, 0x06A3, 0x0752, 0x0B65, 0x056A, 0x0AAB, 0x052B, 0x0C95, + 0x0D4A, 0x0DA5, 0x05CA, 0x0AD6, 0x0957, 0x04AB, 0x094B, 0x0AA5, 0x0B52, 0x0B6A, 0x0575, + 0x0276, 0x08B7, 0x045B, 0x0555, 0x05A9, 0x05B4, 0x09DA, 0x04DD, 0x026E, 0x0936, 0x0AAA, + 0x0D54, 0x0DB2, 0x05D5, 0x02DA, 0x095B, 0x04AB, 0x0A55, 0x0B49, 0x0B64, 0x0B71, 0x05B4, + 0x0AB5, 0x0A55, 0x0D25, 0x0E92, 0x0EC9, 0x06D4, 0x0AE9, 0x096B, 0x04AB, 0x0A93, 0x0D49, + 0x0DA4, 0x0DB2, 0x0AB9, 0x04BA, 0x0A5B, 0x052B, 0x0A95, 0x0B2A, 0x0B55, 0x055C, 0x04BD, + 0x023D, 0x091D, 0x0A95, 0x0B4A, 0x0B5A, 0x056D, 0x02B6, 0x093B, 0x049B, 0x0655, 0x06A9, + 0x0754, 0x0B6A, 0x056C, 0x0AAD, 0x0555, 0x0B29, 0x0B92, 0x0BA9, 0x05D4, 0x0ADA, 0x055A, + 0x0AAB, 0x0595, 0x0749, 0x0764, 0x0BAA, 0x05B5, 0x02B6, 0x0A56, 0x0E4D, 0x0B25, 0x0B52, + 0x0B6A, 0x05AD, 0x02AE, 0x092F, 0x0497, 0x064B, 0x06A5, 0x06AC, 0x0AD6, 0x055D, 0x049D, + 0x0A4D, 0x0D16, 0x0D95, 0x05AA, 0x05B5, 0x02DA, 0x095B, 0x04AD, 0x0595, 0x06CA, 0x06E4, + 0x0AEA, 0x04F5, 0x02B6, 0x0956, 0x0AAA, 0x0B54, 0x0BD2, 0x05D9, 0x02EA, 0x096D, 0x04AD, + 0x0A95, 0x0B4A, 0x0BA5, 0x05B2, 0x09B5, 0x04D6, 0x0A97, 0x0547, 0x0693, 0x0749, 0x0B55, + 0x056A, 0x0A6B, 0x052B, 0x0A8B, 0x0D46, 0x0DA3, 0x05CA, 0x0AD6, 0x04DB, 0x026B, 0x094B, + 0x0AA5, 0x0B52, 0x0B69, 0x0575, 0x0176, 0x08B7, 0x025B, 0x052B, 0x0565, 0x05B4, 0x09DA, + 0x04ED, 0x016D, 0x08B6, 0x0AA6, 0x0D52, 0x0DA9, 0x05D4, 0x0ADA, 0x095B, 0x04AB, 0x0653, + 0x0729, 0x0762, 0x0BA9, 0x05B2, 0x0AB5, 0x0555, 0x0B25, 0x0D92, 0x0EC9, 0x06D2, 0x0AE9, + 0x056B, 0x04AB, 0x0A55, 0x0D29, 0x0D54, 0x0DAA, 0x09B5, 0x04BA, 0x0A3B, 0x049B, 0x0A4D, + 0x0AAA, 0x0AD5, 0x02DA, 0x095D, 0x045E, 0x0A2E, 0x0C9A, 0x0D55, 0x06B2, 0x06B9, 0x04BA, + 0x0A5D, 0x052D, 0x0A95, 0x0B52, 0x0BA8, 0x0BB4, 0x05B9, 0x02DA, 0x095A, 0x0B4A, 0x0DA4, + 0x0ED1, 0x06E8, 0x0B6A, 0x056D, 0x0535, 0x0695, 0x0D4A, 0x0DA8, 0x0DD4, 0x06DA, 0x055B, + 0x029D, 0x062B, 0x0B15, 0x0B4A, 0x0B95, 0x05AA, 0x0AAE, 0x092E, 0x0C8F, 0x0527, 0x0695, + 0x06AA, 0x0AD6, 0x055D, 0x029D, + ]; + + // From https://github.com/unicode-org/icu/blob/1bf6bf774dbc8c6c2051963a81100ea1114b497f/icu4c/source/i18n/islamcal.cpp#L264 + const ICU4C_YEAR_START_ESTIMATE_FIX: [i64; 1601 - 1300] = [ + 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 1, 1, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, -1, 0, 0, 0, 1, 0, 0, -1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 1, 0, 0, -1, 0, 1, 0, 1, 1, 0, 0, -1, + 0, 1, 0, 0, 0, -1, 0, 1, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, -1, -1, 0, -1, 0, 1, 0, 0, 0, + -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, -1, 0, 0, 0, 1, 0, 0, -1, -1, 0, -1, 0, 0, + -1, -1, 0, -1, 0, -1, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 1, 1, 0, 0, -1, 0, + 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 1, 1, 0, 0, -1, 0, 1, 0, 1, 1, 0, 0, 0, + 0, 1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, -1, 0, 1, 0, 0, 0, + -1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, -1, + -1, 0, -1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 1, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, + ]; + + let icu4c = ICU4C_ENCODED_MONTH_LENGTHS + .into_iter() + .zip(ICU4C_YEAR_START_ESTIMATE_FIX) + .enumerate() + .map( + |(years_since_1300, (encoded_months_lengths, year_start_estimate_fix))| { + // https://github.com/unicode-org/icu/blob/1bf6bf774dbc8c6c2051963a81100ea1114b497f/icu4c/source/i18n/islamcal.cpp#L858 + let month_lengths = + core::array::from_fn(|i| (1 << (11 - i)) & encoded_months_lengths != 0); + // From https://github.com/unicode-org/icu/blob/1bf6bf774dbc8c6c2051963a81100ea1114b497f/icu4c/source/i18n/islamcal.cpp#L813 + let year_start = ((354.36720 * years_since_1300 as f64) + 460322.05 + 0.5) + as i64 + + year_start_estimate_fix; + HijriYearInfo { + value: 1300 + years_since_1300 as i32, + month_lengths, + start_day: ISLAMIC_EPOCH_FRIDAY + year_start, + } + }, + ) + .collect::>(); + + let icu4x = (1300..=1600) + .map(|y| HijriUmmAlQura.load_or_compute_info(y)) + .collect::>(); + + assert_eq!(icu4x, icu4c); + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/hijri/ummalqura_data.rs b/deps/crates/vendor/icu_calendar/src/cal/hijri/ummalqura_data.rs new file mode 100644 index 00000000000000..718286a8c1f830 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/hijri/ummalqura_data.rs @@ -0,0 +1,317 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::provider::hijri::PackedHijriYearInfo; + +pub const UMMALQURA_DATA_STARTING_YEAR: i32 = 1300; + +#[rustfmt::skip] +pub const UMMALQURA_DATA: [PackedHijriYearInfo; 1601 - UMMALQURA_DATA_STARTING_YEAR as usize] = { + use calendrical_calculations::iso::const_fixed_from_iso as iso; + let l = true; // long + let s = false; // short + [ + PackedHijriYearInfo::new(UMMALQURA_DATA_STARTING_YEAR, [l, s, l, s, l, s, l, s, l, s, l, s], iso(1882, 11, 12)), + PackedHijriYearInfo::new(1301, [l, l, s, l, s, l, s, l, s, l, s, s], iso(1883, 11, 1)), + PackedHijriYearInfo::new(1302, [l, l, l, s, l, l, s, s, l, s, s, l], iso(1884, 10, 20)), + PackedHijriYearInfo::new(1303, [s, l, l, s, l, l, s, l, s, l, s, s], iso(1885, 10, 10)), + PackedHijriYearInfo::new(1304, [s, l, l, s, l, l, l, s, l, s, l, s], iso(1886, 9, 29)), + PackedHijriYearInfo::new(1305, [s, s, l, l, s, l, l, s, l, l, s, s], iso(1887, 9, 19)), + PackedHijriYearInfo::new(1306, [l, s, l, s, l, s, l, s, l, l, s, l], iso(1888, 9, 7)), + PackedHijriYearInfo::new(1307, [s, l, s, l, s, l, s, l, s, l, s, l], iso(1889, 8, 28)), + PackedHijriYearInfo::new(1308, [s, l, l, s, l, s, l, s, l, s, s, l], iso(1890, 8, 17)), + PackedHijriYearInfo::new(1309, [s, l, l, l, l, s, s, l, s, s, l, s], iso(1891, 8, 6)), + PackedHijriYearInfo::new(1310, [l, s, l, l, l, s, l, s, l, s, s, l], iso(1892, 7, 25)), + PackedHijriYearInfo::new(1311, [s, l, s, l, l, l, s, l, s, l, s, s], iso(1893, 7, 15)), + PackedHijriYearInfo::new(1312, [l, s, l, s, l, l, s, l, l, s, l, s], iso(1894, 7, 4)), + PackedHijriYearInfo::new(1313, [s, l, s, l, s, l, s, l, l, l, s, s], iso(1895, 6, 24)), + PackedHijriYearInfo::new(1314, [l, l, s, l, s, s, l, s, l, l, s, l], iso(1896, 6, 12)), + PackedHijriYearInfo::new(1315, [s, l, l, s, l, s, s, l, s, l, s, l], iso(1897, 6, 2)), + PackedHijriYearInfo::new(1316, [s, l, l, l, s, l, s, s, l, s, l, s], iso(1898, 5, 22)), + PackedHijriYearInfo::new(1317, [l, s, l, l, s, l, s, l, s, l, s, s], iso(1899, 5, 11)), + PackedHijriYearInfo::new(1318, [l, s, l, l, s, l, l, s, l, s, l, s], iso(1900, 4, 30)), + PackedHijriYearInfo::new(1319, [s, l, s, l, l, s, l, s, l, l, s, l], iso(1901, 4, 20)), + PackedHijriYearInfo::new(1320, [s, l, s, s, l, s, l, s, l, l, l, s], iso(1902, 4, 10)), + PackedHijriYearInfo::new(1321, [l, s, l, s, s, l, s, s, l, l, l, l], iso(1903, 3, 30)), + PackedHijriYearInfo::new(1322, [s, l, s, l, s, s, s, l, s, l, l, l], iso(1904, 3, 19)), + PackedHijriYearInfo::new(1323, [s, l, l, s, l, s, s, s, l, s, l, l], iso(1905, 3, 8)), + PackedHijriYearInfo::new(1324, [s, l, l, s, l, s, l, s, s, l, s, l], iso(1906, 2, 25)), + PackedHijriYearInfo::new(1325, [l, s, l, s, l, l, s, l, s, l, s, l], iso(1907, 2, 14)), + PackedHijriYearInfo::new(1326, [s, s, l, s, l, l, s, l, s, l, l, s], iso(1908, 2, 4)), + PackedHijriYearInfo::new(1327, [l, s, s, l, s, l, s, l, l, s, l, l], iso(1909, 1, 23)), + PackedHijriYearInfo::new(1328, [s, l, s, s, l, s, s, l, l, l, s, l], iso(1910, 1, 13)), + PackedHijriYearInfo::new(1329, [l, s, l, s, s, l, s, s, l, l, s, l], iso(1911, 1, 2)), + PackedHijriYearInfo::new(1330, [l, l, s, l, s, s, l, s, s, l, l, s], iso(1911, 12, 22)), + PackedHijriYearInfo::new(1331, [l, l, s, l, l, s, s, l, s, l, s, l], iso(1912, 12, 10)), + PackedHijriYearInfo::new(1332, [s, l, s, l, l, s, l, s, l, l, s, s], iso(1913, 11, 30)), + PackedHijriYearInfo::new(1333, [l, s, s, l, l, s, l, l, s, l, l, s], iso(1914, 11, 19)), + PackedHijriYearInfo::new(1334, [s, s, l, s, l, s, l, l, l, s, l, s], iso(1915, 11, 9)), + PackedHijriYearInfo::new(1335, [l, s, l, s, s, l, s, l, l, s, l, l], iso(1916, 10, 28)), + PackedHijriYearInfo::new(1336, [s, l, s, l, s, s, l, s, l, s, l, l], iso(1917, 10, 18)), + PackedHijriYearInfo::new(1337, [l, s, l, s, l, s, s, l, s, l, s, l], iso(1918, 10, 7)), + PackedHijriYearInfo::new(1338, [s, l, l, s, l, l, s, s, l, s, l, s], iso(1919, 9, 26)), + PackedHijriYearInfo::new(1339, [l, s, l, s, l, l, l, s, l, s, s, l], iso(1920, 9, 14)), + PackedHijriYearInfo::new(1340, [s, s, l, s, l, l, l, l, s, l, s, s], iso(1921, 9, 4)), + PackedHijriYearInfo::new(1341, [l, s, s, l, s, l, l, l, s, l, l, s], iso(1922, 8, 24)), + PackedHijriYearInfo::new(1342, [s, s, l, s, l, s, l, l, s, l, l, s], iso(1923, 8, 14)), + PackedHijriYearInfo::new(1343, [l, s, s, l, s, l, s, l, s, l, l, s], iso(1924, 8, 2)), + PackedHijriYearInfo::new(1344, [l, s, l, s, l, l, s, s, l, s, l, s], iso(1925, 7, 22)), + PackedHijriYearInfo::new(1345, [l, s, l, l, l, s, l, s, s, l, s, s], iso(1926, 7, 11)), + PackedHijriYearInfo::new(1346, [l, s, l, l, l, l, s, l, s, s, l, s], iso(1927, 6, 30)), + PackedHijriYearInfo::new(1347, [s, l, s, l, l, l, s, l, l, s, s, l], iso(1928, 6, 19)), + PackedHijriYearInfo::new(1348, [s, s, l, s, l, l, s, l, l, l, s, s], iso(1929, 6, 9)), + PackedHijriYearInfo::new(1349, [l, s, s, l, s, l, l, s, l, l, s, l], iso(1930, 5, 29)), + PackedHijriYearInfo::new(1350, [s, l, s, l, s, l, s, s, l, l, s, l], iso(1931, 5, 19)), + PackedHijriYearInfo::new(1351, [l, s, l, s, l, s, l, s, s, l, s, l], iso(1932, 5, 7)), + PackedHijriYearInfo::new(1352, [l, s, l, l, s, l, s, l, s, s, l, s], iso(1933, 4, 26)), + PackedHijriYearInfo::new(1353, [l, s, l, l, l, s, l, s, s, l, s, l], iso(1934, 4, 15)), + PackedHijriYearInfo::new(1354, [s, l, s, l, l, s, l, l, s, l, s, s], iso(1935, 4, 5)), + PackedHijriYearInfo::new(1355, [l, s, s, l, l, s, l, l, s, l, l, s], iso(1936, 3, 24)), + PackedHijriYearInfo::new(1356, [s, l, s, l, s, l, s, l, s, l, l, l], iso(1937, 3, 14)), + PackedHijriYearInfo::new(1357, [s, s, l, s, l, s, s, l, s, l, l, l], iso(1938, 3, 4)), + PackedHijriYearInfo::new(1358, [s, l, s, l, s, l, s, s, l, s, l, l], iso(1939, 2, 21)), + PackedHijriYearInfo::new(1359, [s, l, l, s, l, s, l, s, s, s, l, l], iso(1940, 2, 10)), + PackedHijriYearInfo::new(1360, [s, l, l, l, s, l, s, l, s, s, l, s], iso(1941, 1, 29)), + PackedHijriYearInfo::new(1361, [l, s, l, l, s, l, l, s, s, l, s, l], iso(1942, 1, 18)), + PackedHijriYearInfo::new(1362, [s, l, s, l, s, l, l, s, l, s, l, s], iso(1943, 1, 8)), + PackedHijriYearInfo::new(1363, [l, s, l, s, l, s, l, s, l, s, l, l], iso(1943, 12, 28)), + PackedHijriYearInfo::new(1364, [s, l, s, l, s, s, l, s, l, s, l, l], iso(1944, 12, 17)), + PackedHijriYearInfo::new(1365, [l, l, s, s, l, s, s, l, s, l, s, l], iso(1945, 12, 6)), + PackedHijriYearInfo::new(1366, [l, l, s, l, s, l, s, s, l, s, l, s], iso(1946, 11, 25)), + PackedHijriYearInfo::new(1367, [l, l, s, l, l, s, l, s, s, l, s, l], iso(1947, 11, 14)), + PackedHijriYearInfo::new(1368, [s, l, s, l, l, l, s, s, l, s, l, s], iso(1948, 11, 3)), + PackedHijriYearInfo::new(1369, [l, s, l, s, l, l, s, l, s, l, l, s], iso(1949, 10, 23)), + PackedHijriYearInfo::new(1370, [l, s, s, l, s, l, s, l, s, l, l, l], iso(1950, 10, 13)), + PackedHijriYearInfo::new(1371, [s, l, s, s, l, s, l, s, l, s, l, l], iso(1951, 10, 3)), + PackedHijriYearInfo::new(1372, [l, s, s, l, s, l, s, s, l, s, l, l], iso(1952, 9, 21)), + PackedHijriYearInfo::new(1373, [l, s, l, s, l, s, l, s, s, l, s, l], iso(1953, 9, 10)), + PackedHijriYearInfo::new(1374, [l, s, l, l, s, l, s, l, s, s, l, s], iso(1954, 8, 30)), + PackedHijriYearInfo::new(1375, [l, s, l, l, s, l, l, s, l, s, l, s], iso(1955, 8, 19)), + PackedHijriYearInfo::new(1376, [s, l, s, l, s, l, l, l, s, l, s, l], iso(1956, 8, 8)), + PackedHijriYearInfo::new(1377, [s, s, l, s, s, l, l, l, s, l, l, s], iso(1957, 7, 29)), + PackedHijriYearInfo::new(1378, [l, s, s, s, l, s, l, l, s, l, l, l], iso(1958, 7, 18)), + PackedHijriYearInfo::new(1379, [s, l, s, s, s, l, s, l, l, s, l, l], iso(1959, 7, 8)), + PackedHijriYearInfo::new(1380, [s, l, s, l, s, l, s, l, s, l, s, l], iso(1960, 6, 26)), + PackedHijriYearInfo::new(1381, [s, l, s, l, l, s, l, s, l, s, s, l], iso(1961, 6, 15)), + PackedHijriYearInfo::new(1382, [s, l, s, l, l, s, l, l, s, l, s, s], iso(1962, 6, 4)), + PackedHijriYearInfo::new(1383, [l, s, s, l, l, l, s, l, l, s, l, s], iso(1963, 5, 24)), + PackedHijriYearInfo::new(1384, [s, l, s, s, l, l, s, l, l, l, s, l], iso(1964, 5, 13)), + PackedHijriYearInfo::new(1385, [s, s, l, s, s, l, l, s, l, l, l, s], iso(1965, 5, 3)), + PackedHijriYearInfo::new(1386, [l, s, s, l, s, s, l, l, s, l, l, s], iso(1966, 4, 22)), + PackedHijriYearInfo::new(1387, [l, s, l, s, l, s, l, s, l, s, l, s], iso(1967, 4, 11)), + PackedHijriYearInfo::new(1388, [l, l, s, l, s, l, s, l, s, l, s, s], iso(1968, 3, 30)), + PackedHijriYearInfo::new(1389, [l, l, s, l, l, s, l, l, s, s, l, s], iso(1969, 3, 19)), + PackedHijriYearInfo::new(1390, [s, l, s, l, l, l, s, l, s, l, s, l], iso(1970, 3, 9)), + PackedHijriYearInfo::new(1391, [s, s, l, s, l, l, s, l, l, s, l, s], iso(1971, 2, 27)), + PackedHijriYearInfo::new(1392, [l, s, s, l, s, l, s, l, l, s, l, l], iso(1972, 2, 16)), + PackedHijriYearInfo::new(1393, [s, l, s, s, l, s, l, s, l, s, l, l], iso(1973, 2, 5)), + PackedHijriYearInfo::new(1394, [l, s, l, s, s, l, s, l, s, l, s, l], iso(1974, 1, 25)), + PackedHijriYearInfo::new(1395, [l, s, l, l, s, l, s, s, l, s, s, l], iso(1975, 1, 14)), + PackedHijriYearInfo::new(1396, [l, s, l, l, s, l, l, s, s, l, s, s], iso(1976, 1, 3)), + PackedHijriYearInfo::new(1397, [l, s, l, l, s, l, l, l, s, s, s, l], iso(1976, 12, 22)), + PackedHijriYearInfo::new(1398, [s, l, s, l, l, s, l, l, s, l, s, s], iso(1977, 12, 12)), + PackedHijriYearInfo::new(1399, [l, s, l, s, l, s, l, l, s, l, s, l], iso(1978, 12, 1)), + PackedHijriYearInfo::new(1400, [l, s, l, s, s, l, s, l, s, l, s, l], iso(1979, 11, 21)), + PackedHijriYearInfo::new(1401, [l, l, s, l, s, s, l, s, s, l, s, l], iso(1980, 11, 9)), + PackedHijriYearInfo::new(1402, [l, l, l, s, l, s, s, l, s, s, l, s], iso(1981, 10, 29)), + PackedHijriYearInfo::new(1403, [l, l, l, s, l, l, s, s, l, s, s, l], iso(1982, 10, 18)), + PackedHijriYearInfo::new(1404, [s, l, l, s, l, l, s, l, s, l, s, s], iso(1983, 10, 8)), + PackedHijriYearInfo::new(1405, [l, s, l, s, l, l, l, s, l, s, s, l], iso(1984, 9, 26)), + PackedHijriYearInfo::new(1406, [l, s, s, l, s, l, l, s, l, s, l, l], iso(1985, 9, 16)), + PackedHijriYearInfo::new(1407, [s, l, s, s, l, s, l, s, l, s, l, l], iso(1986, 9, 6)), + PackedHijriYearInfo::new(1408, [l, s, l, s, l, s, s, l, s, s, l, l], iso(1987, 8, 26)), + PackedHijriYearInfo::new(1409, [l, l, s, l, s, l, s, s, l, s, s, l], iso(1988, 8, 14)), + PackedHijriYearInfo::new(1410, [l, l, s, l, l, s, l, s, s, l, s, s], iso(1989, 8, 3)), + PackedHijriYearInfo::new(1411, [l, l, s, l, l, s, l, l, s, s, l, s], iso(1990, 7, 23)), + PackedHijriYearInfo::new(1412, [l, s, l, s, l, s, l, l, l, s, s, l], iso(1991, 7, 13)), + PackedHijriYearInfo::new(1413, [s, l, s, s, l, s, l, l, l, s, l, s], iso(1992, 7, 2)), + PackedHijriYearInfo::new(1414, [l, s, l, s, s, l, s, l, l, s, l, l], iso(1993, 6, 21)), + PackedHijriYearInfo::new(1415, [s, l, s, l, s, s, l, s, l, s, l, l], iso(1994, 6, 11)), + PackedHijriYearInfo::new(1416, [l, s, l, s, l, s, s, l, s, l, s, l], iso(1995, 5, 31)), + PackedHijriYearInfo::new(1417, [l, s, l, l, s, s, l, s, l, s, l, s], iso(1996, 5, 19)), + PackedHijriYearInfo::new(1418, [l, s, l, l, s, l, s, l, s, l, s, l], iso(1997, 5, 8)), + PackedHijriYearInfo::new(1419, [s, l, s, l, s, l, s, l, l, l, s, s], iso(1998, 4, 28)), + PackedHijriYearInfo::new(1420, [s, l, s, s, l, s, l, l, l, l, s, l], iso(1999, 4, 17)), + PackedHijriYearInfo::new(1421, [s, s, l, s, s, s, l, l, l, l, s, l], iso(2000, 4, 6)), + PackedHijriYearInfo::new(1422, [l, s, s, l, s, s, s, l, l, l, s, l], iso(2001, 3, 26)), + PackedHijriYearInfo::new(1423, [l, s, l, s, l, s, s, l, s, l, s, l], iso(2002, 3, 15)), + PackedHijriYearInfo::new(1424, [l, s, l, l, s, l, s, s, l, s, l, s], iso(2003, 3, 4)), + PackedHijriYearInfo::new(1425, [l, s, l, l, s, l, s, l, l, s, l, s], iso(2004, 2, 21)), + PackedHijriYearInfo::new(1426, [s, l, s, l, s, l, l, s, l, l, s, l], iso(2005, 2, 10)), + PackedHijriYearInfo::new(1427, [s, s, l, s, l, s, l, l, s, l, l, s], iso(2006, 1, 31)), + PackedHijriYearInfo::new(1428, [l, s, s, l, s, s, l, l, l, s, l, l], iso(2007, 1, 20)), + PackedHijriYearInfo::new(1429, [s, l, s, s, l, s, s, l, l, s, l, l], iso(2008, 1, 10)), + PackedHijriYearInfo::new(1430, [s, l, l, s, s, l, s, l, s, l, s, l], iso(2008, 12, 29)), + PackedHijriYearInfo::new(1431, [s, l, l, s, l, s, l, s, l, s, s, l], iso(2009, 12, 18)), + PackedHijriYearInfo::new(1432, [s, l, l, l, s, l, s, l, s, l, s, s], iso(2010, 12, 7)), + PackedHijriYearInfo::new(1433, [l, s, l, l, s, l, l, s, l, s, l, s], iso(2011, 11, 26)), + PackedHijriYearInfo::new(1434, [s, l, s, l, s, l, l, s, l, l, s, s], iso(2012, 11, 15)), + PackedHijriYearInfo::new(1435, [l, s, l, s, l, s, l, s, l, l, s, l], iso(2013, 11, 4)), + PackedHijriYearInfo::new(1436, [s, l, s, l, s, l, s, l, s, l, s, l], iso(2014, 10, 25)), + PackedHijriYearInfo::new(1437, [l, s, l, l, s, s, l, s, l, s, s, l], iso(2015, 10, 14)), + PackedHijriYearInfo::new(1438, [l, s, l, l, l, s, s, l, s, s, l, s], iso(2016, 10, 2)), + PackedHijriYearInfo::new(1439, [l, s, l, l, l, s, l, s, l, s, s, l], iso(2017, 9, 21)), + PackedHijriYearInfo::new(1440, [s, l, s, l, l, l, s, l, s, l, s, s], iso(2018, 9, 11)), + PackedHijriYearInfo::new(1441, [l, s, l, s, l, l, s, l, l, s, l, s], iso(2019, 8, 31)), + PackedHijriYearInfo::new(1442, [s, l, s, l, s, l, s, l, l, s, l, s], iso(2020, 8, 20)), + PackedHijriYearInfo::new(1443, [l, s, l, s, l, s, l, s, l, s, l, l], iso(2021, 8, 9)), + PackedHijriYearInfo::new(1444, [s, l, s, l, l, s, s, l, s, l, s, l], iso(2022, 7, 30)), + PackedHijriYearInfo::new(1445, [s, l, l, l, s, l, s, s, l, s, s, l], iso(2023, 7, 19)), + PackedHijriYearInfo::new(1446, [s, l, l, l, s, l, l, s, s, l, s, s], iso(2024, 7, 7)), + PackedHijriYearInfo::new(1447, [l, s, l, l, l, s, l, s, l, s, l, s], iso(2025, 6, 26)), + PackedHijriYearInfo::new(1448, [s, l, s, l, l, s, l, l, s, l, s, l], iso(2026, 6, 16)), + PackedHijriYearInfo::new(1449, [s, s, l, s, l, s, l, l, s, l, l, s], iso(2027, 6, 6)), + PackedHijriYearInfo::new(1450, [l, s, l, s, s, l, s, l, s, l, l, s], iso(2028, 5, 25)), + PackedHijriYearInfo::new(1451, [l, l, l, s, s, l, s, s, l, l, s, l], iso(2029, 5, 14)), + PackedHijriYearInfo::new(1452, [l, s, l, l, s, s, l, s, s, l, s, l], iso(2030, 5, 4)), + PackedHijriYearInfo::new(1453, [l, s, l, l, s, l, s, l, s, s, l, s], iso(2031, 4, 23)), + PackedHijriYearInfo::new(1454, [l, s, l, l, s, l, l, s, l, s, l, s], iso(2032, 4, 11)), + PackedHijriYearInfo::new(1455, [s, l, s, l, l, s, l, s, l, l, s, l], iso(2033, 4, 1)), + PackedHijriYearInfo::new(1456, [s, s, l, s, l, s, l, s, l, l, l, s], iso(2034, 3, 22)), + PackedHijriYearInfo::new(1457, [l, s, s, l, s, s, l, s, l, l, l, l], iso(2035, 3, 11)), + PackedHijriYearInfo::new(1458, [s, l, s, s, l, s, s, l, s, l, l, l], iso(2036, 2, 29)), + PackedHijriYearInfo::new(1459, [s, l, l, s, s, l, s, s, l, s, l, l], iso(2037, 2, 17)), + PackedHijriYearInfo::new(1460, [s, l, l, s, l, s, l, s, s, l, s, l], iso(2038, 2, 6)), + PackedHijriYearInfo::new(1461, [s, l, l, s, l, s, l, s, l, l, s, s], iso(2039, 1, 26)), + PackedHijriYearInfo::new(1462, [l, s, l, s, l, l, s, l, s, l, l, s], iso(2040, 1, 15)), + PackedHijriYearInfo::new(1463, [s, l, s, l, s, l, s, l, l, l, s, l], iso(2041, 1, 4)), + PackedHijriYearInfo::new(1464, [s, l, s, s, l, s, s, l, l, l, s, l], iso(2041, 12, 25)), + PackedHijriYearInfo::new(1465, [l, s, l, s, s, l, s, s, l, l, s, l], iso(2042, 12, 14)), + PackedHijriYearInfo::new(1466, [l, l, s, l, s, s, s, l, s, l, l, s], iso(2043, 12, 3)), + PackedHijriYearInfo::new(1467, [l, l, s, l, l, s, s, l, s, l, s, l], iso(2044, 11, 21)), + PackedHijriYearInfo::new(1468, [s, l, s, l, l, s, l, s, l, s, l, s], iso(2045, 11, 11)), + PackedHijriYearInfo::new(1469, [s, l, s, l, l, s, l, l, s, l, s, l], iso(2046, 10, 31)), + PackedHijriYearInfo::new(1470, [s, s, l, s, l, l, s, l, l, s, l, s], iso(2047, 10, 21)), + PackedHijriYearInfo::new(1471, [l, s, s, l, s, l, s, l, l, s, l, l], iso(2048, 10, 9)), + PackedHijriYearInfo::new(1472, [s, l, s, s, l, s, l, s, l, l, s, l], iso(2049, 9, 29)), + PackedHijriYearInfo::new(1473, [s, l, s, l, l, s, s, l, s, l, s, l], iso(2050, 9, 18)), + PackedHijriYearInfo::new(1474, [s, l, l, s, l, l, s, s, l, s, l, s], iso(2051, 9, 7)), + PackedHijriYearInfo::new(1475, [s, l, l, s, l, l, l, s, s, l, s, s], iso(2052, 8, 26)), + PackedHijriYearInfo::new(1476, [l, s, l, s, l, l, l, s, l, s, l, s], iso(2053, 8, 15)), + PackedHijriYearInfo::new(1477, [s, l, s, s, l, l, l, l, s, l, s, l], iso(2054, 8, 5)), + PackedHijriYearInfo::new(1478, [s, s, l, s, l, s, l, l, s, l, l, s], iso(2055, 7, 26)), + PackedHijriYearInfo::new(1479, [l, s, s, l, s, l, s, l, s, l, l, s], iso(2056, 7, 14)), + PackedHijriYearInfo::new(1480, [l, s, l, s, l, s, l, s, l, s, l, s], iso(2057, 7, 3)), + PackedHijriYearInfo::new(1481, [l, s, l, l, s, l, s, l, s, l, s, s], iso(2058, 6, 22)), + PackedHijriYearInfo::new(1482, [l, s, l, l, l, l, s, l, s, s, l, s], iso(2059, 6, 11)), + PackedHijriYearInfo::new(1483, [s, l, s, l, l, l, s, l, l, s, s, l], iso(2060, 5, 31)), + PackedHijriYearInfo::new(1484, [s, s, l, s, l, l, l, s, l, s, l, s], iso(2061, 5, 21)), + PackedHijriYearInfo::new(1485, [l, s, s, l, s, l, l, s, l, l, s, l], iso(2062, 5, 10)), + PackedHijriYearInfo::new(1486, [s, l, s, s, l, s, l, s, l, l, s, l], iso(2063, 4, 30)), + PackedHijriYearInfo::new(1487, [l, s, l, s, l, s, s, l, s, l, s, l], iso(2064, 4, 18)), + PackedHijriYearInfo::new(1488, [l, s, l, l, s, l, s, s, l, s, l, s], iso(2065, 4, 7)), + PackedHijriYearInfo::new(1489, [l, s, l, l, l, s, l, s, s, l, s, l], iso(2066, 3, 27)), + PackedHijriYearInfo::new(1490, [s, l, s, l, l, s, l, l, s, s, l, s], iso(2067, 3, 17)), + PackedHijriYearInfo::new(1491, [l, s, s, l, l, s, l, l, s, l, s, l], iso(2068, 3, 5)), + PackedHijriYearInfo::new(1492, [s, l, s, s, l, l, s, l, s, l, l, s], iso(2069, 2, 23)), + PackedHijriYearInfo::new(1493, [l, s, l, s, l, s, s, l, s, l, l, l], iso(2070, 2, 12)), + PackedHijriYearInfo::new(1494, [s, l, s, l, s, l, s, s, s, l, l, l], iso(2071, 2, 2)), + PackedHijriYearInfo::new(1495, [s, l, l, s, l, s, s, l, s, s, l, l], iso(2072, 1, 22)), + PackedHijriYearInfo::new(1496, [s, l, l, l, s, l, s, s, l, s, s, l], iso(2073, 1, 10)), + PackedHijriYearInfo::new(1497, [l, s, l, l, s, l, s, l, s, l, s, l], iso(2073, 12, 30)), + PackedHijriYearInfo::new(1498, [s, l, s, l, s, l, l, s, l, s, l, s], iso(2074, 12, 20)), + PackedHijriYearInfo::new(1499, [l, s, l, s, s, l, l, s, l, s, l, l], iso(2075, 12, 9)), + PackedHijriYearInfo::new(1500, [s, l, s, l, s, s, l, s, l, s, l, l], iso(2076, 11, 28)), + PackedHijriYearInfo::new(1501, [l, s, l, s, l, s, s, s, l, s, l, l], iso(2077, 11, 17)), + PackedHijriYearInfo::new(1502, [l, l, s, l, s, l, s, s, s, l, l, s], iso(2078, 11, 6)), + PackedHijriYearInfo::new(1503, [l, l, s, l, l, s, l, s, s, s, l, l], iso(2079, 10, 26)), + PackedHijriYearInfo::new(1504, [s, l, s, l, l, l, s, s, l, s, l, s], iso(2080, 10, 15)), + PackedHijriYearInfo::new(1505, [l, s, l, s, l, l, s, l, s, l, l, s], iso(2081, 10, 4)), + PackedHijriYearInfo::new(1506, [s, l, s, s, l, l, s, l, l, s, l, l], iso(2082, 9, 24)), + PackedHijriYearInfo::new(1507, [s, s, l, s, s, l, l, s, l, s, l, l], iso(2083, 9, 14)), + PackedHijriYearInfo::new(1508, [l, s, s, l, s, l, s, s, l, s, l, l], iso(2084, 9, 2)), + PackedHijriYearInfo::new(1509, [l, s, l, s, l, s, l, s, s, l, s, l], iso(2085, 8, 22)), + PackedHijriYearInfo::new(1510, [l, s, l, l, s, l, s, l, s, s, l, s], iso(2086, 8, 11)), + PackedHijriYearInfo::new(1511, [l, s, l, l, s, l, l, s, l, s, s, l], iso(2087, 7, 31)), + PackedHijriYearInfo::new(1512, [s, l, s, l, s, l, l, l, s, l, s, l], iso(2088, 7, 20)), + PackedHijriYearInfo::new(1513, [s, s, s, l, s, l, l, l, s, l, l, s], iso(2089, 7, 10)), + PackedHijriYearInfo::new(1514, [l, s, s, s, l, s, l, l, s, l, l, l], iso(2090, 6, 29)), + PackedHijriYearInfo::new(1515, [s, s, l, s, s, l, s, l, l, s, l, l], iso(2091, 6, 19)), + PackedHijriYearInfo::new(1516, [s, l, s, l, s, s, l, s, l, s, l, l], iso(2092, 6, 7)), + PackedHijriYearInfo::new(1517, [s, l, s, l, s, l, l, s, s, l, s, l], iso(2093, 5, 27)), + PackedHijriYearInfo::new(1518, [s, l, s, l, l, s, l, l, s, l, s, s], iso(2094, 5, 16)), + PackedHijriYearInfo::new(1519, [l, s, s, l, l, l, s, l, l, s, l, s], iso(2095, 5, 5)), + PackedHijriYearInfo::new(1520, [s, l, s, s, l, l, l, s, l, l, s, l], iso(2096, 4, 24)), + PackedHijriYearInfo::new(1521, [s, s, s, l, s, l, l, s, l, l, s, l], iso(2097, 4, 14)), + PackedHijriYearInfo::new(1522, [l, s, s, s, l, s, l, l, s, l, l, s], iso(2098, 4, 3)), + PackedHijriYearInfo::new(1523, [l, s, l, s, l, s, l, s, s, l, l, s], iso(2099, 3, 23)), + PackedHijriYearInfo::new(1524, [l, l, s, l, s, l, s, l, s, s, l, s], iso(2100, 3, 12)), + PackedHijriYearInfo::new(1525, [l, l, s, l, l, s, l, s, l, s, s, l], iso(2101, 3, 1)), + PackedHijriYearInfo::new(1526, [s, l, s, l, l, l, s, l, s, l, s, s], iso(2102, 2, 19)), + PackedHijriYearInfo::new(1527, [l, s, l, s, l, l, s, l, l, s, l, s], iso(2103, 2, 8)), + PackedHijriYearInfo::new(1528, [l, s, s, l, s, l, s, l, l, s, l, l], iso(2104, 1, 29)), + PackedHijriYearInfo::new(1529, [s, l, s, s, l, s, l, s, l, s, l, l], iso(2105, 1, 18)), + PackedHijriYearInfo::new(1530, [s, l, l, s, s, l, s, l, s, s, l, l], iso(2106, 1, 7)), + PackedHijriYearInfo::new(1531, [s, l, l, l, s, s, l, s, l, s, s, l], iso(2106, 12, 27)), + PackedHijriYearInfo::new(1532, [s, l, l, l, s, l, l, s, s, s, l, s], iso(2107, 12, 16)), + PackedHijriYearInfo::new(1533, [l, s, l, l, l, s, l, s, l, s, s, l], iso(2108, 12, 4)), + PackedHijriYearInfo::new(1534, [s, l, s, l, l, s, l, l, s, s, l, s], iso(2109, 11, 24)), + PackedHijriYearInfo::new(1535, [l, s, l, s, l, s, l, l, s, l, s, l], iso(2110, 11, 13)), + PackedHijriYearInfo::new(1536, [s, l, s, l, s, l, s, l, s, l, s, l], iso(2111, 11, 3)), + PackedHijriYearInfo::new(1537, [l, s, l, l, s, s, l, s, s, l, s, l], iso(2112, 10, 22)), + PackedHijriYearInfo::new(1538, [l, l, s, l, l, s, s, l, s, s, l, s], iso(2113, 10, 11)), + PackedHijriYearInfo::new(1539, [l, l, l, s, l, l, s, s, l, s, s, l], iso(2114, 9, 30)), + PackedHijriYearInfo::new(1540, [s, l, l, s, l, l, s, l, s, s, l, s], iso(2115, 9, 20)), + PackedHijriYearInfo::new(1541, [l, s, l, s, l, l, l, s, l, s, s, l], iso(2116, 9, 8)), + PackedHijriYearInfo::new(1542, [s, l, s, l, s, l, l, s, l, s, l, l], iso(2117, 8, 29)), + PackedHijriYearInfo::new(1543, [s, l, s, s, l, s, l, s, l, s, l, l], iso(2118, 8, 19)), + PackedHijriYearInfo::new(1544, [l, s, l, s, s, l, s, l, s, l, s, l], iso(2119, 8, 8)), + PackedHijriYearInfo::new(1545, [l, l, s, l, s, s, l, s, l, s, s, l], iso(2120, 7, 27)), + PackedHijriYearInfo::new(1546, [l, l, s, l, s, l, s, l, s, l, s, s], iso(2121, 7, 16)), + PackedHijriYearInfo::new(1547, [l, l, s, l, l, s, l, s, l, s, l, s], iso(2122, 7, 5)), + PackedHijriYearInfo::new(1548, [l, s, s, l, l, s, l, l, s, l, s, l], iso(2123, 6, 25)), + PackedHijriYearInfo::new(1549, [s, l, s, s, l, s, l, l, l, s, l, s], iso(2124, 6, 14)), + PackedHijriYearInfo::new(1550, [l, s, l, s, s, s, l, l, l, s, l, l], iso(2125, 6, 3)), + PackedHijriYearInfo::new(1551, [s, l, s, s, l, s, s, l, l, s, l, l], iso(2126, 5, 24)), + PackedHijriYearInfo::new(1552, [l, s, l, s, s, l, s, s, l, l, s, l], iso(2127, 5, 13)), + PackedHijriYearInfo::new(1553, [l, s, l, s, l, s, l, s, l, s, l, s], iso(2128, 5, 1)), + PackedHijriYearInfo::new(1554, [l, s, l, s, l, l, s, l, s, l, s, l], iso(2129, 4, 20)), + PackedHijriYearInfo::new(1555, [s, s, l, s, l, l, s, l, l, s, l, s], iso(2130, 4, 10)), + PackedHijriYearInfo::new(1556, [l, s, s, l, s, l, s, l, l, l, s, l], iso(2131, 3, 30)), + PackedHijriYearInfo::new(1557, [s, l, s, s, s, l, s, l, l, l, l, s], iso(2132, 3, 19)), + PackedHijriYearInfo::new(1558, [l, s, l, s, s, s, l, s, l, l, l, s], iso(2133, 3, 8)), + PackedHijriYearInfo::new(1559, [l, l, s, s, l, s, s, l, l, s, l, s], iso(2134, 2, 25)), + PackedHijriYearInfo::new(1560, [l, l, s, l, s, l, s, l, s, l, s, l], iso(2135, 2, 14)), + PackedHijriYearInfo::new(1561, [s, l, l, s, l, s, l, l, s, s, l, s], iso(2136, 2, 4)), + PackedHijriYearInfo::new(1562, [s, l, l, s, l, s, l, l, l, s, s, l], iso(2137, 1, 23)), + PackedHijriYearInfo::new(1563, [s, l, s, s, l, s, l, l, l, s, l, s], iso(2138, 1, 13)), + PackedHijriYearInfo::new(1564, [l, s, l, s, s, l, s, l, l, l, s, l], iso(2139, 1, 2)), + PackedHijriYearInfo::new(1565, [s, l, s, l, s, s, l, s, l, l, s, l], iso(2139, 12, 23)), + PackedHijriYearInfo::new(1566, [l, s, l, s, l, s, s, l, s, l, s, l], iso(2140, 12, 11)), + PackedHijriYearInfo::new(1567, [l, s, l, l, s, l, s, l, s, s, l, s], iso(2141, 11, 30)), + PackedHijriYearInfo::new(1568, [l, s, l, l, l, s, l, s, l, s, s, s], iso(2142, 11, 19)), + PackedHijriYearInfo::new(1569, [l, s, l, l, l, s, l, l, s, l, s, s], iso(2143, 11, 8)), + PackedHijriYearInfo::new(1570, [s, l, s, l, l, s, l, l, l, s, s, l], iso(2144, 10, 28)), + PackedHijriYearInfo::new(1571, [s, s, l, s, l, l, s, l, l, s, l, s], iso(2145, 10, 18)), + PackedHijriYearInfo::new(1572, [l, s, s, l, s, l, s, l, l, s, l, s], iso(2146, 10, 7)), + PackedHijriYearInfo::new(1573, [l, s, l, l, s, l, s, s, l, s, l, s], iso(2147, 9, 26)), + PackedHijriYearInfo::new(1574, [l, l, s, l, l, s, l, s, s, l, s, s], iso(2148, 9, 14)), + PackedHijriYearInfo::new(1575, [l, l, l, s, l, l, s, l, s, s, s, l], iso(2149, 9, 3)), + PackedHijriYearInfo::new(1576, [s, l, l, s, l, l, l, s, l, s, s, s], iso(2150, 8, 24)), + PackedHijriYearInfo::new(1577, [l, s, l, l, s, l, l, s, l, s, l, s], iso(2151, 8, 13)), + PackedHijriYearInfo::new(1578, [s, l, s, l, s, l, l, s, l, l, s, l], iso(2152, 8, 2)), + PackedHijriYearInfo::new(1579, [s, l, s, l, s, s, l, l, s, l, s, l], iso(2153, 7, 23)), + PackedHijriYearInfo::new(1580, [s, l, l, s, l, s, s, l, s, l, s, l], iso(2154, 7, 12)), + PackedHijriYearInfo::new(1581, [l, l, s, l, s, l, s, s, l, s, l, s], iso(2155, 7, 1)), + PackedHijriYearInfo::new(1582, [l, l, s, l, l, s, l, s, l, s, s, s], iso(2156, 6, 19)), + PackedHijriYearInfo::new(1583, [l, l, s, l, l, l, s, l, s, l, s, s], iso(2157, 6, 8)), + PackedHijriYearInfo::new(1584, [s, l, l, s, l, l, s, l, l, s, l, s], iso(2158, 5, 29)), + PackedHijriYearInfo::new(1585, [s, l, s, l, s, l, s, l, l, s, l, l], iso(2159, 5, 19)), + PackedHijriYearInfo::new(1586, [s, s, l, s, l, s, s, l, l, l, s, l], iso(2160, 5, 8)), + PackedHijriYearInfo::new(1587, [s, l, l, s, s, s, l, s, l, s, l, l], iso(2161, 4, 27)), + PackedHijriYearInfo::new(1588, [l, s, l, l, s, s, s, l, s, l, s, l], iso(2162, 4, 16)), + PackedHijriYearInfo::new(1589, [l, s, l, l, s, l, s, s, l, s, l, s], iso(2163, 4, 5)), + PackedHijriYearInfo::new(1590, [l, s, l, l, l, s, s, l, s, l, s, l], iso(2164, 3, 24)), + PackedHijriYearInfo::new(1591, [s, l, s, l, l, s, l, s, l, s, l, s], iso(2165, 3, 14)), + PackedHijriYearInfo::new(1592, [l, s, l, s, l, s, l, s, l, l, l, s], iso(2166, 3, 3)), + PackedHijriYearInfo::new(1593, [l, s, s, l, s, s, l, s, l, l, l, s], iso(2167, 2, 21)), + PackedHijriYearInfo::new(1594, [l, l, s, s, l, s, s, s, l, l, l, l], iso(2168, 2, 10)), + PackedHijriYearInfo::new(1595, [s, l, s, l, s, s, l, s, s, l, l, l], iso(2169, 1, 30)), + PackedHijriYearInfo::new(1596, [s, l, l, s, l, s, s, l, s, l, s, l], iso(2170, 1, 19)), + PackedHijriYearInfo::new(1597, [s, l, l, s, l, s, l, s, l, s, l, s], iso(2171, 1, 8)), + PackedHijriYearInfo::new(1598, [l, s, l, s, l, l, s, l, s, l, l, s], iso(2171, 12, 28)), + PackedHijriYearInfo::new(1599, [s, l, s, l, s, l, s, l, l, l, s, l], iso(2172, 12, 17)), + PackedHijriYearInfo::new(1600, [s, s, l, s, l, s, s, l, l, l, s, l], iso(2173, 12, 7)), + ] +}; diff --git a/deps/crates/vendor/icu_calendar/src/cal/indian.rs b/deps/crates/vendor/icu_calendar/src/cal/indian.rs new file mode 100644 index 00000000000000..608e85e2ead8c2 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/indian.rs @@ -0,0 +1,507 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and implementations for the Indian national calendar. +//! +//! ```rust +//! use icu::calendar::{cal::Indian, Date}; +//! +//! let date_iso = Date::try_new_iso(1970, 1, 2) +//! .expect("Failed to initialize ISO Date instance."); +//! let date_indian = Date::new_from_iso(date_iso, Indian); +//! +//! assert_eq!(date_indian.era_year().year, 1891); +//! assert_eq!(date_indian.month().ordinal, 10); +//! assert_eq!(date_indian.day_of_month().0, 12); +//! ``` + +use crate::cal::iso::{Iso, IsoDateInner}; +use crate::calendar_arithmetic::{ArithmeticDate, CalendarArithmetic}; +use crate::error::DateError; +use crate::{types, Calendar, Date, DateDuration, DateDurationUnit, RangeError}; +use calendrical_calculations::rata_die::RataDie; +use tinystr::tinystr; + +/// The [Indian National (Śaka) Calendar](https://en.wikipedia.org/wiki/Indian_national_calendar) +/// +/// The Indian National calendar is a solar calendar used by the Indian government, with twelve months. +/// +/// This type can be used with [`Date`] to represent dates in this calendar. +/// +/// # Era codes +/// +/// This calendar uses a single era code: `shaka`, with Śaka 0 being 78 CE. Dates before this era use negative years. +/// +/// # Month codes +/// +/// This calendar supports 12 solar month codes (`"M01" - "M12"`) +#[derive(Copy, Clone, Debug, Hash, Default, Eq, PartialEq, PartialOrd, Ord)] +#[allow(clippy::exhaustive_structs)] // this type is stable +pub struct Indian; + +/// The inner date type used for representing [`Date`]s of [`Indian`]. See [`Date`] and [`Indian`] for more details. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +pub struct IndianDateInner(ArithmeticDate); + +impl CalendarArithmetic for Indian { + type YearInfo = i32; + + fn days_in_provided_month(year: i32, month: u8) -> u8 { + if month == 1 { + if Self::provided_year_is_leap(year) { + 31 + } else { + 30 + } + } else if (2..=6).contains(&month) { + 31 + } else if (7..=12).contains(&month) { + 30 + } else { + 0 + } + } + + fn months_in_provided_year(_: i32) -> u8 { + 12 + } + + fn provided_year_is_leap(year: i32) -> bool { + Iso::provided_year_is_leap(year + 78) + } + + fn last_month_day_in_provided_year(_year: i32) -> (u8, u8) { + (12, 30) + } + + fn days_in_provided_year(year: i32) -> u16 { + if Self::provided_year_is_leap(year) { + 366 + } else { + 365 + } + } +} + +/// The Śaka era starts on the 81st day of the Gregorian year (March 22 or 21) +/// which is an 80 day offset. This number should be subtracted from Gregorian dates +const DAY_OFFSET: u16 = 80; +/// The Śaka era is 78 years behind Gregorian. This number should be added to Gregorian dates +const YEAR_OFFSET: i32 = 78; + +impl crate::cal::scaffold::UnstableSealed for Indian {} +impl Calendar for Indian { + type DateInner = IndianDateInner; + type Year = types::EraYear; + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + let year = match era { + Some("shaka") | None => year, + Some(_) => return Err(DateError::UnknownEra), + }; + ArithmeticDate::new_from_codes(self, year, month_code, day).map(IndianDateInner) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + self.from_iso(Iso.from_rata_die(rd)) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + Iso.to_rata_die(&self.to_iso(date)) + } + + // Algorithms directly implemented in icu_calendar since they're not from the book + fn from_iso(&self, iso: IsoDateInner) -> IndianDateInner { + // Get day number in year (1 indexed) + let day_of_year_iso = Iso::day_of_year(iso); + // Convert to Śaka year + let mut year = iso.0.year - YEAR_OFFSET; + // This is in the previous Indian year + let day_of_year_indian = if day_of_year_iso <= DAY_OFFSET { + year -= 1; + let n_days = Self::days_in_provided_year(year); + + // calculate day of year in previous year + n_days + day_of_year_iso - DAY_OFFSET + } else { + day_of_year_iso - DAY_OFFSET + }; + IndianDateInner(ArithmeticDate::date_from_year_day( + year, + day_of_year_indian as u32, + )) + } + + // Algorithms directly implemented in icu_calendar since they're not from the book + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + let day_of_year_indian = date.0.day_of_year().0; // 1-indexed + let days_in_year = date.0.days_in_year(); + + let mut year = date.0.year + YEAR_OFFSET; + // days_in_year is a valid day of the year, so we check > not >= + let day_of_year_iso = if day_of_year_indian + DAY_OFFSET > days_in_year { + year += 1; + // calculate day of year in next year + day_of_year_indian + DAY_OFFSET - days_in_year + } else { + day_of_year_indian + DAY_OFFSET + }; + Iso::iso_from_year_day(year, day_of_year_iso) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + date.0.months_in_year() + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + date.0.days_in_year() + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + date.0.days_in_month() + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + date.0.offset_date(offset, &()); + } + + #[allow(clippy::field_reassign_with_default)] + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + _largest_unit: DateDurationUnit, + _smallest_unit: DateDurationUnit, + ) -> DateDuration { + date1.0.until(date2.0, _largest_unit, _smallest_unit) + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + types::EraYear { + era_index: Some(0), + era: tinystr!(16, "shaka"), + year: self.extended_year(date), + ambiguity: types::YearAmbiguity::CenturyRequired, + } + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + date.0.extended_year() + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Self::provided_year_is_leap(date.0.year) + } + + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + date.0.month() + } + + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + date.0.day_of_month() + } + + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + date.0.day_of_year() + } + + fn debug_name(&self) -> &'static str { + "Indian" + } + + fn calendar_algorithm(&self) -> Option { + Some(crate::preferences::CalendarAlgorithm::Indian) + } +} + +impl Indian { + /// Construct a new Indian Calendar + pub fn new() -> Self { + Self + } +} + +impl Date { + /// Construct new Indian Date, with year provided in the Śaka era. + /// + /// ```rust + /// use icu::calendar::Date; + /// + /// let date_indian = Date::try_new_indian(1891, 10, 12) + /// .expect("Failed to initialize Indian Date instance."); + /// + /// assert_eq!(date_indian.era_year().year, 1891); + /// assert_eq!(date_indian.month().ordinal, 10); + /// assert_eq!(date_indian.day_of_month().0, 12); + /// ``` + pub fn try_new_indian(year: i32, month: u8, day: u8) -> Result, RangeError> { + ArithmeticDate::new_from_ordinals(year, month, day) + .map(IndianDateInner) + .map(|inner| Date::from_raw(inner, Indian)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use calendrical_calculations::rata_die::RataDie; + fn assert_roundtrip(y: i32, m: u8, d: u8, iso_y: i32, iso_m: u8, iso_d: u8) { + let indian = + Date::try_new_indian(y, m, d).expect("Indian date should construct successfully"); + let iso = indian.to_iso(); + + assert_eq!( + iso.era_year().year, + iso_y, + "{y}-{m}-{d}: ISO year did not match" + ); + assert_eq!( + iso.month().ordinal, + iso_m, + "{y}-{m}-{d}: ISO month did not match" + ); + assert_eq!( + iso.day_of_month().0, + iso_d, + "{y}-{m}-{d}: ISO day did not match" + ); + + let roundtrip = iso.to_calendar(Indian); + + assert_eq!( + roundtrip.era_year().year, + indian.era_year().year, + "{y}-{m}-{d}: roundtrip year did not match" + ); + assert_eq!( + roundtrip.month().ordinal, + indian.month().ordinal, + "{y}-{m}-{d}: roundtrip month did not match" + ); + assert_eq!( + roundtrip.day_of_month(), + indian.day_of_month(), + "{y}-{m}-{d}: roundtrip day did not match" + ); + } + + #[test] + fn roundtrip_indian() { + // Ultimately the day of the year will always be identical regardless of it + // being a leap year or not + // Test dates that occur after and before Chaitra 1 (March 22/21), in all years of + // a four-year leap cycle, to ensure that all code paths are tested + assert_roundtrip(1944, 6, 7, 2022, 8, 29); + assert_roundtrip(1943, 6, 7, 2021, 8, 29); + assert_roundtrip(1942, 6, 7, 2020, 8, 29); + assert_roundtrip(1941, 6, 7, 2019, 8, 29); + assert_roundtrip(1944, 11, 7, 2023, 1, 27); + assert_roundtrip(1943, 11, 7, 2022, 1, 27); + assert_roundtrip(1942, 11, 7, 2021, 1, 27); + assert_roundtrip(1941, 11, 7, 2020, 1, 27); + } + + #[derive(Debug)] + struct TestCase { + iso_year: i32, + iso_month: u8, + iso_day: u8, + expected_year: i32, + expected_month: u8, + expected_day: u8, + } + + fn check_case(case: TestCase) { + let iso = Date::try_new_iso(case.iso_year, case.iso_month, case.iso_day).unwrap(); + let indian = iso.to_calendar(Indian); + assert_eq!( + indian.era_year().year, + case.expected_year, + "Year check failed for case: {case:?}" + ); + assert_eq!( + indian.month().ordinal, + case.expected_month, + "Month check failed for case: {case:?}" + ); + assert_eq!( + indian.day_of_month().0, + case.expected_day, + "Day check failed for case: {case:?}" + ); + } + + #[test] + fn test_cases_near_epoch_start() { + let cases = [ + TestCase { + iso_year: 79, + iso_month: 3, + iso_day: 23, + expected_year: 1, + expected_month: 1, + expected_day: 2, + }, + TestCase { + iso_year: 79, + iso_month: 3, + iso_day: 22, + expected_year: 1, + expected_month: 1, + expected_day: 1, + }, + TestCase { + iso_year: 79, + iso_month: 3, + iso_day: 21, + expected_year: 0, + expected_month: 12, + expected_day: 30, + }, + TestCase { + iso_year: 79, + iso_month: 3, + iso_day: 20, + expected_year: 0, + expected_month: 12, + expected_day: 29, + }, + TestCase { + iso_year: 78, + iso_month: 3, + iso_day: 21, + expected_year: -1, + expected_month: 12, + expected_day: 30, + }, + ]; + + for case in cases { + check_case(case); + } + } + + #[test] + fn test_cases_near_rd_zero() { + let cases = [ + TestCase { + iso_year: 1, + iso_month: 3, + iso_day: 22, + expected_year: -77, + expected_month: 1, + expected_day: 1, + }, + TestCase { + iso_year: 1, + iso_month: 3, + iso_day: 21, + expected_year: -78, + expected_month: 12, + expected_day: 30, + }, + TestCase { + iso_year: 1, + iso_month: 1, + iso_day: 1, + expected_year: -78, + expected_month: 10, + expected_day: 11, + }, + TestCase { + iso_year: 0, + iso_month: 3, + iso_day: 21, + expected_year: -78, + expected_month: 1, + expected_day: 1, + }, + TestCase { + iso_year: 0, + iso_month: 1, + iso_day: 1, + expected_year: -79, + expected_month: 10, + expected_day: 11, + }, + TestCase { + iso_year: -1, + iso_month: 3, + iso_day: 21, + expected_year: -80, + expected_month: 12, + expected_day: 30, + }, + ]; + + for case in cases { + check_case(case); + } + } + + #[test] + fn test_roundtrip_near_rd_zero() { + for i in -1000..=1000 { + let initial = RataDie::new(i); + let result = Date::from_rata_die(initial, Iso) + .to_calendar(Indian) + .to_iso() + .to_rata_die(); + assert_eq!( + initial, result, + "Roundtrip failed for initial: {initial:?}, result: {result:?}" + ); + } + } + + #[test] + fn test_roundtrip_near_epoch_start() { + // Epoch start: RD 28570 + for i in 27570..=29570 { + let initial = RataDie::new(i); + let result = Date::from_rata_die(initial, Iso) + .to_calendar(Indian) + .to_iso() + .to_rata_die(); + assert_eq!( + initial, result, + "Roundtrip failed for initial: {initial:?}, result: {result:?}" + ); + } + } + + #[test] + fn test_directionality_near_rd_zero() { + for i in -100..=100 { + for j in -100..=100 { + let rd_i = RataDie::new(i); + let rd_j = RataDie::new(j); + + let indian_i = Date::from_rata_die(rd_i, Indian); + let indian_j = Date::from_rata_die(rd_j, Indian); + + assert_eq!(i.cmp(&j), indian_i.cmp(&indian_j), "Directionality test failed for i: {i}, j: {j}, indian_i: {indian_i:?}, indian_j: {indian_j:?}"); + } + } + } + + #[test] + fn test_directionality_near_epoch_start() { + // Epoch start: RD 28570 + for i in 28470..=28670 { + for j in 28470..=28670 { + let indian_i = Date::from_rata_die(RataDie::new(i), Indian); + let indian_j = Date::from_rata_die(RataDie::new(j), Indian); + + assert_eq!(i.cmp(&j), indian_i.cmp(&indian_j), "Directionality test failed for i: {i}, j: {j}, indian_i: {indian_i:?}, indian_j: {indian_j:?}"); + } + } + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/iso.rs b/deps/crates/vendor/icu_calendar/src/cal/iso.rs new file mode 100644 index 00000000000000..989485dc7a1733 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/iso.rs @@ -0,0 +1,576 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and implementations for the ISO calendar. +//! +//! ```rust +//! use icu::calendar::Date; +//! +//! let date_iso = Date::try_new_iso(1970, 1, 2) +//! .expect("Failed to initialize ISO Date instance."); +//! +//! assert_eq!(date_iso.era_year().year, 1970); +//! assert_eq!(date_iso.month().ordinal, 1); +//! assert_eq!(date_iso.day_of_month().0, 2); +//! ``` + +use crate::calendar_arithmetic::{ArithmeticDate, CalendarArithmetic}; +use crate::error::DateError; +use crate::{types, Calendar, Date, DateDuration, DateDurationUnit, RangeError}; +use calendrical_calculations::helpers::I32CastError; +use calendrical_calculations::rata_die::RataDie; +use tinystr::tinystr; + +/// The [ISO-8601 Calendar](https://en.wikipedia.org/wiki/ISO_8601#Dates) +/// +/// The ISO-8601 Calendar is a standardized solar calendar with twelve months. +/// It is identical to the [`Gregorian`](super::Gregorian) calendar, except it uses +/// negative years for years before 1 CE, and may have differing formatting data for a given locale. +/// +/// This type can be used with [`Date`] to represent dates in this calendar. +/// +/// # Era codes +/// +/// This calendar uses a single era: `default` + +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[allow(clippy::exhaustive_structs)] // this type is stable +pub struct Iso; + +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +/// The inner date type used for representing [`Date`]s of [`Iso`]. See [`Date`] and [`Iso`] for more details. +pub struct IsoDateInner(pub(crate) ArithmeticDate); + +impl CalendarArithmetic for Iso { + type YearInfo = i32; + + fn days_in_provided_month(year: i32, month: u8) -> u8 { + match month { + 4 | 6 | 9 | 11 => 30, + 2 if Self::provided_year_is_leap(year) => 29, + 2 => 28, + 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31, + _ => 0, + } + } + + fn months_in_provided_year(_: i32) -> u8 { + 12 + } + + fn provided_year_is_leap(year: i32) -> bool { + calendrical_calculations::iso::is_leap_year(year) + } + + fn last_month_day_in_provided_year(_year: i32) -> (u8, u8) { + (12, 31) + } + + fn days_in_provided_year(year: i32) -> u16 { + if Self::provided_year_is_leap(year) { + 366 + } else { + 365 + } + } +} + +impl crate::cal::scaffold::UnstableSealed for Iso {} +impl Calendar for Iso { + type DateInner = IsoDateInner; + type Year = types::EraYear; + /// Construct a date from era/month codes and fields + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + let year = match era { + Some("default") | None => year, + Some(_) => return Err(DateError::UnknownEra), + }; + + ArithmeticDate::new_from_codes(self, year, month_code, day).map(IsoDateInner) + } + + fn from_rata_die(&self, date: RataDie) -> IsoDateInner { + IsoDateInner(match calendrical_calculations::iso::iso_from_fixed(date) { + Err(I32CastError::BelowMin) => ArithmeticDate::min_date(), + Err(I32CastError::AboveMax) => ArithmeticDate::max_date(), + Ok((year, month, day)) => ArithmeticDate::new_unchecked(year, month, day), + }) + } + + fn to_rata_die(&self, date: &IsoDateInner) -> RataDie { + calendrical_calculations::iso::fixed_from_iso(date.0.year, date.0.month, date.0.day) + } + + fn from_iso(&self, iso: IsoDateInner) -> IsoDateInner { + iso + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + *date + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + date.0.months_in_year() + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + date.0.days_in_year() + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + date.0.days_in_month() + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + date.0.offset_date(offset, &()); + } + + #[allow(clippy::field_reassign_with_default)] + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + _largest_unit: DateDurationUnit, + _smallest_unit: DateDurationUnit, + ) -> DateDuration { + date1.0.until(date2.0, _largest_unit, _smallest_unit) + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + types::EraYear { + era_index: Some(0), + era: tinystr!(16, "default"), + year: self.extended_year(date), + ambiguity: types::YearAmbiguity::Unambiguous, + } + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + date.0.extended_year() + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Self::provided_year_is_leap(date.0.year) + } + + /// The calendar-specific month represented by `date` + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + date.0.month() + } + + /// The calendar-specific day-of-month represented by `date` + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + date.0.day_of_month() + } + + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + date.0.day_of_year() + } + + fn debug_name(&self) -> &'static str { + "ISO" + } + + fn calendar_algorithm(&self) -> Option { + None + } +} + +impl Date { + /// Construct a new ISO date from integers. + /// + /// ```rust + /// use icu::calendar::Date; + /// + /// let date_iso = Date::try_new_iso(1970, 1, 2) + /// .expect("Failed to initialize ISO Date instance."); + /// + /// assert_eq!(date_iso.era_year().year, 1970); + /// assert_eq!(date_iso.month().ordinal, 1); + /// assert_eq!(date_iso.day_of_month().0, 2); + /// ``` + pub fn try_new_iso(year: i32, month: u8, day: u8) -> Result, RangeError> { + ArithmeticDate::new_from_ordinals(year, month, day) + .map(IsoDateInner) + .map(|inner| Date::from_raw(inner, Iso)) + } +} + +impl Iso { + /// Construct a new ISO Calendar + pub fn new() -> Self { + Self + } + + pub(crate) fn iso_from_year_day(year: i32, year_day: u16) -> IsoDateInner { + let mut month = 1; + let mut day = year_day as i32; + while month <= 12 { + let month_days = Self::days_in_provided_month(year, month) as i32; + if day <= month_days { + break; + } else { + debug_assert!(month < 12); // don't try going to month 13 + day -= month_days; + month += 1; + } + } + let day = day as u8; // day <= month_days < u8::MAX + + // month in 1..=12, day <= month_days + IsoDateInner(ArithmeticDate::new_unchecked(year, month, day)) + } + + pub(crate) fn day_of_year(date: IsoDateInner) -> u16 { + // Cumulatively how much are dates in each month + // offset from "30 days in each month" (in non leap years) + let month_offset = [0, 1, -1, 0, 0, 1, 1, 2, 3, 3, 4, 4]; + #[allow(clippy::indexing_slicing)] // date.0.month in 1..=12 + let mut offset = month_offset[date.0.month as usize - 1]; + if Self::provided_year_is_leap(date.0.year) && date.0.month > 2 { + // Months after February in a leap year are offset by one less + offset += 1; + } + let prev_month_days = (30 * (date.0.month as i32 - 1) + offset) as u16; + + prev_month_days + date.0.day as u16 + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::types::Weekday; + + #[test] + fn iso_overflow() { + #[derive(Debug)] + struct TestCase { + year: i32, + month: u8, + day: u8, + rd: RataDie, + saturating: bool, + } + // Calculates the max possible year representable using i32::MAX as the RD + let max_year = Iso.from_rata_die(RataDie::new(i32::MAX as i64)).0.year; + + // Calculates the minimum possible year representable using i32::MIN as the RD + // *Cannot be tested yet due to hard coded date not being available yet (see line 436) + let min_year = -5879610; + + let cases = [ + TestCase { + // Earliest date that can be represented before causing a minimum overflow + year: min_year, + month: 6, + day: 22, + rd: RataDie::new(i32::MIN as i64), + saturating: false, + }, + TestCase { + year: min_year, + month: 6, + day: 23, + rd: RataDie::new(i32::MIN as i64 + 1), + saturating: false, + }, + TestCase { + year: min_year, + month: 6, + day: 21, + rd: RataDie::new(i32::MIN as i64 - 1), + saturating: false, + }, + TestCase { + year: min_year, + month: 12, + day: 31, + rd: RataDie::new(-2147483456), + saturating: false, + }, + TestCase { + year: min_year + 1, + month: 1, + day: 1, + rd: RataDie::new(-2147483455), + saturating: false, + }, + TestCase { + year: max_year, + month: 6, + day: 11, + rd: RataDie::new(i32::MAX as i64 - 30), + saturating: false, + }, + TestCase { + year: max_year, + month: 7, + day: 9, + rd: RataDie::new(i32::MAX as i64 - 2), + saturating: false, + }, + TestCase { + year: max_year, + month: 7, + day: 10, + rd: RataDie::new(i32::MAX as i64 - 1), + saturating: false, + }, + TestCase { + // Latest date that can be represented before causing a maximum overflow + year: max_year, + month: 7, + day: 11, + rd: RataDie::new(i32::MAX as i64), + saturating: false, + }, + TestCase { + year: max_year, + month: 7, + day: 12, + rd: RataDie::new(i32::MAX as i64 + 1), + saturating: false, + }, + TestCase { + year: i32::MIN, + month: 1, + day: 2, + rd: RataDie::new(-784352296669), + saturating: false, + }, + TestCase { + year: i32::MIN, + month: 1, + day: 1, + rd: RataDie::new(-784352296670), + saturating: false, + }, + TestCase { + year: i32::MIN, + month: 1, + day: 1, + rd: RataDie::new(-784352296671), + saturating: true, + }, + TestCase { + year: i32::MAX, + month: 12, + day: 30, + rd: RataDie::new(784352295938), + saturating: false, + }, + TestCase { + year: i32::MAX, + month: 12, + day: 31, + rd: RataDie::new(784352295939), + saturating: false, + }, + TestCase { + year: i32::MAX, + month: 12, + day: 31, + rd: RataDie::new(784352295940), + saturating: true, + }, + ]; + + for case in cases { + let date = Date::try_new_iso(case.year, case.month, case.day).unwrap(); + if !case.saturating { + assert_eq!(date.to_rata_die(), case.rd, "{case:?}"); + } + assert_eq!(Date::from_rata_die(case.rd, Iso), date, "{case:?}"); + } + } + + // Calculates the minimum possible year representable using a large negative fixed date + #[test] + fn min_year() { + assert_eq!( + Date::from_rata_die(RataDie::big_negative(), Iso) + .year() + .era() + .unwrap() + .year, + i32::MIN + ); + } + + #[test] + fn test_day_of_week() { + // June 23, 2021 is a Wednesday + assert_eq!( + Date::try_new_iso(2021, 6, 23).unwrap().day_of_week(), + Weekday::Wednesday, + ); + // Feb 2, 1983 was a Wednesday + assert_eq!( + Date::try_new_iso(1983, 2, 2).unwrap().day_of_week(), + Weekday::Wednesday, + ); + // Jan 21, 2021 was a Tuesday + assert_eq!( + Date::try_new_iso(2020, 1, 21).unwrap().day_of_week(), + Weekday::Tuesday, + ); + } + + #[test] + fn test_day_of_year() { + // June 23, 2021 was day 174 + assert_eq!(Date::try_new_iso(2021, 6, 23).unwrap().day_of_year().0, 174,); + // June 23, 2020 was day 175 + assert_eq!(Date::try_new_iso(2020, 6, 23).unwrap().day_of_year().0, 175,); + // Feb 2, 1983 was a Wednesday + assert_eq!(Date::try_new_iso(1983, 2, 2).unwrap().day_of_year().0, 33,); + } + + fn simple_subtract(a: &Date, b: &Date) -> DateDuration { + let a = a.inner(); + let b = b.inner(); + DateDuration::new( + a.0.year - b.0.year, + a.0.month as i32 - b.0.month as i32, + 0, + a.0.day as i32 - b.0.day as i32, + ) + } + + #[test] + fn test_offset() { + let today = Date::try_new_iso(2021, 6, 23).unwrap(); + let today_plus_5000 = Date::try_new_iso(2035, 3, 2).unwrap(); + let offset = today.added(DateDuration::new(0, 0, 0, 5000)); + assert_eq!(offset, today_plus_5000); + let offset = today.added(simple_subtract(&today_plus_5000, &today)); + assert_eq!(offset, today_plus_5000); + + let today = Date::try_new_iso(2021, 6, 23).unwrap(); + let today_minus_5000 = Date::try_new_iso(2007, 10, 15).unwrap(); + let offset = today.added(DateDuration::new(0, 0, 0, -5000)); + assert_eq!(offset, today_minus_5000); + let offset = today.added(simple_subtract(&today_minus_5000, &today)); + assert_eq!(offset, today_minus_5000); + } + + #[test] + fn test_offset_at_month_boundary() { + let today = Date::try_new_iso(2020, 2, 28).unwrap(); + let today_plus_2 = Date::try_new_iso(2020, 3, 1).unwrap(); + let offset = today.added(DateDuration::new(0, 0, 0, 2)); + assert_eq!(offset, today_plus_2); + + let today = Date::try_new_iso(2020, 2, 28).unwrap(); + let today_plus_3 = Date::try_new_iso(2020, 3, 2).unwrap(); + let offset = today.added(DateDuration::new(0, 0, 0, 3)); + assert_eq!(offset, today_plus_3); + + let today = Date::try_new_iso(2020, 2, 28).unwrap(); + let today_plus_1 = Date::try_new_iso(2020, 2, 29).unwrap(); + let offset = today.added(DateDuration::new(0, 0, 0, 1)); + assert_eq!(offset, today_plus_1); + + let today = Date::try_new_iso(2019, 2, 28).unwrap(); + let today_plus_2 = Date::try_new_iso(2019, 3, 2).unwrap(); + let offset = today.added(DateDuration::new(0, 0, 0, 2)); + assert_eq!(offset, today_plus_2); + + let today = Date::try_new_iso(2019, 2, 28).unwrap(); + let today_plus_1 = Date::try_new_iso(2019, 3, 1).unwrap(); + let offset = today.added(DateDuration::new(0, 0, 0, 1)); + assert_eq!(offset, today_plus_1); + + let today = Date::try_new_iso(2020, 3, 1).unwrap(); + let today_minus_1 = Date::try_new_iso(2020, 2, 29).unwrap(); + let offset = today.added(DateDuration::new(0, 0, 0, -1)); + assert_eq!(offset, today_minus_1); + } + + #[test] + fn test_offset_handles_negative_month_offset() { + let today = Date::try_new_iso(2020, 3, 1).unwrap(); + let today_minus_2_months = Date::try_new_iso(2020, 1, 1).unwrap(); + let offset = today.added(DateDuration::new(0, -2, 0, 0)); + assert_eq!(offset, today_minus_2_months); + + let today = Date::try_new_iso(2020, 3, 1).unwrap(); + let today_minus_4_months = Date::try_new_iso(2019, 11, 1).unwrap(); + let offset = today.added(DateDuration::new(0, -4, 0, 0)); + assert_eq!(offset, today_minus_4_months); + + let today = Date::try_new_iso(2020, 3, 1).unwrap(); + let today_minus_24_months = Date::try_new_iso(2018, 3, 1).unwrap(); + let offset = today.added(DateDuration::new(0, -24, 0, 0)); + assert_eq!(offset, today_minus_24_months); + + let today = Date::try_new_iso(2020, 3, 1).unwrap(); + let today_minus_27_months = Date::try_new_iso(2017, 12, 1).unwrap(); + let offset = today.added(DateDuration::new(0, -27, 0, 0)); + assert_eq!(offset, today_minus_27_months); + } + + #[test] + fn test_offset_handles_out_of_bound_month_offset() { + let today = Date::try_new_iso(2021, 1, 31).unwrap(); + // since 2021/02/31 isn't a valid date, `offset_date` auto-adjusts by adding 3 days to 2021/02/28 + let today_plus_1_month = Date::try_new_iso(2021, 3, 3).unwrap(); + let offset = today.added(DateDuration::new(0, 1, 0, 0)); + assert_eq!(offset, today_plus_1_month); + + let today = Date::try_new_iso(2021, 1, 31).unwrap(); + // since 2021/02/31 isn't a valid date, `offset_date` auto-adjusts by adding 3 days to 2021/02/28 + let today_plus_1_month_1_day = Date::try_new_iso(2021, 3, 4).unwrap(); + let offset = today.added(DateDuration::new(0, 1, 0, 1)); + assert_eq!(offset, today_plus_1_month_1_day); + } + + #[test] + fn test_iso_to_from_rd() { + // Reminder: ISO year 0 is Gregorian year 1 BCE. + // Year 0 is a leap year due to the 400-year rule. + fn check(rd: i64, year: i32, month: u8, day: u8) { + let rd = RataDie::new(rd); + + assert_eq!( + Date::from_rata_die(rd, Iso), + Date::try_new_iso(year, month, day).unwrap(), + "RD: {rd:?}" + ); + } + check(-1828, -5, 12, 30); + check(-1827, -5, 12, 31); // leap year + check(-1826, -4, 1, 1); + check(-1462, -4, 12, 30); + check(-1461, -4, 12, 31); + check(-1460, -3, 1, 1); + check(-1459, -3, 1, 2); + check(-732, -2, 12, 30); + check(-731, -2, 12, 31); + check(-730, -1, 1, 1); + check(-367, -1, 12, 30); + check(-366, -1, 12, 31); + check(-365, 0, 1, 1); // leap year + check(-364, 0, 1, 2); + check(-1, 0, 12, 30); + check(0, 0, 12, 31); + check(1, 1, 1, 1); + check(2, 1, 1, 2); + check(364, 1, 12, 30); + check(365, 1, 12, 31); + check(366, 2, 1, 1); + check(1459, 4, 12, 29); + check(1460, 4, 12, 30); + check(1461, 4, 12, 31); // leap year + check(1462, 5, 1, 1); + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/japanese.rs b/deps/crates/vendor/icu_calendar/src/cal/japanese.rs new file mode 100644 index 00000000000000..d52874b265413d --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/japanese.rs @@ -0,0 +1,955 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and implementations for the Japanese calendar. +//! +//! ```rust +//! use icu::calendar::cal::Japanese; +//! use icu::calendar::Date; +//! use tinystr::tinystr; +//! +//! let japanese_calendar = Japanese::new(); +//! +//! let date_iso = Date::try_new_iso(1970, 1, 2) +//! .expect("Failed to initialize ISO Date instance."); +//! let date_japanese = Date::new_from_iso(date_iso, japanese_calendar); +//! +//! assert_eq!(date_japanese.era_year().year, 45); +//! assert_eq!(date_japanese.month().ordinal, 1); +//! assert_eq!(date_japanese.day_of_month().0, 2); +//! assert_eq!(date_japanese.era_year().era, "showa"); +//! ``` + +use crate::cal::iso::{Iso, IsoDateInner}; +use crate::error::{year_check, DateError}; +use crate::provider::{CalendarJapaneseExtendedV1, CalendarJapaneseModernV1, EraStartDate}; +use crate::{types, AsCalendar, Calendar, Date, DateDuration, DateDurationUnit, Ref}; +use calendrical_calculations::rata_die::RataDie; +use icu_provider::prelude::*; +use tinystr::{tinystr, TinyStr16}; + +/// The [Japanese Calendar] (with modern eras only) +/// +/// The [Japanese calendar] is a solar calendar used in Japan, with twelve months. +/// The months and days are identical to that of the Gregorian calendar, however the years are counted +/// differently using the Japanese era system. +/// +/// This calendar only contains eras after Meiji, for all historical eras, check out [`JapaneseExtended`]. +/// +/// This type can be used with [`Date`] to represent dates in this calendar. +/// +/// [Japanese calendar]: https://en.wikipedia.org/wiki/Japanese_calendar +/// +/// # Era codes +/// +/// This calendar currently supports seven era codes. It supports the five post-Meiji eras +/// (`meiji`, `taisho`, `showa`, `heisei`, `reiwa`), as well as using the Gregorian +/// `bce` (alias `bc`), and `ce` (alias `ad`) for dates before the Meiji era. +/// +/// Future eras will also be added to this type when they are decided. +/// +/// These eras are loaded from data, requiring a data provider capable of providing [`CalendarJapaneseModernV1`] +/// data. +/// +/// # Month codes +/// +/// This calendar supports 12 solar month codes (`M01` - `M12`) +#[derive(Clone, Debug, Default)] +pub struct Japanese { + eras: DataPayload, +} + +/// The [Japanese Calendar] (with historical eras) +/// +/// The [Japanese calendar] is a solar calendar used in Japan, with twelve months. +/// The months and days are identical to that of the Gregorian calendar, however the years are counted +/// differently using the Japanese era system. +/// +/// This type can be used with [`Date`] to represent dates in this calendar. +/// +/// [Japanese calendar]: https://en.wikipedia.org/wiki/Japanese_calendar +/// +/// # Era codes +/// +/// This calendar supports a large number of era codes. It supports the five post-Meiji eras +/// (`meiji`, `taisho`, `showa`, `heisei`, `reiwa`). Pre-Meiji eras are represented +/// with their names converted to lowercase ascii and followed by their start year. E.g. the *Ten'ō* +/// era (781 - 782 CE) has the code `teno-781`. The Gregorian `bce` (alias `bc`), and `ce` (alias `ad`) +/// are used for dates before the first known era era. +/// +/// +/// These eras are loaded from data, requiring a data provider capable of providing [`CalendarJapaneseExtendedV1`] +/// data. +/// +/// # Month codes +/// +/// This calendar supports 12 solar month codes (`M01` - `M12`) +#[derive(Clone, Debug, Default)] +pub struct JapaneseExtended(Japanese); + +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +/// The inner date type used for representing [`Date`]s of [`Japanese`]. See [`Date`] and [`Japanese`] for more details. +pub struct JapaneseDateInner { + inner: IsoDateInner, + adjusted_year: i32, + era: TinyStr16, +} + +impl Japanese { + /// Creates a new [`Japanese`] using only modern eras (post-meiji) from compiled data. + /// + /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + #[cfg(feature = "compiled_data")] + pub const fn new() -> Self { + Self { + eras: DataPayload::from_static_ref( + crate::provider::Baked::SINGLETON_CALENDAR_JAPANESE_MODERN_V1, + ), + } + } + + icu_provider::gen_buffer_data_constructors!(() -> error: DataError, + functions: [ + new: skip, + try_new_with_buffer_provider, + try_new_unstable, + Self, + ]); + + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new)] + pub fn try_new_unstable + ?Sized>( + provider: &D, + ) -> Result { + Ok(Self { + eras: provider.load(Default::default())?.payload, + }) + } + + pub(crate) const DEBUG_NAME: &'static str = "Japanese"; +} + +impl JapaneseExtended { + /// Creates a new [`Japanese`] from using all eras (including pre-meiji) from compiled data. + /// + /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + #[cfg(feature = "compiled_data")] + pub const fn new() -> Self { + Self(Japanese { + eras: DataPayload::from_static_ref( + crate::provider::Baked::SINGLETON_CALENDAR_JAPANESE_EXTENDED_V1, + ), + }) + } + + icu_provider::gen_buffer_data_constructors!(() -> error: DataError, + functions: [ + new: skip, + try_new_with_buffer_provider, + try_new_unstable, + Self, + ]); + + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new)] + pub fn try_new_unstable + ?Sized>( + provider: &D, + ) -> Result { + Ok(Self(Japanese { + eras: provider.load(Default::default())?.payload.cast(), + })) + } + + pub(crate) const DEBUG_NAME: &'static str = "Japanese (historical era data)"; +} + +impl crate::cal::scaffold::UnstableSealed for Japanese {} +impl Calendar for Japanese { + type DateInner = JapaneseDateInner; + type Year = types::EraYear; + + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + let Some((month, false)) = month_code.parsed() else { + return Err(DateError::UnknownMonthCode(month_code)); + }; + + if month > 12 { + return Err(DateError::UnknownMonthCode(month_code)); + } + + self.new_japanese_date_inner(era.unwrap_or("ce"), year, month, day) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + self.from_iso(Iso.from_rata_die(rd)) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + Iso.to_rata_die(&self.to_iso(date)) + } + + fn from_iso(&self, iso: IsoDateInner) -> JapaneseDateInner { + let (adjusted_year, era) = self.adjusted_year_for(iso); + JapaneseDateInner { + inner: iso, + adjusted_year, + era, + } + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + date.inner + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + Iso.months_in_year(&date.inner) + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + Iso.days_in_year(&date.inner) + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + Iso.days_in_month(&date.inner) + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + Iso.offset_date(&mut date.inner, offset.cast_unit()); + let (adjusted_year, era) = self.adjusted_year_for(date.inner); + date.adjusted_year = adjusted_year; + date.era = era + } + + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + largest_unit: DateDurationUnit, + smallest_unit: DateDurationUnit, + ) -> DateDuration { + Iso.until( + &date1.inner, + &date2.inner, + &Iso, + largest_unit, + smallest_unit, + ) + .cast_unit() + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + types::EraYear { + era: date.era, + era_index: None, + year: date.adjusted_year, + ambiguity: types::YearAmbiguity::CenturyRequired, + } + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + Iso.extended_year(&date.inner) + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Iso.is_in_leap_year(&date.inner) + } + + /// The calendar-specific month represented by `date` + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + Iso.month(&date.inner) + } + + /// The calendar-specific day-of-month represented by `date` + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + Iso.day_of_month(&date.inner) + } + + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + Iso.day_of_year(&date.inner) + } + + fn debug_name(&self) -> &'static str { + Self::DEBUG_NAME + } + + fn calendar_algorithm(&self) -> Option { + Some(crate::preferences::CalendarAlgorithm::Japanese) + } +} + +impl crate::cal::scaffold::UnstableSealed for JapaneseExtended {} +impl Calendar for JapaneseExtended { + type DateInner = JapaneseDateInner; + type Year = types::EraYear; + + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + self.0.from_codes(era, year, month_code, day) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + Japanese::from_rata_die(&self.0, rd) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + Japanese::to_rata_die(&self.0, date) + } + + fn from_iso(&self, iso: IsoDateInner) -> JapaneseDateInner { + Japanese::from_iso(&self.0, iso) + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + Japanese::to_iso(&self.0, date) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + Japanese::months_in_year(&self.0, date) + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + Japanese::days_in_year(&self.0, date) + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + Japanese::days_in_month(&self.0, date) + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + Japanese::offset_date(&self.0, date, offset.cast_unit()) + } + + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + calendar2: &Self, + largest_unit: DateDurationUnit, + smallest_unit: DateDurationUnit, + ) -> DateDuration { + Japanese::until( + &self.0, + date1, + date2, + &calendar2.0, + largest_unit, + smallest_unit, + ) + .cast_unit() + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + Japanese::year_info(&self.0, date) + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + Japanese::extended_year(&self.0, date) + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Japanese::is_in_leap_year(&self.0, date) + } + + /// The calendar-specific month represented by `date` + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + Japanese::month(&self.0, date) + } + + /// The calendar-specific day-of-month represented by `date` + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + Japanese::day_of_month(&self.0, date) + } + + /// Information of the day of the year + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + Japanese::day_of_year(&self.0, date) + } + + fn debug_name(&self) -> &'static str { + Self::DEBUG_NAME + } + + fn calendar_algorithm(&self) -> Option { + Some(crate::preferences::CalendarAlgorithm::Japanese) + } +} + +impl Date { + /// Construct a new Japanese Date. + /// + /// Years are specified in the era provided, and must be in range for Japanese + /// eras (e.g. dates past April 30 Heisei 31 must be in Reiwa; "Jun 5 Heisei 31" and "Jan 1 Heisei 32" + /// will not be adjusted to being in Reiwa 1 and 2 respectively) + /// + /// However, dates may always be specified in "bce" or "ce" and they will be adjusted as necessary. + /// + /// ```rust + /// use icu::calendar::cal::Japanese; + /// use icu::calendar::{Date, Ref}; + /// use tinystr::tinystr; + /// + /// let japanese_calendar = Japanese::new(); + /// // for easy sharing + /// let japanese_calendar = Ref(&japanese_calendar); + /// + /// let era = "heisei"; + /// + /// let date = + /// Date::try_new_japanese_with_calendar(era, 14, 1, 2, japanese_calendar) + /// .expect("Constructing a date should succeed"); + /// + /// assert_eq!(date.era_year().era, era); + /// assert_eq!(date.era_year().year, 14); + /// assert_eq!(date.month().ordinal, 1); + /// assert_eq!(date.day_of_month().0, 2); + /// + /// // This function will error for eras that are out of bounds: + /// // (Heisei was 32 years long, Heisei 33 is in Reiwa) + /// let oob_date = + /// Date::try_new_japanese_with_calendar(era, 33, 1, 2, japanese_calendar); + /// assert!(oob_date.is_err()); + /// + /// // and for unknown eras + /// let fake_era = "neko"; // 🐱 + /// let fake_date = Date::try_new_japanese_with_calendar( + /// fake_era, + /// 10, + /// 1, + /// 2, + /// japanese_calendar, + /// ); + /// assert!(fake_date.is_err()); + /// ``` + pub fn try_new_japanese_with_calendar>( + era: &str, + year: i32, + month: u8, + day: u8, + japanese_calendar: A, + ) -> Result, DateError> { + let inner = japanese_calendar + .as_calendar() + .new_japanese_date_inner(era, year, month, day)?; + Ok(Date::from_raw(inner, japanese_calendar)) + } +} + +impl Date { + /// Construct a new Japanese Date with all eras. + /// + /// Years are specified in the era provided, and must be in range for Japanese + /// eras (e.g. dates past April 30 Heisei 31 must be in Reiwa; "Jun 5 Heisei 31" and "Jan 1 Heisei 32" + /// will not be adjusted to being in Reiwa 1 and 2 respectively) + /// + /// However, dates may always be specified in "bce" or "ce" and they will be adjusted as necessary. + /// + /// ```rust + /// use icu::calendar::cal::JapaneseExtended; + /// use icu::calendar::{Date, Ref}; + /// use tinystr::tinystr; + /// + /// let japanext_calendar = JapaneseExtended::new(); + /// // for easy sharing + /// let japanext_calendar = Ref(&japanext_calendar); + /// + /// let era = "kansei-1789"; + /// + /// let date = Date::try_new_japanese_extended_with_calendar( + /// era, + /// 7, + /// 1, + /// 2, + /// japanext_calendar, + /// ) + /// .expect("Constructing a date should succeed"); + /// + /// assert_eq!(date.era_year().era, era); + /// assert_eq!(date.era_year().year, 7); + /// assert_eq!(date.month().ordinal, 1); + /// assert_eq!(date.day_of_month().0, 2); + /// ``` + pub fn try_new_japanese_extended_with_calendar>( + era: &str, + year: i32, + month: u8, + day: u8, + japanext_calendar: A, + ) -> Result, DateError> { + let inner = japanext_calendar + .as_calendar() + .0 + .new_japanese_date_inner(era, year, month, day)?; + Ok(Date::from_raw(inner, japanext_calendar)) + } +} + +const MEIJI_START: EraStartDate = EraStartDate { + year: 1868, + month: 10, + day: 23, +}; +const TAISHO_START: EraStartDate = EraStartDate { + year: 1912, + month: 7, + day: 30, +}; +const SHOWA_START: EraStartDate = EraStartDate { + year: 1926, + month: 12, + day: 25, +}; +const HEISEI_START: EraStartDate = EraStartDate { + year: 1989, + month: 1, + day: 8, +}; +const REIWA_START: EraStartDate = EraStartDate { + year: 2019, + month: 5, + day: 1, +}; + +impl Japanese { + /// Given an ISO date, give year and era for that date in the Japanese calendar + /// + /// This will also use Gregorian eras for eras that are before the earliest era + fn adjusted_year_for(&self, date: IsoDateInner) -> (i32, TinyStr16) { + let date: EraStartDate = EraStartDate { + year: date.0.year, + month: date.0.month, + day: date.0.day, + }; + let (start, era) = self.japanese_era_for(date); + // The year in which an era starts is Year 1, and it may be short + // The only time this function will experience dates that are *before* + // the era start date are for the first era (Currently, taika-645 + // for japanext, meiji for japanese), + // In such a case, we instead fall back to Gregorian era codes + if date < start { + if date.year <= 0 { + (1 - date.year, tinystr!(16, "bce")) + } else { + (date.year, tinystr!(16, "ce")) + } + } else { + (date.year - start.year + 1, era) + } + } + + /// Given an date, obtain the era data (not counting spliced gregorian eras) + fn japanese_era_for(&self, date: EraStartDate) -> (EraStartDate, TinyStr16) { + let era_data = self.eras.get(); + // We optimize for the five "modern" post-Meiji eras, which are stored in a smaller + // array and also hardcoded. The hardcoded version is not used if data indicates the + // presence of newer eras. + if date >= MEIJI_START + && era_data.dates_to_eras.last().map(|x| x.1) == Some(tinystr!(16, "reiwa")) + { + // Fast path in case eras have not changed since this code was written + return if date >= REIWA_START { + (REIWA_START, tinystr!(16, "reiwa")) + } else if date >= HEISEI_START { + (HEISEI_START, tinystr!(16, "heisei")) + } else if date >= SHOWA_START { + (SHOWA_START, tinystr!(16, "showa")) + } else if date >= TAISHO_START { + (TAISHO_START, tinystr!(16, "taisho")) + } else { + (MEIJI_START, tinystr!(16, "meiji")) + }; + } + let data = &era_data.dates_to_eras; + match data.binary_search_by(|(d, _)| d.cmp(&date)) { + Ok(index) => data.get(index), + Err(index) if index == 0 => data.get(index), + Err(index) => data.get(index - 1).or_else(|| data.iter().next_back()), + } + .unwrap_or((REIWA_START, tinystr!(16, "reiwa"))) + } + + /// Returns the range of dates for a given Japanese era code, + /// not handling "bce" or "ce" + /// + /// Returns (era_start, era_end) + fn japanese_era_range_for( + &self, + era: TinyStr16, + ) -> Result<(EraStartDate, Option), DateError> { + // Avoid linear search by trying well known eras + if era == tinystr!(16, "reiwa") { + // Check if we're the last + if let Some(last) = self.eras.get().dates_to_eras.last() { + if last.1 == era { + return Ok((REIWA_START, None)); + } + } + } else if era == tinystr!(16, "heisei") { + return Ok((HEISEI_START, Some(REIWA_START))); + } else if era == tinystr!(16, "showa") { + return Ok((SHOWA_START, Some(HEISEI_START))); + } else if era == tinystr!(16, "taisho") { + return Ok((TAISHO_START, Some(SHOWA_START))); + } else if era == tinystr!(16, "meiji") { + return Ok((MEIJI_START, Some(TAISHO_START))); + } + + let era_data = self.eras.get(); + let data = &era_data.dates_to_eras; + // Try to avoid linear search by binary searching for the year suffix + if let Some(year) = era.split('-').nth(1) { + if let Ok(ref int) = year.parse::() { + if let Ok(index) = data.binary_search_by(|(d, _)| d.year.cmp(int)) { + #[allow(clippy::expect_used)] // see expect message + let (era_start, code) = data + .get(index) + .expect("Indexing from successful binary search must succeed"); + // There is a slight chance we hit the case where there are two eras in the same year + // There are a couple of rare cases of this, but it's not worth writing a range-based binary search + // to catch them since this is an optimization + if code == era { + return Ok((era_start, data.get(index + 1).map(|e| e.0))); + } + } + } + } + + // Avoidance didn't work. Let's find the era manually, searching back from the present + if let Some((index, (start, _))) = data.iter().enumerate().rev().find(|d| d.1 .1 == era) { + return Ok((start, data.get(index + 1).map(|e| e.0))); + } + + Err(DateError::UnknownEra) + } + + fn new_japanese_date_inner( + &self, + era: &str, + year: i32, + month: u8, + day: u8, + ) -> Result { + let cal = Ref(self); + let era = match era { + "ce" | "ad" => { + return Ok(Date::try_new_gregorian(year_check(year, 1..)?, month, day)? + .to_calendar(cal) + .inner); + } + "bce" | "bc" => { + return Ok( + Date::try_new_gregorian(1 - year_check(year, 1..)?, month, day)? + .to_calendar(cal) + .inner, + ); + } + e => e.parse().map_err(|_| DateError::UnknownEra)?, + }; + + let (era_start, next_era_start) = self.japanese_era_range_for(era)?; + + let next_era_start = next_era_start.unwrap_or(EraStartDate { + year: i32::MAX, + month: 12, + day: 31, + }); + + let date_in_iso = EraStartDate { + year: era_start.year + year - 1, + month, + day, + }; + + if date_in_iso < era_start { + return Err(if date_in_iso.year < era_start.year { + DateError::Range { + field: "year", + value: year, + min: 1, + max: 1 + next_era_start.year - era_start.year, + } + } else if date_in_iso.month < era_start.month { + DateError::Range { + field: "month", + value: month as i32, + min: era_start.month as i32, + max: 12, + } + } else + /* if date_in_iso.day < era_start.day */ + { + DateError::Range { + field: "day", + value: day as i32, + min: era_start.day as i32, + max: 31, + } + }); + } else if date_in_iso >= next_era_start { + return Err(if date_in_iso.year > era_start.year { + DateError::Range { + field: "year", + value: year, + min: 1, + max: 1 + next_era_start.year - era_start.year, + } + } else if date_in_iso.month > era_start.month { + DateError::Range { + field: "month", + value: month as i32, + min: 1, + max: next_era_start.month as i32 - 1, + } + } else + /* if date_in_iso.day >= era_start.day */ + { + DateError::Range { + field: "day", + value: day as i32, + min: 1, + max: next_era_start.day as i32 - 1, + } + }); + } + + let iso = Date::try_new_iso(date_in_iso.year, date_in_iso.month, date_in_iso.day)?; + Ok(JapaneseDateInner { + inner: iso.inner, + adjusted_year: year, + era, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::Ref; + + fn single_test_roundtrip(calendar: Ref, era: &str, year: i32, month: u8, day: u8) { + let date = Date::try_new_japanese_with_calendar(era, year, month, day, calendar) + .unwrap_or_else(|e| { + panic!("Failed to construct date with {era:?}, {year}, {month}, {day}: {e:?}") + }); + let iso = date.to_iso(); + let reconstructed = Date::new_from_iso(iso, calendar); + assert_eq!( + date, reconstructed, + "Failed to roundtrip with {era:?}, {year}, {month}, {day}" + ); + + // Extra coverage for https://github.com/unicode-org/icu4x/issues/4968 + assert_eq!(reconstructed.era_year().era, era); + assert_eq!(reconstructed.era_year().year, year); + } + + fn single_test_roundtrip_ext( + calendar: Ref, + era: &str, + year: i32, + month: u8, + day: u8, + ) { + let date = Date::try_new_japanese_extended_with_calendar(era, year, month, day, calendar) + .unwrap_or_else(|e| { + panic!("Failed to construct date with {era:?}, {year}, {month}, {day}: {e:?}") + }); + let iso = date.to_iso(); + let reconstructed = Date::new_from_iso(iso, calendar); + assert_eq!( + date, reconstructed, + "Failed to roundtrip with {era:?}, {year}, {month}, {day}" + ) + } + + // test that the Gregorian eras roundtrip to Japanese ones + fn single_test_gregorian_roundtrip_ext( + calendar: Ref, + era: &str, + year: i32, + month: u8, + day: u8, + era2: &str, + year2: i32, + ) { + let expected = Date::try_new_japanese_extended_with_calendar(era2, year2, month, day, calendar) + .unwrap_or_else(|e| { + panic!( + "Failed to construct expectation date with {era2:?}, {year2}, {month}, {day}: {e:?}" + ) + }); + + let date = Date::try_new_japanese_extended_with_calendar(era, year, month, day, calendar) + .unwrap_or_else(|e| { + panic!("Failed to construct date with {era:?}, {year}, {month}, {day}: {e:?}") + }); + let iso = date.to_iso(); + let reconstructed = Date::new_from_iso(iso, calendar); + assert_eq!( + expected, reconstructed, + "Failed to roundtrip with {era:?}, {year}, {month}, {day} == {era2:?}, {year}" + ) + } + + fn single_test_error( + calendar: Ref, + era: &str, + year: i32, + month: u8, + day: u8, + error: DateError, + ) { + let date = Date::try_new_japanese_with_calendar(era, year, month, day, calendar); + assert_eq!( + date, + Err(error), + "Construction with {era:?}, {year}, {month}, {day} did not return {error:?}" + ) + } + + fn single_test_error_ext( + calendar: Ref, + era: &str, + year: i32, + month: u8, + day: u8, + error: DateError, + ) { + let date = Date::try_new_japanese_extended_with_calendar(era, year, month, day, calendar); + assert_eq!( + date, + Err(error), + "Construction with {era:?}, {year}, {month}, {day} did not return {error:?}" + ) + } + + #[test] + fn test_japanese() { + let calendar = Japanese::new(); + let calendar_ext = JapaneseExtended::new(); + let calendar = Ref(&calendar); + let calendar_ext = Ref(&calendar_ext); + + single_test_roundtrip(calendar, "heisei", 12, 3, 1); + single_test_roundtrip(calendar, "taisho", 3, 3, 1); + // Heisei did not start until later in the year + single_test_error( + calendar, + "heisei", + 1, + 1, + 1, + DateError::Range { + field: "day", + value: 1, + min: 8, + max: 31, + }, + ); + + single_test_roundtrip_ext(calendar_ext, "heisei", 12, 3, 1); + single_test_roundtrip_ext(calendar_ext, "taisho", 3, 3, 1); + single_test_error_ext( + calendar_ext, + "heisei", + 1, + 1, + 1, + DateError::Range { + field: "day", + value: 1, + min: 8, + max: 31, + }, + ); + + single_test_roundtrip_ext(calendar_ext, "hakuho-672", 4, 3, 1); + single_test_error(calendar, "hakuho-672", 4, 3, 1, DateError::UnknownEra); + + // handle bce/ce + single_test_roundtrip(calendar, "bce", 100, 3, 1); + single_test_roundtrip(calendar, "bce", 1, 3, 1); + single_test_roundtrip(calendar, "ce", 1, 3, 1); + single_test_roundtrip(calendar, "ce", 100, 3, 1); + single_test_roundtrip_ext(calendar_ext, "ce", 100, 3, 1); + single_test_roundtrip(calendar, "ce", 1000, 3, 1); + single_test_error( + calendar, + "ce", + 0, + 3, + 1, + DateError::Range { + field: "year", + value: 0, + min: 1, + max: i32::MAX, + }, + ); + single_test_error( + calendar, + "bce", + -1, + 3, + 1, + DateError::Range { + field: "year", + value: -1, + min: 1, + max: i32::MAX, + }, + ); + + // handle the cases where bce/ce get adjusted to different eras + // single_test_gregorian_roundtrip(calendar, "ce", 2021, 3, 1, "reiwa", 3); + single_test_gregorian_roundtrip_ext(calendar_ext, "ce", 1000, 3, 1, "choho-999", 2); + single_test_gregorian_roundtrip_ext(calendar_ext, "ce", 749, 5, 10, "tenpyokampo-749", 1); + single_test_gregorian_roundtrip_ext(calendar_ext, "bce", 10, 3, 1, "bce", 10); + + // There were multiple eras in this year + // This one is from Apr 14 to July 2 + single_test_roundtrip_ext(calendar_ext, "tenpyokampo-749", 1, 4, 20); + single_test_roundtrip_ext(calendar_ext, "tenpyokampo-749", 1, 4, 14); + single_test_roundtrip_ext(calendar_ext, "tenpyokampo-749", 1, 7, 1); + single_test_error_ext( + calendar_ext, + "tenpyokampo-749", + 1, + 7, + 5, + DateError::Range { + field: "month", + value: 7, + min: 1, + max: 6, + }, + ); + single_test_error_ext( + calendar_ext, + "tenpyokampo-749", + 1, + 4, + 13, + DateError::Range { + field: "day", + value: 13, + min: 14, + max: 31, + }, + ); + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/julian.rs b/deps/crates/vendor/icu_calendar/src/cal/julian.rs new file mode 100644 index 00000000000000..92379e0bde1f22 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/julian.rs @@ -0,0 +1,493 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and implementations for the Julian calendar. +//! +//! ```rust +//! use icu::calendar::{cal::Julian, Date}; +//! +//! let date_iso = Date::try_new_iso(1970, 1, 2) +//! .expect("Failed to initialize ISO Date instance."); +//! let date_julian = Date::new_from_iso(date_iso, Julian); +//! +//! assert_eq!(date_julian.era_year().year, 1969); +//! assert_eq!(date_julian.month().ordinal, 12); +//! assert_eq!(date_julian.day_of_month().0, 20); +//! ``` + +use crate::cal::iso::{Iso, IsoDateInner}; +use crate::calendar_arithmetic::{ArithmeticDate, CalendarArithmetic}; +use crate::error::{year_check, DateError}; +use crate::{types, Calendar, Date, DateDuration, DateDurationUnit, RangeError}; +use calendrical_calculations::helpers::I32CastError; +use calendrical_calculations::rata_die::RataDie; +use tinystr::tinystr; + +/// The [Julian Calendar] +/// +/// The [Julian calendar] is a solar calendar that was used commonly historically, with twelve months. +/// +/// This type can be used with [`Date`] to represent dates in this calendar. +/// +/// [Julian calendar]: https://en.wikipedia.org/wiki/Julian_calendar +/// +/// # Era codes +/// +/// This calendar uses two era codes: `bce` (alias `bc`), and `ce` (alias `ad`), corresponding to the BCE and CE eras. +/// +/// # Month codes +/// +/// This calendar supports 12 solar month codes (`"M01" - "M12"`) +#[derive(Copy, Clone, Debug, Hash, Default, Eq, PartialEq, PartialOrd, Ord)] +#[allow(clippy::exhaustive_structs)] // this type is stable +pub struct Julian; + +/// The inner date type used for representing [`Date`]s of [`Julian`]. See [`Date`] and [`Julian`] for more details. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] +// The inner date type used for representing Date +pub struct JulianDateInner(pub(crate) ArithmeticDate); + +impl CalendarArithmetic for Julian { + type YearInfo = i32; + + fn days_in_provided_month(year: i32, month: u8) -> u8 { + match month { + 4 | 6 | 9 | 11 => 30, + 2 if Self::provided_year_is_leap(year) => 29, + 2 => 28, + 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31, + _ => 0, + } + } + + fn months_in_provided_year(_: i32) -> u8 { + 12 + } + + fn provided_year_is_leap(year: i32) -> bool { + calendrical_calculations::julian::is_leap_year(year) + } + + fn last_month_day_in_provided_year(_year: i32) -> (u8, u8) { + (12, 31) + } + + fn days_in_provided_year(year: i32) -> u16 { + if Self::provided_year_is_leap(year) { + 366 + } else { + 365 + } + } +} + +impl crate::cal::scaffold::UnstableSealed for Julian {} +impl Calendar for Julian { + type DateInner = JulianDateInner; + type Year = types::EraYear; + + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + let year = match era { + Some("ce" | "ad") | None => year_check(year, 1..)?, + Some("bce" | "bc") => 1 - year_check(year, 1..)?, + Some(_) => return Err(DateError::UnknownEra), + }; + + ArithmeticDate::new_from_codes(self, year, month_code, day).map(JulianDateInner) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + JulianDateInner( + match calendrical_calculations::julian::julian_from_fixed(rd) { + Err(I32CastError::BelowMin) => ArithmeticDate::min_date(), + Err(I32CastError::AboveMax) => ArithmeticDate::max_date(), + Ok((year, month, day)) => ArithmeticDate::new_unchecked(year, month, day), + }, + ) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + calendrical_calculations::julian::fixed_from_julian(date.0.year, date.0.month, date.0.day) + } + + fn from_iso(&self, iso: IsoDateInner) -> JulianDateInner { + self.from_rata_die(Iso.to_rata_die(&iso)) + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + Iso.from_rata_die(self.to_rata_die(date)) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + date.0.months_in_year() + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + date.0.days_in_year() + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + date.0.days_in_month() + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + date.0.offset_date(offset, &()); + } + + #[allow(clippy::field_reassign_with_default)] + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + _largest_unit: DateDurationUnit, + _smallest_unit: DateDurationUnit, + ) -> DateDuration { + date1.0.until(date2.0, _largest_unit, _smallest_unit) + } + + /// The calendar-specific year represented by `date` + /// Julian has the same era scheme as Gregorian + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + let extended_year = self.extended_year(date); + if extended_year > 0 { + types::EraYear { + era: tinystr!(16, "ce"), + era_index: Some(1), + year: extended_year, + ambiguity: types::YearAmbiguity::CenturyRequired, + } + } else { + types::EraYear { + era: tinystr!(16, "bce"), + era_index: Some(0), + year: 1_i32.saturating_sub(extended_year), + ambiguity: types::YearAmbiguity::EraAndCenturyRequired, + } + } + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + date.0.extended_year() + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Self::provided_year_is_leap(date.0.year) + } + + /// The calendar-specific month represented by `date` + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + date.0.month() + } + + /// The calendar-specific day-of-month represented by `date` + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + date.0.day_of_month() + } + + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + date.0.day_of_year() + } + + fn debug_name(&self) -> &'static str { + "Julian" + } + + fn calendar_algorithm(&self) -> Option { + None + } +} + +impl Julian { + /// Construct a new Julian Calendar + pub fn new() -> Self { + Self + } +} + +impl Date { + /// Construct new Julian Date. + /// + /// Years are arithmetic, meaning there is a year 0. Zero and negative years are in BC, with year 0 = 1 BC + /// + /// ```rust + /// use icu::calendar::Date; + /// + /// let date_julian = Date::try_new_julian(1969, 12, 20) + /// .expect("Failed to initialize Julian Date instance."); + /// + /// assert_eq!(date_julian.era_year().year, 1969); + /// assert_eq!(date_julian.month().ordinal, 12); + /// assert_eq!(date_julian.day_of_month().0, 20); + /// ``` + pub fn try_new_julian(year: i32, month: u8, day: u8) -> Result, RangeError> { + ArithmeticDate::new_from_ordinals(year, month, day) + .map(JulianDateInner) + .map(|inner| Date::from_raw(inner, Julian)) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_day_iso_to_julian() { + // March 1st 200 is same on both calendars + let iso_date = Date::try_new_iso(200, 3, 1).unwrap(); + let julian_date = Date::new_from_iso(iso_date, Julian).inner; + assert_eq!(julian_date.0.year, 200); + assert_eq!(julian_date.0.month, 3); + assert_eq!(julian_date.0.day, 1); + + // Feb 28th, 200 (iso) = Feb 29th, 200 (julian) + let iso_date = Date::try_new_iso(200, 2, 28).unwrap(); + let julian_date = Date::new_from_iso(iso_date, Julian).inner; + assert_eq!(julian_date.0.year, 200); + assert_eq!(julian_date.0.month, 2); + assert_eq!(julian_date.0.day, 29); + + // March 1st 400 (iso) = Feb 29th, 400 (julian) + let iso_date = Date::try_new_iso(400, 3, 1).unwrap(); + let julian_date = Date::new_from_iso(iso_date, Julian).inner; + assert_eq!(julian_date.0.year, 400); + assert_eq!(julian_date.0.month, 2); + assert_eq!(julian_date.0.day, 29); + + // Jan 1st, 2022 (iso) = Dec 19, 2021 (julian) + let iso_date = Date::try_new_iso(2022, 1, 1).unwrap(); + let julian_date = Date::new_from_iso(iso_date, Julian).inner; + assert_eq!(julian_date.0.year, 2021); + assert_eq!(julian_date.0.month, 12); + assert_eq!(julian_date.0.day, 19); + } + + #[test] + fn test_day_julian_to_iso() { + // March 1st 200 is same on both calendars + let julian_date = Date::try_new_julian(200, 3, 1).unwrap(); + let iso_date = julian_date.to_iso(); + let iso_expected_date = Date::try_new_iso(200, 3, 1).unwrap(); + assert_eq!(iso_date, iso_expected_date); + + // Feb 28th, 200 (iso) = Feb 29th, 200 (julian) + let julian_date = Date::try_new_julian(200, 2, 29).unwrap(); + let iso_date = julian_date.to_iso(); + let iso_expected_date = Date::try_new_iso(200, 2, 28).unwrap(); + assert_eq!(iso_date, iso_expected_date); + + // March 1st 400 (iso) = Feb 29th, 400 (julian) + let julian_date = Date::try_new_julian(400, 2, 29).unwrap(); + let iso_date = julian_date.to_iso(); + let iso_expected_date = Date::try_new_iso(400, 3, 1).unwrap(); + assert_eq!(iso_date, iso_expected_date); + + // Jan 1st, 2022 (iso) = Dec 19, 2021 (julian) + let julian_date = Date::try_new_julian(2021, 12, 19).unwrap(); + let iso_date = julian_date.to_iso(); + let iso_expected_date = Date::try_new_iso(2022, 1, 1).unwrap(); + assert_eq!(iso_date, iso_expected_date); + + // March 1st, 2022 (iso) = Feb 16, 2022 (julian) + let julian_date = Date::try_new_julian(2022, 2, 16).unwrap(); + let iso_date = julian_date.to_iso(); + let iso_expected_date = Date::try_new_iso(2022, 3, 1).unwrap(); + assert_eq!(iso_date, iso_expected_date); + } + + #[test] + fn test_roundtrip_negative() { + // https://github.com/unicode-org/icu4x/issues/2254 + let iso_date = Date::try_new_iso(-1000, 3, 3).unwrap(); + let julian = iso_date.to_calendar(Julian::new()); + let recovered_iso = julian.to_iso(); + assert_eq!(iso_date, recovered_iso); + } + + #[test] + fn test_julian_near_era_change() { + // Tests that the Julian calendar gives the correct expected + // day, month, and year for positive years (CE) + + #[derive(Debug)] + struct TestCase { + rd: i64, + iso_year: i32, + iso_month: u8, + iso_day: u8, + expected_year: i32, + expected_era: &'static str, + expected_month: u8, + expected_day: u8, + } + + let cases = [ + TestCase { + rd: 1, + iso_year: 1, + iso_month: 1, + iso_day: 1, + expected_year: 1, + expected_era: "ce", + expected_month: 1, + expected_day: 3, + }, + TestCase { + rd: 0, + iso_year: 0, + iso_month: 12, + iso_day: 31, + expected_year: 1, + expected_era: "ce", + expected_month: 1, + expected_day: 2, + }, + TestCase { + rd: -1, + iso_year: 0, + iso_month: 12, + iso_day: 30, + expected_year: 1, + expected_era: "ce", + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: -2, + iso_year: 0, + iso_month: 12, + iso_day: 29, + expected_year: 1, + expected_era: "bce", + expected_month: 12, + expected_day: 31, + }, + TestCase { + rd: -3, + iso_year: 0, + iso_month: 12, + iso_day: 28, + expected_year: 1, + expected_era: "bce", + expected_month: 12, + expected_day: 30, + }, + TestCase { + rd: -367, + iso_year: -1, + iso_month: 12, + iso_day: 30, + expected_year: 1, + expected_era: "bce", + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: -368, + iso_year: -1, + iso_month: 12, + iso_day: 29, + expected_year: 2, + expected_era: "bce", + expected_month: 12, + expected_day: 31, + }, + TestCase { + rd: -1462, + iso_year: -4, + iso_month: 12, + iso_day: 30, + expected_year: 4, + expected_era: "bce", + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: -1463, + iso_year: -4, + iso_month: 12, + iso_day: 29, + expected_year: 5, + expected_era: "bce", + expected_month: 12, + expected_day: 31, + }, + ]; + + for case in cases { + let iso_from_rd = Date::from_rata_die(RataDie::new(case.rd), crate::Iso); + let julian_from_rd = Date::from_rata_die(RataDie::new(case.rd), Julian); + assert_eq!(julian_from_rd.era_year().year, case.expected_year, + "Failed year check from RD: {case:?}\nISO: {iso_from_rd:?}\nJulian: {julian_from_rd:?}"); + assert_eq!(julian_from_rd.era_year().era, case.expected_era, + "Failed era check from RD: {case:?}\nISO: {iso_from_rd:?}\nJulian: {julian_from_rd:?}"); + assert_eq!(julian_from_rd.month().ordinal, case.expected_month, + "Failed month check from RD: {case:?}\nISO: {iso_from_rd:?}\nJulian: {julian_from_rd:?}"); + assert_eq!(julian_from_rd.day_of_month().0, case.expected_day, + "Failed day check from RD: {case:?}\nISO: {iso_from_rd:?}\nJulian: {julian_from_rd:?}"); + + let iso_date_man = Date::try_new_iso(case.iso_year, case.iso_month, case.iso_day) + .expect("Failed to initialize ISO date for {case:?}"); + let julian_date_man = Date::new_from_iso(iso_date_man, Julian); + assert_eq!(iso_from_rd, iso_date_man, + "ISO from RD not equal to ISO generated from manually-input ymd\nCase: {case:?}\nRD: {iso_from_rd:?}\nMan: {iso_date_man:?}"); + assert_eq!(julian_from_rd, julian_date_man, + "Julian from RD not equal to Julian generated from manually-input ymd\nCase: {case:?}\nRD: {julian_from_rd:?}\nMan: {julian_date_man:?}"); + } + } + + #[test] + fn test_julian_rd_date_conversion() { + // Tests that converting from RD to Julian then + // back to RD yields the same RD + for i in -10000..=10000 { + let rd = RataDie::new(i); + let julian = Date::from_rata_die(rd, Julian); + let new_rd = julian.to_rata_die(); + assert_eq!(rd, new_rd); + } + } + + #[test] + fn test_julian_directionality() { + // Tests that for a large range of RDs, if a RD + // is less than another, the corresponding YMD should also be less + // than the other, without exception. + for i in -100..=100 { + for j in -100..=100 { + let julian_i = Date::from_rata_die(RataDie::new(i), Julian); + let julian_j = Date::from_rata_die(RataDie::new(j), Julian); + + assert_eq!( + i.cmp(&j), + julian_i.inner.0.cmp(&julian_j.inner.0), + "Julian directionality inconsistent with directionality for i: {i}, j: {j}" + ); + } + } + } + + #[test] + fn test_hebrew_epoch() { + assert_eq!( + calendrical_calculations::julian::fixed_from_julian_book_version(-3761, 10, 7), + RataDie::new(-1373427) + ); + } + + #[test] + fn test_julian_leap_years() { + assert!(Julian::provided_year_is_leap(4)); + assert!(Julian::provided_year_is_leap(0)); + assert!(Julian::provided_year_is_leap(-4)); + + Date::try_new_julian(2020, 2, 29).unwrap(); + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/mod.rs b/deps/crates/vendor/icu_calendar/src/cal/mod.rs new file mode 100644 index 00000000000000..0014aac559b5e3 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/mod.rs @@ -0,0 +1,51 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! Types for individual calendars +pub(crate) mod buddhist; +pub(crate) mod chinese; +pub(crate) mod chinese_based; +pub(crate) mod coptic; +pub(crate) mod dangi; +pub(crate) mod ethiopian; +pub(crate) mod gregorian; +pub(crate) mod hebrew; +pub(crate) mod hijri; +pub(crate) mod indian; +pub(crate) mod iso; +pub(crate) mod japanese; +pub(crate) mod julian; +pub(crate) mod persian; +pub(crate) mod roc; + +pub use buddhist::Buddhist; +pub use chinese::Chinese; +pub use coptic::Coptic; +pub use dangi::Dangi; +pub use ethiopian::{Ethiopian, EthiopianEraStyle}; +pub use gregorian::Gregorian; +pub use hebrew::Hebrew; +pub use hijri::{ + HijriSimulated, HijriTabular, HijriTabularEpoch, HijriTabularLeapYears, HijriUmmAlQura, +}; +pub use indian::Indian; +pub use iso::Iso; +pub use japanese::{Japanese, JapaneseExtended}; +pub use julian::Julian; +pub use persian::Persian; +pub use roc::Roc; + +pub use crate::any_calendar::{AnyCalendar, AnyCalendarKind}; + +/// Internal scaffolding types +pub mod scaffold { + /// Trait marking other traits that are considered unstable and should not generally be + /// implemented outside of the calendar crate. + /// + ///

+ pub trait UnstableSealed {} +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/persian.rs b/deps/crates/vendor/icu_calendar/src/cal/persian.rs new file mode 100644 index 00000000000000..fc58e879925737 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/persian.rs @@ -0,0 +1,726 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and implementations for the Persian calendar. +//! +//! ```rust +//! use icu::calendar::Date; +//! +//! let persian_date = Date::try_new_persian(1348, 10, 11) +//! .expect("Failed to initialize Persian Date instance."); +//! +//! assert_eq!(persian_date.era_year().year, 1348); +//! assert_eq!(persian_date.month().ordinal, 10); +//! assert_eq!(persian_date.day_of_month().0, 11); +//! ``` + +use crate::cal::iso::{Iso, IsoDateInner}; +use crate::calendar_arithmetic::{ArithmeticDate, CalendarArithmetic}; +use crate::error::DateError; +use crate::{types, Calendar, Date, DateDuration, DateDurationUnit, RangeError}; +use ::tinystr::tinystr; +use calendrical_calculations::helpers::I32CastError; +use calendrical_calculations::rata_die::RataDie; + +/// The [Persian Calendar](https://en.wikipedia.org/wiki/Solar_Hijri_calendar) +/// +/// The Persian Calendar is a solar calendar used officially by the countries of Iran and Afghanistan and many Persian-speaking regions. +/// It has 12 months and other similarities to the [`Gregorian`](super::Gregorian) Calendar. +/// +/// This type can be used with [`Date`] to represent dates in this calendar. +/// +/// # Era codes +/// +/// This calendar uses a single era code `ap` (aliases `sh`, `hs`), with Anno Persico/Anno Persarum starting the year of the Hijra. Dates before this era use negative years. +/// +/// # Month codes +/// +/// This calendar supports 12 solar month codes (`"M01" - "M12"`) +#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq, PartialOrd, Ord)] +#[allow(clippy::exhaustive_structs)] +pub struct Persian; + +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] + +/// The inner date type used for representing [`Date`]s of [`Persian`]. See [`Date`] and [`Persian`] for more details. +pub struct PersianDateInner(ArithmeticDate); + +impl CalendarArithmetic for Persian { + type YearInfo = i32; + + fn days_in_provided_month(year: i32, month: u8) -> u8 { + match month { + 1..=6 => 31, + 7..=11 => 30, + 12 if Self::provided_year_is_leap(year) => 30, + 12 => 29, + _ => 0, + } + } + + fn months_in_provided_year(_: i32) -> u8 { + 12 + } + + fn provided_year_is_leap(p_year: i32) -> bool { + calendrical_calculations::persian::is_leap_year(p_year) + } + + fn days_in_provided_year(year: i32) -> u16 { + if Self::provided_year_is_leap(year) { + 366 + } else { + 365 + } + } + + fn last_month_day_in_provided_year(year: i32) -> (u8, u8) { + if Self::provided_year_is_leap(year) { + (12, 30) + } else { + (12, 29) + } + } +} + +impl crate::cal::scaffold::UnstableSealed for Persian {} +impl Calendar for Persian { + type DateInner = PersianDateInner; + type Year = types::EraYear; + + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + let year = match era { + Some("ap" | "sh" | "hs") | None => year, + Some(_) => return Err(DateError::UnknownEra), + }; + + ArithmeticDate::new_from_codes(self, year, month_code, day).map(PersianDateInner) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + PersianDateInner( + match calendrical_calculations::persian::fast_persian_from_fixed(rd) { + Err(I32CastError::BelowMin) => ArithmeticDate::min_date(), + Err(I32CastError::AboveMax) => ArithmeticDate::max_date(), + Ok((year, month, day)) => ArithmeticDate::new_unchecked(year, month, day), + }, + ) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + calendrical_calculations::persian::fixed_from_fast_persian( + date.0.year, + date.0.month, + date.0.day, + ) + } + + fn from_iso(&self, iso: IsoDateInner) -> PersianDateInner { + self.from_rata_die(Iso.to_rata_die(&iso)) + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + Iso.from_rata_die(self.to_rata_die(date)) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + date.0.months_in_year() + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + date.0.days_in_year() + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + date.0.days_in_month() + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { + date.0.offset_date(offset, &()) + } + + #[allow(clippy::field_reassign_with_default)] + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + _largest_unit: DateDurationUnit, + _smallest_unit: DateDurationUnit, + ) -> DateDuration { + date1.0.until(date2.0, _largest_unit, _smallest_unit) + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + types::EraYear { + era: tinystr!(16, "ap"), + era_index: Some(0), + year: self.extended_year(date), + ambiguity: types::YearAmbiguity::CenturyRequired, + } + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + date.0.extended_year() + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Self::provided_year_is_leap(date.0.year) + } + + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + date.0.month() + } + + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + date.0.day_of_month() + } + + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + date.0.day_of_year() + } + + fn debug_name(&self) -> &'static str { + "Persian" + } + + fn calendar_algorithm(&self) -> Option { + Some(crate::preferences::CalendarAlgorithm::Persian) + } +} + +impl Persian { + /// Constructs a new Persian Calendar + pub fn new() -> Self { + Self + } +} + +impl Date { + /// Construct new Persian Date. + /// + /// Has no negative years, only era is the AH/AP. + /// + /// ```rust + /// use icu::calendar::Date; + /// + /// let date_persian = Date::try_new_persian(1392, 4, 25) + /// .expect("Failed to initialize Persian Date instance."); + /// + /// assert_eq!(date_persian.era_year().year, 1392); + /// assert_eq!(date_persian.month().ordinal, 4); + /// assert_eq!(date_persian.day_of_month().0, 25); + /// ``` + pub fn try_new_persian(year: i32, month: u8, day: u8) -> Result, RangeError> { + ArithmeticDate::new_from_ordinals(year, month, day) + .map(PersianDateInner) + .map(|inner| Date::from_raw(inner, Persian)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[derive(Debug)] + struct DateCase { + year: i32, + month: u8, + day: u8, + } + + static TEST_RD: [i64; 21] = [ + 656786, 664224, 671401, 694799, 702806, 704424, 708842, 709409, 709580, 727274, 728714, + 739330, 739331, 744313, 763436, 763437, 764652, 775123, 775488, 775489, 1317874, + ]; + + // Test data are provided for the range 1178-3000 AP, for which + // we know the 33-year rule, with the override table, matches the + // astronomical calculations based on the 52.5 degrees east meridian. + static CASES: [DateCase; 21] = [ + // First year for which 33-year rule matches the astronomical calculation + DateCase { + year: 1178, + month: 1, + day: 1, + }, + DateCase { + year: 1198, + month: 5, + day: 10, + }, + DateCase { + year: 1218, + month: 1, + day: 7, + }, + DateCase { + year: 1282, + month: 1, + day: 29, + }, + // The beginning of the year the calendar was adopted + DateCase { + year: 1304, + month: 1, + day: 1, + }, + DateCase { + year: 1308, + month: 6, + day: 3, + }, + DateCase { + year: 1320, + month: 7, + day: 7, + }, + DateCase { + year: 1322, + month: 1, + day: 29, + }, + DateCase { + year: 1322, + month: 7, + day: 14, + }, + DateCase { + year: 1370, + month: 12, + day: 27, + }, + DateCase { + year: 1374, + month: 12, + day: 6, + }, + // First day that the 2820-year rule fails + DateCase { + year: 1403, + month: 12, + day: 30, + }, + // First Nowruz that the 2820-year rule fails + DateCase { + year: 1404, + month: 1, + day: 1, + }, + DateCase { + year: 1417, + month: 8, + day: 19, + }, + // First day the unmodified astronomical algorithm fails + DateCase { + year: 1469, + month: 12, + day: 30, + }, + // First Nowruz the unmodified astronomical algorithm fails + DateCase { + year: 1470, + month: 1, + day: 1, + }, + DateCase { + year: 1473, + month: 4, + day: 28, + }, + // Last year the 33-year rule matches the modified astronomical calculation + DateCase { + year: 1501, + month: 12, + day: 29, + }, + DateCase { + year: 1502, + month: 12, + day: 29, + }, + DateCase { + year: 1503, + month: 1, + day: 1, + }, + DateCase { + year: 2988, + month: 1, + day: 1, + }, + ]; + + fn days_in_provided_year_core(year: i32) -> u16 { + let ny = + calendrical_calculations::persian::fixed_from_fast_persian(year, 1, 1).to_i64_date(); + let next_ny = calendrical_calculations::persian::fixed_from_fast_persian(year + 1, 1, 1) + .to_i64_date(); + + (next_ny - ny) as u16 + } + + #[test] + fn test_persian_leap_year() { + let mut leap_years: [i32; 21] = [0; 21]; + // These values were computed from the "Calendrical Calculations" reference code output + let expected_values = [ + false, false, true, false, true, false, false, false, false, true, false, true, false, + false, true, false, false, false, false, true, true, + ]; + + for (index, case) in CASES.iter().enumerate() { + leap_years[index] = case.year; + } + for (year, bool) in leap_years.iter().zip(expected_values.iter()) { + assert_eq!(Persian::provided_year_is_leap(*year), *bool); + } + } + + #[test] + fn days_in_provided_year_test() { + for case in CASES.iter() { + assert_eq!( + days_in_provided_year_core(case.year), + Persian::days_in_provided_year(case.year) + ); + } + } + + #[test] + fn test_rd_from_persian() { + for (case, f_date) in CASES.iter().zip(TEST_RD.iter()) { + let date = Date::try_new_persian(case.year, case.month, case.day).unwrap(); + + assert_eq!(date.to_rata_die().to_i64_date(), *f_date, "{case:?}"); + } + } + #[test] + fn test_persian_from_rd() { + for (case, f_date) in CASES.iter().zip(TEST_RD.iter()) { + let date = Date::try_new_persian(case.year, case.month, case.day).unwrap(); + assert_eq!( + Persian.from_rata_die(RataDie::new(*f_date)), + date.inner, + "{case:?}" + ); + } + } + + // From https://calendar.ut.ac.ir/Fa/News/Data/Doc/KabiseShamsi1206-1498-new.pdf + // Plain text version at https://github.com/roozbehp/persiancalendar/blob/main/kabise.txt + static CALENDAR_UT_AC_IR_TEST_DATA: [(i32, bool, i32, u8, u8); 293] = [ + (1206, false, 1827, 3, 22), + (1207, false, 1828, 3, 21), + (1208, false, 1829, 3, 21), + (1209, false, 1830, 3, 21), + (1210, true, 1831, 3, 21), + (1211, false, 1832, 3, 21), + (1212, false, 1833, 3, 21), + (1213, false, 1834, 3, 21), + (1214, true, 1835, 3, 21), + (1215, false, 1836, 3, 21), + (1216, false, 1837, 3, 21), + (1217, false, 1838, 3, 21), + (1218, true, 1839, 3, 21), + (1219, false, 1840, 3, 21), + (1220, false, 1841, 3, 21), + (1221, false, 1842, 3, 21), + (1222, true, 1843, 3, 21), + (1223, false, 1844, 3, 21), + (1224, false, 1845, 3, 21), + (1225, false, 1846, 3, 21), + (1226, true, 1847, 3, 21), + (1227, false, 1848, 3, 21), + (1228, false, 1849, 3, 21), + (1229, false, 1850, 3, 21), + (1230, true, 1851, 3, 21), + (1231, false, 1852, 3, 21), + (1232, false, 1853, 3, 21), + (1233, false, 1854, 3, 21), + (1234, true, 1855, 3, 21), + (1235, false, 1856, 3, 21), + (1236, false, 1857, 3, 21), + (1237, false, 1858, 3, 21), + (1238, true, 1859, 3, 21), + (1239, false, 1860, 3, 21), + (1240, false, 1861, 3, 21), + (1241, false, 1862, 3, 21), + (1242, false, 1863, 3, 21), + (1243, true, 1864, 3, 20), + (1244, false, 1865, 3, 21), + (1245, false, 1866, 3, 21), + (1246, false, 1867, 3, 21), + (1247, true, 1868, 3, 20), + (1248, false, 1869, 3, 21), + (1249, false, 1870, 3, 21), + (1250, false, 1871, 3, 21), + (1251, true, 1872, 3, 20), + (1252, false, 1873, 3, 21), + (1253, false, 1874, 3, 21), + (1254, false, 1875, 3, 21), + (1255, true, 1876, 3, 20), + (1256, false, 1877, 3, 21), + (1257, false, 1878, 3, 21), + (1258, false, 1879, 3, 21), + (1259, true, 1880, 3, 20), + (1260, false, 1881, 3, 21), + (1261, false, 1882, 3, 21), + (1262, false, 1883, 3, 21), + (1263, true, 1884, 3, 20), + (1264, false, 1885, 3, 21), + (1265, false, 1886, 3, 21), + (1266, false, 1887, 3, 21), + (1267, true, 1888, 3, 20), + (1268, false, 1889, 3, 21), + (1269, false, 1890, 3, 21), + (1270, false, 1891, 3, 21), + (1271, true, 1892, 3, 20), + (1272, false, 1893, 3, 21), + (1273, false, 1894, 3, 21), + (1274, false, 1895, 3, 21), + (1275, false, 1896, 3, 20), + (1276, true, 1897, 3, 20), + (1277, false, 1898, 3, 21), + (1278, false, 1899, 3, 21), + (1279, false, 1900, 3, 21), + (1280, true, 1901, 3, 21), + (1281, false, 1902, 3, 22), + (1282, false, 1903, 3, 22), + (1283, false, 1904, 3, 21), + (1284, true, 1905, 3, 21), + (1285, false, 1906, 3, 22), + (1286, false, 1907, 3, 22), + (1287, false, 1908, 3, 21), + (1288, true, 1909, 3, 21), + (1289, false, 1910, 3, 22), + (1290, false, 1911, 3, 22), + (1291, false, 1912, 3, 21), + (1292, true, 1913, 3, 21), + (1293, false, 1914, 3, 22), + (1294, false, 1915, 3, 22), + (1295, false, 1916, 3, 21), + (1296, true, 1917, 3, 21), + (1297, false, 1918, 3, 22), + (1298, false, 1919, 3, 22), + (1299, false, 1920, 3, 21), + (1300, true, 1921, 3, 21), + (1301, false, 1922, 3, 22), + (1302, false, 1923, 3, 22), + (1303, false, 1924, 3, 21), + (1304, true, 1925, 3, 21), + (1305, false, 1926, 3, 22), + (1306, false, 1927, 3, 22), + (1307, false, 1928, 3, 21), + (1308, false, 1929, 3, 21), + (1309, true, 1930, 3, 21), + (1310, false, 1931, 3, 22), + (1311, false, 1932, 3, 21), + (1312, false, 1933, 3, 21), + (1313, true, 1934, 3, 21), + (1314, false, 1935, 3, 22), + (1315, false, 1936, 3, 21), + (1316, false, 1937, 3, 21), + (1317, true, 1938, 3, 21), + (1318, false, 1939, 3, 22), + (1319, false, 1940, 3, 21), + (1320, false, 1941, 3, 21), + (1321, true, 1942, 3, 21), + (1322, false, 1943, 3, 22), + (1323, false, 1944, 3, 21), + (1324, false, 1945, 3, 21), + (1325, true, 1946, 3, 21), + (1326, false, 1947, 3, 22), + (1327, false, 1948, 3, 21), + (1328, false, 1949, 3, 21), + (1329, true, 1950, 3, 21), + (1330, false, 1951, 3, 22), + (1331, false, 1952, 3, 21), + (1332, false, 1953, 3, 21), + (1333, true, 1954, 3, 21), + (1334, false, 1955, 3, 22), + (1335, false, 1956, 3, 21), + (1336, false, 1957, 3, 21), + (1337, true, 1958, 3, 21), + (1338, false, 1959, 3, 22), + (1339, false, 1960, 3, 21), + (1340, false, 1961, 3, 21), + (1341, false, 1962, 3, 21), + (1342, true, 1963, 3, 21), + (1343, false, 1964, 3, 21), + (1344, false, 1965, 3, 21), + (1345, false, 1966, 3, 21), + (1346, true, 1967, 3, 21), + (1347, false, 1968, 3, 21), + (1348, false, 1969, 3, 21), + (1349, false, 1970, 3, 21), + (1350, true, 1971, 3, 21), + (1351, false, 1972, 3, 21), + (1352, false, 1973, 3, 21), + (1353, false, 1974, 3, 21), + (1354, true, 1975, 3, 21), + (1355, false, 1976, 3, 21), + (1356, false, 1977, 3, 21), + (1357, false, 1978, 3, 21), + (1358, true, 1979, 3, 21), + (1359, false, 1980, 3, 21), + (1360, false, 1981, 3, 21), + (1361, false, 1982, 3, 21), + (1362, true, 1983, 3, 21), + (1363, false, 1984, 3, 21), + (1364, false, 1985, 3, 21), + (1365, false, 1986, 3, 21), + (1366, true, 1987, 3, 21), + (1367, false, 1988, 3, 21), + (1368, false, 1989, 3, 21), + (1369, false, 1990, 3, 21), + (1370, true, 1991, 3, 21), + (1371, false, 1992, 3, 21), + (1372, false, 1993, 3, 21), + (1373, false, 1994, 3, 21), + (1374, false, 1995, 3, 21), + (1375, true, 1996, 3, 20), + (1376, false, 1997, 3, 21), + (1377, false, 1998, 3, 21), + (1378, false, 1999, 3, 21), + (1379, true, 2000, 3, 20), + (1380, false, 2001, 3, 21), + (1381, false, 2002, 3, 21), + (1382, false, 2003, 3, 21), + (1383, true, 2004, 3, 20), + (1384, false, 2005, 3, 21), + (1385, false, 2006, 3, 21), + (1386, false, 2007, 3, 21), + (1387, true, 2008, 3, 20), + (1388, false, 2009, 3, 21), + (1389, false, 2010, 3, 21), + (1390, false, 2011, 3, 21), + (1391, true, 2012, 3, 20), + (1392, false, 2013, 3, 21), + (1393, false, 2014, 3, 21), + (1394, false, 2015, 3, 21), + (1395, true, 2016, 3, 20), + (1396, false, 2017, 3, 21), + (1397, false, 2018, 3, 21), + (1398, false, 2019, 3, 21), + (1399, true, 2020, 3, 20), + (1400, false, 2021, 3, 21), + (1401, false, 2022, 3, 21), + (1402, false, 2023, 3, 21), + (1403, true, 2024, 3, 20), + (1404, false, 2025, 3, 21), + (1405, false, 2026, 3, 21), + (1406, false, 2027, 3, 21), + (1407, false, 2028, 3, 20), + (1408, true, 2029, 3, 20), + (1409, false, 2030, 3, 21), + (1410, false, 2031, 3, 21), + (1411, false, 2032, 3, 20), + (1412, true, 2033, 3, 20), + (1413, false, 2034, 3, 21), + (1414, false, 2035, 3, 21), + (1415, false, 2036, 3, 20), + (1416, true, 2037, 3, 20), + (1417, false, 2038, 3, 21), + (1418, false, 2039, 3, 21), + (1419, false, 2040, 3, 20), + (1420, true, 2041, 3, 20), + (1421, false, 2042, 3, 21), + (1422, false, 2043, 3, 21), + (1423, false, 2044, 3, 20), + (1424, true, 2045, 3, 20), + (1425, false, 2046, 3, 21), + (1426, false, 2047, 3, 21), + (1427, false, 2048, 3, 20), + (1428, true, 2049, 3, 20), + (1429, false, 2050, 3, 21), + (1430, false, 2051, 3, 21), + (1431, false, 2052, 3, 20), + (1432, true, 2053, 3, 20), + (1433, false, 2054, 3, 21), + (1434, false, 2055, 3, 21), + (1435, false, 2056, 3, 20), + (1436, true, 2057, 3, 20), + (1437, false, 2058, 3, 21), + (1438, false, 2059, 3, 21), + (1439, false, 2060, 3, 20), + (1440, false, 2061, 3, 20), + (1441, true, 2062, 3, 20), + (1442, false, 2063, 3, 21), + (1443, false, 2064, 3, 20), + (1444, false, 2065, 3, 20), + (1445, true, 2066, 3, 20), + (1446, false, 2067, 3, 21), + (1447, false, 2068, 3, 20), + (1448, false, 2069, 3, 20), + (1449, true, 2070, 3, 20), + (1450, false, 2071, 3, 21), + (1451, false, 2072, 3, 20), + (1452, false, 2073, 3, 20), + (1453, true, 2074, 3, 20), + (1454, false, 2075, 3, 21), + (1455, false, 2076, 3, 20), + (1456, false, 2077, 3, 20), + (1457, true, 2078, 3, 20), + (1458, false, 2079, 3, 21), + (1459, false, 2080, 3, 20), + (1460, false, 2081, 3, 20), + (1461, true, 2082, 3, 20), + (1462, false, 2083, 3, 21), + (1463, false, 2084, 3, 20), + (1464, false, 2085, 3, 20), + (1465, true, 2086, 3, 20), + (1466, false, 2087, 3, 21), + (1467, false, 2088, 3, 20), + (1468, false, 2089, 3, 20), + (1469, true, 2090, 3, 20), + (1470, false, 2091, 3, 21), + (1471, false, 2092, 3, 20), + (1472, false, 2093, 3, 20), + (1473, false, 2094, 3, 20), + (1474, true, 2095, 3, 20), + (1475, false, 2096, 3, 20), + (1476, false, 2097, 3, 20), + (1477, false, 2098, 3, 20), + (1478, true, 2099, 3, 20), + (1479, false, 2100, 3, 21), + (1480, false, 2101, 3, 21), + (1481, false, 2102, 3, 21), + (1482, true, 2103, 3, 21), + (1483, false, 2104, 3, 21), + (1484, false, 2105, 3, 21), + (1485, false, 2106, 3, 21), + (1486, true, 2107, 3, 21), + (1487, false, 2108, 3, 21), + (1488, false, 2109, 3, 21), + (1489, false, 2110, 3, 21), + (1490, true, 2111, 3, 21), + (1491, false, 2112, 3, 21), + (1492, false, 2113, 3, 21), + (1493, false, 2114, 3, 21), + (1494, true, 2115, 3, 21), + (1495, false, 2116, 3, 21), + (1496, false, 2117, 3, 21), + (1497, false, 2118, 3, 21), + (1498, true, 2119, 3, 21), + ]; + + #[test] + fn test_calendar_ut_ac_ir_data() { + for (p_year, leap, iso_year, iso_month, iso_day) in CALENDAR_UT_AC_IR_TEST_DATA.iter() { + assert_eq!(Persian::provided_year_is_leap(*p_year), *leap); + let persian_date = Date::try_new_persian(*p_year, 1, 1).unwrap(); + let iso_date = persian_date.to_calendar(Iso); + assert_eq!(iso_date.era_year().year, *iso_year); + assert_eq!(iso_date.month().ordinal, *iso_month); + assert_eq!(iso_date.day_of_month().0, *iso_day); + } + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/roc.rs b/deps/crates/vendor/icu_calendar/src/cal/roc.rs new file mode 100644 index 00000000000000..1c81c0a2646620 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/roc.rs @@ -0,0 +1,443 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains types and implementations for the Republic of China calendar. +//! +//! ```rust +//! use icu::calendar::{cal::Roc, Date}; +//! +//! let date_iso = Date::try_new_iso(1970, 1, 2) +//! .expect("Failed to initialize ISO Date instance."); +//! let date_roc = Date::new_from_iso(date_iso, Roc); +//! +//! assert_eq!(date_roc.era_year().year, 59); +//! assert_eq!(date_roc.month().ordinal, 1); +//! assert_eq!(date_roc.day_of_month().0, 2); +//! ``` + +use crate::error::year_check; +use crate::{ + cal::iso::IsoDateInner, calendar_arithmetic::ArithmeticDate, error::DateError, types, Calendar, + Date, Iso, RangeError, +}; +use calendrical_calculations::rata_die::RataDie; +use tinystr::tinystr; + +/// Year of the beginning of the Taiwanese (ROC/Minguo) calendar. +/// 1912 ISO = ROC 1 +const ROC_ERA_OFFSET: i32 = 1911; + +/// The [Republic of China Calendar](https://en.wikipedia.org/wiki/Republic_of_China_calendar) +/// +/// The ROC calendar is a solar calendar used in Taiwan and Penghu, as well as by overseas diaspora from +/// those locations. Months and days are identical to the [`Gregorian`](super::Gregorian) calendar, while years are counted +/// with 1912, the year of the establishment of the Republic of China, as year 1 of the ROC/Minguo/民国/民國 era. +/// +/// The ROC calendar should not be confused with the Chinese traditional lunar calendar +/// (see [`Chinese`](crate::cal::Chinese)). +/// +/// # Era codes +/// +/// This calendar uses two era codes: `roc`, corresponding to years in the 民國 era (CE year 1912 and +/// after), and `broc`, corresponding to years before the 民國 era (CE year 1911 and before). +/// +/// +/// # Month codes +/// +/// This calendar supports 12 solar month codes (`"M01" - "M12"`) +#[derive(Copy, Clone, Debug, Default)] +#[allow(clippy::exhaustive_structs)] // this type is stable +pub struct Roc; + +/// The inner date type used for representing [`Date`]s of [`Roc`]. See [`Date`] and [`Roc`] for more info. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +pub struct RocDateInner(IsoDateInner); + +impl crate::cal::scaffold::UnstableSealed for Roc {} +impl Calendar for Roc { + type DateInner = RocDateInner; + type Year = types::EraYear; + + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: crate::types::MonthCode, + day: u8, + ) -> Result { + let year = match era { + Some("roc") | None => ROC_ERA_OFFSET + year_check(year, 1..)?, + Some("broc") => ROC_ERA_OFFSET + 1 - year_check(year, 1..)?, + Some(_) => return Err(DateError::UnknownEra), + }; + + ArithmeticDate::new_from_codes(self, year, month_code, day) + .map(IsoDateInner) + .map(RocDateInner) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + RocDateInner(Iso.from_rata_die(rd)) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + Iso.to_rata_die(&date.0) + } + + fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner { + RocDateInner(iso) + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + date.0 + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + Iso.months_in_year(&date.0) + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + Iso.days_in_year(&date.0) + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + Iso.days_in_month(&date.0) + } + + fn offset_date(&self, date: &mut Self::DateInner, offset: crate::DateDuration) { + Iso.offset_date(&mut date.0, offset.cast_unit()) + } + + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + _calendar2: &Self, + largest_unit: crate::DateDurationUnit, + smallest_unit: crate::DateDurationUnit, + ) -> crate::DateDuration { + Iso.until(&date1.0, &date2.0, &Iso, largest_unit, smallest_unit) + .cast_unit() + } + + fn debug_name(&self) -> &'static str { + "ROC" + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + let extended_year = self.extended_year(date); + if extended_year > 0 { + types::EraYear { + era: tinystr!(16, "roc"), + era_index: Some(1), + year: extended_year, + ambiguity: types::YearAmbiguity::CenturyRequired, + } + } else { + types::EraYear { + era: tinystr!(16, "broc"), + era_index: Some(0), + year: 1 - extended_year, + ambiguity: types::YearAmbiguity::EraAndCenturyRequired, + } + } + } + + fn extended_year(&self, date: &Self::DateInner) -> i32 { + Iso.extended_year(&date.0) - ROC_ERA_OFFSET + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + Iso.is_in_leap_year(&date.0) + } + + fn month(&self, date: &Self::DateInner) -> crate::types::MonthInfo { + Iso.month(&date.0) + } + + fn day_of_month(&self, date: &Self::DateInner) -> crate::types::DayOfMonth { + Iso.day_of_month(&date.0) + } + + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + Iso.day_of_year(&date.0) + } + + fn calendar_algorithm(&self) -> Option { + Some(crate::preferences::CalendarAlgorithm::Roc) + } +} + +impl Date { + /// Construct a new Republic of China calendar Date. + /// + /// Years are specified in the "roc" era. This function accepts an extended year in that era, so dates + /// before Minguo are negative and year 0 is 1 Before Minguo. To specify dates using explicit era + /// codes, use [`Date::try_new_from_codes()`]. + /// + /// ```rust + /// use icu::calendar::Date; + /// use icu::calendar::cal::Gregorian; + /// use tinystr::tinystr; + /// + /// // Create a new ROC Date + /// let date_roc = Date::try_new_roc(1, 2, 3) + /// .expect("Failed to initialize ROC Date instance."); + /// + /// assert_eq!(date_roc.era_year().era, tinystr!(16, "roc")); + /// assert_eq!(date_roc.era_year().year, 1, "ROC year check failed!"); + /// assert_eq!(date_roc.month().ordinal, 2, "ROC month check failed!"); + /// assert_eq!(date_roc.day_of_month().0, 3, "ROC day of month check failed!"); + /// + /// // Convert to an equivalent Gregorian date + /// let date_gregorian = date_roc.to_calendar(Gregorian); + /// + /// assert_eq!(date_gregorian.era_year().year, 1912, "Gregorian from ROC year check failed!"); + /// assert_eq!(date_gregorian.month().ordinal, 2, "Gregorian from ROC month check failed!"); + /// assert_eq!(date_gregorian.day_of_month().0, 3, "Gregorian from ROC day of month check failed!"); + pub fn try_new_roc(year: i32, month: u8, day: u8) -> Result, RangeError> { + let iso_year = year.saturating_add(ROC_ERA_OFFSET); + Date::try_new_iso(iso_year, month, day).map(|d| Date::new_from_iso(d, Roc)) + } +} + +#[cfg(test)] +mod test { + + use super::*; + use calendrical_calculations::rata_die::RataDie; + + #[derive(Debug)] + struct TestCase { + rd: RataDie, + iso_year: i32, + iso_month: u8, + iso_day: u8, + expected_year: i32, + expected_era: &'static str, + expected_month: u8, + expected_day: u8, + } + + fn check_test_case(case: TestCase) { + let iso_from_rd = Date::from_rata_die(case.rd, Iso); + let roc_from_rd = Date::from_rata_die(case.rd, Roc); + assert_eq!( + roc_from_rd.era_year().year, + case.expected_year, + "Failed year check from RD: {case:?}\nISO: {iso_from_rd:?}\nROC: {roc_from_rd:?}" + ); + assert_eq!( + roc_from_rd.era_year().era, + case.expected_era, + "Failed era check from RD: {case:?}\nISO: {iso_from_rd:?}\nROC: {roc_from_rd:?}" + ); + assert_eq!( + roc_from_rd.extended_year(), + if case.expected_era == "roc" { + case.expected_year + } else { + 1 - case.expected_year + }, + "Failed year check from RD: {case:?}\nISO: {iso_from_rd:?}\nROC: {roc_from_rd:?}" + ); + assert_eq!( + roc_from_rd.month().ordinal, + case.expected_month, + "Failed month check from RD: {case:?}\nISO: {iso_from_rd:?}\nROC: {roc_from_rd:?}" + ); + assert_eq!(roc_from_rd.day_of_month().0, case.expected_day, + "Failed day_of_month check from RD: {case:?}\nISO: {iso_from_rd:?}\nROC: {roc_from_rd:?}"); + + let iso_from_case = Date::try_new_iso(case.iso_year, case.iso_month, case.iso_day) + .expect("Failed to initialize ISO date for {case:?}"); + let roc_from_case = Date::new_from_iso(iso_from_case, Roc); + assert_eq!(iso_from_rd, iso_from_case, + "ISO from RD not equal to ISO generated from manually-input ymd\nCase: {case:?}\nRD: {iso_from_rd:?}\nManual: {iso_from_case:?}"); + assert_eq!(roc_from_rd, roc_from_case, + "ROC date from RD not equal to ROC generated from manually-input ymd\nCase: {case:?}\nRD: {roc_from_rd:?}\nManual: {roc_from_case:?}"); + } + + #[test] + fn test_roc_current_era() { + // Tests that the ROC calendar gives the correct expected day, month, and year for years >= 1912 + // (years in the ROC/minguo era) + // + // Jan 1. 1912 CE = RD 697978 + + let cases = [ + TestCase { + rd: RataDie::new(697978), + iso_year: 1912, + iso_month: 1, + iso_day: 1, + expected_year: 1, + expected_era: "roc", + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: RataDie::new(698037), + iso_year: 1912, + iso_month: 2, + iso_day: 29, + expected_year: 1, + expected_era: "roc", + expected_month: 2, + expected_day: 29, + }, + TestCase { + rd: RataDie::new(698524), + iso_year: 1913, + iso_month: 6, + iso_day: 30, + expected_year: 2, + expected_era: "roc", + expected_month: 6, + expected_day: 30, + }, + TestCase { + rd: RataDie::new(738714), + iso_year: 2023, + iso_month: 7, + iso_day: 13, + expected_year: 112, + expected_era: "roc", + expected_month: 7, + expected_day: 13, + }, + ]; + + for case in cases { + check_test_case(case); + } + } + + #[test] + fn test_roc_prior_era() { + // Tests that the ROC calendar gives the correct expected day, month, and year for years <= 1911 + // (years in the ROC/minguo era) + // + // Jan 1. 1912 CE = RD 697978 + let cases = [ + TestCase { + rd: RataDie::new(697977), + iso_year: 1911, + iso_month: 12, + iso_day: 31, + expected_year: 1, + expected_era: "broc", + expected_month: 12, + expected_day: 31, + }, + TestCase { + rd: RataDie::new(697613), + iso_year: 1911, + iso_month: 1, + iso_day: 1, + expected_year: 1, + expected_era: "broc", + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: RataDie::new(697612), + iso_year: 1910, + iso_month: 12, + iso_day: 31, + expected_year: 2, + expected_era: "broc", + expected_month: 12, + expected_day: 31, + }, + TestCase { + rd: RataDie::new(696576), + iso_year: 1908, + iso_month: 2, + iso_day: 29, + expected_year: 4, + expected_era: "broc", + expected_month: 2, + expected_day: 29, + }, + TestCase { + rd: RataDie::new(1), + iso_year: 1, + iso_month: 1, + iso_day: 1, + expected_year: 1911, + expected_era: "broc", + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: RataDie::new(0), + iso_year: 0, + iso_month: 12, + iso_day: 31, + expected_year: 1912, + expected_era: "broc", + expected_month: 12, + expected_day: 31, + }, + ]; + + for case in cases { + check_test_case(case); + } + } + + #[test] + fn test_roc_directionality_near_epoch() { + // Tests that for a large range of RDs near the beginning of the minguo era (CE 1912), + // the comparison between those two RDs should be equal to the comparison between their + // corresponding YMD. + let rd_epoch_start = 697978; + for i in (rd_epoch_start - 100)..=(rd_epoch_start + 100) { + for j in (rd_epoch_start - 100)..=(rd_epoch_start + 100) { + let iso_i = Date::from_rata_die(RataDie::new(i), Iso); + let iso_j = Date::from_rata_die(RataDie::new(j), Iso); + + let roc_i = Date::from_rata_die(RataDie::new(i), Roc); + let roc_j = Date::from_rata_die(RataDie::new(j), Roc); + + assert_eq!( + i.cmp(&j), + iso_i.cmp(&iso_j), + "ISO directionality inconsistent with directionality for i: {i}, j: {j}" + ); + assert_eq!( + i.cmp(&j), + roc_i.cmp(&roc_j), + "ROC directionality inconsistent with directionality for i: {i}, j: {j}" + ); + } + } + } + + #[test] + fn test_roc_directionality_near_rd_zero() { + // Same as `test_directionality_near_epoch`, but with a focus around RD 0 + for i in -100..=100 { + for j in -100..100 { + let iso_i = Date::from_rata_die(RataDie::new(i), Iso); + let iso_j = Date::from_rata_die(RataDie::new(j), Iso); + + let roc_i = Date::from_rata_die(RataDie::new(i), Roc); + let roc_j = Date::from_rata_die(RataDie::new(j), Roc); + + assert_eq!( + i.cmp(&j), + iso_i.cmp(&iso_j), + "ISO directionality inconsistent with directionality for i: {i}, j: {j}" + ); + assert_eq!( + i.cmp(&j), + roc_i.cmp(&roc_j), + "ROC directionality inconsistent with directionality for i: {i}, j: {j}" + ); + } + } + } +} diff --git a/deps/crates/vendor/icu_calendar/src/calendar.rs b/deps/crates/vendor/icu_calendar/src/calendar.rs new file mode 100644 index 00000000000000..5b0ea851d1388e --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/calendar.rs @@ -0,0 +1,105 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use calendrical_calculations::rata_die::RataDie; + +use crate::cal::iso::IsoDateInner; +use crate::error::DateError; +use crate::{types, DateDuration, DateDurationUnit}; +use core::fmt; + +/// A calendar implementation +/// +/// Only implementors of [`Calendar`] should care about these methods, in general users of +/// these calendars should use the methods on [`Date`](crate::Date) instead. +/// +/// Individual [`Calendar`] implementations may have inherent utility methods +/// allowing for direct construction, etc. +/// +///
+/// 🚫 This trait is sealed; it should not be implemented by user code. If an API requests an item that implements this +/// trait, please consider using a type from the implementors listed below. +/// +/// It is still possible to implement this trait in userland (since `UnstableSealed` is public), +/// do not do so unless you are prepared for things to occasionally break. +///
+pub trait Calendar: crate::cal::scaffold::UnstableSealed { + /// The internal type used to represent dates + type DateInner: Eq + Copy + fmt::Debug; + /// The type of YearInfo returned by the date + type Year: fmt::Debug + Into; + + /// Construct a date from era/month codes and fields + /// + /// The year is extended_year if no era is provided + #[allow(clippy::wrong_self_convention)] + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result; + + /// Construct the date from an ISO date + #[allow(clippy::wrong_self_convention)] + fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner; + /// Obtain an ISO date from this date + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner; + + /// Construct the date from a [`RataDie`] + #[allow(clippy::wrong_self_convention)] + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner; + /// Obtain a [`RataDie`] from this date + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie; + + /// Count the number of months in a given year, specified by providing a date + /// from that year + fn months_in_year(&self, date: &Self::DateInner) -> u8; + /// Count the number of days in a given year, specified by providing a date + /// from that year + fn days_in_year(&self, date: &Self::DateInner) -> u16; + /// Count the number of days in a given month, specified by providing a date + /// from that year/month + fn days_in_month(&self, date: &Self::DateInner) -> u8; + /// Calculate if a date is in a leap year + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool; + + /// Information about the year + fn year_info(&self, date: &Self::DateInner) -> Self::Year; + /// The extended year value + fn extended_year(&self, date: &Self::DateInner) -> i32; + /// The calendar-specific month represented by `date` + fn month(&self, date: &Self::DateInner) -> types::MonthInfo; + /// The calendar-specific day-of-month represented by `date` + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth; + /// Information of the day of the year + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear; + + #[doc(hidden)] // unstable + /// Add `offset` to `date` + fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration); + #[doc(hidden)] // unstable + /// Calculate `date2 - date` as a duration + /// + /// `calendar2` is the calendar object associated with `date2`. In case the specific calendar objects + /// differ on data, the data for the first calendar is used, and `date2` may be converted if necessary. + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + calendar2: &Self, + largest_unit: DateDurationUnit, + smallest_unit: DateDurationUnit, + ) -> DateDuration; + + /// Returns the [`CalendarAlgorithm`](crate::preferences::CalendarAlgorithm) that is required to match + /// when parsing into this calendar. + /// + /// If left empty, any algorithm will parse successfully. + fn calendar_algorithm(&self) -> Option; + + /// Obtain a name for the calendar for debug printing + fn debug_name(&self) -> &'static str; +} diff --git a/deps/crates/vendor/icu_calendar/src/calendar_arithmetic.rs b/deps/crates/vendor/icu_calendar/src/calendar_arithmetic.rs new file mode 100644 index 00000000000000..fc1da7d8c6823a --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/calendar_arithmetic.rs @@ -0,0 +1,427 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::error::DateError; +use crate::types::DayOfYear; +use crate::{types, Calendar, DateDuration, DateDurationUnit, RangeError}; +use core::cmp::Ordering; +use core::convert::TryInto; +use core::fmt::Debug; +use core::hash::{Hash, Hasher}; +use core::marker::PhantomData; +use tinystr::tinystr; + +#[derive(Debug)] +#[allow(clippy::exhaustive_structs)] // this type is stable +pub(crate) struct ArithmeticDate { + pub year: C::YearInfo, + /// 1-based month of year + pub month: u8, + /// 1-based day of month + pub day: u8, + marker: PhantomData, +} + +// Manual impls since the derive will introduce a C: Trait bound +// and only the year value should be compared +impl Copy for ArithmeticDate {} +impl Clone for ArithmeticDate { + fn clone(&self) -> Self { + *self + } +} + +impl PartialEq for ArithmeticDate { + fn eq(&self, other: &Self) -> bool { + self.year.into() == other.year.into() && self.month == other.month && self.day == other.day + } +} + +impl Eq for ArithmeticDate {} + +impl Ord for ArithmeticDate { + fn cmp(&self, other: &Self) -> Ordering { + self.year + .into() + .cmp(&other.year.into()) + .then(self.month.cmp(&other.month)) + .then(self.day.cmp(&other.day)) + } +} + +impl PartialOrd for ArithmeticDate { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Hash for ArithmeticDate { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.year.into().hash(state); + self.month.hash(state); + self.day.hash(state); + } +} + +/// Maximum number of iterations when iterating through the days of a month; can be increased if necessary +#[allow(dead_code)] // TODO: Remove dead code tag after use +pub(crate) const MAX_ITERS_FOR_DAYS_OF_MONTH: u8 = 33; + +pub(crate) trait CalendarArithmetic: Calendar { + /// This stores the year as either an i32, or a type containing more + /// useful computational information. + type YearInfo: Copy + Debug + Into; + + // TODO(#3933): potentially make these methods take &self instead, and absorb certain y/m parameters + // based on usage patterns (e.g month_days is only ever called with self.year) + fn days_in_provided_month(year: Self::YearInfo, month: u8) -> u8; + fn months_in_provided_year(year: Self::YearInfo) -> u8; + fn provided_year_is_leap(year: Self::YearInfo) -> bool; + fn last_month_day_in_provided_year(year: Self::YearInfo) -> (u8, u8); + + /// Calculate the days in a given year + /// Can be overridden with simpler implementations for solar calendars + /// (typically, 366 in leap, 365 otherwise) Leave this as the default + /// for lunar calendars + /// + /// The name has `provided` in it to avoid clashes with Calendar + fn days_in_provided_year(year: Self::YearInfo) -> u16 { + let months_in_year = Self::months_in_provided_year(year); + let mut days: u16 = 0; + for month in 1..=months_in_year { + days += Self::days_in_provided_month(year, month) as u16; + } + days + } +} + +pub(crate) trait PrecomputedDataSource { + /// Given a calendar year, load (or compute) the YearInfo for it + /// + /// In the future we may pass in an optional previous YearInfo alongside the year + /// it matches to allow code to take shortcuts. + fn load_or_compute_info(&self, year: i32) -> YearInfo; +} + +impl PrecomputedDataSource for () { + fn load_or_compute_info(&self, year: i32) -> i32 { + year + } +} + +impl ArithmeticDate { + /// Create a new `ArithmeticDate` without checking that `month` and `day` are in bounds. + #[inline] + pub const fn new_unchecked(year: C::YearInfo, month: u8, day: u8) -> Self { + ArithmeticDate { + year, + month, + day, + marker: PhantomData, + } + } + + #[inline] + pub fn min_date() -> Self + where + C: CalendarArithmetic, + { + ArithmeticDate { + year: i32::MIN, + month: 1, + day: 1, + marker: PhantomData, + } + } + + #[inline] + pub fn max_date() -> Self + where + C: CalendarArithmetic, + { + let year = i32::MAX; + let (month, day) = C::last_month_day_in_provided_year(year); + ArithmeticDate { + year: i32::MAX, + month, + day, + marker: PhantomData, + } + } + + #[inline] + fn offset_days(&mut self, mut day_offset: i32, data: &impl PrecomputedDataSource) { + while day_offset != 0 { + let month_days = C::days_in_provided_month(self.year, self.month); + if self.day as i32 + day_offset > month_days as i32 { + self.offset_months(1, data); + day_offset -= month_days as i32; + } else if self.day as i32 + day_offset < 1 { + self.offset_months(-1, data); + day_offset += C::days_in_provided_month(self.year, self.month) as i32; + } else { + self.day = (self.day as i32 + day_offset) as u8; + day_offset = 0; + } + } + } + + #[inline] + fn offset_months( + &mut self, + mut month_offset: i32, + data: &impl PrecomputedDataSource, + ) { + while month_offset != 0 { + let year_months = C::months_in_provided_year(self.year); + if self.month as i32 + month_offset > year_months as i32 { + self.year = data.load_or_compute_info(self.year.into() + 1); + month_offset -= year_months as i32; + } else if self.month as i32 + month_offset < 1 { + self.year = data.load_or_compute_info(self.year.into() - 1); + month_offset += C::months_in_provided_year(self.year) as i32; + } else { + self.month = (self.month as i32 + month_offset) as u8; + month_offset = 0 + } + } + } + + #[inline] + pub fn offset_date( + &mut self, + offset: DateDuration, + data: &impl PrecomputedDataSource, + ) { + if offset.years != 0 { + // For offset_date to work with lunar calendars, need to handle an edge case where the original month is not valid in the future year. + self.year = data.load_or_compute_info(self.year.into() + offset.years); + } + + self.offset_months(offset.months, data); + + let day_offset = offset.days + offset.weeks * 7 + self.day as i32 - 1; + self.day = 1; + self.offset_days(day_offset, data); + } + + #[inline] + pub fn until( + &self, + date2: ArithmeticDate, + _largest_unit: DateDurationUnit, + _smaller_unit: DateDurationUnit, + ) -> DateDuration { + // This simple implementation does not need C::PrecomputedDataSource right now, but it + // likely will once we've written a proper implementation + DateDuration::new( + self.year.into() - date2.year.into(), + self.month as i32 - date2.month as i32, + 0, + self.day as i32 - date2.day as i32, + ) + } + + #[inline] + pub fn days_in_year(&self) -> u16 { + C::days_in_provided_year(self.year) + } + + #[inline] + pub fn months_in_year(&self) -> u8 { + C::months_in_provided_year(self.year) + } + + #[inline] + pub fn days_in_month(&self) -> u8 { + C::days_in_provided_month(self.year, self.month) + } + + #[inline] + pub fn date_from_year_day(year: i32, year_day: u32) -> ArithmeticDate + where + C: CalendarArithmetic, + { + let mut month = 1; + let mut day = year_day as i32; + while month <= C::months_in_provided_year(year) { + let month_days = C::days_in_provided_month(year, month) as i32; + if day <= month_days { + break; + } else { + day -= month_days; + month += 1; + } + } + + debug_assert!(day <= C::days_in_provided_month(year, month) as i32); + #[allow(clippy::unwrap_used)] + // The day is expected to be within the range of month_days of C + ArithmeticDate { + year, + month, + day: day.try_into().unwrap_or(1), + marker: PhantomData, + } + } + + #[inline] + pub fn day_of_month(&self) -> types::DayOfMonth { + types::DayOfMonth(self.day) + } + + #[inline] + pub fn day_of_year(&self) -> DayOfYear { + let mut day_of_year = 0; + for month in 1..self.month { + day_of_year += C::days_in_provided_month(self.year, month) as u16; + } + DayOfYear(day_of_year + (self.day as u16)) + } + + pub fn extended_year(&self) -> i32 { + self.year.into() + } + + /// The [`types::MonthInfo`] for the current month (with month code) for a solar calendar + /// Lunar calendars should not use this method and instead manually implement a month code + /// resolver. + /// Originally "solar_month" but renamed because it can be used for some lunar calendars + /// + /// Returns "und" if run with months that are out of bounds for the current + /// calendar. + #[inline] + pub fn month(&self) -> types::MonthInfo { + let code = match self.month { + a if a > C::months_in_provided_year(self.year) => tinystr!(4, "und"), + 1 => tinystr!(4, "M01"), + 2 => tinystr!(4, "M02"), + 3 => tinystr!(4, "M03"), + 4 => tinystr!(4, "M04"), + 5 => tinystr!(4, "M05"), + 6 => tinystr!(4, "M06"), + 7 => tinystr!(4, "M07"), + 8 => tinystr!(4, "M08"), + 9 => tinystr!(4, "M09"), + 10 => tinystr!(4, "M10"), + 11 => tinystr!(4, "M11"), + 12 => tinystr!(4, "M12"), + 13 => tinystr!(4, "M13"), + _ => tinystr!(4, "und"), + }; + types::MonthInfo { + ordinal: self.month, + standard_code: types::MonthCode(code), + formatting_code: types::MonthCode(code), + } + } + + /// Construct a new arithmetic date from a year, month code, and day, bounds checking + /// the month and day + /// Originally (new_from_solar_codes) but renamed because it works for some lunar calendars + pub fn new_from_codes( + // Separate type since the debug_name() impl may differ when DateInner types + // are nested (e.g. in GregorianDateInner) + _cal: &C2, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result + where + C: CalendarArithmetic, + { + let month = if let Some((ordinal, false)) = month_code.parsed() { + ordinal + } else { + return Err(DateError::UnknownMonthCode(month_code)); + }; + + if month > C::months_in_provided_year(year) { + return Err(DateError::UnknownMonthCode(month_code)); + } + + let max_day = C::days_in_provided_month(year, month); + if day == 0 || day > max_day { + return Err(DateError::Range { + field: "day", + value: day as i32, + min: 1, + max: max_day as i32, + }); + } + + Ok(Self::new_unchecked(year, month, day)) + } + + /// Construct a new arithmetic date from a year, month ordinal, and day, bounds checking + /// the month and day + pub fn new_from_ordinals(year: C::YearInfo, month: u8, day: u8) -> Result { + let max_month = C::months_in_provided_year(year); + if month == 0 || month > max_month { + return Err(RangeError { + field: "month", + value: month as i32, + min: 1, + max: max_month as i32, + }); + } + let max_day = C::days_in_provided_month(year, month); + if day == 0 || day > max_day { + return Err(RangeError { + field: "day", + value: day as i32, + min: 1, + max: max_day as i32, + }); + } + + Ok(Self::new_unchecked(year, month, day)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::cal::Iso; + + #[test] + fn test_ord() { + let dates_in_order = [ + ArithmeticDate::::new_unchecked(-10, 1, 1), + ArithmeticDate::::new_unchecked(-10, 1, 2), + ArithmeticDate::::new_unchecked(-10, 2, 1), + ArithmeticDate::::new_unchecked(-1, 1, 1), + ArithmeticDate::::new_unchecked(-1, 1, 2), + ArithmeticDate::::new_unchecked(-1, 2, 1), + ArithmeticDate::::new_unchecked(0, 1, 1), + ArithmeticDate::::new_unchecked(0, 1, 2), + ArithmeticDate::::new_unchecked(0, 2, 1), + ArithmeticDate::::new_unchecked(1, 1, 1), + ArithmeticDate::::new_unchecked(1, 1, 2), + ArithmeticDate::::new_unchecked(1, 2, 1), + ArithmeticDate::::new_unchecked(10, 1, 1), + ArithmeticDate::::new_unchecked(10, 1, 2), + ArithmeticDate::::new_unchecked(10, 2, 1), + ]; + for (i, i_date) in dates_in_order.iter().enumerate() { + for (j, j_date) in dates_in_order.iter().enumerate() { + let result1 = i_date.cmp(j_date); + let result2 = j_date.cmp(i_date); + assert_eq!(result1.reverse(), result2); + assert_eq!(i.cmp(&j), i_date.cmp(j_date)); + } + } + } + + #[test] + pub fn zero() { + use crate::Date; + Date::try_new_iso(2024, 0, 1).unwrap_err(); + Date::try_new_iso(2024, 1, 0).unwrap_err(); + Date::try_new_iso(2024, 0, 0).unwrap_err(); + } +} diff --git a/deps/crates/vendor/icu_calendar/src/date.rs b/deps/crates/vendor/icu_calendar/src/date.rs new file mode 100644 index 00000000000000..5c4c0cf5d9fcab --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/date.rs @@ -0,0 +1,524 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::any_calendar::{AnyCalendar, IntoAnyCalendar}; +use crate::calendar_arithmetic::CalendarArithmetic; +use crate::error::DateError; +use crate::types::{CyclicYear, EraYear, IsoWeekOfYear}; +use crate::week::{RelativeUnit, WeekCalculator, WeekOf}; +use crate::{types, Calendar, DateDuration, DateDurationUnit, Iso}; +#[cfg(feature = "alloc")] +use alloc::rc::Rc; +#[cfg(feature = "alloc")] +use alloc::sync::Arc; +use calendrical_calculations::rata_die::RataDie; +use core::fmt; +use core::ops::Deref; + +/// Types that contain a calendar +/// +/// This allows one to use [`Date`] with wrappers around calendars, +/// e.g. reference counted calendars. +pub trait AsCalendar { + /// The calendar being wrapped + type Calendar: Calendar; + /// Obtain the inner calendar + fn as_calendar(&self) -> &Self::Calendar; +} + +impl AsCalendar for C { + type Calendar = C; + #[inline] + fn as_calendar(&self) -> &Self { + self + } +} + +#[cfg(feature = "alloc")] +impl AsCalendar for Rc { + type Calendar = C::Calendar; + #[inline] + fn as_calendar(&self) -> &Self::Calendar { + self.as_ref().as_calendar() + } +} + +#[cfg(feature = "alloc")] +impl AsCalendar for Arc { + type Calendar = C::Calendar; + #[inline] + fn as_calendar(&self) -> &Self::Calendar { + self.as_ref().as_calendar() + } +} + +/// This exists as a wrapper around `&'a T` so that +/// `Date<&'a C>` is possible for calendar `C`. +/// +/// Unfortunately, +/// [`AsCalendar`] cannot be implemented on `&'a T` directly because +/// `&'a T` is `#[fundamental]` and the impl would clash with the one above with +/// `AsCalendar` for `C: Calendar`. +/// +/// Use `Date>` where you would use `Date<&'a C>` +#[allow(clippy::exhaustive_structs)] // newtype +#[derive(PartialEq, Eq, Debug)] +pub struct Ref<'a, C>(pub &'a C); + +impl Copy for Ref<'_, C> {} + +impl Clone for Ref<'_, C> { + fn clone(&self) -> Self { + *self + } +} + +impl AsCalendar for Ref<'_, C> { + type Calendar = C::Calendar; + #[inline] + fn as_calendar(&self) -> &Self::Calendar { + self.0.as_calendar() + } +} + +impl Deref for Ref<'_, C> { + type Target = C; + fn deref(&self) -> &C { + self.0 + } +} + +/// A date for a given calendar. +/// +/// **The primary definition of this type is in the [`icu_calendar`](https://docs.rs/icu_calendar) crate. Other ICU4X crates re-export it for convenience.** +/// +/// This can work with wrappers around [`Calendar`] types, +/// e.g. `Rc`, via the [`AsCalendar`] trait. +/// +/// This can be constructed constructed +/// from its fields via [`Self::try_new_from_codes()`], or can be constructed with one of the +/// `new__date()` per-calendar methods (and then freely converted between calendars). +/// +/// ```rust +/// use icu::calendar::Date; +/// +/// // Example: creation of ISO date from integers. +/// let date_iso = Date::try_new_iso(1970, 1, 2) +/// .expect("Failed to initialize ISO Date instance."); +/// +/// assert_eq!(date_iso.era_year().year, 1970); +/// assert_eq!(date_iso.month().ordinal, 1); +/// assert_eq!(date_iso.day_of_month().0, 2); +/// ``` +pub struct Date { + pub(crate) inner: ::DateInner, + pub(crate) calendar: A, +} + +impl Date
{ + /// Construct a date from from era/month codes and fields, and some calendar representation + /// + /// The year is `extended_year` if no era is provided + #[inline] + pub fn try_new_from_codes( + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + calendar: A, + ) -> Result { + let inner = calendar + .as_calendar() + .from_codes(era, year, month_code, day)?; + Ok(Date { inner, calendar }) + } + + /// Construct a date from a [`RataDie`] and some calendar representation + #[inline] + pub fn from_rata_die(rd: RataDie, calendar: A) -> Self { + Date { + inner: calendar.as_calendar().from_rata_die(rd), + calendar, + } + } + + /// Convert the date to a [`RataDie`] + #[inline] + pub fn to_rata_die(&self) -> RataDie { + self.calendar.as_calendar().to_rata_die(self.inner()) + } + + /// Construct a date from an ISO date and some calendar representation + #[inline] + pub fn new_from_iso(iso: Date, calendar: A) -> Self { + let inner = calendar.as_calendar().from_iso(iso.inner); + Date { inner, calendar } + } + + /// Convert the Date to an ISO Date + #[inline] + pub fn to_iso(&self) -> Date { + Date::from_raw(self.calendar.as_calendar().to_iso(self.inner()), Iso) + } + + /// Convert the Date to a date in a different calendar + #[inline] + pub fn to_calendar(&self, calendar: A2) -> Date { + Date::new_from_iso(self.to_iso(), calendar) + } + + /// The number of months in the year of this date + #[inline] + pub fn months_in_year(&self) -> u8 { + self.calendar.as_calendar().months_in_year(self.inner()) + } + + /// The number of days in the year of this date + #[inline] + pub fn days_in_year(&self) -> u16 { + self.calendar.as_calendar().days_in_year(self.inner()) + } + + /// The number of days in the month of this date + #[inline] + pub fn days_in_month(&self) -> u8 { + self.calendar.as_calendar().days_in_month(self.inner()) + } + + /// The day of the week for this date + #[inline] + pub fn day_of_week(&self) -> types::Weekday { + self.to_rata_die().into() + } + + /// Add a `duration` to this date, mutating it + #[doc(hidden)] // unstable + #[inline] + pub fn add(&mut self, duration: DateDuration) { + self.calendar + .as_calendar() + .offset_date(&mut self.inner, duration) + } + + /// Add a `duration` to this date, returning the new one + #[doc(hidden)] // unstable + #[inline] + pub fn added(mut self, duration: DateDuration) -> Self { + self.add(duration); + self + } + + /// Calculating the duration between `other - self` + #[doc(hidden)] // unstable + #[inline] + pub fn until>( + &self, + other: &Date, + largest_unit: DateDurationUnit, + smallest_unit: DateDurationUnit, + ) -> DateDuration { + self.calendar.as_calendar().until( + self.inner(), + other.inner(), + other.calendar.as_calendar(), + largest_unit, + smallest_unit, + ) + } + + /// The calendar-specific year-info. + /// + /// This returns an enum, see [`Date::era_year()`] and [`Date::cyclic_year()`] which are available + /// for concrete calendar types and return concrete types. + #[inline] + pub fn year(&self) -> types::YearInfo { + self.calendar.as_calendar().year_info(&self.inner).into() + } + + /// The "extended year", typically anchored with year 1 as the year 1 of either the most modern or + /// otherwise some "major" era for the calendar + /// + /// See [`Self::year()`] for more information about the year. + #[inline] + pub fn extended_year(&self) -> i32 { + self.calendar.as_calendar().extended_year(&self.inner) + } + + /// Returns whether `self` is in a calendar-specific leap year + #[inline] + pub fn is_in_leap_year(&self) -> bool { + self.calendar.as_calendar().is_in_leap_year(&self.inner) + } + + /// The calendar-specific month represented by `self` + #[inline] + pub fn month(&self) -> types::MonthInfo { + self.calendar.as_calendar().month(&self.inner) + } + + /// The calendar-specific day-of-month represented by `self` + #[inline] + pub fn day_of_month(&self) -> types::DayOfMonth { + self.calendar.as_calendar().day_of_month(&self.inner) + } + + /// The calendar-specific day-of-month represented by `self` + #[inline] + pub fn day_of_year(&self) -> types::DayOfYear { + self.calendar.as_calendar().day_of_year(&self.inner) + } + + /// Construct a date from raw values for a given calendar. This does not check any + /// invariants for the date and calendar, and should only be called by calendar implementations. + /// + /// Calling this outside of calendar implementations is sound, but calendar implementations are not + /// expected to do anything sensible with such invalid dates. + /// + /// AnyCalendar *will* panic if AnyCalendar [`Date`] objects with mismatching + /// date and calendar types are constructed + #[inline] + pub fn from_raw(inner: ::DateInner, calendar: A) -> Self { + Self { inner, calendar } + } + + /// Get the inner date implementation. Should not be called outside of calendar implementations + #[inline] + pub fn inner(&self) -> &::DateInner { + &self.inner + } + + /// Get a reference to the contained calendar + #[inline] + pub fn calendar(&self) -> &A::Calendar { + self.calendar.as_calendar() + } + + /// Get a reference to the contained calendar wrapper + /// + /// (Useful in case the user wishes to e.g. clone an Rc) + #[inline] + pub fn calendar_wrapper(&self) -> &A { + &self.calendar + } +} + +impl, C: Calendar> Date { + /// Returns information about the era for calendars using eras. + pub fn era_year(&self) -> EraYear { + self.calendar.as_calendar().year_info(self.inner()) + } +} + +impl, C: Calendar> Date { + /// Returns information about the year cycle, for cyclic calendars. + pub fn cyclic_year(&self) -> CyclicYear { + self.calendar.as_calendar().year_info(self.inner()) + } +} + +impl Date { + /// The ISO week of the year containing this date. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::types::IsoWeekOfYear; + /// use icu::calendar::Date; + /// + /// let date = Date::try_new_iso(2022, 8, 26).unwrap(); + /// + /// assert_eq!( + /// date.week_of_year(), + /// IsoWeekOfYear { + /// week_number: 34, + /// iso_year: 2022, + /// } + /// ); + /// ``` + pub fn week_of_year(&self) -> IsoWeekOfYear { + let week_of = WeekCalculator::ISO + .week_of( + Iso::days_in_provided_year(self.inner.0.year.saturating_sub(1)), + self.days_in_year(), + self.day_of_year().0, + self.day_of_week(), + ) + .unwrap_or_else(|_| { + // ISO calendar has more than 14 days per year + debug_assert!(false); + WeekOf { + week: 1, + unit: crate::week::RelativeUnit::Current, + } + }); + + IsoWeekOfYear { + week_number: week_of.week, + iso_year: match week_of.unit { + RelativeUnit::Current => self.inner.0.year, + RelativeUnit::Next => self.inner.0.year.saturating_add(1), + RelativeUnit::Previous => self.inner.0.year.saturating_sub(1), + }, + } + } +} + +impl Date { + /// Type-erase the date, converting it to a date for [`AnyCalendar`] + pub fn to_any(self) -> Date { + Date::from_raw( + self.calendar.date_to_any(&self.inner), + self.calendar.to_any(), + ) + } +} + +impl Date { + /// Wrap the contained calendar type in `Rc`, making it cheaper to clone. + /// + /// Useful when paired with [`Self::to_any()`] to obtain a `Date>` + #[cfg(feature = "alloc")] + pub fn into_ref_counted(self) -> Date> { + Date::from_raw(self.inner, Rc::new(self.calendar)) + } + + /// Wrap the contained calendar type in `Arc`, making it cheaper to clone in a thread-safe manner. + /// + /// Useful when paired with [`Self::to_any()`] to obtain a `Date>` + #[cfg(feature = "alloc")] + pub fn into_atomic_ref_counted(self) -> Date> { + Date::from_raw(self.inner, Arc::new(self.calendar)) + } + + /// Wrap the calendar type in `Ref`, making it cheaper to clone (by introducing a borrow) + /// + /// Useful for converting a `&Date` into an equivalent `Date` without cloning + /// the calendar. + pub fn as_borrowed(&self) -> Date> { + Date::from_raw(self.inner, Ref(&self.calendar)) + } +} + +impl PartialEq> for Date +where + C: Calendar, + A: AsCalendar, + B: AsCalendar, +{ + fn eq(&self, other: &Date) -> bool { + self.inner.eq(&other.inner) + } +} + +impl Eq for Date {} + +impl PartialOrd> for Date +where + C: Calendar, + C::DateInner: PartialOrd, + A: AsCalendar, + B: AsCalendar, +{ + fn partial_cmp(&self, other: &Date) -> Option { + self.inner.partial_cmp(&other.inner) + } +} + +impl Ord for Date +where + C: Calendar, + C::DateInner: Ord, + A: AsCalendar, +{ + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.inner.cmp(&other.inner) + } +} + +impl fmt::Debug for Date { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + let month = self.month().ordinal; + let day = self.day_of_month().0; + let calendar = self.calendar.as_calendar().debug_name(); + match self.year() { + types::YearInfo::Era(EraYear { year, era, .. }) => { + write!( + f, + "Date({year}-{month}-{day}, {era} era, for calendar {calendar})" + ) + } + types::YearInfo::Cyclic(CyclicYear { year, related_iso }) => { + write!( + f, + "Date({year}-{month}-{day}, ISO year {related_iso}, for calendar {calendar})" + ) + } + } + } +} + +impl Clone for Date { + fn clone(&self) -> Self { + Self { + inner: self.inner, + calendar: self.calendar.clone(), + } + } +} + +impl Copy for Date where A: AsCalendar + Copy {} + +#[cfg(test)] +mod tests { + use super::*; + use crate::types::Weekday; + + #[test] + fn test_ord() { + let dates_in_order = [ + Date::try_new_iso(-10, 1, 1).unwrap(), + Date::try_new_iso(-10, 1, 2).unwrap(), + Date::try_new_iso(-10, 2, 1).unwrap(), + Date::try_new_iso(-1, 1, 1).unwrap(), + Date::try_new_iso(-1, 1, 2).unwrap(), + Date::try_new_iso(-1, 2, 1).unwrap(), + Date::try_new_iso(0, 1, 1).unwrap(), + Date::try_new_iso(0, 1, 2).unwrap(), + Date::try_new_iso(0, 2, 1).unwrap(), + Date::try_new_iso(1, 1, 1).unwrap(), + Date::try_new_iso(1, 1, 2).unwrap(), + Date::try_new_iso(1, 2, 1).unwrap(), + Date::try_new_iso(10, 1, 1).unwrap(), + Date::try_new_iso(10, 1, 2).unwrap(), + Date::try_new_iso(10, 2, 1).unwrap(), + ]; + for (i, i_date) in dates_in_order.iter().enumerate() { + for (j, j_date) in dates_in_order.iter().enumerate() { + let result1 = i_date.cmp(j_date); + let result2 = j_date.cmp(i_date); + assert_eq!(result1.reverse(), result2); + assert_eq!(i.cmp(&j), i_date.cmp(j_date)); + } + } + } + + #[test] + fn test_day_of_week() { + // June 23, 2021 is a Wednesday + assert_eq!( + Date::try_new_iso(2021, 6, 23).unwrap().day_of_week(), + Weekday::Wednesday, + ); + // Feb 2, 1983 was a Wednesday + assert_eq!( + Date::try_new_iso(1983, 2, 2).unwrap().day_of_week(), + Weekday::Wednesday, + ); + // Jan 21, 2021 was a Tuesday + assert_eq!( + Date::try_new_iso(2020, 1, 21).unwrap().day_of_week(), + Weekday::Tuesday, + ); + } +} diff --git a/deps/crates/vendor/icu_calendar/src/duration.rs b/deps/crates/vendor/icu_calendar/src/duration.rs new file mode 100644 index 00000000000000..b8f21743d1460a --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/duration.rs @@ -0,0 +1,158 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::Calendar; +use core::fmt; +use core::marker::PhantomData; + +/// A duration between two dates +/// +/// Can be used to perform date arithmetic +/// +/// # Example +/// +/// ```rust +/// use icu::calendar::{types::Weekday, Date, DateDuration, DateDurationUnit}; +/// +/// // Creating ISO date: 1992-09-02. +/// let mut date_iso = Date::try_new_iso(1992, 9, 2) +/// .expect("Failed to initialize ISO Date instance."); +/// +/// assert_eq!(date_iso.day_of_week(), Weekday::Wednesday); +/// assert_eq!(date_iso.era_year().year, 1992); +/// assert_eq!(date_iso.month().ordinal, 9); +/// assert_eq!(date_iso.day_of_month().0, 2); +/// +/// // Answering questions about days in month and year. +/// assert_eq!(date_iso.days_in_year(), 366); +/// assert_eq!(date_iso.days_in_month(), 30); +/// +/// // Advancing date in-place by 1 year, 2 months, 3 weeks, 4 days. +/// date_iso.add(DateDuration::new(1, 2, 3, 4)); +/// assert_eq!(date_iso.era_year().year, 1993); +/// assert_eq!(date_iso.month().ordinal, 11); +/// assert_eq!(date_iso.day_of_month().0, 27); +/// +/// // Reverse date advancement. +/// date_iso.add(DateDuration::new(-1, -2, -3, -4)); +/// assert_eq!(date_iso.era_year().year, 1992); +/// assert_eq!(date_iso.month().ordinal, 9); +/// assert_eq!(date_iso.day_of_month().0, 2); +/// +/// // Creating ISO date: 2022-01-30. +/// let newer_date_iso = Date::try_new_iso(2022, 1, 30) +/// .expect("Failed to initialize ISO Date instance."); +/// +/// // Comparing dates: 2022-01-30 and 1992-09-02. +/// let duration = newer_date_iso.until( +/// &date_iso, +/// DateDurationUnit::Years, +/// DateDurationUnit::Days, +/// ); +/// assert_eq!(duration.years, 30); +/// assert_eq!(duration.months, -8); +/// assert_eq!(duration.days, 28); +/// +/// // Create new date with date advancement. Reassign to new variable. +/// let mutated_date_iso = date_iso.added(DateDuration::new(1, 2, 3, 4)); +/// assert_eq!(mutated_date_iso.era_year().year, 1993); +/// assert_eq!(mutated_date_iso.month().ordinal, 11); +/// assert_eq!(mutated_date_iso.day_of_month().0, 27); +/// ``` +/// +/// Currently unstable for ICU4X 1.0 +#[derive(Eq, PartialEq)] +#[allow(clippy::exhaustive_structs)] // this type should be stable (and is intended to be constructed manually) +#[doc(hidden)] // unstable +pub struct DateDuration { + /// The number of years + pub years: i32, + /// The number of months + pub months: i32, + /// The number of weeks + pub weeks: i32, + /// The number of days + pub days: i32, + /// A marker for the calendar + pub marker: PhantomData, +} + +// Custom impl so that C need not be bound on Copy/Clone +impl Clone for DateDuration { + fn clone(&self) -> Self { + *self + } +} + +// Custom impl so that C need not be bound on Copy/Clone +impl Copy for DateDuration {} + +/// A "duration unit" used to specify the minimum or maximum duration of time to +/// care about +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +#[allow(clippy::exhaustive_enums)] // this type should be stable +#[doc(hidden)] // unstable +pub enum DateDurationUnit { + /// Duration in years + Years, + /// Duration in months + Months, + /// Duration in weeks + Weeks, + /// Duration in days + Days, +} + +impl Default for DateDuration { + fn default() -> Self { + Self { + years: 0, + months: 0, + weeks: 0, + days: 0, + marker: PhantomData, + } + } +} + +impl DateDuration { + /// Construct a DateDuration + /// + /// ```rust + /// # use icu::calendar::*; + /// // two years, three months, and five days + /// let duration: DateDuration = DateDuration::new(2, 3, 0, 5); + /// ``` + pub fn new(years: i32, months: i32, weeks: i32, days: i32) -> Self { + DateDuration { + years, + months, + weeks, + days, + marker: PhantomData, + } + } + + /// Explicitly cast duration to one for a different calendar + pub fn cast_unit(self) -> DateDuration { + DateDuration { + years: self.years, + months: self.months, + days: self.days, + weeks: self.weeks, + marker: PhantomData, + } + } +} + +impl fmt::Debug for DateDuration { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.debug_struct("DateDuration") + .field("years", &self.years) + .field("months", &self.months) + .field("weeks", &self.weeks) + .field("days", &self.days) + .finish() + } +} diff --git a/deps/crates/vendor/icu_calendar/src/error.rs b/deps/crates/vendor/icu_calendar/src/error.rs new file mode 100644 index 00000000000000..2e050a93a3f04a --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/error.rs @@ -0,0 +1,92 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::types::MonthCode; +use displaydoc::Display; + +#[derive(Debug, Copy, Clone, PartialEq, Display)] +/// Error type for date creation. +#[non_exhaustive] +pub enum DateError { + /// A field is out of range for its domain. + #[displaydoc("The {field} = {value} argument is out of range {min}..={max}")] + Range { + /// The field that is out of range, such as "year" + field: &'static str, + /// The actual value + value: i32, + /// The minimum value (inclusive). This might not be tight. + min: i32, + /// The maximum value (inclusive). This might not be tight. + max: i32, + }, + /// Unknown era + #[displaydoc("Unknown era")] + UnknownEra, + /// Unknown month code + #[displaydoc("Unknown month code {0:?}")] + UnknownMonthCode(MonthCode), +} + +impl core::error::Error for DateError {} + +#[derive(Debug, Copy, Clone, PartialEq, Display)] +/// An argument is out of range for its domain. +#[displaydoc("The {field} = {value} argument is out of range {min}..={max}")] +#[allow(clippy::exhaustive_structs)] +pub struct RangeError { + /// The argument that is out of range, such as "year" + pub field: &'static str, + /// The actual value + pub value: i32, + /// The minimum value (inclusive). This might not be tight. + pub min: i32, + /// The maximum value (inclusive). This might not be tight. + pub max: i32, +} + +impl core::error::Error for RangeError {} + +impl From for DateError { + fn from(value: RangeError) -> Self { + let RangeError { + field, + value, + min, + max, + } = value; + DateError::Range { + field, + value, + min, + max, + } + } +} + +pub(crate) fn year_check( + year: i32, + bounds: impl core::ops::RangeBounds, +) -> Result { + use core::ops::Bound::*; + + if !bounds.contains(&year) { + return Err(RangeError { + field: "year", + value: year, + min: match bounds.start_bound() { + Included(&m) => m, + Excluded(&m) => m + 1, + Unbounded => i32::MIN, + }, + max: match bounds.end_bound() { + Included(&m) => m, + Excluded(&m) => m - 1, + Unbounded => i32::MAX, + }, + }); + } + + Ok(year) +} diff --git a/deps/crates/vendor/icu_calendar/src/ixdtf.rs b/deps/crates/vendor/icu_calendar/src/ixdtf.rs new file mode 100644 index 00000000000000..0256dcd6c40eb6 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/ixdtf.rs @@ -0,0 +1,120 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use core::str::FromStr; + +use crate::{AsCalendar, Calendar, Date, Iso, RangeError}; +use icu_locale_core::preferences::extensions::unicode::keywords::CalendarAlgorithm; +use ixdtf::parsers::records::IxdtfParseRecord; +use ixdtf::parsers::IxdtfParser; +use ixdtf::ParseError as Rfc9557Error; + +/// An error returned from parsing an RFC 9557 string to an `icu_calendar` type. +#[derive(Debug, displaydoc::Display)] +#[non_exhaustive] +pub enum ParseError { + /// Syntax error. + #[displaydoc("Syntax error in the RFC 9557 string: {0}")] + Syntax(Rfc9557Error), + /// Value is out of range. + #[displaydoc("Value out of range: {0}")] + Range(RangeError), + /// The RFC 9557 string is missing fields required for parsing into the chosen type. + MissingFields, + /// The RFC 9557 string specifies an unknown calendar. + UnknownCalendar, + /// Expected a different calendar. + #[displaydoc("Expected calendar {0:?} but found calendar {1:?}")] + MismatchedCalendar(CalendarAlgorithm, CalendarAlgorithm), +} + +impl From for ParseError { + fn from(value: RangeError) -> Self { + Self::Range(value) + } +} + +impl From for ParseError { + fn from(value: Rfc9557Error) -> Self { + Self::Syntax(value) + } +} + +impl FromStr for Date { + type Err = ParseError; + fn from_str(rfc_9557_str: &str) -> Result { + Self::try_from_str(rfc_9557_str, Iso) + } +} + +impl Date { + /// Creates a [`Date`] in the given calendar from an RFC 9557 string. + /// + /// Returns an error if the string has a calendar annotation that does not + /// match the calendar argument, unless the argument is [`Iso`]. + /// + /// ✨ *Enabled with the `ixdtf` Cargo feature.* + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::{Date, Gregorian}; + /// + /// let date = Date::try_from_str("2024-07-17", Gregorian).unwrap(); + /// let date = + /// Date::try_from_str("2024-07-17[u-ca=gregory]", Gregorian).unwrap(); + /// let _ = + /// Date::try_from_str("2024-07-17[u-ca=hebrew]", Gregorian).unwrap_err(); + /// + /// assert_eq!(date.era_year().year, 2024); + /// assert_eq!( + /// date.month().standard_code, + /// icu::calendar::types::MonthCode(tinystr::tinystr!(4, "M07")) + /// ); + /// assert_eq!(date.day_of_month().0, 17); + /// ``` + pub fn try_from_str(rfc_9557_str: &str, calendar: A) -> Result { + Self::try_from_utf8(rfc_9557_str.as_bytes(), calendar) + } + + /// Creates a [`Date`] in the given calendar from an RFC 9557 string. + /// + /// Returns an error if the string has a calendar annotation that does not + /// match the calendar argument. + /// + /// See [`Self::try_from_str()`]. + /// + /// ✨ *Enabled with the `ixdtf` Cargo feature.* + pub fn try_from_utf8(rfc_9557_str: &[u8], calendar: A) -> Result { + let ixdtf_record = IxdtfParser::from_utf8(rfc_9557_str).parse()?; + Self::try_from_ixdtf_record(&ixdtf_record, calendar) + } + + #[doc(hidden)] + pub fn try_from_ixdtf_record( + ixdtf_record: &IxdtfParseRecord, + calendar: A, + ) -> Result { + let date_record = ixdtf_record.date.ok_or(ParseError::MissingFields)?; + let iso = Date::try_new_iso(date_record.year, date_record.month, date_record.day)?; + + if let Some(ixdtf_calendar) = ixdtf_record.calendar { + if let Some(expected_calendar) = calendar.as_calendar().calendar_algorithm() { + if let Some(parsed_calendar) = + icu_locale_core::extensions::unicode::Value::try_from_utf8(ixdtf_calendar) + .ok() + .and_then(|v| CalendarAlgorithm::try_from(&v).ok()) + { + if parsed_calendar != expected_calendar { + return Err(ParseError::MismatchedCalendar( + expected_calendar, + parsed_calendar, + )); + } + } + } + } + Ok(iso.to_calendar(calendar)) + } +} diff --git a/deps/crates/vendor/icu_calendar/src/lib.rs b/deps/crates/vendor/icu_calendar/src/lib.rs new file mode 100644 index 00000000000000..77d5a4b46aeadf --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/lib.rs @@ -0,0 +1,140 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! Types for dealing with dates and custom calendars. +//! +//! This module is published as its own crate ([`icu_calendar`](https://docs.rs/icu_calendar/latest/icu_calendar/)) +//! and as part of the [`icu`](https://docs.rs/icu/latest/icu/) crate. See the latter for more details on the ICU4X project. +//! The [`types`] module has a lot of common types for dealing with dates. +//! +//! [`Calendar`] is a trait that allows one to define custom calendars, and [`Date`] +//! can represent dates for arbitrary calendars. +//! +//! The [`Iso`] and [`Gregorian`] types are implementations for the ISO and +//! Gregorian calendars respectively. Further calendars can be found in the [`cal`] module. +//! +//! Most interaction with this crate will be done via the [`Date`] type. +//! +//! Some of the algorithms implemented here are based on +//! Dershowitz, Nachum, and Edward M. Reingold. _Calendrical calculations_. Cambridge University Press, 2008. +//! with associated Lisp code found at . +//! +//! # Examples +//! +//! Examples of date manipulation using `Date` object. `Date` objects are useful +//! for working with dates, encompassing information about the day, month, year, +//! as well as the calendar type. +//! +//! ```rust +//! use icu::calendar::{types::Weekday, Date}; +//! +//! // Creating ISO date: 1992-09-02. +//! let mut date_iso = Date::try_new_iso(1992, 9, 2) +//! .expect("Failed to initialize ISO Date instance."); +//! +//! assert_eq!(date_iso.day_of_week(), Weekday::Wednesday); +//! assert_eq!(date_iso.era_year().year, 1992); +//! assert_eq!(date_iso.month().ordinal, 9); +//! assert_eq!(date_iso.day_of_month().0, 2); +//! +//! // Answering questions about days in month and year. +//! assert_eq!(date_iso.days_in_year(), 366); +//! assert_eq!(date_iso.days_in_month(), 30); +//! ``` +//! +//! Example of converting an ISO date across Indian and Buddhist calendars. +//! +//! ```rust +//! use icu::calendar::cal::{Buddhist, Indian}; +//! use icu::calendar::Date; +//! +//! // Creating ISO date: 1992-09-02. +//! let mut date_iso = Date::try_new_iso(1992, 9, 2) +//! .expect("Failed to initialize ISO Date instance."); +//! +//! assert_eq!(date_iso.era_year().year, 1992); +//! assert_eq!(date_iso.month().ordinal, 9); +//! assert_eq!(date_iso.day_of_month().0, 2); +//! +//! // Conversion into Indian calendar: 1914-08-02. +//! let date_indian = date_iso.to_calendar(Indian); +//! assert_eq!(date_indian.era_year().year, 1914); +//! assert_eq!(date_indian.month().ordinal, 6); +//! assert_eq!(date_indian.day_of_month().0, 11); +//! +//! // Conversion into Buddhist calendar: 2535-09-02. +//! let date_buddhist = date_iso.to_calendar(Buddhist); +//! assert_eq!(date_buddhist.era_year().year, 2535); +//! assert_eq!(date_buddhist.month().ordinal, 9); +//! assert_eq!(date_buddhist.day_of_month().0, 2); +//! ``` +//! +//! [`ICU4X`]: ../icu/index.html + +// https://github.com/unicode-org/icu4x/blob/main/documents/process/boilerplate.md#library-annotations +#![cfg_attr(not(any(test, doc)), no_std)] +#![cfg_attr( + not(test), + deny( + clippy::indexing_slicing, + clippy::unwrap_used, + clippy::expect_used, + clippy::panic, + clippy::exhaustive_structs, + clippy::exhaustive_enums, + clippy::trivially_copy_pass_by_ref, + missing_debug_implementations, + ) +)] +#![warn(missing_docs)] + +#[cfg(feature = "alloc")] +extern crate alloc; + +// Make sure inherent docs go first +mod date; + +// Public modules +mod any_calendar; +pub mod cal; +pub mod provider; +pub mod types; +pub mod week; + +mod calendar; +mod calendar_arithmetic; +mod duration; +mod error; +#[cfg(feature = "ixdtf")] +mod ixdtf; + +// Top-level types +pub use any_calendar::IntoAnyCalendar; +pub use calendar::Calendar; +pub use date::{AsCalendar, Date, Ref}; +#[doc(hidden)] // unstable +pub use duration::{DateDuration, DateDurationUnit}; +pub use error::{DateError, RangeError}; +#[cfg(feature = "ixdtf")] +pub use ixdtf::ParseError; + +// Reexports +#[doc(no_inline)] +pub use cal::{AnyCalendar, AnyCalendarKind, Gregorian, Iso}; + +/// Locale preferences used by this crate +pub mod preferences { + pub use crate::any_calendar::CalendarPreferences; + #[doc(inline)] + /// **This is a reexport of a type in [`icu::locale`](icu_locale_core::preferences::extensions::unicode::keywords)**. + #[doc = "\n"] // prevent autoformatting + pub use icu_locale_core::preferences::extensions::unicode::keywords::CalendarAlgorithm; + #[doc(inline)] + /// **This is a reexport of a type in [`icu::locale`](icu_locale_core::preferences::extensions::unicode::keywords)**. + #[doc = "\n"] // prevent autoformatting + pub use icu_locale_core::preferences::extensions::unicode::keywords::HijriCalendarAlgorithm; +} + +#[cfg(test)] +mod tests; diff --git a/deps/crates/vendor/icu_calendar/src/provider.rs b/deps/crates/vendor/icu_calendar/src/provider.rs new file mode 100644 index 00000000000000..71e7369abfd360 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/provider.rs @@ -0,0 +1,342 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! 🚧 \[Unstable\] Data provider struct definitions for this ICU4X component. +//! +//!
+//! 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, +//! including in SemVer minor releases. While the serde representation of data structs is guaranteed +//! to be stable, their Rust representation might not be. Use with caution. +//!
+//! +//! Read more about data providers: [`icu_provider`] + +// Provider structs must be stable +#![allow(clippy::exhaustive_structs, clippy::exhaustive_enums)] + +pub mod chinese_based; +pub mod hijri; +pub use chinese_based::{CalendarChineseV1, CalendarDangiV1}; +pub use hijri::CalendarHijriSimulatedMeccaV1; + +use crate::types::Weekday; +use icu_provider::fallback::{LocaleFallbackConfig, LocaleFallbackPriority}; +use icu_provider::prelude::*; +use tinystr::TinyStr16; +use zerovec::ZeroVec; + +#[cfg(feature = "compiled_data")] +#[derive(Debug)] +/// Baked data +/// +///
+/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, +/// including in SemVer minor releases. In particular, the `DataProvider` implementations are only +/// guaranteed to match with this version's `*_unstable` providers. Use with caution. +///
+pub struct Baked; + +#[cfg(feature = "compiled_data")] +#[allow(unused_imports)] +const _: () = { + use icu_calendar_data::*; + pub mod icu { + pub use crate as calendar; + pub use icu_locale as locale; + } + make_provider!(Baked); + impl_calendar_chinese_v1!(Baked); + impl_calendar_dangi_v1!(Baked); + impl_calendar_hijri_simulated_mecca_v1!(Baked); + impl_calendar_japanese_modern_v1!(Baked); + impl_calendar_japanese_extended_v1!(Baked); + impl_calendar_week_v1!(Baked); +}; + +icu_provider::data_marker!( + /// Modern Japanese era names + CalendarJapaneseModernV1, + "calendar/japanese/modern/v1", + JapaneseEras<'static>, + is_singleton = true +); +icu_provider::data_marker!( + /// Full Japanese era names + CalendarJapaneseExtendedV1, + "calendar/japanese/extended/v1", + JapaneseEras<'static>, + is_singleton = true +); +icu_provider::data_marker!( + /// Week information + CalendarWeekV1, + "calendar/week/v1", + WeekData, + fallback_config = { + let mut config = LocaleFallbackConfig::default(); + config.priority = LocaleFallbackPriority::Region; + config + }, +); + +#[cfg(feature = "datagen")] +/// The latest minimum set of markers required by this component. +pub const MARKERS: &[DataMarkerInfo] = &[ + CalendarChineseV1::INFO, + CalendarDangiV1::INFO, + CalendarHijriSimulatedMeccaV1::INFO, + CalendarJapaneseModernV1::INFO, + CalendarJapaneseExtendedV1::INFO, + CalendarWeekV1::INFO, +]; + +/// The date at which an era started +/// +/// The order of fields in this struct is important! +/// +///
+/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, +/// including in SemVer minor releases. While the serde representation of data structs is guaranteed +/// to be stable, their Rust representation might not be. Use with caution. +///
+#[zerovec::make_ule(EraStartDateULE)] +#[derive( + Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, yoke::Yokeable, zerofrom::ZeroFrom, +)] +#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))] +#[cfg_attr(feature = "datagen", databake(path = icu_calendar::provider))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize))] +pub struct EraStartDate { + /// The year the era started in + pub year: i32, + /// The month the era started in + pub month: u8, + /// The day the era started in + pub day: u8, +} + +/// A data structure containing the necessary era data for constructing a +/// [`Japanese`](crate::cal::Japanese) calendar object +/// +///
+/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, +/// including in SemVer minor releases. While the serde representation of data structs is guaranteed +/// to be stable, their Rust representation might not be. Use with caution. +///
+#[derive(Debug, PartialEq, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)] +#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))] +#[cfg_attr(feature = "datagen", databake(path = icu_calendar::provider))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize))] +pub struct JapaneseEras<'data> { + /// A map from era start dates to their era codes + #[cfg_attr(feature = "serde", serde(borrow))] + pub dates_to_eras: ZeroVec<'data, (EraStartDate, TinyStr16)>, +} + +icu_provider::data_struct!( + JapaneseEras<'_>, + #[cfg(feature = "datagen")] +); + +/// An ICU4X mapping to a subset of CLDR weekData. +/// See CLDR-JSON's weekData.json for more context. +/// +///
+/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, +/// including in SemVer minor releases. While the serde representation of data structs is guaranteed +/// to be stable, their Rust representation might not be. Use with caution. +///
+#[derive(Clone, Copy, Debug, PartialEq, yoke::Yokeable, zerofrom::ZeroFrom)] +#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))] +#[cfg_attr(feature = "datagen", databake(path = icu_calendar::provider))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize))] +#[allow(clippy::exhaustive_structs)] // used in data provider +pub struct WeekData { + /// The first day of a week. + pub first_weekday: Weekday, + /// Bitset representing weekdays that are part of the 'weekend', for calendar purposes. + /// The number of days can be different between locales, and may not be contiguous. + pub weekend: WeekdaySet, +} + +icu_provider::data_struct!( + WeekData, + #[cfg(feature = "datagen")] +); + +/// Bitset representing weekdays. +// +// This Bitset uses an [u8] to represent the weekend, thus leaving one bit free. +// Each bit represents a day in the following order: +// +// ┌▷Mon +// │┌▷Tue +// ││┌▷Wed +// │││┌▷Thu +// ││││ ┌▷Fri +// ││││ │┌▷Sat +// ││││ ││┌▷Sun +// ││││ │││ +// 0b0000_1010 +// +// Please note that this is not a range, this are the discrete days representing a weekend. Other examples: +// 0b0101_1000 -> Tue, Thu, Fri +// 0b0000_0110 -> Sat, Sun +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct WeekdaySet(u8); + +impl WeekdaySet { + /// Returns whether the set contains the day. + pub const fn contains(&self, day: Weekday) -> bool { + self.0 & day.bit_value() != 0 + } +} + +impl WeekdaySet { + /// Creates a new [WeekdaySet] using the provided days. + pub const fn new(days: &[Weekday]) -> Self { + let mut i = 0; + let mut w = 0; + #[allow(clippy::indexing_slicing)] + while i < days.len() { + w |= days[i].bit_value(); + i += 1; + } + Self(w) + } +} + +impl Weekday { + /// Defines the bit order used for encoding and reading weekend days. + const fn bit_value(self) -> u8 { + match self { + Weekday::Monday => 1 << 6, + Weekday::Tuesday => 1 << 5, + Weekday::Wednesday => 1 << 4, + Weekday::Thursday => 1 << 3, + Weekday::Friday => 1 << 2, + Weekday::Saturday => 1 << 1, + Weekday::Sunday => 1 << 0, + } + } +} + +#[cfg(feature = "datagen")] +impl databake::Bake for WeekdaySet { + fn bake(&self, ctx: &databake::CrateEnv) -> databake::TokenStream { + ctx.insert("icu_calendar"); + let days = + crate::week::WeekdaySetIterator::new(Weekday::Monday, *self).map(|d| d.bake(ctx)); + databake::quote! { + icu_calendar::provider::WeekdaySet::new(&[#(#days),*]) + } + } +} + +#[cfg(feature = "datagen")] +impl databake::BakeSize for WeekdaySet { + fn borrows_size(&self) -> usize { + 0 + } +} + +#[cfg(feature = "datagen")] +impl serde::Serialize for WeekdaySet { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + if serializer.is_human_readable() { + use serde::ser::SerializeSeq; + + let mut seq = serializer.serialize_seq(None)?; + for day in crate::week::WeekdaySetIterator::new(Weekday::Monday, *self) { + seq.serialize_element(&day)?; + } + seq.end() + } else { + self.0.serialize(serializer) + } + } +} + +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for WeekdaySet { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + if deserializer.is_human_readable() { + use core::marker::PhantomData; + + struct Visitor<'de>(PhantomData<&'de ()>); + impl<'de> serde::de::Visitor<'de> for Visitor<'de> { + type Value = WeekdaySet; + fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::write!(f, "a sequence of Weekdays") + } + fn visit_seq>( + self, + mut seq: A, + ) -> Result { + let mut set = WeekdaySet::new(&[]); + while let Some(day) = seq.next_element::()? { + set.0 |= day.bit_value(); + } + Ok(set) + } + } + deserializer.deserialize_seq(Visitor(PhantomData)) + } else { + u8::deserialize(deserializer).map(Self) + } + } +} + +#[test] +fn test_weekdayset_bake() { + databake::test_bake!( + WeekdaySet, + const, + crate::provider::WeekdaySet::new(&[ + crate::types::Weekday::Monday, + crate::types::Weekday::Wednesday, + crate::types::Weekday::Friday + ]), + icu_calendar + ); +} + +#[test] +fn test_weekdayset_new() { + use Weekday::*; + + let sat_sun_bitmap = Saturday.bit_value() | Sunday.bit_value(); + let sat_sun_weekend = WeekdaySet::new(&[Saturday, Sunday]); + assert_eq!(sat_sun_bitmap, sat_sun_weekend.0); + + let fri_sat_bitmap = Friday.bit_value() | Saturday.bit_value(); + let fri_sat_weekend = WeekdaySet::new(&[Friday, Saturday]); + assert_eq!(fri_sat_bitmap, fri_sat_weekend.0); + + let fri_sun_bitmap = Friday.bit_value() | Sunday.bit_value(); + let fri_sun_weekend = WeekdaySet::new(&[Friday, Sunday]); + assert_eq!(fri_sun_bitmap, fri_sun_weekend.0); + + let fri_bitmap = Friday.bit_value(); + let fri_weekend = WeekdaySet::new(&[Friday, Friday]); + assert_eq!(fri_bitmap, fri_weekend.0); + + let sun_mon_bitmap = Sunday.bit_value() | Monday.bit_value(); + let sun_mon_weekend = WeekdaySet::new(&[Sunday, Monday]); + assert_eq!(sun_mon_bitmap, sun_mon_weekend.0); + + let mon_sun_bitmap = Monday.bit_value() | Sunday.bit_value(); + let mon_sun_weekend = WeekdaySet::new(&[Monday, Sunday]); + assert_eq!(mon_sun_bitmap, mon_sun_weekend.0); + + let mon_bitmap = Monday.bit_value(); + let mon_weekend = WeekdaySet::new(&[Monday]); + assert_eq!(mon_bitmap, mon_weekend.0); +} diff --git a/deps/crates/vendor/icu_calendar/src/provider/chinese_based.rs b/deps/crates/vendor/icu_calendar/src/provider/chinese_based.rs new file mode 100644 index 00000000000000..da6fbd372b069e --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/provider/chinese_based.rs @@ -0,0 +1,298 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! 🚧 \[Unstable\] Data provider struct definitions for chinese-based calendars. +//! +//!
+//! 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, +//! including in SemVer minor releases. While the serde representation of data structs is guaranteed +//! to be stable, their Rust representation might not be. Use with caution. +//!
+//! +//! Read more about data providers: [`icu_provider`] + +use icu_provider::prelude::*; +use zerovec::ule::{AsULE, ULE}; +use zerovec::ZeroVec; + +icu_provider::data_marker!( + /// Precomputed data for the Chinese calendar + CalendarChineseV1, + "calendar/chinese/v1", + ChineseBasedCache<'static>, + is_singleton = true +); +icu_provider::data_marker!( + /// Precomputed data for the Dangi calendar + CalendarDangiV1, + "calendar/dangi/v1", + ChineseBasedCache<'static>, + is_singleton = true +); + +/// Cached/precompiled data for a certain range of years for a chinese-based +/// calendar. Avoids the need to perform lunar calendar arithmetic for most calendrical +/// operations. +#[derive(Debug, PartialEq, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)] +#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))] +#[cfg_attr(feature = "datagen", databake(path = icu_calendar::provider::chinese_based))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize))] +pub struct ChineseBasedCache<'data> { + /// The ISO year corresponding to the first data entry for this year + pub first_related_iso_year: i32, + /// A list of precomputed data for each year beginning with first_related_iso_year + #[cfg_attr(feature = "serde", serde(borrow))] + pub data: ZeroVec<'data, PackedChineseBasedYearInfo>, +} + +icu_provider::data_struct!( + ChineseBasedCache<'_>, + #[cfg(feature = "datagen")] +); + +/// The struct containing compiled ChineseData +/// +/// Bit structure (little endian: note that shifts go in the opposite direction!) +/// +/// ```text +/// Bit: 0 1 2 3 4 5 6 7 +/// Byte 0: [ month lengths ............. +/// Byte 1: .. month lengths ] | [ leap month index .. +/// Byte 2: ] | [ NY offset ] | unused +/// ``` +/// +/// Where the New Year Offset is the offset from ISO Jan 21 of that year for Chinese New Year, +/// the month lengths are stored as 1 = 30, 0 = 29 for each month including the leap month. +/// The largest possible offset is 33, which requires 6 bits of storage. +/// +///
+/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, +/// including in SemVer minor releases. While the serde representation of data structs is guaranteed +/// to be stable, their Rust representation might not be. Use with caution. +///
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ULE)] +#[cfg_attr(feature = "datagen", derive(databake::Bake))] +#[cfg_attr(feature = "datagen", databake(path = icu_calendar::provider))] +#[repr(C, packed)] +pub struct PackedChineseBasedYearInfo(pub u8, pub u8, pub u8); + +impl PackedChineseBasedYearInfo { + /// The first day of the ISO year on which Chinese New Year may occur + /// + /// According to Reingold & Dershowitz, ch 19.6, Chinese New Year occurs on Jan 21 - Feb 21 inclusive. + /// + /// Chinese New Year in the year 30 AD is January 20 (30-01-20). + /// + /// We allow it to occur as early as January 19 which is the earliest the second new moon + /// could occur after the Winter Solstice if the solstice is pinned to December 20. + const FIRST_NY: i64 = 18; + + pub(crate) fn new( + month_lengths: [bool; 13], + leap_month_idx: Option, + ny_offset: i64, + ) -> Self { + debug_assert!( + !month_lengths[12] || leap_month_idx.is_some(), + "Last month length should not be set for non-leap years" + ); + let ny_offset = ny_offset - Self::FIRST_NY; + debug_assert!(ny_offset >= 0, "Year offset too small to store"); + debug_assert!(ny_offset < 34, "Year offset too big to store"); + debug_assert!( + leap_month_idx.map(|l| l <= 13).unwrap_or(true), + "Leap month indices must be 1 <= i <= 13" + ); + let mut all = 0u32; // last byte unused + + for (month, length_30) in month_lengths.iter().enumerate() { + #[allow(clippy::indexing_slicing)] + if *length_30 { + all |= 1 << month as u32; + } + } + let leap_month_idx = leap_month_idx.unwrap_or(0); + all |= (leap_month_idx as u32) << (8 + 5); + all |= (ny_offset as u32) << (16 + 1); + let le = all.to_le_bytes(); + Self(le[0], le[1], le[2]) + } + + // Get the new year difference from the ISO new year + pub(crate) fn ny_offset(self) -> u8 { + Self::FIRST_NY as u8 + (self.2 >> 1) + } + + pub(crate) fn leap_month(self) -> Option { + let bits = (self.1 >> 5) + ((self.2 & 0b1) << 3); + + (bits != 0).then_some(bits) + } + + // Whether a particular month has 30 days (month is 1-indexed) + pub(crate) fn month_has_30_days(self, month: u8) -> bool { + let months = u16::from_le_bytes([self.0, self.1]); + months & (1 << (month - 1) as u16) != 0 + } + + #[cfg(any(test, feature = "datagen"))] + pub(crate) fn month_lengths(self) -> [bool; 13] { + core::array::from_fn(|i| self.month_has_30_days(i as u8 + 1)) + } + + // Which day of year is the last day of a month (month is 1-indexed) + pub(crate) fn last_day_of_month(self, month: u8) -> u16 { + let months = u16::from_le_bytes([self.0, self.1]); + // month is 1-indexed, so `29 * month` includes the current month + let mut prev_month_lengths = 29 * month as u16; + // month is 1-indexed, so `1 << month` is a mask with all zeroes except + // for a 1 at the bit index at the next month. Subtracting 1 from it gets us + // a bitmask for all months up to now + let long_month_bits = months & ((1 << month as u16) - 1); + prev_month_lengths += long_month_bits.count_ones().try_into().unwrap_or(0); + prev_month_lengths + } +} + +impl AsULE for PackedChineseBasedYearInfo { + type ULE = Self; + fn to_unaligned(self) -> Self { + self + } + fn from_unaligned(other: Self) -> Self { + other + } +} + +#[cfg(feature = "serde")] +mod serialization { + use super::*; + + #[cfg(feature = "datagen")] + use serde::{ser, Serialize}; + use serde::{Deserialize, Deserializer}; + + #[derive(Deserialize)] + #[cfg_attr(feature = "datagen", derive(Serialize))] + struct SerdePackedChineseBasedYearInfo { + ny_offset: u8, + month_has_30_days: [bool; 13], + leap_month_idx: Option, + } + + impl<'de> Deserialize<'de> for PackedChineseBasedYearInfo { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + if deserializer.is_human_readable() { + SerdePackedChineseBasedYearInfo::deserialize(deserializer).map(Into::into) + } else { + let data = <(u8, u8, u8)>::deserialize(deserializer)?; + Ok(PackedChineseBasedYearInfo(data.0, data.1, data.2)) + } + } + } + + #[cfg(feature = "datagen")] + impl Serialize for PackedChineseBasedYearInfo { + fn serialize(&self, serializer: S) -> Result + where + S: ser::Serializer, + { + if serializer.is_human_readable() { + SerdePackedChineseBasedYearInfo::from(*self).serialize(serializer) + } else { + (self.0, self.1, self.2).serialize(serializer) + } + } + } + + #[cfg(feature = "datagen")] + impl From for SerdePackedChineseBasedYearInfo { + fn from(other: PackedChineseBasedYearInfo) -> Self { + Self { + ny_offset: other.ny_offset(), + month_has_30_days: other.month_lengths(), + leap_month_idx: other.leap_month(), + } + } + } + + impl From for PackedChineseBasedYearInfo { + fn from(other: SerdePackedChineseBasedYearInfo) -> Self { + Self::new( + other.month_has_30_days, + other.leap_month_idx, + other.ny_offset as i64, + ) + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + fn packed_roundtrip_single( + mut month_lengths: [bool; 13], + leap_month_idx: Option, + ny_offset: i64, + ) { + if leap_month_idx.is_none() { + // Avoid bad invariants + month_lengths[12] = false; + } + let packed = PackedChineseBasedYearInfo::new(month_lengths, leap_month_idx, ny_offset); + + assert_eq!( + ny_offset, + packed.ny_offset() as i64, + "Roundtrip with {month_lengths:?}, {leap_month_idx:?}, {ny_offset}" + ); + assert_eq!( + leap_month_idx, + packed.leap_month(), + "Roundtrip with {month_lengths:?}, {leap_month_idx:?}, {ny_offset}" + ); + let month_lengths_roundtrip = packed.month_lengths(); + assert_eq!( + month_lengths, month_lengths_roundtrip, + "Roundtrip with {month_lengths:?}, {leap_month_idx:?}, {ny_offset}" + ); + } + + #[test] + fn test_roundtrip_packed() { + const SHORT: [bool; 13] = [false; 13]; + const LONG: [bool; 13] = [true; 13]; + const ALTERNATING1: [bool; 13] = [ + false, true, false, true, false, true, false, true, false, true, false, true, false, + ]; + const ALTERNATING2: [bool; 13] = [ + true, false, true, false, true, false, true, false, true, false, true, false, true, + ]; + const RANDOM1: [bool; 13] = [ + true, true, false, false, true, true, false, true, true, true, true, false, true, + ]; + const RANDOM2: [bool; 13] = [ + false, true, true, true, true, false, true, true, true, false, false, true, false, + ]; + packed_roundtrip_single(SHORT, None, 18 + 5); + packed_roundtrip_single(SHORT, None, 18 + 10); + packed_roundtrip_single(SHORT, Some(11), 18 + 15); + packed_roundtrip_single(LONG, Some(12), 18 + 15); + packed_roundtrip_single(ALTERNATING1, None, 18 + 2); + packed_roundtrip_single(ALTERNATING1, Some(3), 18 + 5); + packed_roundtrip_single(ALTERNATING2, None, 18 + 9); + packed_roundtrip_single(ALTERNATING2, Some(7), 18 + 26); + packed_roundtrip_single(RANDOM1, None, 18 + 29); + packed_roundtrip_single(RANDOM1, Some(12), 18 + 29); + packed_roundtrip_single(RANDOM1, Some(2), 18 + 21); + packed_roundtrip_single(RANDOM2, None, 18 + 25); + packed_roundtrip_single(RANDOM2, Some(2), 18 + 19); + packed_roundtrip_single(RANDOM2, Some(5), 18 + 2); + packed_roundtrip_single(RANDOM2, Some(12), 18 + 5); + } +} diff --git a/deps/crates/vendor/icu_calendar/src/provider/hijri.rs b/deps/crates/vendor/icu_calendar/src/provider/hijri.rs new file mode 100644 index 00000000000000..d0ff61f8b13b57 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/provider/hijri.rs @@ -0,0 +1,165 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! 🚧 \[Unstable\] Data provider struct definitions for chinese-based calendars. +//! +//!
+//! 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, +//! including in SemVer minor releases. While the serde representation of data structs is guaranteed +//! to be stable, their Rust representation might not be. Use with caution. +//!
+//! +//! Read more about data providers: [`icu_provider`] + +use calendrical_calculations::rata_die::RataDie; +use icu_provider::prelude::*; +use zerovec::ule::AsULE; +use zerovec::ZeroVec; + +icu_provider::data_marker!( + /// Precomputed data for the Hijri obsevational calendar + CalendarHijriSimulatedMeccaV1, + "calendar/hijri/simulated/mecca/v1", + HijriData<'static>, + is_singleton = true, +); + +/// Cached/precompiled data for a certain range of years for a chinese-based +/// calendar. Avoids the need to perform lunar calendar arithmetic for most calendrical +/// operations. +#[derive(Debug, PartialEq, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)] +#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))] +#[cfg_attr(feature = "datagen", databake(path = icu_calendar::provider::hijri))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize))] +pub struct HijriData<'data> { + /// The extended year corresponding to the first data entry for this year + pub first_extended_year: i32, + /// A list of precomputed data for each year beginning with first_extended_year + #[cfg_attr(feature = "serde", serde(borrow))] + pub data: ZeroVec<'data, PackedHijriYearInfo>, +} + +icu_provider::data_struct!( + HijriData<'_>, + #[cfg(feature = "datagen")] +); + +/// The struct containing compiled Hijri YearInfo +/// +/// Bit structure +/// +/// ```text +/// Bit: F.........C B.............0 +/// Value: [ start day ][ month lengths ] +/// ``` +/// +/// The start day is encoded as a signed offset from `Self::mean_synodic_start_day`. This number does not +/// appear to be less than 2, however we use all remaining bits for it in case of drift in the math. +/// The month lengths are stored as 1 = 30, 0 = 29 for each month including the leap month. +/// +///
+/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, +/// including in SemVer minor releases. While the serde representation of data structs is guaranteed +/// to be stable, their Rust representation might not be. Use with caution. +///
+#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)] +#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))] +#[cfg_attr(feature = "datagen", databake(path = icu_calendar::provider))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize))] +pub struct PackedHijriYearInfo(pub u16); + +impl PackedHijriYearInfo { + pub(crate) const fn new( + extended_year: i32, + month_lengths: [bool; 12], + start_day: RataDie, + ) -> Self { + let start_offset = start_day.since(Self::mean_synodic_start_day(extended_year)); + + debug_assert!( + -8 < start_offset && start_offset < 8, + "Year offset too big to store" + ); + let start_offset = start_offset as i8; + + let mut all = 0u16; // last byte unused + + let mut i = 0; + while i < 12 { + #[allow(clippy::indexing_slicing)] + if month_lengths[i] { + all |= 1 << i; + } + i += 1; + } + + if start_offset < 0 { + all |= 1 << 12; + } + all |= (start_offset.unsigned_abs() as u16) << 13; + Self(all) + } + + pub(crate) fn unpack(self, extended_year: i32) -> ([bool; 12], RataDie) { + let month_lengths = core::array::from_fn(|i| self.0 & (1 << (i as u8) as u16) != 0); + let start_offset = if (self.0 & 0b1_0000_0000_0000) != 0 { + -((self.0 >> 13) as i64) + } else { + (self.0 >> 13) as i64 + }; + ( + month_lengths, + Self::mean_synodic_start_day(extended_year) + start_offset, + ) + } + + const fn mean_synodic_start_day(extended_year: i32) -> RataDie { + // -1 because the epoch is new year of year 1 + // truncating instead of flooring does not matter, as this is used for positive years only + calendrical_calculations::islamic::ISLAMIC_EPOCH_FRIDAY.add( + ((extended_year - 1) as f64 * calendrical_calculations::islamic::MEAN_YEAR_LENGTH) + as i64, + ) + } +} + +impl AsULE for PackedHijriYearInfo { + type ULE = ::ULE; + fn from_unaligned(unaligned: Self::ULE) -> Self { + Self(::from_unaligned(unaligned)) + } + fn to_unaligned(self) -> Self::ULE { + ::to_unaligned(self.0) + } +} + +#[test] +fn test_hijri_packed_roundtrip() { + fn single_roundtrip(month_lengths: [bool; 12], year_start: RataDie) { + let packed = PackedHijriYearInfo::new(1600, month_lengths, year_start); + let (month_lengths2, year_start2) = packed.unpack(1600); + assert_eq!(month_lengths, month_lengths2, "Month lengths must match for testcase {month_lengths:?} / {year_start:?}, with packed repr: {packed:?}"); + assert_eq!(year_start, year_start2, "Month lengths must match for testcase {month_lengths:?} / {year_start:?}, with packed repr: {packed:?}"); + } + + let l = true; + let s = false; + let all_short = [s; 12]; + let all_long = [l; 12]; + let mixed1 = [l, s, l, s, l, s, l, s, l, s, l, s]; + let mixed2 = [s, s, l, l, l, s, l, s, s, s, l, l]; + + let start_1600 = PackedHijriYearInfo::mean_synodic_start_day(1600); + single_roundtrip(all_short, start_1600); + single_roundtrip(all_long, start_1600); + single_roundtrip(mixed1, start_1600); + single_roundtrip(mixed2, start_1600); + + single_roundtrip(mixed1, start_1600 - 7); + single_roundtrip(mixed2, start_1600 + 7); + single_roundtrip(mixed2, start_1600 + 4); + single_roundtrip(mixed2, start_1600 + 1); + single_roundtrip(mixed2, start_1600 - 1); + single_roundtrip(mixed2, start_1600 - 4); +} diff --git a/deps/crates/vendor/icu_calendar/src/tests/continuity_test.rs b/deps/crates/vendor/icu_calendar/src/tests/continuity_test.rs new file mode 100644 index 00000000000000..f157bdd28826ff --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/tests/continuity_test.rs @@ -0,0 +1,242 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::*; +use core::marker::PhantomData; + +fn check_continuity(mut date: Date
) { + let one_day_duration = DateDuration:: { + years: 0, + months: 0, + weeks: 0, + days: 1, + marker: PhantomData, + }; + + let mut rata_die = date.to_rata_die(); + let mut weekday = date.day_of_week(); + let mut year = date.year(); + let mut is_in_leap_year = date.is_in_leap_year(); + + for _ in 0..(366 * 20) { + let next_date = date.added(one_day_duration); + let next_rata_die = next_date.to_iso().to_rata_die(); + assert_eq!(next_rata_die, rata_die + 1, "{next_date:?}"); + let next_weekday = next_date.day_of_week(); + let next_year = next_date.year(); + let next_is_in_leap_year = next_date.is_in_leap_year(); + assert_eq!( + (next_weekday as usize) % 7, + (weekday as usize + 1) % 7, + "{next_date:?}" + ); + if year == next_year { + assert_eq!(is_in_leap_year, next_is_in_leap_year, "{next_date:?}"); + } + date = next_date; + rata_die = next_rata_die; + weekday = next_weekday; + year = next_year; + is_in_leap_year = next_is_in_leap_year; + } +} + +fn check_every_250_days(mut date: Date) { + let one_thousand_days_duration = DateDuration:: { + years: 0, + months: 0, + weeks: 0, + days: 250, + marker: PhantomData, + }; + + let mut rata_die = date.to_rata_die(); + + for _ in 0..2000 { + let next_date = date.added(one_thousand_days_duration); + let next_iso = next_date.to_iso(); + let next_rata_die = next_iso.to_rata_die(); + assert_eq!(next_rata_die, rata_die + 250, "{next_date:?}"); + let next_date_roundtrip = next_iso.to_calendar(Ref(next_date.calendar())); + assert_eq!(next_date, next_date_roundtrip, "{next_date:?}"); + date = next_date; + rata_die = next_rata_die; + } +} + +#[test] +fn test_buddhist_continuity() { + let date = Date::try_new_buddhist(-10, 1, 1); + check_continuity(date.unwrap()); + let date = Date::try_new_buddhist(-300, 1, 1); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_chinese_continuity() { + let cal = crate::cal::Chinese::new(); + let cal = Ref(&cal); + let date = Date::try_new_chinese_with_calendar(-10, 1, 1, cal); + check_continuity(date.unwrap()); + let date = Date::try_new_chinese_with_calendar(-300, 1, 1, cal); + check_every_250_days(date.unwrap()); + let date = Date::try_new_chinese_with_calendar(-10000, 1, 1, cal); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_coptic_continuity() { + let date = Date::try_new_coptic(-10, 1, 1); + check_continuity(date.unwrap()); + let date = Date::try_new_coptic(-300, 1, 1); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_dangi_continuity() { + let cal = crate::cal::Dangi::new(); + let cal = Ref(&cal); + let date = Date::try_new_dangi_with_calendar(-10, 1, 1, cal); + check_continuity(date.unwrap()); + let date = Date::try_new_dangi_with_calendar(-300, 1, 1, cal); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_ethiopian_continuity() { + use crate::cal::EthiopianEraStyle::*; + let date = Date::try_new_ethiopian(AmeteMihret, -10, 1, 1); + check_continuity(date.unwrap()); + let date = Date::try_new_ethiopian(AmeteMihret, -300, 1, 1); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_ethiopian_amete_alem_continuity() { + use crate::cal::EthiopianEraStyle::*; + let date = Date::try_new_ethiopian(AmeteAlem, -10, 1, 1); + check_continuity(date.unwrap()); + let date = Date::try_new_ethiopian(AmeteAlem, -300, 1, 1); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_gregorian_continuity() { + let date = Date::try_new_gregorian(-10, 1, 1); + check_continuity(date.unwrap()); + let date = Date::try_new_gregorian(-300, 1, 1); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_hebrew_continuity() { + let date = Date::try_new_hebrew(-10, 1, 1); + check_continuity(date.unwrap()); + let date = Date::try_new_hebrew(-300, 1, 1); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_indian_continuity() { + let date = Date::try_new_indian(-10, 1, 1); + check_continuity(date.unwrap()); + let date = Date::try_new_indian(-300, 1, 1); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_hijri_civil_continuity() { + let cal = crate::cal::HijriTabular::new( + crate::cal::HijriTabularLeapYears::TypeII, + crate::cal::HijriTabularEpoch::Friday, + ); + let cal = Ref(&cal); + let date = Date::try_new_hijri_tabular_with_calendar(-10, 1, 1, cal); + check_continuity(date.unwrap()); + let date = Date::try_new_hijri_tabular_with_calendar(-300, 1, 1, cal); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_hijri_simulated_mecca_continuity() { + #[cfg(feature = "logging")] + let _ = simple_logger::SimpleLogger::new().env().init(); + let cal = crate::cal::HijriSimulated::new_mecca_always_calculating(); + let cal = Ref(&cal); + let date = Date::try_new_simulated_hijri_with_calendar(-10, 1, 1, cal); + check_continuity(date.unwrap()); + let date = Date::try_new_simulated_hijri_with_calendar(-300, 1, 1, cal); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_hijri_tabular_continuity() { + let cal = crate::cal::HijriTabular::new( + crate::cal::HijriTabularLeapYears::TypeII, + crate::cal::HijriTabularEpoch::Thursday, + ); + let cal = Ref(&cal); + let date = Date::try_new_hijri_tabular_with_calendar(-10, 1, 1, cal); + check_continuity(date.unwrap()); + let date = Date::try_new_hijri_tabular_with_calendar(-300, 1, 1, cal); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_hijri_umm_al_qura_continuity() { + #[cfg(feature = "logging")] + let _ = simple_logger::SimpleLogger::new().env().init(); + let date = Date::try_new_ummalqura(-10, 1, 1); + check_continuity(date.unwrap()); + let date = Date::try_new_ummalqura(1290, 1, 1); + check_continuity(date.unwrap()); + let date = Date::try_new_ummalqura(1590, 1, 1); + check_continuity(date.unwrap()); + let date = Date::try_new_ummalqura(-300, 1, 1); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_iso_continuity() { + let date = Date::try_new_iso(-10, 1, 1); + check_continuity(date.unwrap()); + let date = Date::try_new_iso(-300, 1, 1); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_japanese_continuity() { + let cal = crate::cal::Japanese::new(); + let cal = Ref(&cal); + let date = Date::try_new_japanese_with_calendar("heisei", 20, 1, 1, cal); + check_continuity(date.unwrap()); + let date = Date::try_new_japanese_with_calendar("bce", 500, 1, 1, cal); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_japanese_extended_continuity() { + let cal = crate::cal::JapaneseExtended::new(); + let cal = Ref(&cal); + let date = Date::try_new_japanese_extended_with_calendar("heisei", 20, 1, 1, cal); + check_continuity(date.unwrap()); + let date = Date::try_new_japanese_extended_with_calendar("bce", 500, 1, 1, cal); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_persian_continuity() { + let date = Date::try_new_persian(-10, 1, 1); + check_continuity(date.unwrap()); + let date = Date::try_new_persian(-300, 1, 1); + check_every_250_days(date.unwrap()); +} + +#[test] +fn test_roc_continuity() { + let date = Date::try_new_roc(-10, 1, 1); + check_continuity(date.unwrap()); + let date = Date::try_new_roc(-300, 1, 1); + check_every_250_days(date.unwrap()); +} diff --git a/deps/crates/vendor/icu_calendar/src/tests/mod.rs b/deps/crates/vendor/icu_calendar/src/tests/mod.rs new file mode 100644 index 00000000000000..a4330b4af10b0c --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/tests/mod.rs @@ -0,0 +1,5 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +mod continuity_test; diff --git a/deps/crates/vendor/icu_calendar/src/types.rs b/deps/crates/vendor/icu_calendar/src/types.rs new file mode 100644 index 00000000000000..c01f363694e57e --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/types.rs @@ -0,0 +1,375 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module contains various types used by `icu_calendar` and `icu::datetime` + +#[doc(no_inline)] +pub use calendrical_calculations::rata_die::RataDie; +use core::fmt; +use tinystr::TinyAsciiStr; +use tinystr::{TinyStr16, TinyStr4}; +use zerovec::maps::ZeroMapKV; +use zerovec::ule::AsULE; + +/// The type of year: Calendars like Chinese don't have an era and instead format with cyclic years. +#[derive(Copy, Clone, Debug, PartialEq)] +#[non_exhaustive] +pub enum YearInfo { + /// An era and a year in that era + Era(EraYear), + /// A cyclic year, and the related ISO year + /// + /// Knowing the cyclic year is typically not enough to pinpoint a date, however cyclic calendars + /// don't typically use eras, so disambiguation can be done by saying things like "Year 甲辰 (2024)" + Cyclic(CyclicYear), +} + +impl From for YearInfo { + fn from(value: EraYear) -> Self { + Self::Era(value) + } +} + +impl From for YearInfo { + fn from(value: CyclicYear) -> Self { + Self::Cyclic(value) + } +} + +impl YearInfo { + /// Get *some* year number that can be displayed + /// + /// Gets the era year for era calendars, and the related ISO year for cyclic calendars. + pub fn era_year_or_related_iso(self) -> i32 { + match self { + YearInfo::Era(e) => e.year, + YearInfo::Cyclic(c) => c.related_iso, + } + } + + /// Get the era year information, if available + pub fn era(self) -> Option { + match self { + Self::Era(e) => Some(e), + Self::Cyclic(_) => None, + } + } + + /// Get the cyclic year informat, if available + pub fn cyclic(self) -> Option { + match self { + Self::Era(_) => None, + Self::Cyclic(c) => Some(c), + } + } +} + +/// Defines whether the era or century is required to interpret the year. +/// +/// For example 2024 AD can be formatted as `2024`, or even `24`, but 1931 AD +/// should not be formatted as `31`, and 2024 BC should not be formatted as `2024`. +#[derive(Copy, Clone, Debug, PartialEq)] +#[allow(clippy::exhaustive_enums)] // logically complete +pub enum YearAmbiguity { + /// The year is unambiguous without a century or era. + Unambiguous, + /// The century is required, the era may be included. + CenturyRequired, + /// The era is required, the century may be included. + EraRequired, + /// The century and era are required. + EraAndCenturyRequired, +} + +/// Year information for a year that is specified with an era +#[derive(Copy, Clone, Debug, PartialEq)] +#[non_exhaustive] +pub struct EraYear { + /// The numeric year in that era + pub year: i32, + /// The era code as defined by CLDR, expect for cases where CLDR does not define a code. + pub era: TinyStr16, + /// An era index, for calendars with a small set of eras. + /// + /// The only guarantee we make is that these values are stable. These do *not* + /// match the indices produced by ICU4C or CLDR. + /// + /// These are used by ICU4X datetime formatting for efficiently storing data. + pub era_index: Option, + /// The ambiguity of the era/year combination + pub ambiguity: YearAmbiguity, +} + +/// Year information for a year that is specified as a cyclic year +#[derive(Copy, Clone, Debug, PartialEq)] +#[non_exhaustive] +pub struct CyclicYear { + /// The year in the cycle, 1-based + pub year: u8, + /// The ISO year corresponding to this year + pub related_iso: i32, +} + +/// Representation of a month in a year +/// +/// Month codes typically look like `M01`, `M02`, etc, but can handle leap months +/// (`M03L`) in lunar calendars. Solar calendars will have codes between `M01` and `M12` +/// potentially with an `M13` for epagomenal months. Check the docs for a particular calendar +/// for details on what its month codes are. +/// +/// Month codes are shared with Temporal, [see Temporal proposal][era-proposal]. +/// +/// [era-proposal]: https://tc39.es/proposal-intl-era-monthcode/ +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[allow(clippy::exhaustive_structs)] // this is a newtype +#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))] +#[cfg_attr(feature = "datagen", databake(path = icu_calendar::types))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize))] +pub struct MonthCode(pub TinyStr4); + +impl MonthCode { + /// Returns an option which is `Some` containing the non-month version of a leap month + /// if the [`MonthCode`] this method is called upon is a leap month, and `None` otherwise. + /// This method assumes the [`MonthCode`] is valid. + pub fn get_normal_if_leap(self) -> Option { + let bytes = self.0.all_bytes(); + if bytes[3] == b'L' { + Some(MonthCode(TinyAsciiStr::try_from_utf8(&bytes[0..3]).ok()?)) + } else { + None + } + } + /// Get the month number and whether or not it is leap from the month code + pub fn parsed(self) -> Option<(u8, bool)> { + // Match statements on tinystrs are annoying so instead + // we calculate it from the bytes directly + + let bytes = self.0.all_bytes(); + let is_leap = bytes[3] == b'L'; + if bytes[0] != b'M' { + return None; + } + if bytes[1] == b'0' { + if bytes[2] >= b'1' && bytes[2] <= b'9' { + return Some((bytes[2] - b'0', is_leap)); + } + } else if bytes[1] == b'1' && bytes[2] >= b'0' && bytes[2] <= b'3' { + return Some((10 + bytes[2] - b'0', is_leap)); + } + None + } + + /// Construct a "normal" month code given a number ("Mxx"). + /// + /// Returns an error for months greater than 99 + pub fn new_normal(number: u8) -> Option { + let tens = number / 10; + let ones = number % 10; + if tens > 9 { + return None; + } + + let bytes = [b'M', b'0' + tens, b'0' + ones, 0]; + Some(MonthCode(TinyAsciiStr::try_from_raw(bytes).ok()?)) + } +} + +#[test] +fn test_get_normal_month_code_if_leap() { + let mc1 = MonthCode(tinystr::tinystr!(4, "M01L")); + let result1 = mc1.get_normal_if_leap(); + assert_eq!(result1, Some(MonthCode(tinystr::tinystr!(4, "M01")))); + + let mc2 = MonthCode(tinystr::tinystr!(4, "M11L")); + let result2 = mc2.get_normal_if_leap(); + assert_eq!(result2, Some(MonthCode(tinystr::tinystr!(4, "M11")))); + + let mc_invalid = MonthCode(tinystr::tinystr!(4, "M10")); + let result_invalid = mc_invalid.get_normal_if_leap(); + assert_eq!(result_invalid, None); +} + +impl AsULE for MonthCode { + type ULE = TinyStr4; + fn to_unaligned(self) -> TinyStr4 { + self.0 + } + fn from_unaligned(u: TinyStr4) -> Self { + Self(u) + } +} + +impl<'a> ZeroMapKV<'a> for MonthCode { + type Container = zerovec::ZeroVec<'a, MonthCode>; + type Slice = zerovec::ZeroSlice; + type GetType = ::ULE; + type OwnedType = MonthCode; +} + +impl fmt::Display for MonthCode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +/// Representation of a formattable month. +#[derive(Copy, Clone, Debug, PartialEq)] +#[non_exhaustive] +pub struct MonthInfo { + /// The month number in this given year. For calendars with leap months, all months after + /// the leap month will end up with an incremented number. + /// + /// In general, prefer using the month code in generic code. + pub ordinal: u8, + + /// The month code, used to distinguish months during leap years. + /// + /// This follows [Temporal's specification](https://tc39.es/proposal-intl-era-monthcode/#table-additional-month-codes). + /// Months considered the "same" have the same code: This means that the Hebrew months "Adar" and "Adar II" ("Adar, but during a leap year") + /// are considered the same month and have the code M05 + pub standard_code: MonthCode, + /// A month code, useable for formatting + /// + /// This may not necessarily be the canonical month code for a month in cases where a month has different + /// formatting in a leap year, for example Adar/Adar II in the Hebrew calendar in a leap year has + /// the standard code M06, but for formatting specifically the Hebrew calendar will return M06L since it is formatted + /// differently. + pub formatting_code: MonthCode, +} + +impl MonthInfo { + /// Gets the month number. A month number N is not necessarily the Nth month in the year + /// if there are leap months in the year, rather it is associated with the Nth month of a "regular" + /// year. There may be multiple month Ns in a year + pub fn month_number(self) -> u8 { + self.standard_code + .parsed() + .map(|(i, _)| i) + .unwrap_or(self.ordinal) + } + + /// Get whether the month is a leap month + pub fn is_leap(self) -> bool { + self.standard_code.parsed().map(|(_, l)| l).unwrap_or(false) + } +} + +/// The current day of the year, 1-based. +#[derive(Copy, Clone, Debug, PartialEq)] +#[allow(clippy::exhaustive_structs)] // this is a newtype +pub struct DayOfYear(pub u16); + +/// A 1-based day number in a month. +#[allow(clippy::exhaustive_structs)] // this is a newtype +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct DayOfMonth(pub u8); + +/// A week number in a year +#[derive(Clone, Copy, Debug, PartialEq)] +#[allow(clippy::exhaustive_structs)] // this is a newtype +pub struct IsoWeekOfYear { + /// The 1-based ISO week number + pub week_number: u8, + /// The ISO year + pub iso_year: i32, +} + +/// A day of week in month. 1-based. +#[derive(Clone, Copy, Debug, PartialEq)] +#[allow(clippy::exhaustive_structs)] // this is a newtype +pub struct DayOfWeekInMonth(pub u8); + +impl From for DayOfWeekInMonth { + fn from(day_of_month: DayOfMonth) -> Self { + DayOfWeekInMonth(1 + ((day_of_month.0 - 1) / 7)) + } +} + +#[test] +fn test_day_of_week_in_month() { + assert_eq!(DayOfWeekInMonth::from(DayOfMonth(1)).0, 1); + assert_eq!(DayOfWeekInMonth::from(DayOfMonth(7)).0, 1); + assert_eq!(DayOfWeekInMonth::from(DayOfMonth(8)).0, 2); +} + +/// A weekday in a 7-day week, according to ISO-8601. +/// +/// The discriminant values correspond to ISO-8601 weekday numbers (Monday = 1, Sunday = 7). +/// +/// # Examples +/// +/// ``` +/// use icu::calendar::types::Weekday; +/// +/// assert_eq!(1, Weekday::Monday as usize); +/// assert_eq!(7, Weekday::Sunday as usize); +/// ``` +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[allow(missing_docs)] // The weekday variants should be self-obvious. +#[repr(i8)] +#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))] +#[cfg_attr(feature = "datagen", databake(path = icu_calendar::types))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize))] +#[allow(clippy::exhaustive_enums)] // This is stable +pub enum Weekday { + Monday = 1, + Tuesday, + Wednesday, + Thursday, + Friday, + Saturday, + Sunday, +} + +// RD 0 is a Sunday +const SUNDAY: RataDie = RataDie::new(0); + +impl From for Weekday { + fn from(value: RataDie) -> Self { + use Weekday::*; + match (value - SUNDAY).rem_euclid(7) { + 0 => Sunday, + 1 => Monday, + 2 => Tuesday, + 3 => Wednesday, + 4 => Thursday, + 5 => Friday, + 6 => Saturday, + _ => unreachable!(), + } + } +} + +impl Weekday { + /// Convert from an ISO-8601 weekday number to an [`Weekday`] enum. 0 is automatically converted + /// to 7 (Sunday). If the number is out of range, it is interpreted modulo 7. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::types::Weekday; + /// + /// assert_eq!(Weekday::Sunday, Weekday::from_days_since_sunday(0)); + /// assert_eq!(Weekday::Monday, Weekday::from_days_since_sunday(1)); + /// assert_eq!(Weekday::Sunday, Weekday::from_days_since_sunday(7)); + /// assert_eq!(Weekday::Monday, Weekday::from_days_since_sunday(8)); + /// ``` + pub fn from_days_since_sunday(input: isize) -> Self { + (SUNDAY + input as i64).into() + } + + /// Returns the day after the current day. + pub(crate) fn next_day(self) -> Weekday { + use Weekday::*; + match self { + Monday => Tuesday, + Tuesday => Wednesday, + Wednesday => Thursday, + Thursday => Friday, + Friday => Saturday, + Saturday => Sunday, + Sunday => Monday, + } + } +} diff --git a/deps/crates/vendor/icu_calendar/src/week.rs b/deps/crates/vendor/icu_calendar/src/week.rs new file mode 100644 index 00000000000000..384b4f55d99290 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/week.rs @@ -0,0 +1,676 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! Functions for region-specific weekday information. + +use crate::{error::RangeError, provider::*, types::Weekday}; +use icu_locale_core::preferences::{define_preferences, extensions::unicode::keywords::FirstDay}; +use icu_provider::prelude::*; + +/// Minimum number of days in a month unit required for using this module +const MIN_UNIT_DAYS: u16 = 14; + +define_preferences!( + /// The preferences for the week information. + [Copy] + WeekPreferences, + { + /// The first day of the week + first_weekday: FirstDay + } +); + +/// Information about the first day of the week and the weekend. +#[derive(Clone, Copy, Debug)] +#[non_exhaustive] +pub struct WeekInformation { + /// The first day of a week. + pub first_weekday: Weekday, + /// The set of weekend days + pub weekend: WeekdaySet, +} + +impl WeekInformation { + icu_provider::gen_buffer_data_constructors!( + (prefs: WeekPreferences) -> error: DataError, + /// Creates a new [`WeekCalculator`] from compiled data. + ); + + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new)] + pub fn try_new_unstable

(provider: &P, prefs: WeekPreferences) -> Result + where + P: DataProvider + ?Sized, + { + let locale = CalendarWeekV1::make_locale(prefs.locale_preferences); + provider + .load(DataRequest { + id: DataIdentifierBorrowed::for_locale(&locale), + ..Default::default() + }) + .map(|response| WeekInformation { + first_weekday: match prefs.first_weekday { + Some(FirstDay::Mon) => Weekday::Monday, + Some(FirstDay::Tue) => Weekday::Tuesday, + Some(FirstDay::Wed) => Weekday::Wednesday, + Some(FirstDay::Thu) => Weekday::Thursday, + Some(FirstDay::Fri) => Weekday::Friday, + Some(FirstDay::Sat) => Weekday::Saturday, + Some(FirstDay::Sun) => Weekday::Sunday, + _ => response.payload.get().first_weekday, + }, + weekend: response.payload.get().weekend, + }) + } + + /// Weekdays that are part of the 'weekend', for calendar purposes. + /// Days may not be contiguous, and order is based off the first weekday. + pub fn weekend(self) -> WeekdaySetIterator { + WeekdaySetIterator::new(self.first_weekday, self.weekend) + } +} + +#[derive(Clone, Copy, Debug)] +pub(crate) struct WeekCalculator { + first_weekday: Weekday, + min_week_days: u8, +} + +impl WeekCalculator { + pub(crate) const ISO: Self = Self { + first_weekday: Weekday::Monday, + min_week_days: 4, + }; + + /// Returns the zero based index of `weekday` vs this calendar's start of week. + fn weekday_index(self, weekday: Weekday) -> i8 { + (7 + (weekday as i8) - (self.first_weekday as i8)) % 7 + } + + /// Computes & returns the week of given month/year according to `calendar`. + /// + /// # Arguments + /// - calendar: Calendar information used to compute the week number. + /// - num_days_in_previous_unit: The number of days in the preceding month/year. + /// - num_days_in_unit: The number of days in the month/year. + /// - day: 1-based day of month/year. + /// - week_day: The weekday of `day`.. + /// + /// # Error + /// If num_days_in_unit/num_days_in_previous_unit < MIN_UNIT_DAYS + pub(crate) fn week_of( + self, + num_days_in_previous_unit: u16, + num_days_in_unit: u16, + day: u16, + week_day: Weekday, + ) -> Result { + let current = UnitInfo::new( + // The first day of this month/year is (day - 1) days from `day`. + add_to_weekday(week_day, 1 - i32::from(day)), + num_days_in_unit, + )?; + + match current.relative_week(self, day) { + RelativeWeek::LastWeekOfPreviousUnit => { + let previous = UnitInfo::new( + add_to_weekday(current.first_day, -i32::from(num_days_in_previous_unit)), + num_days_in_previous_unit, + )?; + + Ok(WeekOf { + week: previous.num_weeks(self), + unit: RelativeUnit::Previous, + }) + } + RelativeWeek::WeekOfCurrentUnit(w) => Ok(WeekOf { + week: w, + unit: RelativeUnit::Current, + }), + RelativeWeek::FirstWeekOfNextUnit => Ok(WeekOf { + week: 1, + unit: RelativeUnit::Next, + }), + } + } +} + +/// Returns the weekday that's `num_days` after `weekday`. +fn add_to_weekday(weekday: Weekday, num_days: i32) -> Weekday { + let new_weekday = (7 + (weekday as i32) + (num_days % 7)) % 7; + Weekday::from_days_since_sunday(new_weekday as isize) +} + +/// Which year or month that a calendar assigns a week to relative to the year/month +/// the week is in. +#[derive(Clone, Copy, Debug, PartialEq)] +#[allow(clippy::enum_variant_names)] +enum RelativeWeek { + /// A week that is assigned to the last week of the previous year/month. e.g. 2021-01-01 is week 54 of 2020 per the ISO calendar. + LastWeekOfPreviousUnit, + /// A week that's assigned to the current year/month. The offset is 1-based. e.g. 2021-01-11 is week 2 of 2021 per the ISO calendar so would be WeekOfCurrentUnit(2). + WeekOfCurrentUnit(u8), + /// A week that is assigned to the first week of the next year/month. e.g. 2019-12-31 is week 1 of 2020 per the ISO calendar. + FirstWeekOfNextUnit, +} + +/// Information about a year or month. +#[derive(Clone, Copy)] +struct UnitInfo { + /// The weekday of this year/month's first day. + first_day: Weekday, + /// The number of days in this year/month. + duration_days: u16, +} + +impl UnitInfo { + /// Creates a UnitInfo for a given year or month. + fn new(first_day: Weekday, duration_days: u16) -> Result { + if duration_days < MIN_UNIT_DAYS { + return Err(RangeError { + field: "num_days_in_unit", + value: duration_days as i32, + min: MIN_UNIT_DAYS as i32, + max: i32::MAX, + }); + } + Ok(UnitInfo { + first_day, + duration_days, + }) + } + + /// Returns the start of this unit's first week. + /// + /// The returned value can be negative if this unit's first week started during the previous + /// unit. + fn first_week_offset(self, calendar: WeekCalculator) -> i8 { + let first_day_index = calendar.weekday_index(self.first_day); + if 7 - first_day_index >= calendar.min_week_days as i8 { + -first_day_index + } else { + 7 - first_day_index + } + } + + /// Returns the number of weeks in this unit according to `calendar`. + fn num_weeks(self, calendar: WeekCalculator) -> u8 { + let first_week_offset = self.first_week_offset(calendar); + let num_days_including_first_week = + (self.duration_days as i32) - (first_week_offset as i32); + debug_assert!( + num_days_including_first_week >= 0, + "Unit is shorter than a week." + ); + ((num_days_including_first_week + 7 - (calendar.min_week_days as i32)) / 7) as u8 + } + + /// Returns the week number for the given day in this unit. + fn relative_week(self, calendar: WeekCalculator, day: u16) -> RelativeWeek { + let days_since_first_week = + i32::from(day) - i32::from(self.first_week_offset(calendar)) - 1; + if days_since_first_week < 0 { + return RelativeWeek::LastWeekOfPreviousUnit; + } + + let week_number = (1 + days_since_first_week / 7) as u8; + if week_number > self.num_weeks(calendar) { + return RelativeWeek::FirstWeekOfNextUnit; + } + RelativeWeek::WeekOfCurrentUnit(week_number) + } +} + +/// The year or month that a calendar assigns a week to relative to the year/month that it is in. +#[derive(Debug, PartialEq)] +#[allow(clippy::exhaustive_enums)] // this type is stable +pub(crate) enum RelativeUnit { + /// A week that is assigned to previous year/month. e.g. 2021-01-01 is week 54 of 2020 per the ISO calendar. + Previous, + /// A week that's assigned to the current year/month. e.g. 2021-01-11 is week 2 of 2021 per the ISO calendar. + Current, + /// A week that is assigned to the next year/month. e.g. 2019-12-31 is week 1 of 2020 per the ISO calendar. + Next, +} + +/// The week number assigned to a given week according to a calendar. +#[derive(Debug, PartialEq)] +#[allow(clippy::exhaustive_structs)] // this type is stable +pub(crate) struct WeekOf { + /// Week of month/year. 1 based. + pub week: u8, + /// The month/year that this week is in, relative to the month/year of the input date. + pub unit: RelativeUnit, +} + +/// [Iterator] that yields weekdays that are part of the weekend. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct WeekdaySetIterator { + /// Determines the order in which we should start reading values from `weekend`. + first_weekday: Weekday, + /// Day being evaluated. + current_day: Weekday, + /// Bitset to read weekdays from. + weekend: WeekdaySet, +} + +impl WeekdaySetIterator { + /// Creates the Iterator. Sets `current_day` to the day after `first_weekday`. + pub(crate) fn new(first_weekday: Weekday, weekend: WeekdaySet) -> Self { + WeekdaySetIterator { + first_weekday, + current_day: first_weekday, + weekend, + } + } +} + +impl Iterator for WeekdaySetIterator { + type Item = Weekday; + + fn next(&mut self) -> Option { + // Check each bit until we find one that is ON or until we are back to the start of the week. + while self.current_day.next_day() != self.first_weekday { + if self.weekend.contains(self.current_day) { + let result = self.current_day; + self.current_day = self.current_day.next_day(); + return Some(result); + } else { + self.current_day = self.current_day.next_day(); + } + } + + if self.weekend.contains(self.current_day) { + // Clear weekend, we've seen all bits. + // Breaks the loop next time `next()` is called + self.weekend = WeekdaySet::new(&[]); + return Some(self.current_day); + } + + Option::None + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{types::Weekday, Date, DateDuration, RangeError}; + + static ISO_CALENDAR: WeekCalculator = WeekCalculator { + first_weekday: Weekday::Monday, + min_week_days: 4, + }; + + static AE_CALENDAR: WeekCalculator = WeekCalculator { + first_weekday: Weekday::Saturday, + min_week_days: 4, + }; + + static US_CALENDAR: WeekCalculator = WeekCalculator { + first_weekday: Weekday::Sunday, + min_week_days: 1, + }; + + #[test] + fn test_weekday_index() { + assert_eq!(ISO_CALENDAR.weekday_index(Weekday::Monday), 0); + assert_eq!(ISO_CALENDAR.weekday_index(Weekday::Sunday), 6); + + assert_eq!(AE_CALENDAR.weekday_index(Weekday::Saturday), 0); + assert_eq!(AE_CALENDAR.weekday_index(Weekday::Friday), 6); + } + + #[test] + fn test_first_week_offset() { + let first_week_offset = + |calendar, day| UnitInfo::new(day, 30).unwrap().first_week_offset(calendar); + assert_eq!(first_week_offset(ISO_CALENDAR, Weekday::Monday), 0); + assert_eq!(first_week_offset(ISO_CALENDAR, Weekday::Tuesday), -1); + assert_eq!(first_week_offset(ISO_CALENDAR, Weekday::Wednesday), -2); + assert_eq!(first_week_offset(ISO_CALENDAR, Weekday::Thursday), -3); + assert_eq!(first_week_offset(ISO_CALENDAR, Weekday::Friday), 3); + assert_eq!(first_week_offset(ISO_CALENDAR, Weekday::Saturday), 2); + assert_eq!(first_week_offset(ISO_CALENDAR, Weekday::Sunday), 1); + + assert_eq!(first_week_offset(AE_CALENDAR, Weekday::Saturday), 0); + assert_eq!(first_week_offset(AE_CALENDAR, Weekday::Sunday), -1); + assert_eq!(first_week_offset(AE_CALENDAR, Weekday::Monday), -2); + assert_eq!(first_week_offset(AE_CALENDAR, Weekday::Tuesday), -3); + assert_eq!(first_week_offset(AE_CALENDAR, Weekday::Wednesday), 3); + assert_eq!(first_week_offset(AE_CALENDAR, Weekday::Thursday), 2); + assert_eq!(first_week_offset(AE_CALENDAR, Weekday::Friday), 1); + + assert_eq!(first_week_offset(US_CALENDAR, Weekday::Sunday), 0); + assert_eq!(first_week_offset(US_CALENDAR, Weekday::Monday), -1); + assert_eq!(first_week_offset(US_CALENDAR, Weekday::Tuesday), -2); + assert_eq!(first_week_offset(US_CALENDAR, Weekday::Wednesday), -3); + assert_eq!(first_week_offset(US_CALENDAR, Weekday::Thursday), -4); + assert_eq!(first_week_offset(US_CALENDAR, Weekday::Friday), -5); + assert_eq!(first_week_offset(US_CALENDAR, Weekday::Saturday), -6); + } + + #[test] + fn test_num_weeks() { + // 4 days in first & last week. + assert_eq!( + UnitInfo::new(Weekday::Thursday, 4 + 2 * 7 + 4) + .unwrap() + .num_weeks(ISO_CALENDAR), + 4 + ); + // 3 days in first week, 4 in last week. + assert_eq!( + UnitInfo::new(Weekday::Friday, 3 + 2 * 7 + 4) + .unwrap() + .num_weeks(ISO_CALENDAR), + 3 + ); + // 3 days in first & last week. + assert_eq!( + UnitInfo::new(Weekday::Friday, 3 + 2 * 7 + 3) + .unwrap() + .num_weeks(ISO_CALENDAR), + 2 + ); + + // 1 day in first & last week. + assert_eq!( + UnitInfo::new(Weekday::Saturday, 1 + 2 * 7 + 1) + .unwrap() + .num_weeks(US_CALENDAR), + 4 + ); + } + + /// Uses enumeration & bucketing to assign each day of a month or year `unit` to a week. + /// + /// This alternative implementation serves as an exhaustive safety check + /// of relative_week() (in addition to the manual test points used + /// for testing week_of()). + fn classify_days_of_unit(calendar: WeekCalculator, unit: &UnitInfo) -> Vec { + let mut weeks: Vec> = Vec::new(); + for day_index in 0..unit.duration_days { + let day = super::add_to_weekday(unit.first_day, i32::from(day_index)); + if day == calendar.first_weekday || weeks.is_empty() { + weeks.push(Vec::new()); + } + weeks.last_mut().unwrap().push(day); + } + + let mut day_week_of_units = Vec::new(); + let mut weeks_in_unit = 0; + for (index, week) in weeks.iter().enumerate() { + let week_of_unit = if week.len() < usize::from(calendar.min_week_days) { + match index { + 0 => RelativeWeek::LastWeekOfPreviousUnit, + x if x == weeks.len() - 1 => RelativeWeek::FirstWeekOfNextUnit, + _ => panic!(), + } + } else { + weeks_in_unit += 1; + RelativeWeek::WeekOfCurrentUnit(weeks_in_unit) + }; + + day_week_of_units.append(&mut [week_of_unit].repeat(week.len())); + } + day_week_of_units + } + + #[test] + fn test_relative_week_of_month() { + for min_week_days in 1..7 { + for start_of_week in 1..7 { + let calendar = WeekCalculator { + first_weekday: Weekday::from_days_since_sunday(start_of_week), + min_week_days, + }; + for unit_duration in super::MIN_UNIT_DAYS..400 { + for start_of_unit in 1..7 { + let unit = UnitInfo::new( + Weekday::from_days_since_sunday(start_of_unit), + unit_duration, + ) + .unwrap(); + let expected = classify_days_of_unit(calendar, &unit); + for (index, expected_week_of) in expected.iter().enumerate() { + let day = index + 1; + assert_eq!( + unit.relative_week(calendar, day as u16), + *expected_week_of, + "For the {day}/{unit_duration} starting on Weekday \ + {start_of_unit} using start_of_week {start_of_week} \ + & min_week_days {min_week_days}" + ); + } + } + } + } + } + } + + fn week_of_month_from_iso_date( + calendar: WeekCalculator, + yyyymmdd: u32, + ) -> Result { + let year = (yyyymmdd / 10000) as i32; + let month = ((yyyymmdd / 100) % 100) as u8; + let day = (yyyymmdd % 100) as u8; + + let date = Date::try_new_iso(year, month, day)?; + let previous_month = date.added(DateDuration::new(0, -1, 0, 0)); + + calendar.week_of( + u16::from(previous_month.days_in_month()), + u16::from(date.days_in_month()), + u16::from(day), + date.day_of_week(), + ) + } + + #[test] + fn test_week_of_month_using_dates() { + assert_eq!( + week_of_month_from_iso_date(ISO_CALENDAR, 20210418).unwrap(), + WeekOf { + week: 3, + unit: RelativeUnit::Current, + } + ); + assert_eq!( + week_of_month_from_iso_date(ISO_CALENDAR, 20210419).unwrap(), + WeekOf { + week: 4, + unit: RelativeUnit::Current, + } + ); + + // First day of year is a Thursday. + assert_eq!( + week_of_month_from_iso_date(ISO_CALENDAR, 20180101).unwrap(), + WeekOf { + week: 1, + unit: RelativeUnit::Current, + } + ); + // First day of year is a Friday. + assert_eq!( + week_of_month_from_iso_date(ISO_CALENDAR, 20210101).unwrap(), + WeekOf { + week: 5, + unit: RelativeUnit::Previous, + } + ); + + // The month ends on a Wednesday. + assert_eq!( + week_of_month_from_iso_date(ISO_CALENDAR, 20200930).unwrap(), + WeekOf { + week: 1, + unit: RelativeUnit::Next, + } + ); + // The month ends on a Thursday. + assert_eq!( + week_of_month_from_iso_date(ISO_CALENDAR, 20201231).unwrap(), + WeekOf { + week: 5, + unit: RelativeUnit::Current, + } + ); + + // US calendar always assigns the week to the current month. 2020-12-31 is a Thursday. + assert_eq!( + week_of_month_from_iso_date(US_CALENDAR, 20201231).unwrap(), + WeekOf { + week: 5, + unit: RelativeUnit::Current, + } + ); + assert_eq!( + week_of_month_from_iso_date(US_CALENDAR, 20210101).unwrap(), + WeekOf { + week: 1, + unit: RelativeUnit::Current, + } + ); + } +} + +#[test] +fn test_first_day() { + use icu_locale_core::locale; + + assert_eq!( + WeekInformation::try_new(locale!("und-US").into()) + .unwrap() + .first_weekday, + Weekday::Sunday, + ); + + assert_eq!( + WeekInformation::try_new(locale!("und-FR").into()) + .unwrap() + .first_weekday, + Weekday::Monday, + ); + + assert_eq!( + WeekInformation::try_new(locale!("und-FR-u-fw-tue").into()) + .unwrap() + .first_weekday, + Weekday::Tuesday, + ); +} + +#[test] +fn test_weekend() { + use icu_locale_core::locale; + + assert_eq!( + WeekInformation::try_new(locale!("und").into()) + .unwrap() + .weekend() + .collect::>(), + vec![Weekday::Saturday, Weekday::Sunday], + ); + + assert_eq!( + WeekInformation::try_new(locale!("und-FR").into()) + .unwrap() + .weekend() + .collect::>(), + vec![Weekday::Saturday, Weekday::Sunday], + ); + + assert_eq!( + WeekInformation::try_new(locale!("und-IQ").into()) + .unwrap() + .weekend() + .collect::>(), + vec![Weekday::Saturday, Weekday::Friday], + ); + + assert_eq!( + WeekInformation::try_new(locale!("und-IR").into()) + .unwrap() + .weekend() + .collect::>(), + vec![Weekday::Friday], + ); +} + +#[test] +fn test_weekdays_iter() { + use Weekday::*; + + // Weekend ends one day before week starts + let default_weekend = WeekdaySetIterator::new(Monday, WeekdaySet::new(&[Saturday, Sunday])); + assert_eq!(vec![Saturday, Sunday], default_weekend.collect::>()); + + // Non-contiguous weekend + let fri_sun_weekend = WeekdaySetIterator::new(Monday, WeekdaySet::new(&[Friday, Sunday])); + assert_eq!(vec![Friday, Sunday], fri_sun_weekend.collect::>()); + + let multiple_contiguous_days = WeekdaySetIterator::new( + Monday, + WeekdaySet::new(&[ + Weekday::Tuesday, + Weekday::Wednesday, + Weekday::Thursday, + Weekday::Friday, + ]), + ); + assert_eq!( + vec![Tuesday, Wednesday, Thursday, Friday], + multiple_contiguous_days.collect::>() + ); + + // Non-contiguous days and iterator yielding elements based off first_weekday + let multiple_non_contiguous_days = WeekdaySetIterator::new( + Wednesday, + WeekdaySet::new(&[ + Weekday::Tuesday, + Weekday::Thursday, + Weekday::Friday, + Weekday::Sunday, + ]), + ); + assert_eq!( + vec![Thursday, Friday, Sunday, Tuesday], + multiple_non_contiguous_days.collect::>() + ); +} + +#[test] +fn test_iso_weeks() { + use crate::types::IsoWeekOfYear; + use crate::Date; + + #[allow(clippy::zero_prefixed_literal)] + for ((y, m, d), (iso_year, week_number)) in [ + // 2010 starts on a Thursday, so 2009 has 53 ISO weeks + ((2009, 12, 30), (2009, 53)), + ((2009, 12, 31), (2009, 53)), + ((2010, 01, 01), (2009, 53)), + ((2010, 01, 02), (2009, 53)), + ((2010, 01, 03), (2009, 53)), + ((2010, 01, 04), (2010, 1)), + ((2010, 01, 05), (2010, 1)), + // 2030 starts on a Monday + ((2029, 12, 29), (2029, 52)), + ((2029, 12, 30), (2029, 52)), + ((2029, 12, 31), (2030, 1)), + ((2030, 01, 01), (2030, 1)), + ((2030, 01, 02), (2030, 1)), + ((2030, 01, 03), (2030, 1)), + ((2030, 01, 04), (2030, 1)), + ] { + assert_eq!( + Date::try_new_iso(y, m, d).unwrap().week_of_year(), + IsoWeekOfYear { + iso_year, + week_number + } + ); + } +} diff --git a/deps/crates/vendor/icu_calendar_data/.cargo-checksum.json b/deps/crates/vendor/icu_calendar_data/.cargo-checksum.json new file mode 100644 index 00000000000000..1f89ad9e1d30ab --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"53ee9b1dd6ad1a0b1dcb72e7c08db14631db21ecbf7f9f1ed3b10f29b6a8899a","LICENSE":"f367c1b8e1aa262435251e442901da4607b4650e0e63a026f5044473ecfb90f2","README.md":"c34a8f4d0526ef4b3acc8383a1ab33422dc040dd3b9cf5bf0684125beb8fdd71","build.rs":"c2d446772e3d766a804963dbf36e51729f910920f91f4b68c0c199fe6ca0853e","data/calendar_chinese_v1.rs.data":"245c945efcd1ab04d9aad235617d9580bac52061403d371c47d23cce14eaab65","data/calendar_dangi_v1.rs.data":"916f004b0aba23972d96faffb83a06459034a8603037c35ea0e5d4e084bfbd2a","data/calendar_hijri_simulated_mecca_v1.rs.data":"111da8179793ee6d03091a525419e3d34dc6018474189e2f246f0775f3324814","data/calendar_japanese_extended_v1.rs.data":"24c71e99ec40cfecdcd10e2e006b8b708498f2427b7fdf7f63ae2ecbdb7e8b61","data/calendar_japanese_modern_v1.rs.data":"f34dd70c859071b74235200d3389a22c8fb08a895fb326e11fbc1be16c92e686","data/calendar_week_v1.rs.data":"908fba042125ff2c1ff911619ef5926423dd0e2d15f8c70ea9838e3a357002ec","data/mod.rs":"9a9f9b8da50eba75f93763b90bf068cf9de34795a9baca05146912dab9fc1bc8","src/lib.rs":"62940139b0cb9cbe9629ab45e716b095403f13042b08c378f17de8357ccab253"},"package":"7219c8639ab936713a87b571eed2bc2615aa9137e8af6eb221446ee5644acc18"} \ No newline at end of file diff --git a/deps/crates/vendor/icu_calendar_data/Cargo.toml b/deps/crates/vendor/icu_calendar_data/Cargo.toml new file mode 100644 index 00000000000000..48da7be47196bc --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/Cargo.toml @@ -0,0 +1,60 @@ +# 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.82" +name = "icu_calendar_data" +version = "2.0.0" +authors = ["The ICU4X Project Developers"] +build = "build.rs" +include = [ + "data/**/*", + "src/**/*", + "examples/**/*", + "benches/**/*", + "tests/**/*", + "Cargo.toml", + "LICENSE", + "README.md", + "build.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Data for the icu_calendar crate" +homepage = "https://icu4x.unicode.org" +readme = "README.md" +categories = ["internationalization"] +license = "Unicode-3.0" +repository = "https://github.com/unicode-org/icu4x" + +[package.metadata.sources.cldr] +tagged = "47.0.0" + +[package.metadata.sources.icuexport] +tagged = "icu4x/2025-05-01/77.x" + +[package.metadata.sources.segmenter_lstm] +tagged = "v0.1.0" + +[lib] +name = "icu_calendar_data" +path = "src/lib.rs" + +[dependencies] + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = ["cfg(icu4x_custom_data)"] diff --git a/deps/crates/vendor/icu_calendar_data/LICENSE b/deps/crates/vendor/icu_calendar_data/LICENSE new file mode 100644 index 00000000000000..c9be6012c53792 --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/LICENSE @@ -0,0 +1,46 @@ +UNICODE LICENSE V3 + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 2020-2024 Unicode, Inc. + +NOTICE TO USER: Carefully read the following legal agreement. BY +DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR +SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT +DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of data files and any associated documentation (the "Data Files") or +software and any associated documentation (the "Software") to deal in the +Data Files or Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, and/or sell +copies of the Data Files or Software, and to permit persons to whom the +Data Files or Software are furnished to do so, provided that either (a) +this copyright and permission notice appear with all copies of the Data +Files or Software, or (b) this copyright and permission notice appear in +associated Documentation. + +THE DATA FILES AND SOFTWARE ARE 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 OF +THIRD PARTY RIGHTS. + +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE +BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA +FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in these Data Files or Software without prior written +authorization of the copyright holder. + +SPDX-License-Identifier: Unicode-3.0 + +— + +Portions of ICU4X may have been adapted from ICU4C and/or ICU4J. +ICU 1.8.1 to ICU 57.1 © 1995-2016 International Business Machines Corporation and others. diff --git a/deps/crates/vendor/icu_calendar_data/README.md b/deps/crates/vendor/icu_calendar_data/README.md new file mode 100644 index 00000000000000..19c1f48292c481 --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/README.md @@ -0,0 +1,14 @@ +# icu_calendar_data [![crates.io](https://img.shields.io/crates/v/icu_calendar_data)](https://crates.io/crates/icu_calendar_data) + + + +Data for the `icu_calendar` crate + +This data was generated with CLDR version 47.0.0, ICU version icu4x/2025-05-01/77.x, and +LSTM segmenter version v0.1.0. + + + +## More Information + +For more information on development, authorship, contributing etc. please visit [`ICU4X home page`](https://github.com/unicode-org/icu4x). diff --git a/deps/crates/vendor/icu_calendar_data/build.rs b/deps/crates/vendor/icu_calendar_data/build.rs new file mode 100644 index 00000000000000..62e9cb73c569dc --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/build.rs @@ -0,0 +1,11 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +fn main() { + if std::env::var("ICU4X_DATA_DIR").is_ok() { + println!("cargo:rustc-cfg=icu4x_custom_data"); + } + println!("cargo:rerun-if-env-changed=ICU4X_DATA_DIR"); + println!("cargo:rustc-check-cfg=cfg(icu4c_enable_renaming)"); +} diff --git a/deps/crates/vendor/icu_calendar_data/data/calendar_chinese_v1.rs.data b/deps/crates/vendor/icu_calendar_data/data/calendar_chinese_v1.rs.data new file mode 100644 index 00000000000000..944a49c45490c8 --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/data/calendar_chinese_v1.rs.data @@ -0,0 +1,75 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +/// +/// Using this implementation will embed the following data in the binary's data segment: +/// * 782B[^1] for the singleton data struct +/// +/// [^1]: these numbers can be smaller in practice due to linker deduplication +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_calendar_chinese_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.82"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.82"] + impl $provider { + #[doc(hidden)] + pub const SINGLETON_CALENDAR_CHINESE_V1: &'static ::DataStruct = &icu::calendar::provider::chinese_based::ChineseBasedCache { first_related_iso_year: 1900i32, data: unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\xD26\x19R\x07>\xA5\x0E(J\xD6\x14K\x068\x9B\n Z\xB5\x0Cj\x052Y\x0B\x1CRw\x06R\x07,%\xFB\x16%\x0B+\x05([\xEA\x10\xAD\n6j\x05\"U\xBB\x0C\xA4\x0B2I\x0B\x1C\x93z\x06\x95\n,-\x15\x156\x05:\xAD\n$\xAA\xD5\x10\xB2\x054\xA5\r\x1EJ\x9D\nJ\r0\x95*\x19\x97\n\xD5\x06&\xC9\xD6\x12I\x078\x93\x06\"+\xB5\n+\x050[\n\x1AZu\x06j\x05*U\x1B\x15\xA4\x0B\xA5\r(J\xFD\x12J\r8\x95\x0C\".\xB5\x0CV\x050\xB5\n\x1A\xB2u\x06\xD2\x06,\xA5\xEE\x14%\x07:K\x06$\x97\xCC\x0E\xAB\x0C2Z\x05\x1E\xD6\x8A\x08i\x0B.R\x97\x19R\x0B>%\x0B(K\xFA\x12K\n6\xAB\x04 [\xC5\n\xAD\x050j\x0B\x1AR{\x06\x92\r,%\x1D\x17%\r:U\n$\xAD\xD4\x0E\xB6\x044\xB5\x05\x1C\xAA\x8D\x08\xC9\x0E.\x92>\x1B\x92\x0E>&\r(V\xEA\x12W\n6V\x05 \xD5\xA6\nU\x070I\x07\x1C\x93\x8E\x04\x93\x06*+\x15\x15+\x05:[\n\"Z\xD5\x0Ej\x054e\x0B\x1EJ\xB7\x08J\x0B.\x95:\x19\x95\n>-\x05&\xAD\xEA\x10\xB5\n6\xAA\x05\"\xA5\xAB\n\xA5\r0J\r\x1C\x95\x9C\x06\x96\x0C*N\x19\x15V\x05:\xB5\n$\xB2\xD5\x0E\xD2\x064\xA5\x0E\x1EJ\xAE\n\x8B\x06,\x97,\x17\xAB\x04<[\x05&\xD6\xEA\x10j\x0B6R\x07\"%\xB7\x0CE\x0B0\x8B\n\x1A\x9Bt\x04\xAB\x04*[\t\x15\xAD\x05:\xAA\x0B&R\xDB\x12\x92\r6%\r K\xBA\nU\n0\xADT\x19\xB6\x04>\xB5\x06(\xAA\xED\x14\xC9\x0E8\x92\x0E$&\xBD\x0E*\r4V\n\x1C\xB6\x94\x06V\x05,\xD5\n\x17U\x0B:J\x07&\x93\xCE\x10\x95\x066+\x05\x1EW\xAA\x08\x9B\n.Z\x95\x1Bj\x05>e\x0B(J\xF7\x14J\x0B:\x15\x0B\"+\xD5\x0CM\x052\xAD\n\x1Cju\x06\xAA\x05,\xA5\x0B\x17\xA5\r for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponse { payload: icu_provider::DataPayload::from_static_ref(Self::SINGLETON_CALENDAR_CHINESE_V1), metadata: icu_provider::DataResponseMetadata::default() }) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + }; + ($ provider : ty , ITER) => { + __impl_calendar_chinese_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::IterableDataProvider for $provider { + fn iter_ids(&self) -> Result>, icu_provider::DataError> { + Ok([Default::default()].into_iter().collect()) + } + } + }; + ($ provider : ty , DRY) => { + __impl_calendar_chinese_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::DryDataProvider for $provider { + fn dry_load(&self, req: icu_provider::DataRequest) -> Result { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponseMetadata::default()) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + }; + ($ provider : ty , DRY , ITER) => { + __impl_calendar_chinese_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::DryDataProvider for $provider { + fn dry_load(&self, req: icu_provider::DataRequest) -> Result { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponseMetadata::default()) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + #[clippy::msrv = "1.82"] + impl icu_provider::IterableDataProvider for $provider { + fn iter_ids(&self) -> Result>, icu_provider::DataError> { + Ok([Default::default()].into_iter().collect()) + } + } + }; +} +#[doc(inline)] +pub use __impl_calendar_chinese_v1 as impl_calendar_chinese_v1; diff --git a/deps/crates/vendor/icu_calendar_data/data/calendar_dangi_v1.rs.data b/deps/crates/vendor/icu_calendar_data/data/calendar_dangi_v1.rs.data new file mode 100644 index 00000000000000..30045896317596 --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/data/calendar_dangi_v1.rs.data @@ -0,0 +1,75 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +/// +/// Using this implementation will embed the following data in the binary's data segment: +/// * 782B[^1] for the singleton data struct +/// +/// [^1]: these numbers can be smaller in practice due to linker deduplication +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_calendar_dangi_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.82"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.82"] + impl $provider { + #[doc(hidden)] + pub const SINGLETON_CALENDAR_DANGI_V1: &'static ::DataStruct = &icu::calendar::provider::chinese_based::ChineseBasedCache { first_related_iso_year: 1900i32, data: unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\xD26\x19R\x07>\xA5\x0E(J\xCE\x14K\x058\x97\n V\xB5\x0Cj\x052U\x0B\x1CRw\x06R\x07,%\xF7\x16%\x0B+\x05([\xEA\x10m\t6j\x0B\"T\xBB\x0E\xA4\x0B2I\x0B\x1C\x93z\x06\x95\n,+\x15\x15-\x05:\xAD\n$j\xD5\x10\xB2\r4\xA4\r I\x9D\nJ\r0\x95:\x19\x96\n>V\x05(\xB5\xEA\x12\xD5\n6\xD2\x06\"\xA5\xAE\x0C\xA5\x0E2J\x0E\x1C\x96\x8C\x06\x9B\n*V\x15\x17j\x05:Y\x0B$R\xD7\x10R\x076%\x07\x1EK\xB6\x08K\n.\xAB2\x19\xAD\x02\xD4\x06(\xC9\xCE\x12I\x078\x93\x06\"'\xB5\n+\x050[\n\x1AZu\x06j\x03*U\x1B\x15\xA4\x0B\xA5\r(J\xDD\x12J\r8\x95\n\"-\xB5\x0CV\x050\xB5\n\x1A\xAAu\x06\xD2\x06,\xA5\xEE\x14\xA5\x0E:J\x0E&\x96\xCC\x10\x9B\x0C2Z\x05\x1E\xD5\x8A\x08i\x0B.R\x97\x19R\x07>%\x0B(K\xF6\x12K\n6\xAB\x04 [\xC5\nm\x050i\x0B\x1AR{\x06\x92\r,%\x1D\x17%\r:M\n$\xAD\xD4\x0E\xB6\x024\xB5\x05\x1C\xA9\x8D\x08\xA9\x0E.\x92=\x1B\x92\x0E>&\r(V\xEA\x12W\n6\xD6\x04 \xB5\xA6\n\xD5\x060\xC9\x0E\x1C\x92\x8E\x06\x93\x06*+\x15\x15+\x05:[\n\"Z\xD5\x0Ej\x054U\x0B\x1EI\xB7\x08I\x0B.\x93:\x19\x95\n>-\x05&\xAD\xEA\x10\xB5\n6\xAA\x05\"\xA5\xAB\n\xA5\r0J\r\x1C\x95\x9A\x06\x95\x0C*.\x15\x15V\x05:\xB5\n$\xB2\xD5\x0E\xD2\x064\xA5\x0E\x1EJ\xBE\nJ\x06.\x97,\x17\xAB\x0C\xB5\x05(\xAA\xED\x14\xC9\x0E8\x92\x0E$%\xBD\x0E&\r4V\n\x1C\xAE\x94\x06\xD6\x04,\xD5\n\x17\xD5\x06:\xC9\x06&\x93\xCE\x10\x93\x066+\x05\x1EW\xAA\x08[\n.ZU\x1Bj\x05>e\x0B(J\xF7\x14I\x0B:\x95\n\"+\xD5\x0C-\x052\xAD\n\x1Cju\x06\xAA\x05,\xA5\x0B\x17\xA5\r for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponse { payload: icu_provider::DataPayload::from_static_ref(Self::SINGLETON_CALENDAR_DANGI_V1), metadata: icu_provider::DataResponseMetadata::default() }) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + }; + ($ provider : ty , ITER) => { + __impl_calendar_dangi_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::IterableDataProvider for $provider { + fn iter_ids(&self) -> Result>, icu_provider::DataError> { + Ok([Default::default()].into_iter().collect()) + } + } + }; + ($ provider : ty , DRY) => { + __impl_calendar_dangi_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::DryDataProvider for $provider { + fn dry_load(&self, req: icu_provider::DataRequest) -> Result { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponseMetadata::default()) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + }; + ($ provider : ty , DRY , ITER) => { + __impl_calendar_dangi_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::DryDataProvider for $provider { + fn dry_load(&self, req: icu_provider::DataRequest) -> Result { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponseMetadata::default()) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + #[clippy::msrv = "1.82"] + impl icu_provider::IterableDataProvider for $provider { + fn iter_ids(&self) -> Result>, icu_provider::DataError> { + Ok([Default::default()].into_iter().collect()) + } + } + }; +} +#[doc(inline)] +pub use __impl_calendar_dangi_v1 as impl_calendar_dangi_v1; diff --git a/deps/crates/vendor/icu_calendar_data/data/calendar_hijri_simulated_mecca_v1.rs.data b/deps/crates/vendor/icu_calendar_data/data/calendar_hijri_simulated_mecca_v1.rs.data new file mode 100644 index 00000000000000..4803503a2a71f8 --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/data/calendar_hijri_simulated_mecca_v1.rs.data @@ -0,0 +1,75 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +/// +/// Using this implementation will embed the following data in the binary's data segment: +/// * 532B[^1] for the singleton data struct +/// +/// [^1]: these numbers can be smaller in practice due to linker deduplication +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_calendar_hijri_simulated_mecca_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.82"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.82"] + impl $provider { + #[doc(hidden)] + pub const SINGLETON_CALENDAR_HIJRI_SIMULATED_MECCA_V1: &'static ::DataStruct = &icu::calendar::provider::hijri::HijriData { first_extended_year: 1317i32, data: unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"O9\xAE\x02\xAD\x05\xA9\r\x92-E-\x8D\n-\x05m\x05j\x0BT'I\x07\x8B\x0E&-V\x05\xAE\nl#j\x07T'\xA5\x06M\x05]\n\\\x05\xBA\n\xB4%\xAA\rT-\xAA*6\t\xB6\x02u5\xEA\nT'\xA9\x06+\x05[\n6\x05v\nl\x05Y\x0BJ+\x95\n+\t[\nZ\x05\xD5\n\xD2&\xA5\x0EJ.\x96\x0C.\tm\nj\x05Y\x0BI/\x94.*-Z*\xBA\x04\xB5\x05\xB2\x0B\xA4+I+\x95\n\xB5\x04m\t\xEA\x02\xE9\x06\xD2\x0E\xA4.*-V\n\xB6\x04u\x05\xEA\n\xE4*\xA9*S\n\xAB\x04W9\xB6\x02\xB5\t\xAA\x05S\r&-N\n\xAE\x04m\t\xEA\x02\xD5\n\xA9\x06S\x05\xA7\x0479\xB5\x02k\x05i\x0BR'\xA5\x06K\x05\xAB\x02[5\xEA\n\xD4%\xC9\r\x92-%+U\t\xAD\x02k5\xE9\n\xD2%\xA5\x05K\x05\x97\x02\xB74\xB6\t\xB4\x03\xA9\x0BJ+\x96\n.\t^\x02\xDD4\xDA\n\xD4%\xA5\x05K\x05W:\xAE\x04n\tl\x03U\x0BJ'\x8D\x06'\x05W\n\xB6\x04\xB5\x06\xAA\r\xA4-I-\x95\n-\x05\xAD\nZ\x03U\x07J\x0F\x92.&+V\x06\xAE\x02u\x05j\x0BT'\xA9&U\x06\xAD\x04]9\xBA\x02\xB9\x05\xB2\rT-*+V\t\xB6\x02u\x05Z\x0B\xD4&\xA9\x06K\x05\x9B\x0C6\tv\x02u\x05i\rR-%\rK\n\x9B\x04[9\xDA\n\xD4&\xA9\x0EJ.\x96,-\tm\nl\x05i\x0BQ/\xA4.J-Z*\xDA\x04\xB9\t\xB4\x05\xA9\x0BR+\xA5\nU\x05m\nl\x05\xE9\x06\xD2.\xA4.J-V\n\xB6\x04u\t\xEA\x04\xE5\n\xAA*U\n\xAB\x04W\x02\xB74\xB5\n\xAA\x05\x95\r*-V\n\xAE\x08m\t\xEA\x02\xD5\n\xA9\x06S\x06'\x05W9\xB5\x02\xB5\x05\xAA\x0B\xA2'E'\x93\x06\xAB\x04k9\xEA\n\xD4%\xC9\r\xA2-%-U\t\xAD\x02m\x05\xEA\t\xD4%\xA5\x05K\x05") } }; + } + #[clippy::msrv = "1.82"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponse { payload: icu_provider::DataPayload::from_static_ref(Self::SINGLETON_CALENDAR_HIJRI_SIMULATED_MECCA_V1), metadata: icu_provider::DataResponseMetadata::default() }) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + }; + ($ provider : ty , ITER) => { + __impl_calendar_hijri_simulated_mecca_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::IterableDataProvider for $provider { + fn iter_ids(&self) -> Result>, icu_provider::DataError> { + Ok([Default::default()].into_iter().collect()) + } + } + }; + ($ provider : ty , DRY) => { + __impl_calendar_hijri_simulated_mecca_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::DryDataProvider for $provider { + fn dry_load(&self, req: icu_provider::DataRequest) -> Result { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponseMetadata::default()) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + }; + ($ provider : ty , DRY , ITER) => { + __impl_calendar_hijri_simulated_mecca_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::DryDataProvider for $provider { + fn dry_load(&self, req: icu_provider::DataRequest) -> Result { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponseMetadata::default()) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + #[clippy::msrv = "1.82"] + impl icu_provider::IterableDataProvider for $provider { + fn iter_ids(&self) -> Result>, icu_provider::DataError> { + Ok([Default::default()].into_iter().collect()) + } + } + }; +} +#[doc(inline)] +pub use __impl_calendar_hijri_simulated_mecca_v1 as impl_calendar_hijri_simulated_mecca_v1; diff --git a/deps/crates/vendor/icu_calendar_data/data/calendar_japanese_extended_v1.rs.data b/deps/crates/vendor/icu_calendar_data/data/calendar_japanese_extended_v1.rs.data new file mode 100644 index 00000000000000..338b69e5c61508 --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/data/calendar_japanese_extended_v1.rs.data @@ -0,0 +1,75 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +/// +/// Using this implementation will embed the following data in the binary's data segment: +/// * 5238B[^1] for the singleton data struct +/// +/// [^1]: these numbers can be smaller in practice due to linker deduplication +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_calendar_japanese_extended_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.82"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.82"] + impl $provider { + #[doc(hidden)] + pub const SINGLETON_CALENDAR_JAPANESE_EXTENDED_V1: &'static ::DataStruct = &icu::calendar::provider::JapaneseEras { dates_to_eras: unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x85\x02\0\0\x06\x13taika-645\0\0\0\0\0\0\0\x8A\x02\0\0\x02\x0Fhakuchi-650\0\0\0\0\0\xA0\x02\0\0\x01\x01hakuho-672\0\0\0\0\0\0\xAE\x02\0\0\x07\x14shucho-686\0\0\0\0\0\0\xBD\x02\0\0\x03\x15taiho-701\0\0\0\0\0\0\0\xC0\x02\0\0\x05\nkeiun-704\0\0\0\0\0\0\0\xC4\x02\0\0\x01\x0Bwado-708\0\0\0\0\0\0\0\0\xCB\x02\0\0\t\x02reiki-715\0\0\0\0\0\0\0\xCD\x02\0\0\x0B\x11yoro-717\0\0\0\0\0\0\0\0\xD4\x02\0\0\x02\x04jinki-724\0\0\0\0\0\0\0\xD9\x02\0\0\x08\x05tenpyo-729\0\0\0\0\0\0\xED\x02\0\0\x04\x0Etenpyokampo-749\0\xED\x02\0\0\x07\x02tenpyoshoho-749\0\xF5\x02\0\0\x08\x12tenpyohoji-757\0\0\xFD\x02\0\0\x01\x07tenpyojingo-765\0\xFF\x02\0\0\x08\x10jingokeiun-767\0\0\x02\x03\0\0\n\x01hoki-770\0\0\0\0\0\0\0\0\r\x03\0\0\x01\x01teno-781\0\0\0\0\0\0\0\0\x0E\x03\0\0\x08\x13enryaku-782\0\0\0\0\0&\x03\0\0\x05\x12daido-806\0\0\0\0\0\0\0*\x03\0\0\t\x13konin-810\0\0\0\0\0\0\08\x03\0\0\x01\x05tencho-824\0\0\0\0\0\0B\x03\0\0\x01\x03jowa-834\0\0\0\0\0\0\0\0P\x03\0\0\x06\rkajo-848\0\0\0\0\0\0\0\0S\x03\0\0\x04\x1Cninju-851\0\0\0\0\0\0\0V\x03\0\0\x0B\x1Esaiko-854\0\0\0\0\0\0\0Y\x03\0\0\x02\x15tenan-857\0\0\0\0\0\0\0[\x03\0\0\x04\x0Fjogan-859\0\0\0\0\0\0\0m\x03\0\0\x04\x10gangyo-877\0\0\0\0\0\0u\x03\0\0\x02\x15ninna-885\0\0\0\0\0\0\0y\x03\0\0\x04\x1Bkanpyo-889\0\0\0\0\0\0\x82\x03\0\0\x04\x1Ashotai-898\0\0\0\0\0\0\x85\x03\0\0\x07\x0Fengi-901\0\0\0\0\0\0\0\0\x9B\x03\0\0\x04\x0Bencho-923\0\0\0\0\0\0\0\xA3\x03\0\0\x04\x1Ajohei-931\0\0\0\0\0\0\0\xAA\x03\0\0\x05\x16tengyo-938\0\0\0\0\0\0\xB3\x03\0\0\x04\x16tenryaku-947\0\0\0\0\xBD\x03\0\0\n\x1Btentoku-957\0\0\0\0\0\xC1\x03\0\0\x02\x10owa-961\0\0\0\0\0\0\0\0\0\xC4\x03\0\0\x07\nkoho-964\0\0\0\0\0\0\0\0\xC8\x03\0\0\x08\ranna-968\0\0\0\0\0\0\0\0\xCA\x03\0\0\x03\x19tenroku-970\0\0\0\0\0\xCD\x03\0\0\x0C\x14tenen-973\0\0\0\0\0\0\0\xD0\x03\0\0\x07\rjogen-976\0\0\0\0\0\0\0\xD2\x03\0\0\x0B\x1Dtengen-978\0\0\0\0\0\0\xD7\x03\0\0\x04\x0Feikan-983\0\0\0\0\0\0\0\xD9\x03\0\0\x04\x1Bkanna-985\0\0\0\0\0\0\0\xDB\x03\0\0\x04\x05eien-987\0\0\0\0\0\0\0\0\xDD\x03\0\0\x08\x08eiso-989\0\0\0\0\0\0\0\0\xDE\x03\0\0\x0B\x07shoryaku-990\0\0\0\0\xE3\x03\0\0\x02\x16chotoku-995\0\0\0\0\0\xE7\x03\0\0\x01\rchoho-999\0\0\0\0\0\0\0\xEC\x03\0\0\x07\x14kanko-1004\0\0\0\0\0\0\xF4\x03\0\0\x0C\x19chowa-1012\0\0\0\0\0\0\xF9\x03\0\0\x04\x17kannin-1017\0\0\0\0\0\xFD\x03\0\0\x02\x02jian-1021\0\0\0\0\0\0\0\0\x04\0\0\x07\rmanju-1024\0\0\0\0\0\0\x04\x04\0\0\x07\x19chogen-1028\0\0\0\0\0\r\x04\0\0\x04\x15choryaku-1037\0\0\0\x10\x04\0\0\x0B\nchokyu-1040\0\0\0\0\0\x14\x04\0\0\x0B\x18kantoku-1044\0\0\0\0\x16\x04\0\0\x04\x0Eeisho-1046\0\0\0\0\0\0\x1D\x04\0\0\x01\x0Btengi-1053\0\0\0\0\0\0\"\x04\0\0\x08\x1Dkohei-1058\0\0\0\0\0\0)\x04\0\0\x08\x02jiryaku-1065\0\0\0\0-\x04\0\0\x04\renkyu-1069\0\0\0\0\0\x002\x04\0\0\x08\x17shoho-1074\0\0\0\0\0\x005\x04\0\0\x0B\x11shoryaku-1077\0\0\09\x04\0\0\x02\neiho-1081\0\0\0\0\0\0\0<\x04\0\0\x02\x07otoku-1084\0\0\0\0\0\0?\x04\0\0\x04\x07kanji-1087\0\0\0\0\0\0F\x04\0\0\x0C\x0Fkaho-1094\0\0\0\0\0\0\0H\x04\0\0\x0C\x11eicho-1096\0\0\0\0\0\0I\x04\0\0\x0B\x15jotoku-1097\0\0\0\0\0K\x04\0\0\x08\x1Ckowa-1099\0\0\0\0\0\0\0P\x04\0\0\x02\nchoji-1104\0\0\0\0\0\0R\x04\0\0\x04\tkasho-1106\0\0\0\0\0\0T\x04\0\0\x08\x03tennin-1108\0\0\0\0\0V\x04\0\0\x07\rtenei-1110\0\0\0\0\0\0Y\x04\0\0\x07\reikyu-1113\0\0\0\0\0\0^\x04\0\0\x04\x03genei-1118\0\0\0\0\0\0`\x04\0\0\x04\nhoan-1120\0\0\0\0\0\0\0d\x04\0\0\x04\x03tenji-1124\0\0\0\0\0\0f\x04\0\0\x01\x16daiji-1126\0\0\0\0\0\0k\x04\0\0\x01\x1Dtensho-1131\0\0\0\0\0l\x04\0\0\x08\x0Bchosho-1132\0\0\0\0\0o\x04\0\0\x04\x1Bhoen-1135\0\0\0\0\0\0\0u\x04\0\0\x07\neiji-1141\0\0\0\0\0\0\0v\x04\0\0\x04\x1Ckoji-1142\0\0\0\0\0\0\0x\x04\0\0\x02\x17tenyo-1144\0\0\0\0\0\0y\x04\0\0\x07\x16kyuan-1145\0\0\0\0\0\0\x7F\x04\0\0\x01\x1Aninpei-1151\0\0\0\0\0\x82\x04\0\0\n\x1Ckyuju-1154\0\0\0\0\0\0\x84\x04\0\0\x04\x1Bhogen-1156\0\0\0\0\0\0\x87\x04\0\0\x04\x14heiji-1159\0\0\0\0\0\0\x88\x04\0\0\x01\neiryaku-1160\0\0\0\0\x89\x04\0\0\t\x04oho-1161\0\0\0\0\0\0\0\0\x8B\x04\0\0\x03\x1Dchokan-1163\0\0\0\0\0\x8D\x04\0\0\x06\x05eiman-1165\0\0\0\0\0\0\x8E\x04\0\0\x08\x1Bninan-1166\0\0\0\0\0\0\x91\x04\0\0\x04\x08kao-1169\0\0\0\0\0\0\0\0\x93\x04\0\0\x04\x15shoan-1171\0\0\0\0\0\0\x97\x04\0\0\x07\x1Cangen-1175\0\0\0\0\0\0\x99\x04\0\0\x08\x04jisho-1177\0\0\0\0\0\0\x9D\x04\0\0\x07\x0Eyowa-1181\0\0\0\0\0\0\0\x9E\x04\0\0\x05\x1Bjuei-1182\0\0\0\0\0\0\0\xA0\x04\0\0\x04\x10genryaku-1184\0\0\0\xA1\x04\0\0\x08\x0Ebunji-1185\0\0\0\0\0\0\xA6\x04\0\0\x04\x0Bkenkyu-1190\0\0\0\0\0\xAF\x04\0\0\x04\x1Bshoji-1199\0\0\0\0\0\0\xB1\x04\0\0\x02\rkennin-1201\0\0\0\0\0\xB4\x04\0\0\x02\x14genkyu-1204\0\0\0\0\0\xB6\x04\0\0\x04\x1Bkenei-1206\0\0\0\0\0\0\xB7\x04\0\0\n\x19jogen-1207\0\0\0\0\0\0\xBB\x04\0\0\x03\tkenryaku-1211\0\0\0\xBD\x04\0\0\x0C\x06kenpo-1213\0\0\0\0\0\0\xC3\x04\0\0\x04\x0Cjokyu-1219\0\0\0\0\0\0\xC6\x04\0\0\x04\rjoo-1222\0\0\0\0\0\0\0\0\xC8\x04\0\0\x0B\x14gennin-1224\0\0\0\0\0\xC9\x04\0\0\x04\x14karoku-1225\0\0\0\0\0\xCB\x04\0\0\x0C\nantei-1227\0\0\0\0\0\0\xCD\x04\0\0\x03\x05kanki-1229\0\0\0\0\0\0\xD0\x04\0\0\x04\x02joei-1232\0\0\0\0\0\0\0\xD1\x04\0\0\x04\x0Ftenpuku-1233\0\0\0\0\xD2\x04\0\0\x0B\x05bunryaku-1234\0\0\0\xD3\x04\0\0\t\x13katei-1235\0\0\0\0\0\0\xD6\x04\0\0\x0B\x17ryakunin-1238\0\0\0\xD7\x04\0\0\x02\x07eno-1239\0\0\0\0\0\0\0\0\xD8\x04\0\0\x07\x10ninji-1240\0\0\0\0\0\0\xDB\x04\0\0\x02\x1Akangen-1243\0\0\0\0\0\xDF\x04\0\0\x02\x1Choji-1247\0\0\0\0\0\0\0\xE1\x04\0\0\x03\x12kencho-1249\0\0\0\0\0\xE8\x04\0\0\n\x05kogen-1256\0\0\0\0\0\0\xE9\x04\0\0\x03\x0Eshoka-1257\0\0\0\0\0\0\xEB\x04\0\0\x03\x1Ashogen-1259\0\0\0\0\0\xEC\x04\0\0\x04\rbuno-1260\0\0\0\0\0\0\0\xED\x04\0\0\x02\x14kocho-1261\0\0\0\0\0\0\xF0\x04\0\0\x02\x1Cbunei-1264\0\0\0\0\0\0\xFB\x04\0\0\x04\x19kenji-1275\0\0\0\0\0\0\xFE\x04\0\0\x02\x1Ckoan-1278\0\0\0\0\0\0\0\x08\x05\0\0\x04\x1Cshoo-1288\0\0\0\0\0\0\0\r\x05\0\0\x08\x05einin-1293\0\0\0\0\0\0\x13\x05\0\0\x04\x19shoan-1299\0\0\0\0\0\0\x16\x05\0\0\x0B\x15kengen-1302\0\0\0\0\0\x17\x05\0\0\x08\x05kagen-1303\0\0\0\0\0\0\x1A\x05\0\0\x0C\x0Etokuji-1306\0\0\0\0\0\x1C\x05\0\0\n\tenkyo-1308\0\0\0\0\0\0\x1F\x05\0\0\x04\x1Cocho-1311\0\0\0\0\0\0\0 \x05\0\0\x03\x14showa-1312\0\0\0\0\0\0%\x05\0\0\x02\x03bunpo-1317\0\0\0\0\0\0'\x05\0\0\x04\x1Cgeno-1319\0\0\0\0\0\0\0)\x05\0\0\x02\x17genko-1321\0\0\0\0\0\0,\x05\0\0\x0C\tshochu-1324\0\0\0\0\0.\x05\0\0\x04\x1Akaryaku-1326\0\0\0\x001\x05\0\0\x08\x1Dgentoku-1329\0\0\0\x003\x05\0\0\x08\tgenko-1331\0\0\0\0\0\x006\x05\0\0\x01\x1Dkenmu-1334\0\0\0\0\0\08\x05\0\0\x02\x1Dengen-1336\0\0\0\0\0\0<\x05\0\0\x04\x1Ckokoku-1340\0\0\0\0\0B\x05\0\0\x0C\x08shohei-1346\0\0\0\0\0Z\x05\0\0\x07\x18kentoku-1370\0\0\0\0\\\x05\0\0\x04\x01bunchu-1372\0\0\0\0\0_\x05\0\0\x05\x1Btenju-1375\0\0\0\0\0\0c\x05\0\0\x03\x16koryaku-1379\0\0\0\0e\x05\0\0\x02\nkowa-1381\0\0\0\0\0\0\0h\x05\0\0\x04\x1Cgenchu-1384\0\0\0\0\0k\x05\0\0\x08\x16meitoku-1387\0\0\0\0k\x05\0\0\x08\x17kakei-1387\0\0\0\0\0\0m\x05\0\0\x02\tkoo-1389\0\0\0\0\0\0\0\0n\x05\0\0\x03\x1Ameitoku-1390\0\0\0\0r\x05\0\0\x07\x05oei-1394\0\0\0\0\0\0\0\0\x94\x05\0\0\x04\x1Bshocho-1428\0\0\0\0\0\x95\x05\0\0\t\x05eikyo-1429\0\0\0\0\0\0\xA1\x05\0\0\x02\x11kakitsu-1441\0\0\0\0\xA4\x05\0\0\x02\x05bunan-1444\0\0\0\0\0\0\xA9\x05\0\0\x07\x1Chotoku-1449\0\0\0\0\0\xAC\x05\0\0\x07\x19kyotoku-1452\0\0\0\0\xAF\x05\0\0\x07\x19kosho-1455\0\0\0\0\0\0\xB1\x05\0\0\t\x1Cchoroku-1457\0\0\0\0\xB4\x05\0\0\x0C\x15kansho-1460\0\0\0\0\0\xBA\x05\0\0\x02\x1Cbunsho-1466\0\0\0\0\0\xBB\x05\0\0\x03\x03onin-1467\0\0\0\0\0\0\0\xBD\x05\0\0\x04\x1Cbunmei-1469\0\0\0\0\0\xCF\x05\0\0\x07\x1Dchokyo-1487\0\0\0\0\0\xD1\x05\0\0\x08\x15entoku-1489\0\0\0\0\0\xD4\x05\0\0\x07\x13meio-1492\0\0\0\0\0\0\0\xDD\x05\0\0\x02\x1Cbunki-1501\0\0\0\0\0\0\xE0\x05\0\0\x02\x1Deisho-1504\0\0\0\0\0\0\xF1\x05\0\0\x08\x17taiei-1521\0\0\0\0\0\0\xF8\x05\0\0\x08\x14kyoroku-1528\0\0\0\0\xFC\x05\0\0\x07\x1Dtenbun-1532\0\0\0\0\0\x13\x06\0\0\n\x17koji-1555\0\0\0\0\0\0\0\x16\x06\0\0\x02\x1Ceiroku-1558\0\0\0\0\0\"\x06\0\0\x04\x17genki-1570\0\0\0\0\0\0%\x06\0\0\x07\x1Ctensho-1573\0\0\0\0\08\x06\0\0\x0C\x08bunroku-1592\0\0\0\0<\x06\0\0\n\x1Bkeicho-1596\0\0\0\0\0O\x06\0\0\x07\rgenna-1615\0\0\0\0\0\0X\x06\0\0\x02\x1Dkanei-1624\0\0\0\0\0\0l\x06\0\0\x0C\x10shoho-1644\0\0\0\0\0\0p\x06\0\0\x02\x0Fkeian-1648\0\0\0\0\0\0t\x06\0\0\t\x12joo-1652\0\0\0\0\0\0\0\0w\x06\0\0\x04\rmeireki-1655\0\0\0\0z\x06\0\0\x07\x17manji-1658\0\0\0\0\0\0}\x06\0\0\x04\x19kanbun-1661\0\0\0\0\0\x89\x06\0\0\t\x15enpo-1673\0\0\0\0\0\0\0\x91\x06\0\0\t\x1Dtenna-1681\0\0\0\0\0\0\x94\x06\0\0\x02\x15jokyo-1684\0\0\0\0\0\0\x98\x06\0\0\t\x1Egenroku-1688\0\0\0\0\xA8\x06\0\0\x03\rhoei-1704\0\0\0\0\0\0\0\xAF\x06\0\0\x04\x19shotoku-1711\0\0\0\0\xB4\x06\0\0\x06\x16kyoho-1716\0\0\0\0\0\0\xC8\x06\0\0\x04\x1Cgenbun-1736\0\0\0\0\0\xCD\x06\0\0\x02\x1Bkanpo-1741\0\0\0\0\0\0\xD0\x06\0\0\x02\x15enkyo-1744\0\0\0\0\0\0\xD4\x06\0\0\x07\x0Ckanen-1748\0\0\0\0\0\0\xD7\x06\0\0\n\x1Bhoreki-1751\0\0\0\0\0\xE4\x06\0\0\x06\x02meiwa-1764\0\0\0\0\0\0\xEC\x06\0\0\x0B\x10anei-1772\0\0\0\0\0\0\0\xF5\x06\0\0\x04\x02tenmei-1781\0\0\0\0\0\xFD\x06\0\0\x01\x19kansei-1789\0\0\0\0\0\t\x07\0\0\x02\x05kyowa-1801\0\0\0\0\0\0\x0C\x07\0\0\x02\x0Bbunka-1804\0\0\0\0\0\0\x1A\x07\0\0\x04\x16bunsei-1818\0\0\0\0\0&\x07\0\0\x0C\ntenpo-1830\0\0\0\0\0\x004\x07\0\0\x0C\x02koka-1844\0\0\0\0\0\0\08\x07\0\0\x02\x1Ckaei-1848\0\0\0\0\0\0\0>\x07\0\0\x0B\x1Bansei-1854\0\0\0\0\0\0D\x07\0\0\x03\x12manen-1860\0\0\0\0\0\0E\x07\0\0\x02\x13bunkyu-1861\0\0\0\0\0H\x07\0\0\x02\x14genji-1864\0\0\0\0\0\0I\x07\0\0\x04\x07keio-1865\0\0\0\0\0\0\0L\x07\0\0\n\x17meiji\0\0\0\0\0\0\0\0\0\0\0x\x07\0\0\x07\x1Etaisho\0\0\0\0\0\0\0\0\0\0\x86\x07\0\0\x0C\x19showa\0\0\0\0\0\0\0\0\0\0\0\xC5\x07\0\0\x01\x08heisei\0\0\0\0\0\0\0\0\0\0\xE3\x07\0\0\x05\x01reiwa\0\0\0\0\0\0\0\0\0\0\0") } }; + } + #[clippy::msrv = "1.82"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponse { payload: icu_provider::DataPayload::from_static_ref(Self::SINGLETON_CALENDAR_JAPANESE_EXTENDED_V1), metadata: icu_provider::DataResponseMetadata::default() }) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + }; + ($ provider : ty , ITER) => { + __impl_calendar_japanese_extended_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::IterableDataProvider for $provider { + fn iter_ids(&self) -> Result>, icu_provider::DataError> { + Ok([Default::default()].into_iter().collect()) + } + } + }; + ($ provider : ty , DRY) => { + __impl_calendar_japanese_extended_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::DryDataProvider for $provider { + fn dry_load(&self, req: icu_provider::DataRequest) -> Result { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponseMetadata::default()) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + }; + ($ provider : ty , DRY , ITER) => { + __impl_calendar_japanese_extended_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::DryDataProvider for $provider { + fn dry_load(&self, req: icu_provider::DataRequest) -> Result { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponseMetadata::default()) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + #[clippy::msrv = "1.82"] + impl icu_provider::IterableDataProvider for $provider { + fn iter_ids(&self) -> Result>, icu_provider::DataError> { + Ok([Default::default()].into_iter().collect()) + } + } + }; +} +#[doc(inline)] +pub use __impl_calendar_japanese_extended_v1 as impl_calendar_japanese_extended_v1; diff --git a/deps/crates/vendor/icu_calendar_data/data/calendar_japanese_modern_v1.rs.data b/deps/crates/vendor/icu_calendar_data/data/calendar_japanese_modern_v1.rs.data new file mode 100644 index 00000000000000..b86298cbcec181 --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/data/calendar_japanese_modern_v1.rs.data @@ -0,0 +1,75 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +/// +/// Using this implementation will embed the following data in the binary's data segment: +/// * 134B[^1] for the singleton data struct +/// +/// [^1]: these numbers can be smaller in practice due to linker deduplication +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_calendar_japanese_modern_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.82"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.82"] + impl $provider { + #[doc(hidden)] + pub const SINGLETON_CALENDAR_JAPANESE_MODERN_V1: &'static ::DataStruct = &icu::calendar::provider::JapaneseEras { dates_to_eras: unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"L\x07\0\0\n\x17meiji\0\0\0\0\0\0\0\0\0\0\0x\x07\0\0\x07\x1Etaisho\0\0\0\0\0\0\0\0\0\0\x86\x07\0\0\x0C\x19showa\0\0\0\0\0\0\0\0\0\0\0\xC5\x07\0\0\x01\x08heisei\0\0\0\0\0\0\0\0\0\0\xE3\x07\0\0\x05\x01reiwa\0\0\0\0\0\0\0\0\0\0\0") } }; + } + #[clippy::msrv = "1.82"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponse { payload: icu_provider::DataPayload::from_static_ref(Self::SINGLETON_CALENDAR_JAPANESE_MODERN_V1), metadata: icu_provider::DataResponseMetadata::default() }) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + }; + ($ provider : ty , ITER) => { + __impl_calendar_japanese_modern_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::IterableDataProvider for $provider { + fn iter_ids(&self) -> Result>, icu_provider::DataError> { + Ok([Default::default()].into_iter().collect()) + } + } + }; + ($ provider : ty , DRY) => { + __impl_calendar_japanese_modern_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::DryDataProvider for $provider { + fn dry_load(&self, req: icu_provider::DataRequest) -> Result { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponseMetadata::default()) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + }; + ($ provider : ty , DRY , ITER) => { + __impl_calendar_japanese_modern_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::DryDataProvider for $provider { + fn dry_load(&self, req: icu_provider::DataRequest) -> Result { + if req.id.locale.is_unknown() { + Ok(icu_provider::DataResponseMetadata::default()) + } else { + Err(icu_provider::DataErrorKind::InvalidRequest.with_req(::INFO, req)) + } + } + } + #[clippy::msrv = "1.82"] + impl icu_provider::IterableDataProvider for $provider { + fn iter_ids(&self) -> Result>, icu_provider::DataError> { + Ok([Default::default()].into_iter().collect()) + } + } + }; +} +#[doc(inline)] +pub use __impl_calendar_japanese_modern_v1 as impl_calendar_japanese_modern_v1; diff --git a/deps/crates/vendor/icu_calendar_data/data/calendar_week_v1.rs.data b/deps/crates/vendor/icu_calendar_data/data/calendar_week_v1.rs.data new file mode 100644 index 00000000000000..6a1c737066c3f0 --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/data/calendar_week_v1.rs.data @@ -0,0 +1,64 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +/// +/// Using this implementation will embed the following data in the binary's data segment: +/// * 292B for the lookup data structure (72 data identifiers) +/// * 20B[^1] for the actual data (10 unique structs) +/// +/// [^1]: these numbers can be smaller in practice due to linker deduplication +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_calendar_week_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.82"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.82"] + impl $provider { + const DATA_CALENDAR_WEEK_V1: icu_provider::baked::zerotrie::Data = { + const TRIE: icu_provider::baked::zerotrie::ZeroTrieSimpleAscii<&'static [u8]> = icu_provider::baked::zerotrie::ZeroTrieSimpleAscii { store: b"und\x80-\xD7ABCDEGHIJKLMNOPQSTUVWYZ\t\x1E$06::DataStruct] = &[icu::calendar::provider::WeekData { first_weekday: icu::calendar::types::Weekday::Monday, weekend: icu::calendar::provider::WeekdaySet::new(&[icu::calendar::types::Weekday::Saturday, icu::calendar::types::Weekday::Sunday]) }, icu::calendar::provider::WeekData { first_weekday: icu::calendar::types::Weekday::Saturday, weekend: icu::calendar::provider::WeekdaySet::new(&[icu::calendar::types::Weekday::Thursday, icu::calendar::types::Weekday::Friday]) }, icu::calendar::provider::WeekData { first_weekday: icu::calendar::types::Weekday::Sunday, weekend: icu::calendar::provider::WeekdaySet::new(&[icu::calendar::types::Weekday::Saturday, icu::calendar::types::Weekday::Sunday]) }, icu::calendar::provider::WeekData { first_weekday: icu::calendar::types::Weekday::Saturday, weekend: icu::calendar::provider::WeekdaySet::new(&[icu::calendar::types::Weekday::Friday, icu::calendar::types::Weekday::Saturday]) }, icu::calendar::provider::WeekData { first_weekday: icu::calendar::types::Weekday::Saturday, weekend: icu::calendar::provider::WeekdaySet::new(&[icu::calendar::types::Weekday::Saturday, icu::calendar::types::Weekday::Sunday]) }, icu::calendar::provider::WeekData { first_weekday: icu::calendar::types::Weekday::Sunday, weekend: icu::calendar::provider::WeekdaySet::new(&[icu::calendar::types::Weekday::Friday, icu::calendar::types::Weekday::Saturday]) }, icu::calendar::provider::WeekData { first_weekday: icu::calendar::types::Weekday::Sunday, weekend: icu::calendar::provider::WeekdaySet::new(&[icu::calendar::types::Weekday::Sunday]) }, icu::calendar::provider::WeekData { first_weekday: icu::calendar::types::Weekday::Saturday, weekend: icu::calendar::provider::WeekdaySet::new(&[icu::calendar::types::Weekday::Friday]) }, icu::calendar::provider::WeekData { first_weekday: icu::calendar::types::Weekday::Friday, weekend: icu::calendar::provider::WeekdaySet::new(&[icu::calendar::types::Weekday::Saturday, icu::calendar::types::Weekday::Sunday]) }, icu::calendar::provider::WeekData { first_weekday: icu::calendar::types::Weekday::Monday, weekend: icu::calendar::provider::WeekdaySet::new(&[icu::calendar::types::Weekday::Sunday]) }]; + unsafe { icu_provider::baked::zerotrie::Data::from_trie_and_values_unchecked(TRIE, VALUES) } + }; + } + #[clippy::msrv = "1.82"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + let mut metadata = icu_provider::DataResponseMetadata::default(); + let payload = if let Some(payload) = icu_provider::baked::DataStore::get(&Self::DATA_CALENDAR_WEEK_V1, req.id, req.metadata.attributes_prefix_match) { + payload + } else { + const FALLBACKER: icu::locale::fallback::LocaleFallbackerWithConfig<'static> = icu::locale::fallback::LocaleFallbacker::new().for_config(::INFO.fallback_config); + let mut fallback_iterator = FALLBACKER.fallback_for(req.id.locale.clone()); + loop { + if let Some(payload) = icu_provider::baked::DataStore::get(&Self::DATA_CALENDAR_WEEK_V1, icu_provider::DataIdentifierBorrowed::for_marker_attributes_and_locale(req.id.marker_attributes, fallback_iterator.get()), req.metadata.attributes_prefix_match) { + metadata.locale = Some(fallback_iterator.take()); + break payload; + } + if fallback_iterator.get().is_unknown() { + return Err(icu_provider::DataErrorKind::IdentifierNotFound.with_req(::INFO, req)); + } + fallback_iterator.step(); + } + }; + Ok(icu_provider::DataResponse { payload, metadata }) + } + } + }; + ($ provider : ty , ITER) => { + __impl_calendar_week_v1!($provider); + #[clippy::msrv = "1.82"] + impl icu_provider::IterableDataProvider for $provider { + fn iter_ids(&self) -> Result>, icu_provider::DataError> { + Ok(icu_provider::baked::DataStore::iter(&Self::DATA_CALENDAR_WEEK_V1).collect()) + } + } + }; + ($ provider : ty , DRY) => {}; + ($ provider : ty , DRY , ITER) => { + __impl_calendar_week_v1!($provider, ITER); + }; +} +#[doc(inline)] +pub use __impl_calendar_week_v1 as impl_calendar_week_v1; diff --git a/deps/crates/vendor/icu_calendar_data/data/mod.rs b/deps/crates/vendor/icu_calendar_data/data/mod.rs new file mode 100644 index 00000000000000..84e6f6c55ee844 --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/data/mod.rs @@ -0,0 +1,44 @@ +// @generated +include!("calendar_japanese_extended_v1.rs.data"); +include!("calendar_japanese_modern_v1.rs.data"); +include!("calendar_week_v1.rs.data"); +include!("calendar_dangi_v1.rs.data"); +include!("calendar_hijri_simulated_mecca_v1.rs.data"); +include!("calendar_chinese_v1.rs.data"); +/// Marks a type as a data provider. You can then use macros like +/// `impl_core_helloworld_v1` to add implementations. +/// +/// ```ignore +/// struct MyProvider; +/// const _: () = { +/// include!("path/to/generated/macros.rs"); +/// make_provider!(MyProvider); +/// impl_core_helloworld_v1!(MyProvider); +/// } +/// ``` +#[doc(hidden)] +#[macro_export] +macro_rules! __make_provider { + ($ name : ty) => { + #[clippy::msrv = "1.82"] + impl $name { + #[allow(dead_code)] + pub(crate) const MUST_USE_MAKE_PROVIDER_MACRO: () = (); + } + icu_provider::marker::impl_data_provider_never_marker!($name); + }; +} +#[doc(inline)] +pub use __make_provider as make_provider; +#[allow(unused_macros)] +macro_rules! impl_data_provider { + ($ provider : ty) => { + make_provider!($provider); + impl_calendar_japanese_extended_v1!($provider); + impl_calendar_japanese_modern_v1!($provider); + impl_calendar_week_v1!($provider); + impl_calendar_dangi_v1!($provider); + impl_calendar_hijri_simulated_mecca_v1!($provider); + impl_calendar_chinese_v1!($provider); + }; +} diff --git a/deps/crates/vendor/icu_calendar_data/src/lib.rs b/deps/crates/vendor/icu_calendar_data/src/lib.rs new file mode 100644 index 00000000000000..2a3674bc16bb94 --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/src/lib.rs @@ -0,0 +1,17 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! Data for the `icu_calendar` crate +//! +//! This data was generated with CLDR version 47.0.0, ICU version icu4x/2025-05-01/77.x, and +//! LSTM segmenter version v0.1.0. + +#![no_std] +// The source is not readable and is massive as HTML. +#![doc(html_no_source)] + +#[cfg(icu4x_custom_data)] +include!(concat!(core::env!("ICU4X_DATA_DIR"), "/mod.rs")); +#[cfg(not(icu4x_custom_data))] +include!("../data/mod.rs"); diff --git a/deps/crates/vendor/icu_collections/.cargo-checksum.json b/deps/crates/vendor/icu_collections/.cargo-checksum.json new file mode 100644 index 00000000000000..87873bb53d1812 --- /dev/null +++ b/deps/crates/vendor/icu_collections/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.lock":"5c3e432c15fb18f16c8343adcedc9c1d0f7dc58bc9b3e09438a06c6215545a26","Cargo.toml":"a1bcce20ab29725ab0d9a44d2b09eda57368c56b2b9d12b73b2958f7d7df4d83","LICENSE":"f367c1b8e1aa262435251e442901da4607b4650e0e63a026f5044473ecfb90f2","README.md":"b1a0b37b61d42026996dda3b7d524d42888181f3e7eaf940c9b2e5f561c449e3","benches/codepointtrie.rs":"4052e9e3a3a744955a5ab3f7089cafaf2920ad5c7566fc8b3b77ee1d39376c20","benches/iai_cpt.rs":"a8ed4e67866d415e6ed0c8c95a9b1887b4198ea409d4cd9efafb50b8c13b3ecc","benches/inv_list.rs":"93a540e1dc30d0d356eef56f044a64b87949d777fa21f35042d53ba1bbcf1fb5","benches/tries/gc_fast.rs":"4761a339f9b266813f4fa7ffa229b3464ced2ed106ce712ae6a96c0e49e5224e","benches/tries/gc_small.rs":"a1a75d2325dbce031e0127de8d84e900ca7c73ec81da1679965ab0127a99c205","benches/tries/mod.rs":"82cfdd1c5870d343613098fdff5a7961cfe5645a33480c6a252efae9a074e022","examples/unicode_bmp_blocks_selector.rs":"a75bc5327fa9df8ab0332dcdf10f72a968924a0698bdba4eb79312a8624cbd44","src/char16trie/mod.rs":"5950a1b427743e956b459956cadd72ff7531fe46bfb871d8e3a848b1e4ab0657","src/char16trie/trie.rs":"18ccf56efa1a2b2af6034b8a7a05310a4078127f496a957ca26ee1e1ae4d1aea","src/codepointinvlist/builder.rs":"dae06a19e6a4275006afcf313d492eabbc74bececa99198de88d29c8facf6415","src/codepointinvlist/conversions.rs":"9d4617631328f5ad668eb5ea6fb100f9881dbebf6f46235ae5a445be2dbb8664","src/codepointinvlist/cpinvlist.rs":"025cd179418d5be9ddf41e97e2ebaa4f9943527fc521a4bb11b93dc02893c33c","src/codepointinvlist/mod.rs":"39f18e0be77508696b80d456f861a1264b902e90298c71a54e00a4585069108f","src/codepointinvlist/utils.rs":"2fcb38b4ce33947e831449ca63e0872b1d90830521144e1089f26842f1b746c8","src/codepointinvliststringlist/mod.rs":"4f0f2ae1ecd9068a0100a48308e08405afcee182eb5c5743990f739d4d7fdc42","src/codepointtrie/cptrie.rs":"dfaaa7271eed2e486bc43f3a36e71579bec19b854f491f6375b97113691c41f6","src/codepointtrie/error.rs":"43d758777ef7ce3f87efe4c8c7fb8fbe7d184b2d40f3f5fb737bce69da5d75a7","src/codepointtrie/impl_const.rs":"ff25fa0d54e174c289b25a6060f50e03c8aa41bad922c9386de3148f8ad95109","src/codepointtrie/mod.rs":"934246b867396119195cce3b4243f1951b76f503f6f455fa73cc6cd66ff792db","src/codepointtrie/planes.rs":"637c63a165397831c8ce8d4c28eff11179467a7d7a6382960acd699d8a087f26","src/codepointtrie/serde.rs":"ada65ec125890ccf86d141a128a1f79dcda5f3a2269605da7a2fa145d3cbd07c","src/codepointtrie/toml.rs":"00d10cb710f69f84dd0fde871c4bd61e8cabe319362a11fc74a0af1f0fda2363","src/iterator_utils.rs":"a6401aa583a2d8a6476f632b24983e91aa000c9dfd075bcddbd8de512b5a06ae","src/lib.rs":"a15ba283ccb32fc9a1cbe67166fa8eac5cd9225e4de022d09b057be4ff8eb688","tests/char16trie.rs":"f8018b90187f3b99a6a835c1c41bced18d98a28c41822abf3536cd1f0f08c44f","tests/cpt.rs":"126c6c671a6aa525dd6fabaf57387c828bae0041b04dffcd7b3a22c674e1dd41","tests/data/char16trie/empty.toml":"b900365b9c786f1b185307f5d8835a901d4860b9b097bce13aa0e592fcb384c4","tests/data/char16trie/months.toml":"439245fc4385fe693f283b7bc179bf5558dd8039a89987314dfc8c4a9e0092b2","tests/data/char16trie/test_a.toml":"34b179dd4e7eef73ce373b74e426ecfa05fb7aa2b0fc15e437bfcf3ea4242a9f","tests/data/char16trie/test_a_ab.toml":"b84452cb9c310203599d3cb8279a3f000c39ff8026728573152026f0d5e2c798","tests/data/char16trie/test_branches.toml":"d787ffc89c62a564b487f3c8fb94588258be0d891044e5b3a79c2ab876cd3e57","tests/data/char16trie/test_compact.toml":"30cb3e794d0989e3e087c12de3db077449d82ce6af57666290166d43bdcd27d3","tests/data/char16trie/test_long_branch.toml":"877d408f7d58063723befd01af6e3b0f01060a9ca1c5611ee1ea88d73383fa5a","tests/data/char16trie/test_long_sequence.toml":"f58645b3f14e47850e2a03733f7e47b69b193067f4cccf96124846b1ad49d970","tests/data/char16trie/test_shortest_branch.toml":"af356553506dbc28a2413b9f0ca1489050cd11a72e90ba4b5020bcb596862e64","tests/data/cpt/free-blocks.16.toml":"e0a66e777c13c0885b6a0f6839cdc9bbbddded2f5fbef4710f8e69a0808791d9","tests/data/cpt/free-blocks.32.toml":"b0bb6068a84d08d3fbcbd54dce7a59385a42b2dcdf0a6fe9d4160754a80a5f9e","tests/data/cpt/free-blocks.8.toml":"2de9950cd4475c3cb9cca9c30cb6793b90f3881ea2dd1353bea0701110c76953","tests/data/cpt/free-blocks.small16.toml":"17cbdef8edec19e8d85802eda775b1095ae2d423a589a4b56064b3b13604af36","tests/data/cpt/grow-data.16.toml":"802c7c61c2bb70dd7c96ce4633584a2ac4d2e6a61ecfb6f5d19c3c419b76f97c","tests/data/cpt/grow-data.32.toml":"3cbf6ad1276eda17f18cbeba4db671340ebec0fe6c0b631ea1f52dab63669881","tests/data/cpt/grow-data.8.toml":"e2d0b066e8a0f0bbf21cffa72393e0fd8c9a7534887886438211600bf7717129","tests/data/cpt/grow-data.small16.toml":"1d4c5d4b47a3da6b392729be3aa7cfa2cfb58d9ae37565cf10dbc10f0b48beca","tests/data/cpt/planes.toml":"a2577942758490bd53f4022b30731cff947fae22f4cbbb03b5ae72c65357aa12","tests/data/cpt/set-empty.16.toml":"6a01c051c5dbbe816097da806b943ca1856312059b0842a1238fe75ad5df220b","tests/data/cpt/set-empty.32.toml":"ec9dec0296b150ccabde07c255e2971ba407f647824a7c37af0272fa2ba89e2d","tests/data/cpt/set-empty.8.toml":"478dd49db8670f447f5aae78bcd3cdbeb6f91f7861dec256d480623b5d00941b","tests/data/cpt/set-empty.small16.toml":"5ff232c9b020bdaaaf762f7c0afe48ccb6f94b40dce08c1ba7dcb66c46ad2423","tests/data/cpt/set-single-value.16.toml":"6720f4a4d8c113ab7085e6308792ea0005cc8fe3c5d8acacb2cf43e74b12f4b3","tests/data/cpt/set-single-value.32.toml":"cb93935dc9ce5ed3cbe0f0acb50b49308b232e2d3fc8e39b08d1c33127c9911d","tests/data/cpt/set-single-value.8.toml":"e5cb6b02341bb8992ec93e49a7b2b059af1fd046ede3021dc207f1833c6a3c95","tests/data/cpt/set-single-value.small16.toml":"3aef34147b20a5c2c2c6e20f6024d38f7c0518313371b05d3cb83ae78a9ef0db","tests/data/cpt/set1.16.toml":"01cc1078f281102bd0c9e854a373b7241f2295bb19caa9488caad1b5350d0beb","tests/data/cpt/set1.32.toml":"cd264d011692df42e9007df87c6500bdde4e098a3a85a89a185f7deeff025a3b","tests/data/cpt/set1.8.toml":"039aa2fca8f140f5a060bcf01a1da3d45618242dfb0a3c437d4263d5166398a3","tests/data/cpt/set1.small16.toml":"b8bf6e216201e0a0c61c4b2456eccd1c3b4f38647d67ba251cd7b08f340df0dc","tests/data/cpt/set2-overlap.16.toml":"49f1d7212cb3f7b10f4a0dbab267b64aeb59380cc28d86c67fd640737da5af0a","tests/data/cpt/set2-overlap.32.toml":"406104b0532ae249c603c03729f4596ab24460ccbb3a244e04fa2b8401795ef0","tests/data/cpt/set2-overlap.small16.toml":"4e8d9c5b25cda2fd80fa72e7e9863e6858548608d3fe2a2d774026eda95c959f","tests/data/cpt/set3-initial-9.16.toml":"f5fdc3d7c6d6813cc527ddffecf35db2d144e2706be0541277bbe4672ea29851","tests/data/cpt/set3-initial-9.32.toml":"da2887d40005fc071eee1bf4e828f40410266c44585deda208e78d369b5ca9a9","tests/data/cpt/set3-initial-9.8.toml":"5974d1961bd8334e6fb1be7431f794dfc87d0fecdee4b832ad1c82e2302a6617","tests/data/cpt/set3-initial-9.small16.toml":"f62d46d2b6492c02944d089885b2ce6b975468e6bceabf986b495ab42a06d595","tests/data/cpt/short-all-same.16.toml":"5c0252591699a35398f75b3bec977d6ed44cfffbf335a87ed7c3cff86ff74391","tests/data/cpt/short-all-same.8.toml":"23f7aa3a8e6c3cc75669b8df55827b03c6791aac1ec9f7c8d7f0bbbdd54f23a9","tests/data/cpt/short-all-same.small16.toml":"5c0252591699a35398f75b3bec977d6ed44cfffbf335a87ed7c3cff86ff74391","tests/data/cpt/small0-in-fast.16.toml":"8d00f5657ee11c3b00c7a3c1e6333632b37dba0762cd4868b2f8ef90c03aab6c","tests/data/cpt/small0-in-fast.32.toml":"4736b4ae18cb0e77adc523382ec44bc517a01e17abdb91522b8859d77fbdc7c6","tests/data/cpt/small0-in-fast.8.toml":"e9214d75c421989eb79b7060817f51fa1d648d55b854fad651ff729962bc49e4","tests/data/cpt/small0-in-fast.small16.toml":"20eb07e89364a1fd6ddf26f3bc302e92c1aaa724be792d9bf8656e4e5a7a6379"},"package":"200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"} \ No newline at end of file diff --git a/deps/crates/vendor/icu_collections/Cargo.lock b/deps/crates/vendor/icu_collections/Cargo.lock new file mode 100644 index 00000000000000..2cf19f6502f5e8 --- /dev/null +++ b/deps/crates/vendor/icu_collections/Cargo.lock @@ -0,0 +1,856 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[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 = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[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.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[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 = "databake" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6ee9e2d2afb173bcdeee45934c89ec341ab26f91c9933774fc15c2b58f83ef" +dependencies = [ + "databake-derive", + "proc-macro2", + "quote", +] + +[[package]] +name = "databake-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6834770958c7b84223607e49758ec0dde273c4df915e734aad50f62968a4c134" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[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 = "hashbrown" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" + +[[package]] +name = "hermit-abi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" + +[[package]] +name = "iai" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678" + +[[package]] +name = "icu_collections" +version = "2.0.0" +dependencies = [ + "criterion", + "databake", + "displaydoc", + "iai", + "postcard", + "potential_utf", + "serde", + "serde_json", + "toml", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is-terminal" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +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.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[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.172" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[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.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + +[[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 = "postcard" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] + +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "serde", + "zerovec", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[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 = "rustversion" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[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.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +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 = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "2.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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 = "toml" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[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 = "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-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 = "winnow" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" +dependencies = [ + "memchr", +] + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +dependencies = [ + "databake", + "serde", + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/deps/crates/vendor/icu_collections/Cargo.toml b/deps/crates/vendor/icu_collections/Cargo.toml new file mode 100644 index 00000000000000..5fd8b60b4ee492 --- /dev/null +++ b/deps/crates/vendor/icu_collections/Cargo.toml @@ -0,0 +1,154 @@ +# 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.82" +name = "icu_collections" +version = "2.0.0" +authors = ["The ICU4X Project Developers"] +build = false +include = [ + "data/**/*", + "src/**/*", + "examples/**/*", + "benches/**/*", + "tests/**/*", + "Cargo.toml", + "LICENSE", + "README.md", + "build.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "Collection of API for use in ICU libraries." +homepage = "https://icu4x.unicode.org" +readme = "README.md" +categories = ["internationalization"] +license = "Unicode-3.0" +repository = "https://github.com/unicode-org/icu4x" + +[package.metadata.docs.rs] +all-features = true + +[features] +alloc = ["zerovec/alloc"] +databake = [ + "dep:databake", + "zerovec/databake", +] +serde = [ + "dep:serde", + "zerovec/serde", + "potential_utf/serde", + "alloc", +] + +[lib] +name = "icu_collections" +path = "src/lib.rs" +bench = false + +[[example]] +name = "unicode_bmp_blocks_selector" +path = "examples/unicode_bmp_blocks_selector.rs" + +[[test]] +name = "char16trie" +path = "tests/char16trie.rs" + +[[test]] +name = "cpt" +path = "tests/cpt.rs" + +[[bench]] +name = "codepointtrie" +path = "benches/codepointtrie.rs" +harness = false + +[[bench]] +name = "iai_cpt" +path = "benches/iai_cpt.rs" +harness = false + +[[bench]] +name = "inv_list" +path = "benches/inv_list.rs" +harness = false + +[dependencies.databake] +version = "0.2.0" +features = ["derive"] +optional = true +default-features = false + +[dependencies.displaydoc] +version = "0.2.3" +default-features = false + +[dependencies.potential_utf] +version = "0.1.1" +features = ["zerovec"] +default-features = false + +[dependencies.serde] +version = "1.0.110" +features = [ + "derive", + "alloc", +] +optional = true +default-features = false + +[dependencies.yoke] +version = "0.8.0" +features = ["derive"] +default-features = false + +[dependencies.zerofrom] +version = "0.1.3" +features = ["derive"] +default-features = false + +[dependencies.zerovec] +version = "0.11.1" +features = [ + "derive", + "yoke", +] +default-features = false + +[dev-dependencies.iai] +version = "0.1.1" + +[dev-dependencies.postcard] +version = "1.0.3" +features = ["alloc"] +default-features = false + +[dev-dependencies.serde] +version = "1.0.110" +features = ["derive"] +default-features = false + +[dev-dependencies.serde_json] +version = "1.0.45" + +[dev-dependencies.toml] +version = "0.8.0" +features = ["parse"] +default-features = false + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies.criterion] +version = "0.5.0" diff --git a/deps/crates/vendor/icu_collections/LICENSE b/deps/crates/vendor/icu_collections/LICENSE new file mode 100644 index 00000000000000..c9be6012c53792 --- /dev/null +++ b/deps/crates/vendor/icu_collections/LICENSE @@ -0,0 +1,46 @@ +UNICODE LICENSE V3 + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 2020-2024 Unicode, Inc. + +NOTICE TO USER: Carefully read the following legal agreement. BY +DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR +SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT +DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of data files and any associated documentation (the "Data Files") or +software and any associated documentation (the "Software") to deal in the +Data Files or Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, and/or sell +copies of the Data Files or Software, and to permit persons to whom the +Data Files or Software are furnished to do so, provided that either (a) +this copyright and permission notice appear with all copies of the Data +Files or Software, or (b) this copyright and permission notice appear in +associated Documentation. + +THE DATA FILES AND SOFTWARE ARE 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 OF +THIRD PARTY RIGHTS. + +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE +BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA +FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in these Data Files or Software without prior written +authorization of the copyright holder. + +SPDX-License-Identifier: Unicode-3.0 + +— + +Portions of ICU4X may have been adapted from ICU4C and/or ICU4J. +ICU 1.8.1 to ICU 57.1 © 1995-2016 International Business Machines Corporation and others. diff --git a/deps/crates/vendor/icu_collections/README.md b/deps/crates/vendor/icu_collections/README.md new file mode 100644 index 00000000000000..e90aa210bb6937 --- /dev/null +++ b/deps/crates/vendor/icu_collections/README.md @@ -0,0 +1,27 @@ +# icu_collections [![crates.io](https://img.shields.io/crates/v/icu_collections)](https://crates.io/crates/icu_collections) + + + +Efficient collections for Unicode data. + +This module is published as its own crate ([`icu_collections`](https://docs.rs/icu_collections/latest/icu_collections/)) +and as part of the [`icu`](https://docs.rs/icu/latest/icu/) crate. See the latter for more details on the ICU4X project. + +ICU4X `CodePointTrie` provides a read-only view of `CodePointTrie` data that is exported +from ICU4C. Detailed information about the design of the data structure can be found in the documentation +for the `CodePointTrie` struct. + +ICU4X `CodePointInversionList` provides necessary functionality for highly efficient querying of sets of Unicode characters. +It is an implementation of the existing [ICU4C UnicodeSet API](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1UnicodeSet.html). + +ICU4X `Char16Trie` provides a data structure for a space-efficient and time-efficient lookup of +sequences of 16-bit units (commonly but not necessarily UTF-16 code units) +which map to integer values. +It is an implementation of the existing [ICU4C UCharsTrie](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1UCharsTrie.html) +/ [ICU4J CharsTrie](https://unicode-org.github.io/icu-docs/apidoc/released/icu4j/com/ibm/icu/util/CharsTrie.html) API. + + + +## More Information + +For more information on development, authorship, contributing etc. please visit [`ICU4X home page`](https://github.com/unicode-org/icu4x). diff --git a/deps/crates/vendor/icu_collections/benches/codepointtrie.rs b/deps/crates/vendor/icu_collections/benches/codepointtrie.rs new file mode 100644 index 00000000000000..e49401634dd5c3 --- /dev/null +++ b/deps/crates/vendor/icu_collections/benches/codepointtrie.rs @@ -0,0 +1,104 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; + +use icu_collections::codepointtrie::CodePointTrie; + +#[path = "tries/mod.rs"] +mod tries; + +mod sample_str_lng { + // "eng" is all ASCII + pub const ENG: &str = "Universal Declaration of Human Rights"; + // "pcd" has ASCII mixed with low-BMP code points + pub const PCD: &str = "Dèclaråcion dès dreûts d' l'ome po tos lès payîs dè monde"; + // "ukr" uses low-BMP code points (less than U+1000) + pub const UKR: &str = "ЗАГАЛЬНА ДЕКЛАРАЦІЯ ПРАВ ЛЮДИНІ"; + // "yue" uses high-BMP code points (greater than U+1000), so it benefits from fast mode + pub const YUE: &str = "世界人权宣言"; + // "ccp" exercises supplementary code points + pub const CCP: &str = "𑄟𑄚𑄬𑄭𑄃𑄇𑄴𑄇𑄥𑄧𑄁𑄢𑄴 𑄝𑄬𑄇𑄴𑄅𑄚𑄮𑄢𑄴 𑄟𑄧𑄚𑄳𑄢𑄧𑄧𑄇𑄉𑄮𑄌𑄴"; +} + +const SAMPLE_STRING_MIXED: &str = "Dèclaråcion ЗАГАЛЬНА 世界人权宣言 𑄟𑄚𑄬𑄭𑄃𑄇𑄴𑄇𑄥𑄧𑄁𑄢𑄴"; + +/// A function that returns 100 code points in the desired language +fn one_hundred_code_points(sample_str: &str) -> String { + sample_str.chars().cycle().take(100).collect() +} + +fn get_trie_small() -> CodePointTrie<'static, u8> { + CodePointTrie::try_new( + tries::gc_small::HEADER, + tries::gc_small::INDEX, + tries::gc_small::DATA, + ) + .unwrap() +} + +fn get_trie_fast() -> CodePointTrie<'static, u8> { + CodePointTrie::try_new( + tries::gc_fast::HEADER, + tries::gc_fast::INDEX, + tries::gc_fast::DATA, + ) + .unwrap() +} + +fn overview_bench(c: &mut Criterion) { + let s = one_hundred_code_points(SAMPLE_STRING_MIXED); + let cpt_small = get_trie_small(); + + c.bench_function("cpt/overview", |b| { + b.iter(|| { + black_box(&s) + .chars() + .map(|c| black_box(&cpt_small).get32(c as u32)) + .reduce(|a, b| a.wrapping_add(b)) + }); + }); + + c.bench_function("cpt/get_range", |b| { + b.iter(|| { + black_box(&s) + .chars() + .map(|c| black_box(&cpt_small).get_range(c as u32).unwrap()) + .fold(0u32, |acc, ele| { + acc.wrapping_add(ele.range.end() - ele.range.start() + ele.value as u32) + }) + }); + }); + + { + let cpt_fast = get_trie_fast(); + lang_bench(c, &cpt_small, "small/eng", sample_str_lng::ENG); + lang_bench(c, &cpt_small, "small/pcd", sample_str_lng::PCD); + lang_bench(c, &cpt_small, "small/ukr", sample_str_lng::UKR); + lang_bench(c, &cpt_small, "small/yue", sample_str_lng::YUE); + lang_bench(c, &cpt_small, "small/ccp", sample_str_lng::CCP); + lang_bench(c, &cpt_fast, "fast/eng", sample_str_lng::ENG); + lang_bench(c, &cpt_fast, "fast/pcd", sample_str_lng::PCD); + lang_bench(c, &cpt_fast, "fast/ukr", sample_str_lng::UKR); + lang_bench(c, &cpt_fast, "fast/yue", sample_str_lng::YUE); + lang_bench(c, &cpt_fast, "fast/ccp", sample_str_lng::CCP); + } +} + +fn lang_bench(c: &mut Criterion, cpt: &CodePointTrie, lid: &str, sample_str: &str) { + let bench_name = format!("cpt/get/{lid}"); + let s = one_hundred_code_points(sample_str); + + c.bench_function(&bench_name, |b| { + b.iter(|| { + black_box(&s) + .chars() + .map(|c| black_box(&cpt).get32(c as u32)) + .reduce(|a, b| a.wrapping_add(b)) + }); + }); +} + +criterion_group!(benches, overview_bench,); +criterion_main!(benches); diff --git a/deps/crates/vendor/icu_collections/benches/iai_cpt.rs b/deps/crates/vendor/icu_collections/benches/iai_cpt.rs new file mode 100644 index 00000000000000..3d57cbb4a168b2 --- /dev/null +++ b/deps/crates/vendor/icu_collections/benches/iai_cpt.rs @@ -0,0 +1,77 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use icu_collections::codepointtrie::CodePointTrie; + +#[path = "tries/mod.rs"] +mod tries; + +// The string has 41 chars. +const SAMPLE_STRING_LATIN1: &str = "Declaration loremips umdolo loremipsompi"; +const SAMPLE_STRING_MIXED: &str = "Dèclaråcion ЗАГАЛЬНА 世界人权宣言 𑄟𑄚𑄬𑄭𑄃𑄇𑄴𑄇𑄥𑄧𑄁𑄢𑄴"; + +fn get_trie_small() -> CodePointTrie<'static, u8> { + CodePointTrie::try_new( + tries::gc_small::HEADER, + tries::gc_small::INDEX, + tries::gc_small::DATA, + ) + .unwrap() +} + +fn get_trie_fast() -> CodePointTrie<'static, u8> { + CodePointTrie::try_new( + tries::gc_fast::HEADER, + tries::gc_fast::INDEX, + tries::gc_fast::DATA, + ) + .unwrap() +} + +fn bench_iai_cpt_overview(fast: bool, mixed: bool) { + // Tests the instructions required to get CPT for 100,000 chars. + + let cpt = if fast { + get_trie_fast() + } else { + get_trie_small() + }; + let sample = if mixed { + SAMPLE_STRING_MIXED + } else { + SAMPLE_STRING_LATIN1 + }; + + let mut i: u8 = 0; + for c in sample.chars() { + i = i.wrapping_add(cpt.get32(c as u32)) + //i = i.wrapping_add(1); + } + + // Ensure the loop is not DCEd + assert!(i < 255); +} + +fn bench_iai_cpt_latin_fast() { + bench_iai_cpt_overview(true, false); +} + +fn bench_iai_cpt_latin_small() { + bench_iai_cpt_overview(false, false); +} + +fn bench_iai_cpt_mixed_fast() { + bench_iai_cpt_overview(true, true); +} + +fn bench_iai_cpt_mixed_small() { + bench_iai_cpt_overview(false, true); +} + +iai::main!( + bench_iai_cpt_latin_fast, + bench_iai_cpt_latin_small, + bench_iai_cpt_mixed_fast, + bench_iai_cpt_mixed_small, +); diff --git a/deps/crates/vendor/icu_collections/benches/inv_list.rs b/deps/crates/vendor/icu_collections/benches/inv_list.rs new file mode 100644 index 00000000000000..41a23568046090 --- /dev/null +++ b/deps/crates/vendor/icu_collections/benches/inv_list.rs @@ -0,0 +1,66 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use criterion::{criterion_group, criterion_main, Criterion}; +use icu_collections::codepointinvlist::CodePointInversionList; +use std::char; + +fn uniset_bench(c: &mut Criterion) { + let best_ex = [0x41, 0x46]; + let best_sample = CodePointInversionList::try_from_u32_inversion_list_slice(&best_ex).unwrap(); + let worst_ex: Vec = (0x0..((char::MAX as u32) + 1)).collect(); + let worst_sample = + CodePointInversionList::try_from_u32_inversion_list_slice(&worst_ex).unwrap(); + + c.bench_function("uniset/overview", |b| { + #[allow(clippy::suspicious_map)] + b.iter(|| { + best_sample + .iter_chars() + .map(|ch| best_sample.contains(ch)) + .count(); + worst_sample + .iter_chars() + .map(|ch| worst_sample.contains(ch)) + .count(); + best_sample + .iter_chars() + .map(|ch| best_sample.contains_range('A'..ch)) + .count(); + worst_sample + .iter_chars() + .take(100) + .map(|ch| worst_sample.contains_range(char::from_u32(0x0).unwrap()..ch)) + .count(); + }) + }); + + { + let mut group = c.benchmark_group("uniset/contains"); + group.bench_with_input("best", &best_sample, |b, sample| { + b.iter(|| sample.iter_chars().map(|ch| sample.contains(ch))) + }); + group.bench_with_input("worst", &worst_sample, |b, sample| { + b.iter(|| sample.iter_chars().take(100).map(|ch| sample.contains(ch))) + }); + group.finish(); + + let mut group = c.benchmark_group("uniset/contains_range"); + group.bench_with_input("best", &best_sample, |b, sample| { + b.iter(|| sample.iter_chars().map(|ch| sample.contains_range('A'..ch))) + }); + group.bench_with_input("worst", &worst_sample, |b, sample| { + b.iter(|| { + sample + .iter_chars() + .take(100) + .map(|ch| sample.contains_range(char::from_u32(0x0).unwrap()..ch)) + }) + }); + group.finish(); + } +} + +criterion_group!(benches, uniset_bench); +criterion_main!(benches); diff --git a/deps/crates/vendor/icu_collections/benches/tries/gc_fast.rs b/deps/crates/vendor/icu_collections/benches/tries/gc_fast.rs new file mode 100644 index 00000000000000..ba98a40f78e8d8 --- /dev/null +++ b/deps/crates/vendor/icu_collections/benches/tries/gc_fast.rs @@ -0,0 +1,1128 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use icu_collections::codepointtrie::{CodePointTrieHeader, TrieType}; +use zerovec::ule::AsULE; +use zerovec::{zerovec, ZeroVec}; + +#[rustfmt::skip] +pub const INDEX: ZeroVec = zerovec!(u16; ::ULE::from_unsigned; + [ + 0,0x40,0x7f,0xbf,0xff,0x12e,0x16d,0x1ad,0x1e5,0x224,0x250,0x28e,0x2ce,0x2de,0x31e,0x34f, + 0x38c,0x3bc,0x3fa,0x43a,0x44a,0x47b,0x4b2,0x4f2,0x532,0x572,0x5a3,0x5cf,0x60f,0x644,0x65e,0x69e, + 0x6de,0x71e,0x756,0x78d,0x7ca,0x809,0x848,0x887,0x8c6,0x905,0x944,0x983,0x9c3,0xa01,0xa3f,0xa7f, + 0xabf,0xafe,0xb3e,0xb7e,0xbbe,0xbfd,0xc3d,0xc7d,0xcbc,0xcfc,0xd3b,0xd7b,0xdbb,0xdfb,0xe3b,0xe79, + 0xeb9,0xef9,0xf37,0xf71,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0xfb1,0xfe8,0x1026,0x1055,0x107a,0x10ba,0x10da, + 0x111a,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x112d,0x116d,0x118d,0x11cd,0x120d,0x124d,0x128b, + 0x12cb,0x1308,0x1348,0x1378,0x13b8,0x13f8,0x1438,0x146e,0x14ae,0x14d9,0x1519,0x1558,0x1598,0x15d6,0x1616,0x1650, + 0x1690,0x16d0,0x1710,0x1750,0x1790,0x17bc,0x17a1,0x2ce,0x17fc,0x17fc,0x1826,0x17fc,0x1865,0x18a5,0x18e5,0x1924, + 0x1964,0x19a3,0x19e3,0x1a22,0x1a62,0x1aa2,0x1adf,0x1b11,0x1b45,0x1b45,0x1b45,0x1b45,0x1b85,0x1bb0,0x1bed,0x1c21, + 0x1c43,0x1c83,0x1ca7,0x1cc3,0x1d03,0x1d03,0x1bb5,0x1d42,0x1d03,0x1bbd,0x1d03,0x1d03,0x1d03,0x1d82,0x1cef,0x1dc2, + 0x1d03,0x1d03,0x1d03,0x1d03,0x1b45,0x1b45,0x1dff,0x1e27,0x1b45,0x1b45,0x1b45,0x1b45,0x1e67,0x1ea2,0x1ed8,0x1d03, + 0x38c,0x1f18,0x17fc,0x1f57,0x1f97,0x1fc7,0x2007,0x2027,0x2067,0x20a7,0x20e7,0x2102,0x1d03,0x1d03,0x1d03,0x2120, + 0x2160,0x21a0,0x21c9,0x21ea,0x222a,0x5a3,0x225b,0x229b,0x22db,0x2313,0x2329,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x1d03,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x12f6,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x2369,0x23a2,0x5a3,0x5a3,0x5a3,0x5a3,0x23e2,0x2422,0x2462,0x2482,0x24c2,0x24f4,0x2532,0x256e, + 0x25ac,0x25ec,0x262c,0x2668,0x26a8,0x26e1,0x2721,0x2760,0x27a0,0x27e0,0x281e,0x285e,0x289d,0x28cd,0x28fd,0x293d, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x297d,0x29b6, + 0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6, + 0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6,0x29f6, + 0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36, + 0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36, + 0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36, + 0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36, + 0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36, + 0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36, + 0x2a36,0x2a36,0x2a36,0x2a36,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x2a76,0x5a3,0x2aa6,0x2ae6,0x2b26,0x2b34,0x2b71, + 0x5a3,0x5a3,0x5a3,0x5a3,0x2b84,0x2bc4,0x2bf4,0x2c2c,0x2c6c,0x2ca8,0x5a3,0x2cde,0x2d1e,0x2d5e,0x2d8f,0x2dce, + 0xac0,0xade,0xafb,0xb1a,0xb3a,0xb3a,0xb47,0xb64,0xb84,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e, + 0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e, + 0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e,0xb8e, + 0xb8e,0xb8e,0xb8e,0xb8e,0xbae,0xb8e,0xb8e,0xb8e,0xbce,0xbce,0xbce,0xbcf,0xbce,0xbce,0xbce,0xbcf, + 0x865,0x5a3,0xae1,0x2e0e,0x50f,0x50f,0xd18,0xd18,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x73e, + 0x2e1e,0x10a3,0x10a3,0x2e2a,0x1ac2,0x1ac2,0x1ac2,0x2e3a,0x2e43,0x1c5d,0x1c69,0xd18,0xd18,0x1d03,0x1d03,0x2e53, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x510,0x5a3,0x5a3,0x5a3,0x993,0x2e63,0x2e67, + 0x5a3,0x5a3,0x2e6f,0x5a3,0x2e7e,0x5a3,0x5a3,0x2e8e,0x5a3,0x2e9e,0x5a3,0x5a3,0x1460,0x2ead,0xd18,0xd18, + 0x41,0x41,0x342,0x28fd,0x28fd,0x5a3,0x5a3,0x5a3,0x5a3,0x50f,0xb24,0x41,0x41,0x2ebd,0x28fd,0x2ec5, + 0x5a3,0x5a3,0x13a6,0x5a3,0x5a3,0x5a3,0x2ed5,0x335,0x335,0x2ee5,0x2ef3,0x2f01,0xd18,0xd18,0xd18,0xd18, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x13a7,0x5a3,0x13a8,0x13a6,0xd18,0x2f11,0x280,0x280,0x2f16,0xd18,0xd18,0xd18,0xd18, + 0x2f26,0x5a3,0x5a3,0x2f30,0x5a3,0x2f3f,0x5a3,0x2f4f,0x5a3,0x50e,0x1c9c,0xd18,0xd18,0xd18,0x5a3,0x2f5f, + 0x5a3,0x2f6f,0x5a3,0x2f7f,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x5a3,0x2f8f,0x10a3,0x1ca1,0x10a3,0x10a3, + 0x2f9e,0x94e,0x5a3,0x2fae,0x2e6a,0x2fbe,0x5a3,0x2fce,0x5a3,0x2fde,0xd18,0xd18,0x2fee,0x5a3,0x2ff9,0x3009, + 0x5a3,0x5a3,0x5a3,0x3019,0x5a3,0x3029,0x5a3,0x3039,0x5a3,0x3049,0x1c9a,0xd18,0xd18,0xd18,0xd18,0xd18, + 0x5a3,0x5a3,0x5a3,0x5a3,0x1338,0xd18,0xd18,0xd18,0x41,0x41,0x41,0x3059,0x28fd,0x28fd,0x28fd,0x3069, + 0x5a3,0x5a3,0x3079,0xb24,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0x10a3,0x10a8,0x5a3,0x5a3,0x3089,0xd99,0xd18,0xd18,0xd18,0xd18,0x5a3,0x2fde,0x3099,0x5a3,0x577,0x30a9, + 0xd18,0x5a3,0x30b9,0xd18,0xd18,0x5a3,0x30c9,0xd18,0x5a3,0x13a7,0x281b,0x5a3,0x5a3,0x575,0x30d9,0x1ca1, + 0x30e9,0x30f9,0x7cb,0x5a3,0x5a3,0x3109,0x3117,0x5a3,0x1338,0xb24,0x773,0x5a3,0x3127,0x3134,0x3144,0x5a3, + 0x5a3,0x3154,0x7cb,0x5a3,0x5a3,0x3164,0x3173,0x3183,0x1ca2,0x3193,0x5a3,0x954,0x31a3,0x31b2,0xd18,0xd18, + 0xd18,0xd18,0x31c2,0x863,0x31d1,0x5a3,0x5a3,0x630,0x31e1,0xb24,0x31f1,0x858,0x868,0x3200,0x3210,0x3220, + 0x322e,0x1562,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x5a3,0x323e,0x324e,0x325e, + 0xd99,0xd18,0x5a3,0x5a3,0x5a3,0x326e,0x327d,0xb24,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0x5a3,0x5a3,0xed5,0x328d,0x329c,0x32a4,0xd18,0xd18,0x5a3,0x5a3,0x5a3,0x32b4,0x32c3,0xb24, + 0x32d3,0xd18,0x5a3,0x5a3,0x32e3,0x32f3,0xb24,0xd18,0xd18,0xd18,0x5a3,0x108a,0x3303,0x3313,0x13a7,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x31a3,0x3323,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0x41,0x41,0x28fd,0x28fd,0xc23,0x3333,0x3342,0x334e,0x5a3,0x335e,0x336e,0xb24, + 0xd18,0xd18,0xd18,0xd18,0x2a9c,0x5a3,0x5a3,0x337e,0x338e,0xd18,0x339e,0x5a3,0x5a3,0x33ab,0x33ba,0x33ca, + 0x5a3,0x5a3,0x573,0x33da,0x33e8,0x5a3,0x5a3,0x5a3,0x5a3,0x1338,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x868,0x5a3,0xed5,0x33f8,0x3408,0xc23, + 0x10aa,0x550,0x5a3,0xe2a,0x3418,0x3427,0xd18,0xd18,0xd18,0xd18,0x96e,0x5a3,0x5a3,0x3437,0x3446,0xb24, + 0x3456,0x5a3,0x3460,0x3470,0xb24,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0x5a3,0x3480,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0x993,0x10a3,0x3490,0x349f,0x34ad,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x1337,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0x1ac2,0x1ac2,0x1ac2,0x1ac2,0x1ac2,0x1ac2,0x34bd,0x34cd,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0xd97,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x34dd,0x5a3,0x5a3,0x50e,0x34ed,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0x5a3,0x5a3,0x5a3,0x5a3,0x13a7,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0x5a3,0x5a3,0x5a3,0x1338,0x5a3,0x50e,0x2770,0x5a3,0x5a3,0x5a3,0x5a3,0x50e,0xb24,0x5a3,0x50f, + 0x34fd,0x5a3,0x5a3,0x5a3,0x350d,0x351d,0x352d,0x353b,0x741,0x5a3,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0x41,0x41,0x28fd,0x28fd,0x10a3,0x354b,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x5a3, + 0x5a3,0xe1d,0x355b,0x355c,0x355c,0x3564,0x3573,0xd18,0xd18,0xd18,0xd18,0x3581,0x3591,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x13a6,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x13a8,0xd18,0xd18,0x1338,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x35a1,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0xd98,0xd18,0xd18,0xd98,0x2ed1,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x511,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x73e,0x510,0x1338,0x35b1,0x35c1, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0x2ce,0x2ce,0x641,0x2ce,0x1560,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03, + 0x1d03,0x1c66,0xd18,0xd18,0xd18,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03, + 0x1d03,0x1d03,0x1d03,0x1d03,0x1c64,0x1d03,0x1d03,0x1ecf,0x1d03,0x1d03,0x1d03,0x35d1,0x35de,0x35eb,0x1d03,0x35f7, + 0x1d03,0x1d03,0x1d03,0x1c5f,0xd18,0x1d03,0x1d03,0x1d03,0x1d03,0x3605,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0x10a3,0x3615,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1c63,0x10a3,0x2e6a,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0x41,0x3b2,0x28fd,0x3625,0x3ae,0x2ef0,0x1865,0x41,0xdc,0x3635,0x3645, + 0x3653,0x2ef1,0x41,0x3b2,0x28fd,0x3660,0x366d,0x28fd,0x367b,0x368b,0x369a,0x369e,0x41,0xd8,0x28fd,0x41, + 0x3b2,0x28fd,0x3625,0x3ae,0x28fd,0x1865,0x41,0xdc,0x369e,0x41,0xd8,0x28fd,0x41,0x3b2,0x28fd,0x36ae, + 0x41,0x36bd,0xeb,0x38a,0x36cd,0x28fd,0x36d9,0x41,0x36b9,0xe7,0x36c7,0xc7,0x28fd,0xed,0x41,0x36e5, + 0x28fd,0x36f2,0x3700,0x3700,0x3700,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03, + 0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03, + 0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x2ce,0x2ce,0x2ce,0x3710,0x2ce,0x2ce,0x371b,0x3728,0x3734,0x1a27,0x4c2, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0x25a,0x1fae,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xe4c,0x3744,0x3752,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x510,0x3762,0x3772,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x3782,0xd18,0x5a3,0x5a3,0x633,0x3792,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x37a2,0x50e,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x37b2,0x1560,0xd18,0xd18,0x41,0x41,0xdc,0x28fd, + 0x37c2,0x2770,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x1ca2,0x10a3,0x10a3,0x37d2, + 0x37e2,0xd18,0xd18,0xd18,0xd18,0x1ca2,0x10a3,0x37f2,0x10a9,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xae4,0x5a3,0x3802,0x380f,0x381d,0x382d,0x383b,0x3843,0x867,0x511,0x3852, + 0x511,0xd18,0xd18,0xd18,0x3862,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0x1d03,0x1d03,0x1c5e,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1c66,0x1c5b, + 0x148b,0x148b,0x148b,0x1d03,0x1c64,0x1cb6,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1c5c, + 0xd18,0xd18,0xd18,0x1c7d,0x1d03,0x1c67,0x1d03,0x1d03,0x1c5e,0x1c61,0x1c68,0x1c64,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03, + 0x1d03,0x1d03,0x1d03,0x1d03,0x3872,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03, + 0x1d03,0x1d03,0x3882,0x1c5d,0x1c5d,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1c66,0x1d03,0x1d03,0x1d03, + 0x1d03,0x1d03,0x1c61,0x1c5e,0x1c69,0x1c5e,0x1d03,0x1d03,0x1d03,0x1c62,0x10ca,0x1d03,0x1d03,0x1c62,0x1d03,0x1c5c, + 0x1c68,0xd18,0xd18,0xd18,0xd18,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03, + 0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1c66,0x1c5c,0x388f,0x1c63,0x1d03,0x1c5d,0x1c5f,0x1c64,0x10ca,0x1c62,0x1c63, + 0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1d03,0x1eeb,0x1d03,0x1d03,0x1c5f,0xd18,0xd18,0xb24, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0xd18,0xd18, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x1338,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x50f,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0xd99, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x993,0xd18, + 0x5a3,0x50f,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x73e,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0x389e,0xd18,0x38ae,0x38ae,0x38ae,0x38ae,0x38ae,0x38ae,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0xd18, + 0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36, + 0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x2a36,0x38be, + 0x440,0x460,0x480,0x4a0,0x4c0,0x4e0,0x500,0x51a,0x53a,0x55a,0x57a,0x59a,0x5ba,0x5da,0x5fa,0x615, + 0xd0,0x635,0x655,0x66a,0x66a,0x66a,0x66a,0x671,0xd0,0xd0,0x691,0x66a,0x66a,0x66a,0x66a,0x66a, + 0xd0,0x6b1,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a, + 0x66a,0x66a,0xd0,0x6d1,0x66a,0x6ed,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0x70d,0xd0, + 0xd0,0x72d,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a, + 0x66a,0x66a,0x73e,0x75e,0x775,0x66a,0x66a,0x66a,0x66a,0x795,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a, + 0x66a,0x7a5,0x7c5,0x7e5,0x805,0x825,0x845,0x865,0x66a,0x875,0x895,0x8ac,0x66a,0x8bc,0x8dc,0x66a, + 0x8f5,0x915,0x935,0x955,0x845,0x975,0x995,0x9b0,0x66a,0x66a,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0x9d0,0xd0,0xd0,0xd0,0xd0,0xd0, + 0xd0,0xd0,0x9e0,0x9ff,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xa15,0xd0,0xd0,0xd0,0xd0, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xa20,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a, + 0xd0,0xa40,0x66a,0x66a,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xa60,0x66a,0x66a, + 0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a, + 0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0xa80,0x66a, + 0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a, + 0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x66a,0x380,0x380, + 0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380, + 0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0x380,0xaa0 + ] +); + +#[rustfmt::skip] +pub const DATA: ZeroVec = zerovec!(u8; core::convert::identity; + [ + 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, + 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, + 0xc,0x17,0x17,0x17,0x19,0x17,0x17,0x17,0x14,0x15,0x17,0x18,0x17,0x13,0x17,0x17, + 9,9,9,9,9,9,9,9,9,9,0x17,0x17,0x18,0x18,0x18,0x17, + 0x17,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,0x14,0x17,0x15,0x1a,0x16, + 0x1a,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,0x14,0x18,0x15,0x18,0xf, + 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, + 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xc, + 0x17,0x19,0x19,0x19,0x19,0x1b,0x17,0x1a,0x1b,5,0x1c,0x18,0x10,0x1b,0x1a,0x1b, + 0x18,0xb,0xb,0x1a,2,0x17,0x17,0x1a,0xb,5,0x1d,0xb,0xb,0xb,0x17,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,0x18,1,1,1,1,1,1,1,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,0x18,2,2,2,2,2,2,2,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,1,2,1,2,1,2,2,1,1, + 2,1,2,1,1,2,1,1,1,2,2,1,1,1,1,2, + 1,1,2,1,1,1,2,2,2,1,1,2,1,1,2,1, + 2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,1, + 1,2,1,2,1,1,2,2,5,1,2,2,2,5,5,5, + 5,1,3,2,1,3,2,1,3,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,2,1,3, + 2,1,2,1,1,1,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,2,2,2,2,2,2,1, + 1,2,1,1,2,1,2,1,1,1,1,2,1,2,1,2, + 1,2,1,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,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,5,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, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 0x1a,0x1a,0x1a,0x1a,4,4,4,4,4,4,4,4,4,4,4,4, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,4,4, + 4,4,4,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,4,0x1a,4,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,1,2, + 1,2,4,0x1a,1,2,0,0,4,2,2,2,0x17,1,0,0, + 0,0,0x1a,0x1a,1,0x17,1,1,1,0,1,0,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2, + 2,1,1,1,2,2,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,2, + 2,2,2,1,2,0x18,1,2,1,1,2,2,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,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,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,2,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,0x1b,6,6,6, + 6,6,7,7,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,0,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,0,0,4,0x17,0x17,0x17,0x17,0x17,0x17,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,2,2,0x17,0x13,0,0,0x1b, + 0x1b,0x19,0,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 0x13,6,0x17,6,6,0x17,6,6,0x17,6,0,0,0,0,0,0, + 0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0, + 0,5,5,5,5,0x17,0x17,0,0,0,0,0,0,0,0,0, + 0,0,0x10,0x10,0x10,0x10,0x10,0x10,0x18,0x18,0x18,0x17,0x17,0x19,0x17,0x17, + 0x1b,0x1b,6,6,6,6,6,6,6,6,6,6,6,0x17,0x10,0x17, + 0x17,0x17,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,4,5,5,5,5,5,5,5,5,5,5,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,9,9,9,9,9,9,9,9,9,9,0x17,0x17,0x17,0x17, + 5,5,6,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,0x17,5,6,6,6,6,6,6,6,0x10,0x1b,6,6, + 6,6,6,6,4,4,6,6,0x1b,6,6,6,6,5,5,9, + 9,9,9,9,9,9,9,9,9,5,5,5,0x1b,0x1b,5,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0x10,5, + 6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,0, + 0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,5, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9, + 9,9,9,9,9,9,9,9,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6, + 6,6,4,4,0x1b,0x17,0x17,0x17,4,0,0,6,0x19,0x19,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,6,6,6,6,4,6,6,6,6,6,6,6, + 6,6,4,6,6,6,4,6,6,6,6,6,0,0,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,6,6,6,0,0,0x17,0,5,5, + 5,5,5,5,5,5,5,5,5,0,0,0,0,0,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x1a,5, + 5,5,5,5,5,0,0x10,0x10,0,0,0,0,0,0,6,6, + 6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,4,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,0x10, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,8,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,6,8,6,5,8,8,6,6,6,6,6,6, + 6,6,8,8,8,8,6,8,8,5,6,6,6,6,6,6, + 6,5,5,5,5,5,5,5,5,5,5,6,6,0x17,0x17,9, + 9,9,9,9,9,9,9,9,9,0x17,4,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,6,8,8,0,5,5,5, + 5,5,5,5,5,0,0,5,5,0,0,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,0,5,5,5,5,5,5,5,0,5,0,0,0,5,5, + 5,5,0,0,6,5,8,8,6,6,6,6,0,0,8,8, + 0,0,8,8,6,5,0,0,0,0,0,0,0,0,8,0, + 0,0,0,5,5,0,5,5,5,6,6,0,0,9,9,9, + 9,9,9,9,9,9,9,5,5,0x19,0x19,0xb,0xb,0xb,0xb,0xb, + 0xb,0x1b,0x19,5,0x17,6,0,6,6,8,0,5,5,5,5,5, + 5,0,0,0,0,5,5,0,0,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, + 5,5,5,5,5,5,5,0,5,5,0,5,5,0,5,5, + 0,0,6,0,8,8,6,6,0,0,0,0,6,6,0,0, + 6,6,6,0,0,0,6,0,0,0,0,0,0,0,5,5, + 5,5,0,5,0,0,0,0,0,0,0,9,9,9,9,9, + 9,9,9,9,9,6,6,5,5,5,6,0x17,0,0,0,0, + 0,0,0,0,0,6,6,8,0,5,5,5,5,5,5,5, + 5,5,0,5,5,5,0,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5, + 5,5,5,5,5,0,5,5,0,5,5,5,5,5,0,0, + 6,5,8,8,6,6,6,6,6,0,6,6,8,0,8,8, + 6,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,5,5,6,6,0,0,9,9,9,9,9,9,9, + 9,9,9,0x17,0x19,0,0,0,0,0,0,0,5,6,6,6, + 6,6,6,0,6,8,8,0,5,5,5,5,5,5,5,5, + 0,0,5,5,0,0,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,0,5,5,5, + 5,5,5,5,0,5,5,0,5,5,5,5,5,0,0,6, + 5,8,6,6,6,6,0,0,8,8,0,0,8,8,6,0, + 0,0,0,0,0,0,6,6,8,0,0,0,0,5,5,0, + 5,5,5,6,6,0,0,9,9,9,9,9,9,9,9,9, + 9,0x1b,5,0xb,0xb,0xb,0xb,0xb,0xb,0,0,0,0,0,0,0, + 0,6,5,0,5,5,5,5,5,5,0,0,0,5,5,5, + 0,5,5,5,5,0,0,0,5,5,0,5,0,5,5,0, + 0,0,5,5,0,0,0,5,5,5,0,0,0,5,5,5, + 5,5,5,5,5,5,5,5,5,0,0,0,0,8,8,6, + 8,8,0,0,0,8,8,8,0,8,8,8,6,0,0,5, + 0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,0xb, + 0xb,0xb,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x1b,0,0,0,0,0,6, + 8,8,8,6,5,5,5,5,5,5,5,5,0,5,5,5, + 0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,0,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,0,0,6,5,6,6,8, + 8,8,8,0,6,6,6,0,6,6,6,6,0,0,0,0, + 0,0,0,6,6,0,5,5,5,0,0,5,0,0,5,5, + 6,6,0,0,9,9,9,9,9,9,9,9,9,9,0,0, + 0,0,0,0,0,0x17,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0x1b,5,6, + 8,8,0x17,5,5,5,5,5,5,5,5,0,5,5,5,0, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,5, + 5,5,0,5,5,5,5,5,0,0,6,5,8,6,8,8, + 8,8,8,0,6,8,8,0,8,8,6,6,0,0,0,0, + 0,0,0,8,8,0,0,0,0,0,0,5,5,0,5,5, + 6,6,0,0,9,9,9,9,9,9,9,9,9,9,0,5, + 5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6, + 8,8,5,5,5,5,5,5,5,5,5,0,5,5,5,0, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,6,6,5,8,8,6,6, + 6,6,0,8,8,8,0,8,8,8,6,5,0x1b,0,0,0, + 0,5,5,5,8,0xb,0xb,0xb,0xb,0xb,0xb,0xb,5,5,5,6, + 6,0,0,9,9,9,9,9,9,9,9,9,9,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0x1b,5,5,5,5,5,5,0,6,8, + 8,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,0,0,0,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, + 5,5,5,5,5,5,5,5,5,0,5,0,0,5,5,5, + 5,5,5,5,0,0,0,6,0,0,0,0,8,8,8,6, + 6,6,0,6,0,8,8,8,8,8,8,8,8,0,0,0, + 0,0,0,9,9,9,9,9,9,9,9,9,9,0,0,8, + 8,0x17,0,0,0,0,0,0,0,0,0,0,0,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,6,5,5, + 6,6,6,6,6,6,6,0,0,0,0,0x19,5,5,5,5, + 5,5,4,6,6,6,6,6,6,6,6,0x17,9,9,9,9, + 9,9,9,9,9,9,0x17,0x17,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,0,0,0,0,5,5,0,5, + 0,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, + 5,0,5,5,5,5,5,5,5,5,5,5,6,5,5,6, + 6,6,6,6,6,6,6,6,5,0,0,5,5,5,5,5, + 0,4,0,6,6,6,6,6,6,0,0,9,9,9,9,9, + 9,9,9,9,9,0,0,5,5,5,5,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,5,0x1b,0x1b,0x1b,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x1b,0x17, + 0x1b,0x1b,0x1b,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,9,9,9,9,9, + 9,9,9,9,9,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0x1b, + 6,0x1b,6,0x1b,6,0x14,0x15,0x14,0x15,8,8,5,5,5,5,5, + 5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,0,0,0,0,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,8,6,6,6,6,6, + 0x17,6,6,5,5,5,5,5,6,6,6,6,6,6,6,6, + 6,6,6,0,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b,0x1b,0x17,0x17,0x17,0x17,0x17,0x1b,0x1b, + 0x1b,0x1b,0x17,0x17,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,0,0,0,0,0,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,8,8,6,6,6,6,8,6,6,6,6,6, + 6,8,6,6,8,8,6,6,5,9,9,9,9,9,9,9, + 9,9,9,0x17,0x17,0x17,0x17,0x17,0x17,5,5,5,5,5,5,8, + 8,6,6,5,5,5,5,6,6,6,5,8,8,8,5,5, + 8,8,8,8,8,8,8,5,5,5,6,6,6,6,5,5, + 5,5,5,5,5,5,5,5,5,6,8,8,6,6,8,8, + 8,8,8,8,6,5,8,9,9,9,9,9,9,9,9,9, + 9,8,8,8,6,0x1b,0x1b,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,0,1,0,0,0,0,0,1,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,2, + 2,2,2,2,2,2,2,2,2,2,2,2,0x17,4,2,2, + 2,5,5,5,5,5,5,5,5,5,0,5,5,5,5,0, + 0,5,5,5,5,5,5,5,0,5,0,5,5,5,5,0, + 0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,0,5,5,5,5,0,0,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,0,5,5,5,5,0,0, + 5,5,5,5,5,5,5,0,5,5,5,5,0,0,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,0,5,5,5,5,0,0,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,0,0,6,6,6,0x17,0x17,0x17,0x17,0x17,0x17, + 0x17,0x17,0x17,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0,0,0,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,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,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,2,2,2,2,2,2,0,0,0x13,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,0x1b,0x17,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,0xc,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,0x14,0x15,0,0,0,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,0x17,0x17,0x17,0xa,0xa,0xa,5,5, + 5,5,5,5,5,5,0,0,0,0,0,0,0,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6, + 6,6,8,0,0,0,0,0,0,0,0,0,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6, + 6,8,0x17,0x17,0,0,0,0,0,0,0,0,0,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6, + 6,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5, + 5,5,5,5,5,5,5,5,5,5,0,5,5,5,0,6, + 6,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,6,6,8,6,6,6,6,6,6,6,8,8,8,8,8, + 8,6,8,8,6,6,6,6,6,6,6,6,6,6,6,0x17, + 0x17,0x17,4,0x17,0x17,0x17,0x19,5,6,0,0,9,9,9,9,9, + 9,9,9,9,9,0,0,0,0,0,0,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0,0,0,0,0,0,0x17,0x17,0x17,0x17,0x17, + 0x17,0x13,0x17,0x17,0x17,0x17,6,6,6,0x10,6,9,9,9,9,9, + 9,9,9,9,9,0,0,0,0,0,0,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,4,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,0,0,0,0,0,0,0,5,5,5,5,5,6,6,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,6,5,0,0,0,0,0,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, + 0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,0,6,6,6,8,8,8,8,6, + 6,8,8,8,0,0,0,0,8,8,6,8,8,8,8,8, + 8,6,6,6,0,0,0,0,0x1b,0,0,0,0x17,0x17,9,9, + 9,9,9,9,9,9,9,9,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,0,0,5,5,5,5,5,0,0,0, + 0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,0,0,0,0,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,0,0,0,0,0,0,9,9, + 9,9,9,9,9,9,9,9,0xb,0,0,0,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,6,6,8,8,6,0,0,0x17,0x17,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,8,6, + 8,6,6,6,6,6,6,6,0,6,8,6,8,8,6,6, + 6,6,6,6,6,6,8,8,8,8,8,8,6,6,6,6, + 6,6,6,6,6,6,0,0,6,9,9,9,9,9,9,9, + 9,9,9,0,0,0,0,0,0,9,9,9,9,9,9,9, + 9,9,9,0,0,0,0,0,0,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 4,0x17,0x17,0x17,0x17,0x17,0x17,0,0,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,7,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,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,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,6,6,6,6,8,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,6,8,6,6, + 6,6,6,8,6,8,8,8,6,8,8,5,5,5,5,5, + 5,5,5,0,0,0,9,9,9,9,9,9,9,9,9,9, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,6,6,6,6,6,6,6,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x17,0x17,0,6,6,8,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,8,6,6,6,6,8,8,6,6, + 8,6,6,6,5,5,9,9,9,9,9,9,9,9,9,9, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,6,8,6,6,8,8,8,6,8,6, + 6,6,8,8,0,0,0,0,0,0,0,0,0x17,0x17,0x17,0x17, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,8,8,8,8,8,8,8,8,6,6,6,6, + 6,6,6,6,8,8,6,6,0,0,0,0x17,0x17,0x17,0x17,0x17, + 9,9,9,9,9,9,9,9,9,9,0,0,0,5,5,5, + 9,9,9,9,9,9,9,9,9,9,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,4,4,4,4,4,4,0x17,0x17, + 2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0, + 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, + 1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,0, + 6,6,6,0x17,6,6,6,6,6,6,6,6,6,6,6,6, + 6,8,6,6,6,6,6,6,6,5,5,5,5,6,5,5, + 5,5,5,5,6,5,5,8,6,6,5,0,0,0,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,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2, + 2,2,2,2,4,2,2,2,2,2,2,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,2,2,2,2, + 2,2,2,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,2,2,2,2,2,2,2,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,0,0,1,1,1, + 1,1,1,0,0,2,2,2,2,2,2,2,2,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,0,0,1,1,1, + 1,1,1,0,0,2,2,2,2,2,2,2,2,0,1,0, + 1,0,1,0,1,2,2,2,2,2,2,2,2,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,0,0,2,2,2,2,2,2,2,2,3,3,3, + 3,3,3,3,3,2,2,2,2,2,2,2,2,3,3,3, + 3,3,3,3,3,2,2,2,2,2,2,2,2,3,3,3, + 3,3,3,3,3,2,2,2,2,2,0,2,2,1,1,1, + 1,3,0x1a,2,0x1a,0x1a,2,2,2,0,2,2,1,1,1,1, + 3,0x1a,0x1a,0x1a,2,2,2,2,0,0,2,2,1,1,1,1, + 0,0x1a,0x1a,0x1a,2,2,2,2,2,2,2,2,1,1,1,1, + 1,0x1a,0x1a,0x1a,0,0,2,2,2,0,2,2,1,1,1,1, + 3,0x1a,0x1a,0,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0x10, + 0x10,0x10,0x10,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x17,0x17,0x1c,0x1d,0x14,0x1c, + 0x1c,0x1d,0x14,0x1c,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0xd,0xe,0x10,0x10, + 0x10,0x10,0x10,0xc,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x1c,0x1d,0x17, + 0x17,0x17,0x17,0x16,0x17,0x17,0x17,0x18,0x14,0x15,0x17,0x17,0x17,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,0x18,0x17,0x16,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x17,0x17,0xc,0x10,0x10,0x10,0x10,0x10,0,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0xb,4,0,0,0xb,0xb,0xb,0xb,0xb,0xb,0x18,0x18,0x18, + 0x14,0x15,4,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0x18,0x18,0x18, + 0x14,0x15,0,4,4,4,4,4,4,4,4,4,4,4,4,4, + 0,0,0,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,6,6,6,6,6,6,6,6,6,6,6,6,6,7, + 7,7,7,6,7,7,7,6,6,6,6,6,6,6,6,6, + 6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0x1b,0x1b,1,0x1b,0x1b,0x1b,0x1b,1,0x1b,0x1b,2,1,1,1, + 2,2,1,1,1,2,0x1b,1,0x1b,0x1b,0x18,1,1,1,1,1, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,1,0x1b,1,0x1b,1,0x1b,1,1,1,1, + 0x1b,2,1,1,1,1,2,5,5,5,5,2,0x1b,0x1b,2,2, + 1,1,0x18,0x18,0x18,0x18,0x18,1,2,2,2,2,0x1b,0x18,0x1b,0x1b, + 2,0x1b,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, + 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, + 0xa,0xa,1,2,0xa,0xa,0xa,0xa,0xb,0x1b,0x1b,0,0,0,0,0x18, + 0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x18, + 0x1b,0x1b,0x18,0x1b,0x1b,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18, + 0x18,0x1b,0x1b,0x18,0x1b,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x14,0x15,0x14, + 0x15,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x14,0x15, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18, + 0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,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,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x14,0x15,0x14,0x15,0x14,0x15, + 0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0x18,0x18,0x18,0x18,0x18,0x14,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15, + 0x14,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15, + 0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x14, + 0x15,0x14,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x14,0x15,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,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,2,2,1,2,1,1,1,2,2,1, + 2,1,2,1,2,1,1,1,1,2,1,2,2,1,2,2, + 2,2,2,2,4,4,1,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,2,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,1,2,1,2,6,6,6,1,2,0,0,0,0,0, + 0x17,0x17,0x17,0x17,0xb,0x17,0x17,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,2,2,2,2,2,2,2,2,0,2,0, + 0,0,0,0,2,0,0,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, + 0,0,0,0,0,0,4,0x17,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,6,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, + 0,0,0,0,0,0,0,5,5,5,5,5,5,5,0,5, + 5,5,5,5,5,5,0,5,5,5,5,5,5,5,0,5, + 5,5,5,5,5,5,0,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,0x17,0x17,0x1c,0x1d,0x1c,0x1d,0x17,0x17,0x17, + 0x1c,0x1d,0x17,0x1c,0x1d,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x13,0x17, + 0x17,0x13,0x17,0x1c,0x1d,0x17,0x17,0x1c,0x1d,0x14,0x15,0x14,0x15,0x14,0x15,0x14, + 0x15,0x17,0x17,0x17,0x17,0x17,4,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x17,0x13,0x13,0x17,0x17,0x17,0x17,0x13,0x17,0x14,0x17,0x17,0x17,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x1b,0x1b,0x17,0x17,0x17,0x14,0x15,0x14,0x15, + 0x14,0x15,0x14,0x15,0x13,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,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,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, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0, + 0xc,0x17,0x17,0x17,0x1b,4,5,0xa,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15, + 0x14,0x15,0x1b,0x1b,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x13,0x14,0x15,0x15, + 0x1b,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,6,6,6,6,8,8, + 0x13,4,4,4,4,4,0x1b,0x1b,0xa,0xa,0xa,4,5,0x17,0x1b,0x1b, + 0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 0,0,6,6,0x1a,0x1a,4,4,5,0x13,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,0x17,4,4,4,5,0,0,0,0,0,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,0,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,0,0x1b,0x1b,0xb,0xb,0xb, + 0xb,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0, + 0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0x1b,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,5,5,5,5,5,5,5, + 5,5,5,5,5,5,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0, + 0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,4, + 0x17,0x17,5,5,5,5,5,5,5,5,5,5,5,5,4,0x17, + 0x17,0x17,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,9,9,9,9,9,9,9,9,9,9,5,5,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 5,6,7,7,7,0x17,6,6,6,6,6,6,6,6,6,6, + 0x17,4,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,4,4, + 6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, + 0xa,0xa,6,6,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0, + 0,0,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,4,4,4,4,4,4,4, + 4,4,0x1a,0x1a,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,2,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,4,2,2,2,2,2,2,2,2,1,2,1, + 2,1,1,2,1,2,1,2,1,2,4,0x1a,0x1a,1,2,1, + 2,5,1,2,1,2,2,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,1,1,1, + 1,2,1,1,1,1,1,2,1,2,1,2,1,2,1,2, + 1,2,1,1,1,1,2,1,2,0,0,0,0,0,1,2, + 0,2,0,2,1,2,1,2,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 4,4,4,1,2,5,4,4,2,5,5,5,5,5,6,5, + 5,5,6,5,5,5,5,6,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,8, + 8,6,6,8,0x1b,0x1b,0x1b,0x1b,6,0,0,0,0xb,0xb,0xb,0xb, + 0xb,0xb,0x1b,0x1b,0x19,0x1b,0,0,0,0,0,0,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,0,8,8,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 8,8,8,8,8,8,8,8,8,8,8,8,6,6,0,0, + 0,0,0,0,0,0,0x17,0x17,9,9,9,9,9,9,9,9, + 9,9,0,0,0,0,0,0,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,5,5,5,5,5,5, + 0x17,0x17,0x17,5,0x17,5,5,6,9,9,9,9,9,9,9,9, + 9,9,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6, + 6,6,6,6,6,6,0x17,0x17,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6, + 6,6,6,8,8,0,0,0,0,0,0,0,0,0,0,0, + 0x17,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, + 0,6,6,6,8,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,6,8,8,6,6,6,6,8,8,6,6,8, + 8,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,4, + 9,9,9,9,9,9,9,9,9,9,0,0,0,0,0x17,0x17, + 5,5,5,5,5,6,4,5,5,5,5,5,5,5,5,5, + 9,9,9,9,9,9,9,9,9,9,5,5,5,5,5,0, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,8, + 8,6,6,8,8,6,6,0,0,0,0,0,0,0,0,0, + 5,5,5,6,5,5,5,5,5,5,5,5,6,8,0,0, + 9,9,9,9,9,9,9,9,9,9,0,0,0x17,0x17,0x17,0x17, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 4,5,5,5,5,5,5,0x1b,0x1b,0x1b,5,8,6,8,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,5, + 6,6,6,5,5,6,6,5,5,5,5,5,6,6,5,6, + 5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,5,5,4,0x17,0x17,5,5, + 5,5,5,5,5,5,5,5,5,8,6,6,8,8,0x17,0x17, + 5,4,4,8,6,0,0,0,0,0,0,0,0,0,5,5, + 5,5,5,5,0,0,5,5,5,5,5,5,0,0,5,5, + 5,5,5,5,0,0,0,0,0,0,0,0,0,5,5,5, + 5,5,5,5,0,5,5,5,5,5,5,5,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,0x1a,4,4,4,4,2,2,2, + 2,2,2,2,2,2,4,0x1a,0x1a,0,0,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,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,2,2,2,2,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 8,8,6,8,8,6,8,8,0x17,8,6,0,0,9,9,9, + 9,9,9,9,9,9,9,0,0,0,0,0,0,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0, + 0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,0,0,0,0,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,0,0,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 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, + 0,0,0,0,0,0,2,2,2,2,2,2,2,0,0,0, + 0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0, + 0,0,0,5,6,5,5,5,5,5,5,5,5,5,5,0x18, + 5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5, + 5,5,5,0,5,0,5,5,0,5,5,0,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,0x15,0x14,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,0,0,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,0,0,0,0,0,0,0,0x1b,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,5,5,5,5, + 5,5,5,5,5,5,5,5,0x19,0x1b,0x1b,0x1b,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,0x17,0x17,0x17,0x17, + 0x17,0x17,0x17,0x14,0x15,0x17,0,0,0,0,0,0,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,0x17,0x13,0x13,0x16, + 0x16,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x17,0x17,0x14, + 0x15,0x17,0x17,0x17,0x17,0x16,0x16,0x16,0x17,0x17,0x17,0,0x17,0x17,0x17,0x17, + 0x13,0x14,0x15,0x14,0x15,0x14,0x15,0x17,0x17,0x17,0x18,0x13,0x18,0x18,0x18,0, + 0x17,0x19,0x17,0x17,0,0,0,0,5,5,5,5,5,0,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,0,0,0x10,0,0x17, + 0x17,0x17,0x19,0x17,0x17,0x17,0x14,0x15,0x17,0x18,0x17,0x13,0x17,0x17,9,9, + 9,9,9,9,9,9,9,9,0x17,0x17,0x18,0x18,0x18,0x17,0x17,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,0x14,0x17,0x15,0x1a,0x16,0x1a,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,0x14,0x18,0x15,0x18,0x14,0x15,0x17, + 0x14,0x15,0x17,0x17,5,5,5,5,5,5,5,5,5,5,4,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,4,4,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, + 5,5,5,5,5,5,0,0,5,5,5,5,5,5,0,0, + 5,5,5,5,5,5,0,0,5,5,5,0,0,0,0x19,0x19, + 0x18,0x1a,0x1b,0x19,0x19,0,0x1b,0x18,0x18,0x18,0x18,0x1b,0x1b,0,0,0, + 0,0,0,0,0,0,0,0x10,0x10,0x10,0x1b,0x1b,0,0,5,5, + 5,5,5,5,5,5,5,5,5,0,5,5,0,5,0x17,0x17, + 0x17,0,0,0,0,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0,0, + 0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0xa,0xa,0xa,0xa,0xa,0xb, + 0xb,0xb,0xb,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0xb,0xb,0x1b, + 0x1b,0x1b,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 6,0,0,6,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0,0,0,0,0,0,0,0,0,5,5,5,0xa, + 5,5,5,5,5,5,5,5,0xa,0,0,0,0,0,5,5, + 5,5,5,5,6,6,6,6,6,0,0,0,0,0,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,0,0x17,0xa,0xa, + 0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,1,1,1, + 1,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2, + 2,0,0,0,0,5,5,5,5,0,0,0,0,0,0,0, + 0,0,0,0,0x17,1,1,1,0,1,1,0,2,2,2,2, + 2,2,2,2,2,0,2,2,2,2,2,2,2,2,2,2, + 2,2,2,0,2,2,2,2,2,2,2,0,2,2,0,0, + 0,4,4,4,4,4,4,0,4,4,4,4,4,4,4,4, + 4,0,0,0,0,0,5,5,5,5,5,5,0,0,5,0, + 5,5,5,5,5,5,0,5,5,0,0,0,5,0,0,5, + 5,5,5,5,5,0,0x17,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,5, + 5,5,5,5,5,5,0x1b,0x1b,0xb,0xb,0xb,0xb,0xb,0xb,0xb,5, + 5,5,0,5,5,0,0,0,0,0,0xb,0xb,0xb,0xb,0xb,5, + 5,5,5,5,5,0xb,0xb,0xb,0xb,0xb,0xb,0,0,0,0x17,5, + 5,5,5,5,5,5,5,5,5,0,0,0,0,0,0x17,5, + 5,5,5,5,5,5,5,0,0,0,0,0xb,0xb,5,5,6, + 6,6,0,6,6,0,0,0,0,0,6,6,6,6,5,5, + 5,5,5,5,0,0,6,6,6,0,0,0,0,6,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,5,5, + 5,5,5,5,5,5,5,5,5,5,5,0xb,0xb,0x17,5,5, + 5,5,5,5,5,5,5,5,5,5,5,0xb,0xb,0xb,5,5, + 5,5,5,5,5,5,0x1b,5,5,5,5,5,5,5,6,6, + 0,0,0,0,0xb,0xb,0xb,0xb,0xb,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,0, + 0,0,0x17,0x17,0x17,0x17,0x17,0x17,0x17,5,5,5,5,5,5,0, + 0,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,5,5,5,0,0,0,0, + 0,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,5,5,0,0,0,0,0, + 0,0,0x17,0x17,0x17,0x17,0,0,0,1,1,1,0,0,0,0, + 0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0, + 0,0,0,0xb,0xb,0xb,0xb,0xb,0xb,5,5,5,5,6,6,6, + 6,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5, + 5,5,5,0,6,6,0x13,0,0,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 5,0,0,0,0,0,0,0,0,6,0xb,0xb,0xb,0xb,0x17,0x17, + 0x17,0x17,0x17,0,0,0,0,0,0,5,5,6,6,6,6,0x17, + 0x17,0x17,0x17,0,0,0,0,0,0,5,5,5,5,5,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0,0,0,0,6,6,6,6,6,6,6, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0xb,0xb,0xb,0xb,0xb,0xb,9, + 9,9,9,9,9,9,9,9,9,6,5,5,6,6,5,0, + 0,0,0,0,0,0,0,0,6,8,8,8,6,6,6,6, + 8,8,6,6,0x17,0x17,0x10,0x17,0x17,6,0,0,0,0,0,0, + 0,0,0,0,0x10,0,0,5,5,5,5,5,5,5,6,6, + 6,6,6,8,6,6,6,6,6,0,9,9,9,9,9,9, + 9,9,9,9,0x17,0x17,0x17,0x17,5,8,8,5,0,0,0,0, + 0,0,0,0,5,5,5,6,0x17,0x17,5,0,0,0,0,0, + 0,0,0,0,5,5,5,8,8,8,6,6,6,6,6,6, + 6,6,6,8,5,5,5,5,0x17,0x17,0x17,0x17,6,6,6,6, + 0x17,8,6,9,9,9,9,9,9,9,9,9,9,5,0x17,5, + 0x17,0x17,0x17,0xb,0xb,0xb,0xb,0xb,0,0,0,0,0,0,0,0, + 0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,8, + 8,8,6,6,8,8,6,8,6,6,0x17,0x17,0x17,0x17,0x17,0x17, + 6,0,5,5,5,5,5,5,5,0,5,0,5,5,5,5, + 0,5,5,5,5,5,5,5,5,5,0x17,0,0,0,0,0, + 0,8,8,8,6,6,6,6,6,6,6,6,0,0,0,0, + 0,6,6,8,8,0,5,5,5,5,5,5,5,5,0,0, + 5,0,5,5,0,5,5,5,5,5,0,6,6,5,8,8, + 6,8,8,8,8,0,0,8,8,0,0,8,8,8,0,0, + 5,0,0,0,0,0,0,8,0,0,0,0,0,5,5,5, + 8,8,0,0,6,6,6,6,6,6,6,0,0,0,5,5, + 5,5,5,8,8,8,6,6,6,6,6,6,6,6,8,8, + 6,6,6,8,6,5,5,5,5,0x17,0x17,0x17,0x17,0x17,9,9, + 9,9,9,9,9,9,9,9,0x17,0x17,0,0x17,6,5,8,8, + 8,6,6,6,6,6,6,8,6,8,8,8,8,6,8,6, + 6,5,5,0x17,5,0,0,0,0,0,0,0,0,8,8,6, + 6,6,6,0,0,8,8,8,8,6,6,8,6,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,5,5,5,5, + 6,6,0,0,8,8,8,6,6,6,6,6,6,6,6,8, + 8,6,8,6,0x17,0x17,0x17,5,0,0,0,0,0,0,0,0, + 0,0,0,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0,0,0,5,5,5,5,5,5,5,5,5,5,5,6,8, + 6,8,8,6,6,6,6,6,6,8,6,5,0x17,0,0,0, + 0,0,0,8,8,6,6,6,6,8,6,6,6,6,6,0, + 0,0,0,9,9,9,9,9,9,9,9,9,9,0xb,0xb,0x17, + 0x17,0x17,0x1b,6,6,6,6,6,6,6,6,8,6,6,0x17,0, + 0,0,0,0xb,0xb,0xb,0,0,0,0,0,0,0,0,0,0, + 0,0,5,5,5,5,5,5,5,0,0,5,0,0,5,5, + 5,5,0,5,5,0,5,5,5,5,5,5,5,5,8,8, + 8,8,8,8,0,8,8,0,0,6,6,8,6,5,8,5, + 8,6,0x17,0x17,0x17,0,0,0,0,0,0,0,0,0,5,8, + 8,8,6,6,6,6,0,0,6,6,8,8,8,8,6,5, + 0x17,5,8,0,0,0,0,0,0,0,0,0,0,0,5,6, + 6,6,6,6,6,6,6,6,6,5,5,5,5,5,6,6, + 6,6,6,6,8,5,6,6,6,6,0x17,0x17,0x17,0x17,0x17,0x17, + 0x17,6,0,0,0,0,0,0,0,0,5,6,6,6,6,6, + 6,8,8,6,6,6,5,5,5,5,6,6,6,6,6,6, + 6,8,6,6,0x17,0x17,0x17,5,0x17,0x17,0x17,0,0,0,0,0, + 0,0,0,0,0,0,0,0,6,6,6,6,6,6,6,0, + 6,6,6,6,6,6,8,6,5,0x17,0x17,0x17,0x17,0x17,0,0, + 0,0,0,0,0,0,0,0,6,6,6,6,6,6,6,6, + 0,8,6,6,6,6,6,6,8,6,6,8,6,6,0,0, + 0,0,0,0,0,0,0,5,6,6,6,6,6,6,0,0, + 0,6,0,6,6,0,6,6,6,6,6,6,5,6,0,0, + 0,0,0,0,0,0,5,5,5,5,5,5,0,5,5,0, + 5,5,5,5,5,5,5,5,5,5,8,8,8,8,8,0, + 6,6,0,8,8,6,8,6,5,0,0,0,0,0,0,0, + 5,5,5,6,6,8,8,0x17,0x17,0,0,0,0,0,0,0, + 0xb,0xb,0xb,0xb,0xb,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x19,0x19, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0x17,0xa,0xa,0xa, + 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0x17,0x17,0x17, + 0x17,0x17,0,0,0,0,0,0,0,0,0,0,0,5,0x17,0x17, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0x10,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x10,0,0,0,0,0,0,0,6,6,6, + 6,6,0x17,0,0,0,0,0,0,0,0,0,0,6,6,6, + 6,6,6,6,0x17,0x17,0x17,0x17,0x17,0x1b,0x1b,0x1b,0x1b,4,4,4, + 4,0x17,0x1b,0,0,0,0,0,0,0,0,0,0,9,9,9, + 9,9,9,9,9,9,9,0,0xb,0xb,0xb,0xb,0xb,0,5,5, + 5,5,5,5,5,5,5,5,5,5,5,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0x17,0x17,0x17,0x17,0,0,0,0,0,5,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,0,0,0,0, + 0,0,0,6,6,6,4,4,4,4,4,4,4,4,4,4, + 4,4,4,0x17,4,6,0,0,0,0,0,0,0,0,0,0, + 0,8,8,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,4,4,4,4,0,4,4,4,4,4,4,4,0,4,4, + 0,5,5,5,5,5,5,5,5,5,5,0,0,0x1b,6,6, + 0x17,0x10,0x10,0x10,0x10,0,0,0,0,0,0,0,0,0,0,0, + 0,0x1b,0x1b,0x1b,0x1b,0x1b,8,8,6,6,6,0x1b,0x1b,0x1b,8,8, + 8,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,6,6,6,6,6,0x1b,0x1b, + 6,6,6,6,6,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,6,6,6,6,0x1b,0x1b,6,6,6,0x1b,0,0,0,0,0, + 0,0,0,0,0,0xb,0xb,0xb,0xb,0,0,0,0,0,0,0, + 0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1, + 1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2, + 2,1,0,1,1,0,0,1,0,0,1,1,0,0,1,1, + 1,1,0,1,1,1,1,1,1,2,2,2,2,0,2,0, + 2,2,2,2,1,1,0,1,1,1,1,0,0,1,1,1, + 1,1,0,1,1,1,1,1,1,1,0,2,2,2,2,2, + 2,2,2,1,1,0,1,1,1,1,0,1,1,1,1,1, + 0,1,0,0,0,1,1,1,1,1,1,0,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,1,1,1,1,2,2, + 2,2,2,2,0,0,1,1,1,1,1,1,1,1,0x18,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1, + 1,1,1,1,1,1,1,1,0x18,2,2,2,2,2,0x18,2, + 2,2,2,2,2,1,1,1,1,1,1,1,1,1,0x18,2, + 2,2,2,2,2,0x18,2,2,2,2,2,2,1,2,0,0, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 6,6,6,6,6,6,6,0x1b,0x1b,0x1b,0x1b,6,6,6,6,6, + 6,6,6,6,6,6,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,6,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,0x1b,0x1b,0x17,0x17,0x17,0x17,0x17, + 0,0,0,0,6,6,6,6,6,6,6,6,6,0,0,6, + 6,6,6,6,0,6,6,0,6,6,6,6,6,0,0,0, + 0,0,6,6,6,6,6,6,6,4,4,4,4,4,4,4, + 0,0,9,9,9,9,9,9,9,9,9,9,0,0,0,0, + 5,0x1b,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,0,9,9,9,9,9,9,9,9,9,9,0,0,0,0, + 0,0x19,5,5,5,5,5,5,5,0,5,5,5,5,0,5, + 5,0,5,5,5,5,5,0,0,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,2,2,2,2,6,6,6,6,6,6,6,4,0,0, + 0,0,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0x1b,0xb, + 0xb,0xb,0x19,0xb,0xb,0xb,0xb,0,0,0,0,0,0,0,0,0, + 0,0,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0x1b,0xb,0,5,5,0,5,0,0,5,0,5,5,5,5,5, + 5,5,0,5,5,5,5,0,5,0,5,0,0,0,0,5, + 0,0,0,0,5,0,5,0,5,0,5,5,5,0,5,5, + 0,5,0,0,5,0,5,0,5,0,5,0,5,5,0,5, + 0,0,5,5,5,5,0,5,5,5,5,0,5,5,5,5, + 0,5,0,5,5,5,0,5,5,5,5,5,0,5,5,5, + 5,5,0x18,0x18,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0x1b, + 0x1b,0x1b,0x1b,0x1b,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0x10, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0,0 + ] +); + +pub static HEADER: CodePointTrieHeader = CodePointTrieHeader { + high_start: 0x110000, + shifted12_high_start: 0x110, + trie_type: TrieType::Fast, + index3_null_offset: 0x66a, + data_null_offset: 0xd18, + null_value: 0x0, +}; diff --git a/deps/crates/vendor/icu_collections/benches/tries/gc_small.rs b/deps/crates/vendor/icu_collections/benches/tries/gc_small.rs new file mode 100644 index 00000000000000..da297a2d4c607e --- /dev/null +++ b/deps/crates/vendor/icu_collections/benches/tries/gc_small.rs @@ -0,0 +1,865 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use icu_collections::codepointtrie::{CodePointTrieHeader, TrieType}; +use zerovec::ule::AsULE; +use zerovec::{zerovec, ZeroVec}; + +#[rustfmt::skip] +pub const INDEX: ZeroVec = zerovec!(u16; ::ULE::from_unsigned; + [ + 0,0x40,0x7f,0xbf,0xff,0x12e,0x16d,0x1ad,0x1e5,0x224,0x250,0x28e,0x2ce,0x2de,0x31e,0x34f, + 0x38c,0x3bc,0x3fa,0x43a,0x44a,0x47b,0x4b2,0x4f2,0x532,0x572,0x5a3,0x5cf,0x60f,0x644,0x65e,0x69e, + 0x6de,0x71e,0x756,0x78d,0x7ca,0x809,0x848,0x887,0x8c6,0x905,0x944,0x983,0x9c3,0xa01,0xa3f,0xa7f, + 0xabf,0xafe,0xb3e,0xb7e,0xbbe,0xbfd,0xc3d,0xc7d,0xcbc,0xcfc,0xd3b,0xd7b,0xdbb,0xdfb,0xe3b,0xe79, + 0xbbd,0xbd7,0xbe7,0xbfd,0xc1d,0xc3b,0xc58,0xc77,0xc97,0xc97,0xca4,0xcc1,0xce1,0xceb,0xceb,0xceb, + 0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb, + 0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb, + 0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xceb,0xd0b,0xceb,0xceb,0xceb,0xd2b,0xd2b,0xd2b,0xd2c, + 0xd2b,0xd2b,0xd2b,0xd2c,0,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x7f,0x8f,0x9f,0xaf, + 0xbf,0xcf,0xdf,0xef,0xff,0x10f,0x11f,0x12f,0x12e,0x13e,0x14e,0x15e,0x16d,0x17d,0x18d,0x19d, + 0x1ad,0x1bd,0x1cd,0x1dd,0x1e5,0x1f5,0x205,0x215,0x224,0x234,0x244,0x254,0x250,0x260,0x270,0x280, + 0x28e,0x29e,0x2ae,0x2be,0x2ce,0x2de,0x2ee,0x2fe,0x2de,0x2ee,0x2fe,0x30e,0x31e,0x32e,0x33e,0x34e, + 0x34f,0x35f,0x36f,0x37f,0x38c,0x39c,0x3ac,0x3bc,0x3bc,0x3cc,0x3dc,0x3ec,0x3fa,0x40a,0x41a,0x42a, + 0x43a,0x44a,0x45a,0x46a,0x44a,0x45a,0x46a,0x47a,0x47b,0x48b,0x49b,0x4ab,0x4b2,0x4c2,0x4d2,0x4e2, + 0x4f2,0x502,0x512,0x522,0x532,0x542,0x552,0x562,0x572,0x582,0x592,0x5a2,0x5a3,0x5b3,0x5c3,0x5d3, + 0x5cf,0x5df,0x5ef,0x5ff,0x60f,0x61f,0x62f,0x63f,0x644,0x654,0x664,0x674,0x65e,0x66e,0x67e,0x68e, + 0x69e,0x6ae,0x6be,0x6ce,0x6de,0x6ee,0x6fe,0x70e,0x71e,0x72e,0x73e,0x74e,0x756,0x766,0x776,0x786, + 0x78d,0x79d,0x7ad,0x7bd,0x7ca,0x7da,0x7ea,0x7fa,0x809,0x819,0x829,0x839,0x848,0x858,0x868,0x878, + 0x887,0x897,0x8a7,0x8b7,0x8c6,0x8d6,0x8e6,0x8f6,0x905,0x915,0x925,0x935,0x944,0x954,0x964,0x974, + 0x983,0x993,0x9a3,0x9b3,0x9c3,0x9d3,0x9e3,0x9f3,0xa01,0xa11,0xa21,0xa31,0xa3f,0xa4f,0xa5f,0xa6f, + 0xa7f,0xa8f,0xa9f,0xaaf,0xabf,0xacf,0xadf,0xaef,0xafe,0xb0e,0xb1e,0xb2e,0xb3e,0xb4e,0xb5e,0xb6e, + 0xb7e,0xb8e,0xb9e,0xbae,0xbbe,0xbce,0xbde,0xbee,0xbfd,0xc0d,0xc1d,0xc2d,0xc3d,0xc4d,0xc5d,0xc6d, + 0xc7d,0xc8d,0xc9d,0xcad,0xcbc,0xccc,0xcdc,0xcec,0xcfc,0xd0c,0xd1c,0xd2c,0xd3b,0xd4b,0xd5b,0xd6b, + 0xd7b,0xd8b,0xd9b,0xdab,0xdbb,0xdcb,0xddb,0xdeb,0xdfb,0xe0b,0xe1b,0xe2b,0xe3b,0xe4b,0xe5b,0xe6b, + 0xe79,0xe89,0xe99,0xea9,0x5a3,0x5a3,0xeb9,0xec8,0xed8,0xee8,0xef7,0xf06,0xf14,0xf24,0x41,0x41, + 0xf34,0x61,0x61,0xf44,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0xf54,0xf64,0x5a3,0x5a3,0xf54,0x5a3,0x5a3,0xf5c,0xf6c,0xae1,0x5a3,0x5a3, + 0x5a3,0xf6c,0x5a3,0x5a3,0x5a3,0xf74,0xf84,0xf8d,0x5a3,0xf9d,0x41,0x41,0x41,0x41,0x41,0xfad, + 0xfbd,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0xfc0,0x5a3,0xfd0,0xfd5,0x5a3,0x5a3,0x5a3,0x5a3,0xfe5,0xff4,0x5a3,0x1004,0x5a3,0x1013,0x5a3,0x1023, + 0x864,0x1033,0x5a3,0x5a3,0x5a3,0x1043,0x1051,0x105d,0xb24,0x106d,0x107d,0xb24,0x5a3,0x5a3,0x108d,0x5a3, + 0x5a3,0x1094,0x10a4,0x5a3,0x10ab,0x5a3,0x5a3,0x5a3,0x5a3,0x10bb,0x5a3,0x50e,0x10cb,0x10db,0x10eb,0x5a3, + 0x50f,0x10fb,0x5a3,0x5a3,0x511,0x5a3,0x1093,0x110b,0x1119,0x1119,0x5a3,0x1129,0x5a3,0x5a3,0x5a3,0x1139, + 0x1149,0x1156,0xb24,0xb24,0x1166,0x1176,0x640,0xd18,0xd18,0xd18,0x7c9,0x5a3,0x5a3,0x1186,0x1194,0xed8, + 0x11a4,0x11b0,0x7cb,0x5a3,0x11c0,0x69e,0x5a3,0x5a3,0x11ce,0x11dd,0x5a3,0x5a3,0x11ed,0x11f9,0x1209,0x69e, + 0x5a3,0x1216,0x1226,0x41,0x41,0x1236,0x1246,0x1256,0x1265,0x126e,0x61,0x61,0x274,0x280,0x280,0x280, + 0x127e,0x1289,0x61,0x275,0x280,0x280,0x2ce,0x2ce,0x2ce,0x2ce,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x1299,0xff,0xff,0xff,0xff,0xff,0xff,0x12a8,0x12b8,0x12a8,0x12a8,0x12b8,0x12c8, + 0x12a8,0x12d8,0x12e8,0x12e8,0x12e8,0x12f8,0x1307,0x1317,0x1327,0x1337,0x1347,0x1357,0x1367,0x1377,0x1386,0x1394, + 0x13a4,0x13b4,0x13c4,0x13d4,0x13e4,0x13e4,0x13f3,0x1403,0x1412,0x1421,0x1431,0x1441,0x144f,0x145f,0x146f,0x147f, + 0x148f,0x148f,0x149c,0x14ac,0x14bc,0x1119,0x14cb,0x14db,0x1119,0x14e7,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb, + 0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14fb,0x1119,0x150b,0x1119,0x1119,0x1119, + 0x1119,0x1516,0x1119,0x14e0,0x14eb,0x1526,0x1119,0x152a,0x1538,0x1119,0x1119,0x1541,0xd18,0x153d,0xd18,0x147f, + 0x147f,0x147f,0x1551,0x1119,0x1119,0x1119,0x1119,0x155d,0x147f,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119, + 0x1119,0x1119,0x1119,0x1119,0x14c3,0x14c9,0x1119,0x1119,0x14e3,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x156d, + 0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x157d, + 0x1587,0x147f,0x1569,0x1119,0x1119,0x1597,0x14eb,0x15a1,0x14eb,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119, + 0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb, + 0x14eb,0x15a4,0x15ac,0x14eb,0x14eb,0x14eb,0x15b5,0x14eb,0x15c1,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb, + 0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x14eb,0x1119,0x1119,0x1119,0x14eb,0x15cf,0x1119,0x1119, + 0x15dc,0x1119,0x15e6,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x41,0x41,0x41,0x61,0x61,0x61,0x15f6, + 0x1605,0xff,0xff,0xff,0xff,0xff,0xff,0x1614,0x1623,0x61,0x61,0x1633,0x5a3,0x5a3,0x5a3,0x1643, + 0x1653,0x5a3,0x1663,0x86a,0x86a,0x86a,0x86a,0x2ce,0x2ce,0x1673,0x1681,0x1691,0x16a1,0x16b1,0x16c1,0xd18, + 0xd18,0x1119,0x15e2,0x1119,0x1119,0x1119,0x1119,0x1119,0x16d1,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119, + 0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x16e1,0xd18,0x153c,0x16f1,0x16ff,0x170f,0x171f,0x501,0x5a3,0x5a3, + 0x5a3,0x5a3,0x172f,0xfbd,0x5a3,0x5a3,0x5a3,0x5a3,0x173e,0x4fd,0x5a3,0x5a3,0x501,0x5a3,0x5a3,0x5a3, + 0x5a3,0x50e,0x174e,0x5a3,0x5a3,0x1119,0x1119,0x16d1,0x5a3,0x1119,0x1754,0x1553,0x1119,0x1764,0x147e,0x1119, + 0x1119,0x1553,0x1119,0x1119,0x147e,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119, + 0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x1119,0x1119,0x1119,0x1119,0x5a3,0x56d,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x510,0x1119,0x1119, + 0x1119,0x1541,0x5a3,0x5a3,0x1216,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x1774,0x5a3,0x1784,0xd18,0xff,0xff,0x1794,0x17a4,0xff,0x17b4,0x5a3, + 0x5a3,0x5a3,0x5a3,0x17c4,0x17d4,0x2bd,0x17e4,0x17f4,0xfd,0xff,0xff,0xff,0x1804,0x1812,0x1822,0x1828, + 0x1832,0x183e,0x184e,0xd18,0x185c,0x186a,0x5a3,0x1877,0x1887,0x5a3,0x5a3,0x5a3,0x1897,0x18a7,0x5a3,0x5a3, + 0x18b3,0x18bf,0xb24,0x2ce,0x18cf,0x69e,0x5a3,0x18df,0x5a3,0x576,0x18ef,0x5a3,0x510,0x7ca,0x5a3,0x5a3, + 0x18ff,0x190e,0x191e,0x192e,0x10f1,0x5a3,0x5a3,0x1935,0x1944,0x1954,0x1964,0x5a3,0x1974,0x5a3,0x5a3,0x5a3, + 0x1984,0x1994,0x1999,0x19a9,0x19b9,0x19c8,0x10ba,0x86a,0x61,0x61,0x19d8,0x19e8,0x61,0x61,0x61,0x61, + 0x61,0x5a3,0x5a3,0x19f8,0xb24,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0xd97, + 0x5a3,0x1a08,0x5a3,0x5a3,0x511,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18, + 0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a18, + 0x1a18,0x1a18,0x1a18,0x1a18,0x1a18,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28, + 0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28, + 0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x50f,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x1093,0xd18,0xd18,0x1a38, + 0x1a45,0x1a54,0x1a5e,0x1a6e,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x1a7c,0x1a89,0x4ff,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x1a99,0x1119,0x5a3,0x5a3,0x5a3,0x5a3,0x500,0x5a3,0x5a3,0x1aa9,0xd18,0xd18,0x1ab9,0x2ce,0x1ac9,0x2ce, + 0x1ad9,0x1ae5,0x1af5,0x1b04,0xae3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x1b14,0x1b24,0x30,0x40, + 0x50,0x60,0x1b34,0x1b44,0x1b54,0x5a3,0x1b56,0x5a3,0x50e,0x19c7,0x1b66,0x1b76,0x1b85,0x865,0x5a3,0xae1, + 0x1b95,0x50f,0x50f,0xd18,0xd18,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x73e,0x1ba5,0x147f,0x147f, + 0xf96,0x148f,0x148f,0x148f,0x1bb5,0x1bbe,0x153b,0x1bcc,0xd18,0xd18,0x1119,0x1119,0x1bdc,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x510,0x5a3,0x5a3,0x5a3,0x993,0x1bec,0x1bf0,0x5a3,0x5a3,0x1bf8, + 0x5a3,0x1c07,0x5a3,0x5a3,0x1c17,0x5a3,0x1c27,0x5a3,0x5a3,0x1c37,0x1c47,0xd18,0xd18,0x41,0x41,0x342, + 0x61,0x61,0x5a3,0x5a3,0x5a3,0x5a3,0x50f,0xb24,0x41,0x41,0x1c57,0x61,0x1c5f,0x5a3,0x5a3,0x1c6f, + 0x5a3,0x5a3,0x5a3,0x1c73,0x335,0x335,0x1c83,0x1c91,0x1c9f,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x1663,0x5a3,0x10bb,0x1c6f,0xd18,0x1caf,0x280,0x280,0x1cb4,0xd18,0xd18,0xd18,0xd18,0x1cc4,0x5a3,0x5a3, + 0x1cce,0x5a3,0x1cdd,0x5a3,0x1ced,0x5a3,0x50e,0x154a,0xd18,0xd18,0xd18,0x5a3,0x1cfd,0x5a3,0x1d0d,0x5a3, + 0x1d1d,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x5a3,0x1d2d,0x147f,0x1d3d,0x147f,0x147f,0x1d4d,0x94e,0x5a3, + 0x1d5d,0x1bf3,0x1d6d,0x5a3,0x1d7d,0x5a3,0x1d8d,0xd18,0xd18,0x1d9d,0x5a3,0x1da8,0x1db8,0x5a3,0x5a3,0x5a3, + 0x1dc8,0x5a3,0x1dd8,0x5a3,0x1de8,0x5a3,0x1df8,0x1548,0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x5a3, + 0x5a3,0x1094,0xd18,0xd18,0xd18,0x41,0x41,0x41,0x1e08,0x61,0x61,0x61,0x1e18,0x5a3,0x5a3,0x1e28, + 0xb24,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x147f,0x1bed,0x5a3, + 0x5a3,0x1e38,0xd99,0xd18,0xd18,0xd18,0xd18,0x5a3,0x1d8d,0x1e48,0x5a3,0x577,0x1e58,0xd18,0x5a3,0x1e68, + 0xd18,0xd18,0x5a3,0x1e78,0xd18,0x5a3,0x1663,0x1e88,0x5a3,0x5a3,0x575,0x1e98,0x1d3d,0x1ea8,0x1eb8,0x7cb, + 0x5a3,0x5a3,0x1ec8,0x1ed6,0x5a3,0x1094,0xb24,0x773,0x5a3,0x1ee6,0x1ef3,0x1f03,0x5a3,0x5a3,0x1f13,0x7cb, + 0x5a3,0x5a3,0x1f23,0x1f32,0x1f42,0x1f52,0x1f5d,0x5a3,0x954,0x1f6d,0x1f7c,0xd18,0xd18,0xd18,0xd18,0x1f8c, + 0x863,0x1f9b,0x5a3,0x5a3,0x630,0x1fab,0xb24,0x1fbb,0x858,0x868,0x1fca,0x1fda,0x1fea,0x1ff8,0x141d,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x5a3,0x2008,0x2018,0x2028,0xd99,0xd18,0x5a3, + 0x5a3,0x5a3,0x2038,0x2047,0xb24,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3, + 0x5a3,0x2057,0x2066,0x2075,0x207d,0xd18,0xd18,0x5a3,0x5a3,0x5a3,0x208d,0x209c,0xb24,0x20ac,0xd18,0x5a3, + 0x5a3,0x20bc,0x20cc,0xb24,0xd18,0xd18,0xd18,0x5a3,0xf74,0x20dc,0x20ec,0x1663,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x1f6d,0x20fc,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0x41,0x41,0x61,0x61,0xc23,0x210c,0x211b,0x2127,0x5a3,0x2137,0x2147,0xb24,0xd18,0xd18,0xd18, + 0xd18,0x2157,0x5a3,0x5a3,0x2166,0x2176,0xd18,0x2186,0x5a3,0x5a3,0x2193,0x21a2,0x21b2,0x5a3,0x5a3,0x573, + 0x21c2,0x21d0,0x5a3,0x5a3,0x5a3,0x5a3,0x1094,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x868,0x5a3,0x2057,0x21e0,0x21f0,0xc23,0xf8d,0x550,0x5a3, + 0xe2a,0x2200,0x220f,0xd18,0xd18,0xd18,0xd18,0x96e,0x5a3,0x5a3,0x221f,0x222e,0xb24,0x223e,0x5a3,0x2248, + 0x2258,0xb24,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0x5a3,0x2268,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x993,0x147f,0x2278, + 0x2287,0x2295,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x1093,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0x148f,0x148f,0x148f,0x148f,0x148f,0x148f,0x22a5,0x22b5,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0xd97,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x22c5,0x5a3,0x5a3, + 0x50e,0x22d5,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3, + 0x5a3,0x5a3,0x1663,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3, + 0x5a3,0x1094,0x5a3,0x50e,0x191e,0x5a3,0x5a3,0x5a3,0x5a3,0x50e,0xb24,0x5a3,0x50f,0x22e5,0x5a3,0x5a3, + 0x5a3,0x22f5,0x2305,0x2315,0x2323,0x741,0x5a3,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x41,0x41, + 0x61,0x61,0x147f,0x2333,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x5a3,0x5a3,0xe1d,0x2343, + 0x2344,0x2344,0x234c,0x235b,0xd18,0xd18,0xd18,0xd18,0x2369,0x2379,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x1c6f,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x10bb,0xd18,0xd18,0x1094,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x2389,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0xd98,0xd18,0xd18, + 0xd98,0x2398,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x511,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x73e,0x510,0x1094,0x23a8,0x23b8,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0x2ce,0x2ce,0x641,0x2ce,0x141b,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x16d1,0xd18, + 0xd18,0xd18,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119, + 0x1119,0x16e1,0x1119,0x1119,0x23c8,0x1119,0x1119,0x1119,0x23d3,0x23e0,0x23ed,0x1119,0x23f9,0x1119,0x1119,0x1119, + 0x153d,0xd18,0x1119,0x1119,0x1119,0x1119,0x2407,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0x147f,0x2417,0x1119,0x1119,0x1119,0x1119,0x1119,0x1541,0x147f,0x1bf3,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0x41,0x3b2,0x61,0x2427,0x3ae,0x1c8e,0x12a8,0x41,0xdc,0x2437,0x2447,0x2455,0x1c8f,0x41, + 0x3b2,0x61,0x2462,0x246f,0x61,0x247d,0x248d,0x249c,0x24a0,0x41,0xd8,0x61,0x41,0x3b2,0x61,0x2427, + 0x3ae,0x61,0x12a8,0x41,0xdc,0x24a0,0x41,0xd8,0x61,0x41,0x3b2,0x61,0x24b0,0x41,0x24bf,0xeb, + 0x38a,0x24cf,0x61,0x24db,0x41,0x24bb,0xe7,0x24c9,0xc7,0x61,0xed,0x41,0x24e7,0x61,0x24f4,0x2502, + 0x2502,0x2502,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119, + 0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119, + 0x1119,0x1119,0x2ce,0x2ce,0x2ce,0x2512,0x2ce,0x2ce,0x251d,0x252a,0x2536,0x13f8,0x4c2,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0x25a,0x2546,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xe4c,0x2556,0x2564,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0x5a3,0x5a3,0x510,0x2574,0x2584,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0x5a3,0x2594,0xd18,0x5a3,0x5a3,0x633,0x25a4,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x25b4,0x50e,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x25c4,0x141b,0xd18,0xd18,0x41,0x41,0xdc,0x61,0x25d4,0x191e,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x1f52,0x147f,0x147f,0x25e4,0x25f4,0xd18,0xd18, + 0xd18,0xd18,0x1f52,0x147f,0x2604,0x1bee,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xae4,0x5a3,0x2614,0x2621,0x262f,0x263f,0x264d,0x2655,0x867,0x511,0x2664,0x511,0xd18,0xd18, + 0xd18,0x2674,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0x1119,0x1119,0x153c,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x16d1,0x1754,0x1118,0x1118,0x1118, + 0x1119,0x16e1,0x2684,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x153a,0xd18,0xd18,0xd18, + 0x1bd6,0x1119,0x1bca,0x1119,0x1119,0x153c,0x153f,0x1bcb,0x16e1,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119, + 0x1119,0x2691,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x26a1, + 0x153b,0x153b,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x16d1,0x1119,0x1119,0x1119,0x1119,0x1119,0x153f, + 0x153c,0x1bcc,0x153c,0x1119,0x1119,0x1119,0x1540,0xf9d,0x1119,0x1119,0x1540,0x1119,0x153a,0x1bcb,0xd18,0xd18, + 0xd18,0xd18,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x1119, + 0x1119,0x1119,0x16d1,0x153a,0x26ae,0x1541,0x1119,0x153b,0x153d,0x16e1,0xf9d,0x1540,0x1541,0x1119,0x1119,0x1119, + 0x1119,0x1119,0x1119,0x1119,0x1119,0x1119,0x26be,0x1119,0x1119,0x153d,0xd18,0xd18,0xb24,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0xd18,0xd18,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x1094,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x50f,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0xd99,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x993,0xd18,0x5a3,0x50f,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18, + 0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x5a3,0x5a3,0x5a3, + 0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3,0x5a3, + 0x5a3,0x73e,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x26ce,0xd18,0x26de, + 0x26de,0x26de,0x26de,0x26de,0x26de,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0xd18,0x2ce,0x2ce,0x2ce, + 0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0x2ce,0xd18,0x1a28,0x1a28,0x1a28, + 0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28, + 0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x1a28,0x26ee,0x84,0xa4,0xc4, + 0xe4,0x104,0x124,0x144,0x164,0x184,0x1a0,0x1c0,0x1da,0x1fa,0x21a,0x23a,0x25a,0x27a,0x29a,0x2b9, + 0x2d9,0x2f9,0x319,0x339,0x359,0x379,0x399,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3bd,0x3b9,0x3b9, + 0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9, + 0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3dd,0x3b9,0x3f5,0x415,0x435,0x455,0x3b9,0x3b9,0x3b9, + 0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x475,0x495,0x495,0x495,0x495,0x4b5,0x4b5,0x4b5, + 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4c5,0x4df,0x4fd,0x51d,0x53d,0x55d,0x57d, + 0x59d,0x5bd,0x5dd,0x5fd,0x617,0x637,0x657,0x677,0x697,0x6b7,0x6d7,0x6f7,0x712,0x3b9,0x732,0x752, + 0x767,0x767,0x767,0x767,0x76e,0x3b9,0x3b9,0x78e,0x767,0x767,0x767,0x767,0x767,0x3b9,0x7ae,0x767, + 0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x3b9, + 0x7ce,0x767,0x7ea,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x80a,0x3b9,0x3b9,0x82a,0x767, + 0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x83b, + 0x85b,0x872,0x767,0x767,0x767,0x767,0x892,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x8a2,0x8c2, + 0x8e2,0x902,0x922,0x942,0x962,0x767,0x972,0x992,0x9a9,0x767,0x9b9,0x9d9,0x767,0x9f2,0xa12,0xa32, + 0xa52,0x942,0xa72,0xa92,0xaad,0x767,0x767,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9, + 0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9, + 0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0xacd,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0xadd, + 0xafc,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0xb12,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9, + 0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0xb1d,0x767,0x767,0x767,0x767,0x767,0x767,0x3b9,0xb3d,0x767, + 0x767,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0x3b9,0xb5d,0x767,0x767,0x767,0x767,0x767, + 0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767, + 0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0xb7d,0x767,0x767,0x767,0x767, + 0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767, + 0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x767,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, + 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5, + 0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0x4b5,0xb9d + ] +); + +#[rustfmt::skip] +pub const DATA: ZeroVec = zerovec!(u8; core::convert::identity; + [ + 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, + 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, + 0xc,0x17,0x17,0x17,0x19,0x17,0x17,0x17,0x14,0x15,0x17,0x18,0x17,0x13,0x17,0x17, + 9,9,9,9,9,9,9,9,9,9,0x17,0x17,0x18,0x18,0x18,0x17, + 0x17,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,0x14,0x17,0x15,0x1a,0x16, + 0x1a,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,0x14,0x18,0x15,0x18,0xf, + 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, + 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xc, + 0x17,0x19,0x19,0x19,0x19,0x1b,0x17,0x1a,0x1b,5,0x1c,0x18,0x10,0x1b,0x1a,0x1b, + 0x18,0xb,0xb,0x1a,2,0x17,0x17,0x1a,0xb,5,0x1d,0xb,0xb,0xb,0x17,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,0x18,1,1,1,1,1,1,1,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,0x18,2,2,2,2,2,2,2,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,1,2,1,2,1,2,2,1,1, + 2,1,2,1,1,2,1,1,1,2,2,1,1,1,1,2, + 1,1,2,1,1,1,2,2,2,1,1,2,1,1,2,1, + 2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,1, + 1,2,1,2,1,1,2,2,5,1,2,2,2,5,5,5, + 5,1,3,2,1,3,2,1,3,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,2,1,3, + 2,1,2,1,1,1,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,2,2,2,2,2,2,1, + 1,2,1,1,2,1,2,1,1,1,1,2,1,2,1,2, + 1,2,1,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,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,5,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, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 0x1a,0x1a,0x1a,0x1a,4,4,4,4,4,4,4,4,4,4,4,4, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,4,4, + 4,4,4,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,4,0x1a,4,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,1,2, + 1,2,4,0x1a,1,2,0,0,4,2,2,2,0x17,1,0,0, + 0,0,0x1a,0x1a,1,0x17,1,1,1,0,1,0,1,1,2,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2, + 2,1,1,1,2,2,2,1,2,1,2,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,2, + 2,2,2,1,2,0x18,1,2,1,1,2,2,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,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,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,2,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,0x1b,6,6,6, + 6,6,7,7,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,1,2,1,2,1,2,0,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,0,0,4,0x17,0x17,0x17,0x17,0x17,0x17,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,2,2,0x17,0x13,0,0,0x1b, + 0x1b,0x19,0,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 0x13,6,0x17,6,6,0x17,6,6,0x17,6,0,0,0,0,0,0, + 0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0, + 0,5,5,5,5,0x17,0x17,0,0,0,0,0,0,0,0,0, + 0,0,0x10,0x10,0x10,0x10,0x10,0x10,0x18,0x18,0x18,0x17,0x17,0x19,0x17,0x17, + 0x1b,0x1b,6,6,6,6,6,6,6,6,6,6,6,0x17,0x10,0x17, + 0x17,0x17,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,4,5,5,5,5,5,5,5,5,5,5,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,9,9,9,9,9,9,9,9,9,9,0x17,0x17,0x17,0x17, + 5,5,6,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,0x17,5,6,6,6,6,6,6,6,0x10,0x1b,6,6, + 6,6,6,6,4,4,6,6,0x1b,6,6,6,6,5,5,9, + 9,9,9,9,9,9,9,9,9,5,5,5,0x1b,0x1b,5,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0x10,5, + 6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,0, + 0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,5, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,9, + 9,9,9,9,9,9,9,9,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6, + 6,6,4,4,0x1b,0x17,0x17,0x17,4,0,0,6,0x19,0x19,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,6,6,6,6,4,6,6,6,6,6,6,6, + 6,6,4,6,6,6,4,6,6,6,6,6,0,0,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,6,6,6,0,0,0x17,0,5,5, + 5,5,5,5,5,5,5,5,5,0,0,0,0,0,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x1a,5, + 5,5,5,5,5,0,0x10,0x10,0,0,0,0,0,0,6,6, + 6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,4,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,0x10, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,8,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,6,8,6,5,8,8,6,6,6,6,6,6, + 6,6,8,8,8,8,6,8,8,5,6,6,6,6,6,6, + 6,5,5,5,5,5,5,5,5,5,5,6,6,0x17,0x17,9, + 9,9,9,9,9,9,9,9,9,0x17,4,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,6,8,8,0,5,5,5, + 5,5,5,5,5,0,0,5,5,0,0,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,0,5,5,5,5,5,5,5,0,5,0,0,0,5,5, + 5,5,0,0,6,5,8,8,6,6,6,6,0,0,8,8, + 0,0,8,8,6,5,0,0,0,0,0,0,0,0,8,0, + 0,0,0,5,5,0,5,5,5,6,6,0,0,9,9,9, + 9,9,9,9,9,9,9,5,5,0x19,0x19,0xb,0xb,0xb,0xb,0xb, + 0xb,0x1b,0x19,5,0x17,6,0,6,6,8,0,5,5,5,5,5, + 5,0,0,0,0,5,5,0,0,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, + 5,5,5,5,5,5,5,0,5,5,0,5,5,0,5,5, + 0,0,6,0,8,8,6,6,0,0,0,0,6,6,0,0, + 6,6,6,0,0,0,6,0,0,0,0,0,0,0,5,5, + 5,5,0,5,0,0,0,0,0,0,0,9,9,9,9,9, + 9,9,9,9,9,6,6,5,5,5,6,0x17,0,0,0,0, + 0,0,0,0,0,6,6,8,0,5,5,5,5,5,5,5, + 5,5,0,5,5,5,0,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5, + 5,5,5,5,5,0,5,5,0,5,5,5,5,5,0,0, + 6,5,8,8,6,6,6,6,6,0,6,6,8,0,8,8, + 6,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,5,5,6,6,0,0,9,9,9,9,9,9,9, + 9,9,9,0x17,0x19,0,0,0,0,0,0,0,5,6,6,6, + 6,6,6,0,6,8,8,0,5,5,5,5,5,5,5,5, + 0,0,5,5,0,0,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,0,5,5,5, + 5,5,5,5,0,5,5,0,5,5,5,5,5,0,0,6, + 5,8,6,6,6,6,0,0,8,8,0,0,8,8,6,0, + 0,0,0,0,0,0,6,6,8,0,0,0,0,5,5,0, + 5,5,5,6,6,0,0,9,9,9,9,9,9,9,9,9, + 9,0x1b,5,0xb,0xb,0xb,0xb,0xb,0xb,0,0,0,0,0,0,0, + 0,6,5,0,5,5,5,5,5,5,0,0,0,5,5,5, + 0,5,5,5,5,0,0,0,5,5,0,5,0,5,5,0, + 0,0,5,5,0,0,0,5,5,5,0,0,0,5,5,5, + 5,5,5,5,5,5,5,5,5,0,0,0,0,8,8,6, + 8,8,0,0,0,8,8,8,0,8,8,8,6,0,0,5, + 0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,0xb, + 0xb,0xb,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x1b,0,0,0,0,0,6, + 8,8,8,6,5,5,5,5,5,5,5,5,0,5,5,5, + 0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,0,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,0,0,6,5,6,6,8, + 8,8,8,0,6,6,6,0,6,6,6,6,0,0,0,0, + 0,0,0,6,6,0,5,5,5,0,0,5,0,0,5,5, + 6,6,0,0,9,9,9,9,9,9,9,9,9,9,0,0, + 0,0,0,0,0,0x17,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0x1b,5,6, + 8,8,0x17,5,5,5,5,5,5,5,5,0,5,5,5,0, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,0,5,5,5,5,5,5,5,5, + 5,5,0,5,5,5,5,5,0,0,6,5,8,6,8,8, + 8,8,8,0,6,8,8,0,8,8,6,6,0,0,0,0, + 0,0,0,8,8,0,0,0,0,0,0,5,5,0,5,5, + 6,6,0,0,9,9,9,9,9,9,9,9,9,9,0,5, + 5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6, + 8,8,5,5,5,5,5,5,5,5,5,0,5,5,5,0, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,6,6,5,8,8,6,6, + 6,6,0,8,8,8,0,8,8,8,6,5,0x1b,0,0,0, + 0,5,5,5,8,0xb,0xb,0xb,0xb,0xb,0xb,0xb,5,5,5,6, + 6,0,0,9,9,9,9,9,9,9,9,9,9,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0x1b,5,5,5,5,5,5,0,6,8, + 8,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,0,0,0,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, + 5,5,5,5,5,5,5,5,5,0,5,0,0,5,5,5, + 5,5,5,5,0,0,0,6,0,0,0,0,8,8,8,6, + 6,6,0,6,0,8,8,8,8,8,8,8,8,0,0,0, + 0,0,0,9,9,9,9,9,9,9,9,9,9,0,0,8, + 8,0x17,0,0,0,0,0,0,0,0,0,0,0,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,6,5,5, + 6,6,6,6,6,6,6,0,0,0,0,0x19,5,5,5,5, + 5,5,4,6,6,6,6,6,6,6,6,0x17,9,9,9,9, + 9,9,9,9,9,9,0x17,0x17,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,0,0,0,0,5,5,0,5, + 0,5,5,5,5,5,0,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, + 5,0,5,5,5,5,5,5,5,5,5,5,6,5,5,6, + 6,6,6,6,6,6,6,6,5,0,0,5,5,5,5,5, + 0,4,0,6,6,6,6,6,6,0,0,9,9,9,9,9, + 9,9,9,9,9,0,0,5,5,5,5,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,5,0x1b,0x1b,0x1b,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x1b,0x17, + 0x1b,0x1b,0x1b,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,9,9,9,9,9, + 9,9,9,9,9,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0x1b, + 6,0x1b,6,0x1b,6,0x14,0x15,0x14,0x15,8,8,5,5,5,5,5, + 5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,0,0,0,0,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,8,6,6,6,6,6, + 0x17,6,6,5,5,5,5,5,6,6,6,6,6,6,6,6, + 6,6,6,0,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b,0x1b,0x17,0x17,0x17,0x17,0x17,0x1b,0x1b, + 0x1b,0x1b,0x17,0x17,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,0,0,0,0,0,5,5,5,5,5,5,5, + 5,5,5,5,8,8,6,6,6,8,6,6,6,6,6,6, + 8,6,6,8,8,6,6,5,9,9,9,9,9,9,9,9, + 9,9,0x17,0x17,0x17,0x17,0x17,0x17,5,5,5,5,5,5,8,8, + 6,6,5,5,5,5,6,6,5,8,8,8,5,5,8,8, + 8,8,8,8,8,5,5,6,6,6,6,5,5,5,5,5, + 5,5,5,5,5,5,6,8,8,6,6,8,8,8,8,8, + 8,6,5,8,9,9,9,9,9,9,9,9,9,9,8,8, + 8,6,0x1b,0x1b,1,1,1,1,1,1,0,1,0,0,0,0, + 0,1,0,0,2,2,2,2,2,2,2,2,2,2,2,0x17, + 4,2,2,2,5,5,5,5,5,5,5,5,5,0,5,5, + 5,5,0,0,5,5,5,5,5,5,5,0,5,0,5,5, + 5,5,0,0,5,5,5,5,5,5,5,5,5,5,5,0, + 0,6,6,6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0,0,0,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,1,1,1, + 1,1,1,0,0,2,2,2,2,2,2,0,0,0x13,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,0x1b,0x17,5, + 0xc,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 0x14,0x15,0,0,0,5,5,5,5,5,5,5,5,5,5,5, + 0x17,0x17,0x17,0xa,0xa,5,5,5,5,5,5,5,5,0,0,0, + 0,0,0,0,5,5,6,6,6,8,0,0,0,0,0,0, + 0,0,0,5,5,6,6,8,0x17,0x17,0,0,0,0,0,0, + 0,0,0,5,5,6,6,0,0,0,0,0,0,0,0,0, + 0,0,0,5,0,6,6,0,0,0,0,0,0,0,0,0, + 0,0,0,5,5,5,5,6,6,8,6,6,6,6,6,6, + 6,8,8,8,8,8,8,6,8,8,6,6,6,6,6,6, + 6,0x17,0x17,0x17,4,0x17,0x17,0x17,0x19,5,6,0,0,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0,0,0,0,0,0,0x17,0x17,0x17, + 0x17,0x17,0x17,0x13,0x17,0x17,0x17,0x17,6,6,6,0x10,6,5,5,5, + 4,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0, + 0,0,0,0,5,5,5,5,5,6,6,5,5,5,5,5, + 5,5,5,5,6,5,0,0,0,0,0,5,5,5,5,5, + 5,0,0,0,0,0,0,0,0,0,0,6,6,6,8,8, + 8,8,6,6,8,8,8,0,0,0,0,8,8,6,8,8, + 8,8,8,8,6,6,6,0,0,0,0,0x1b,0,0,0,0x17, + 0x17,9,9,9,9,9,9,9,9,9,9,5,5,5,5,5, + 0,0,0,0,0,0,0,0,0,0,0,9,9,9,9,9, + 9,9,9,9,9,0xb,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,5,5,5,5,5,5,5, + 6,6,8,8,6,0,0,0x17,0x17,5,5,5,5,5,8,6, + 8,6,6,6,6,6,6,6,0,6,8,6,8,8,6,6, + 6,6,6,6,6,6,8,8,8,6,6,6,6,6,6,6, + 6,6,6,0,0,6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,4,0x17,0x17, + 0x17,0x17,0x17,0x17,0,0,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,7,6,5,5,5,5,6,8,6,6,6,6, + 6,8,6,8,8,8,6,8,8,5,5,5,5,5,5,5, + 5,0,0,0,0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6, + 6,6,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x17,0x17,0, + 5,8,6,6,6,6,8,8,6,6,8,6,6,6,5,5, + 5,5,5,5,6,8,6,6,8,8,8,6,8,6,6,8, + 8,0,0,0,0,0,0,0,0,0x17,0x17,0x17,0x17,5,5,5, + 5,8,8,8,8,8,8,8,8,6,6,6,6,8,8,6, + 6,0,0,0,0x17,0x17,0x17,0x17,0x17,9,9,9,9,9,9,9, + 9,9,9,0,0,0,5,5,5,5,5,5,5,5,4,4, + 4,4,4,4,0x17,0x17,2,2,2,2,2,2,2,2,2,0, + 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1, + 1,0,0,1,1,1,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0, + 0,0,0,0,0,0,6,6,6,0x17,6,6,6,6,6,6, + 6,6,6,6,6,6,8,6,6,6,6,6,6,6,5,5, + 5,5,6,5,5,8,6,6,5,0,0,0,0,0,4,4, + 4,4,4,4,4,4,4,4,4,2,2,2,2,2,2,2, + 2,4,2,2,2,2,2,2,2,1,2,1,2,1,2,2, + 2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2, + 1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0, + 1,1,1,1,1,1,0,0,2,2,2,2,2,2,2,2, + 0,1,0,1,0,1,0,1,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,2,2,2,2,2,0,2,2, + 1,1,1,1,3,0x1a,2,0x1a,0x1a,2,2,2,0,2,2,1, + 1,1,1,3,0x1a,0x1a,0x1a,2,2,2,2,0,0,2,2,1, + 1,1,1,0,0x1a,0x1a,0x1a,2,2,2,2,2,2,2,2,1, + 1,1,1,1,0x1a,0x1a,0x1a,0,0,2,2,2,0,2,2,1, + 1,1,1,3,0x1a,0x1a,0,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc, + 0xc,0xc,0x10,0x10,0x10,0x10,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x17,0x17,0x1c, + 0x1d,0x14,0x1c,0x1c,0x1d,0x14,0x1c,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0xd, + 0xe,0x10,0x10,0x10,0x10,0x10,0xc,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x1c,0x1d,0x17,0x17,0x17,0x17,0x16,0x17,0x17,0x17,0x18,0x14,0x15,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x17,0x16,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x17,0x17,0x17,0xc,0x10,0x10,0x10,0x10,0x10,0,0x10,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0x10,0xb,4,0,0,0xb,0xb,0xb,0xb,0xb,0xb,0x18,0x18, + 0x18,0x14,0x15,4,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0x18,0x18, + 0x18,0x14,0x15,0,4,4,4,4,4,4,4,4,4,4,4,4, + 4,0,0,0,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,6,7,7,7,6,6,6,6,6,6,6,6,6, + 6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0x1b,0x1b,1,0x1b,0x1b,0x1b,0x1b,1,0x1b,0x1b,2,1,1,1,2, + 2,1,1,1,2,0x1b,1,0x1b,0x1b,0x18,1,1,1,1,1,0x1b, + 0x1b,0x1b,0x1b,1,0x1b,1,0x1b,1,0x1b,1,1,1,1,0x1b,2,1, + 1,1,1,2,5,5,5,5,2,0x1b,0x1b,2,2,1,1,0x18, + 0x18,0x18,0x18,0x18,1,2,2,2,2,0x1b,0x18,0x1b,0x1b,2,0x1b,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xa, + 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,1, + 2,0xa,0xa,0xa,0xa,0xb,0x1b,0x1b,0,0,0,0,0x18,0x18,0x18,0x18, + 0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x18,0x1b,0x1b,0x18, + 0x1b,0x1b,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1b,0x1b,0x18,0x1b,0x18, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x14,0x15,0x14,0x15,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x14,0x15,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x18,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0, + 0,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0xb,0xb,0xb,0xb,0xb,0xb,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0x18,0x18,0x18,0x18,0x18,0x14,0x15,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14, + 0x15,0x14,0x15,0x14,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x14,0x15,0x14, + 0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x14,0x15,0x18, + 0x18,0x18,0x18,0x18,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b, + 0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,1,2,1,1,1,2,2,1,2,1, + 2,1,2,1,1,1,2,1,2,2,1,2,2,2,2,2, + 2,4,4,1,1,2,1,2,2,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,1, + 2,1,2,6,6,1,2,0,0,0,0,0,0x17,0x17,0x17,0x17, + 0xb,0x17,0x17,2,2,2,2,2,2,0,2,0,0,0,0,0, + 2,0,0,5,5,5,5,5,5,5,5,0,0,0,0,0, + 0,0,4,0x17,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,6,5,5,5,5,5,5,5,0,0,0,0,0,0, + 0,0,0,0x17,0x17,0x1c,0x1d,0x1c,0x1d,0x17,0x17,0x17,0x1c,0x1d,0x17,0x1c, + 0x1d,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x13,0x17,0x17,0x13,0x17,0x1c,0x1d,0x17, + 0x17,0x1c,0x1d,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x17,0x17,0x17,0x17,0x17, + 4,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x13,0x13,0x17,0x17,0x17, + 0x17,0x13,0x17,0x14,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x17,0x1b,0x1b,0x17,0x17,0x17,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x13,0, + 0,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0,0,0, + 0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0, + 0,0xc,0x17,0x17,0x17,0x1b,4,5,0xa,0x14,0x15,0x14,0x15,0x14,0x15,0x14, + 0x15,0x1b,0x1b,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x13,0x14,0x15,0x15,0x1b, + 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,6,6,6,6,8,8,0x13, + 4,4,4,4,4,0x1b,0x1b,0xa,0xa,0xa,4,5,0x17,0x1b,0x1b,5, + 5,5,5,5,5,5,0,0,6,6,0x1a,0x1a,4,4,5,5, + 5,5,5,5,5,5,5,5,5,0x17,4,4,4,5,0x1b,0x1b, + 0xb,0xb,0xb,0xb,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,5,5,5,5,5,5,5,5,5,5,5,5, + 4,0x17,0x17,0x17,9,9,9,9,9,9,9,9,9,9,5,5, + 0,0,0,0,1,2,1,2,1,2,1,2,1,2,1,2, + 1,2,5,6,7,7,7,0x17,6,6,6,6,6,6,6,6, + 6,6,0x17,4,1,2,1,2,1,2,1,2,1,2,1,2, + 4,4,6,6,5,5,5,5,5,5,0xa,0xa,0xa,0xa,0xa,0xa, + 0xa,0xa,0xa,0xa,6,6,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0, + 0,0,0,0,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,4,4,4,4,4, + 4,4,4,4,0x1a,0x1a,1,2,1,2,1,2,1,2,1,2, + 1,2,1,2,4,2,2,2,2,2,2,2,2,1,2,1, + 2,1,1,2,1,2,1,2,1,2,4,0x1a,0x1a,1,2,1, + 2,5,1,2,1,2,2,2,1,2,1,2,1,2,1,2, + 1,2,1,1,1,1,1,2,1,2,1,2,1,2,1,2, + 1,2,1,1,1,1,2,1,2,0,0,0,0,0,1,2, + 0,2,0,2,1,2,1,2,0,0,0,0,0,0,4,4, + 4,1,2,5,4,4,2,5,5,5,5,5,6,5,5,5, + 6,5,5,5,5,6,5,5,5,5,8,8,6,6,8,0x1b, + 0x1b,0x1b,0x1b,6,0,0,0,0xb,0xb,0xb,0xb,0xb,0xb,0x1b,0x1b,0x19, + 0x1b,0,0,0,0,0,0,5,5,5,5,0x17,0x17,0x17,0x17,0, + 0,0,0,0,0,0,0,8,8,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,8,8,8,8,8,8,8,8,8, + 8,8,8,6,6,0,0,0,0,0,0,0,0,0x17,0x17,6, + 6,5,5,5,5,5,5,0x17,0x17,0x17,5,0x17,5,5,6,5, + 5,5,5,5,5,6,6,6,6,6,6,6,6,0x17,0x17,6, + 6,8,8,0,0,0,0,0,0,0,0,0,0,0,0x17,5, + 5,5,6,8,8,6,6,6,6,8,8,6,6,8,8,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,4,9,9, + 9,9,9,9,9,9,9,9,0,0,0,0,0x17,0x17,5,5, + 5,5,5,6,4,5,5,5,5,5,5,5,5,5,6,6, + 6,6,6,6,8,6,6,8,8,6,6,0,0,0,0,0, + 0,0,0,0,5,5,5,6,5,5,5,5,5,5,5,5, + 6,8,0,0,9,9,9,9,9,9,9,9,9,9,0,0, + 0x17,0x17,0x17,0x17,4,5,5,5,5,5,5,0x1b,0x1b,0x1b,5,8, + 6,8,5,5,6,5,6,6,6,5,5,6,6,5,5,5, + 5,5,6,6,5,6,5,0,0,0,0,0,0,0,0,0, + 0,0,0,0,5,5,4,0x17,0x17,5,5,5,5,5,5,5, + 5,5,5,5,8,6,6,8,8,0x17,0x17,5,4,4,8,6, + 0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,0, + 0,5,5,5,5,5,5,0,2,2,2,2,2,2,2,2, + 2,2,2,0x1a,4,4,4,4,2,2,2,2,2,2,2,2, + 2,4,0x1a,0x1a,0,0,0,0,5,5,5,8,8,6,8,8, + 6,8,8,0x17,8,6,0,0,5,5,5,5,5,5,5,0, + 0,0,0,5,5,5,5,5,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,2,2,2,2,2,2,2,0, + 0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0, + 0,0,5,6,5,5,5,5,5,5,5,5,5,0x18,5,5, + 5,5,5,5,5,0,5,5,5,5,5,0,5,0,5,5, + 0,5,5,0,5,5,5,5,5,5,5,5,5,5,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0,0,0,0, + 0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,0x15,0x14,5,5,5,5,5,5,5, + 5,0,0,0,0,0,0,0,0x1b,5,5,5,5,5,5,5, + 5,5,5,5,5,0x19,0x1b,0x1b,0x1b,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x14,0x15,0x17,0,0,0,0,0,0,0x17,0x13,0x13,0x16,0x16,0x14,0x15, + 0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x14,0x15,0x17,0x17,0x14,0x15,0x17,0x17, + 0x17,0x17,0x16,0x16,0x16,0x17,0x17,0x17,0,0x17,0x17,0x17,0x17,0x13,0x14,0x15, + 0x14,0x15,0x14,0x15,0x17,0x17,0x18,0x13,0x18,0x18,0x18,0,0x17,0x19,0x17,0x17, + 0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, + 5,0,0,0x10,0,0x17,0x17,0x17,0x19,0x17,0x17,0x17,0x14,0x15,0x17,0x18, + 0x17,0x13,0x17,0x17,2,2,2,2,2,2,2,2,2,2,2,0x14, + 0x18,0x15,0x18,0x14,0x15,0x17,0x14,0x15,0x17,0x17,5,5,5,5,5,5, + 5,5,5,5,4,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,4,4,0,0,5,5,5,5,5,5,0,0, + 5,5,5,0,0,0,0x19,0x19,0x18,0x1a,0x1b,0x19,0x19,0,0x1b,0x18, + 0x18,0x18,0x18,0x1b,0x1b,0,0,0,0,0,0,0,0,0,0x10,0x10, + 0x10,0x1b,0x1b,0,0,5,5,5,5,5,5,5,5,5,5,5, + 0,5,5,0,5,0x17,0x17,0x17,0,0,0,0,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xa,0xa,0xa,0xa,0xa,0xb,0xb,0xb,0xb,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0xb,0xb,0x1b,0x1b,0x1b,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,0,0,6,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0,0,0,0, + 0,0,0,0,0,5,5,5,0xa,5,5,5,5,5,5,5, + 5,0xa,0,0,0,0,0,5,5,5,5,5,5,6,6,6, + 6,6,0,0,0,0,0,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,0,0x17,5,5,5,5,0,0,0,0,5, + 5,5,5,5,5,5,5,0x17,0xa,0xa,0xa,0xa,0xa,0,0,0, + 0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,2, + 2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,5, + 5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0, + 0,0,0x17,1,1,1,0,1,1,0,2,2,2,2,2,2, + 2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2, + 2,0,2,2,2,2,2,2,2,0,2,2,0,0,0,4, + 4,4,4,4,4,0,4,4,4,4,4,4,4,4,4,0, + 0,0,0,0,5,5,5,5,5,5,0,0,5,0,5,5, + 5,5,5,5,0,5,5,0,0,0,5,0,0,5,5,5, + 5,5,5,0,0x17,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,5,5,5, + 5,5,5,5,0x1b,0x1b,0xb,0xb,0xb,0xb,0xb,0xb,0xb,5,5,5, + 0,5,5,0,0,0,0,0,0xb,0xb,0xb,0xb,0xb,5,5,5, + 5,5,5,0xb,0xb,0xb,0xb,0xb,0xb,0,0,0,0x17,5,5,5, + 5,5,5,5,5,5,5,0,0,0,0,0,0x17,5,5,5, + 5,5,5,5,5,0,0,0,0,0xb,0xb,5,5,0,0,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,5,6,6, + 6,0,6,6,0,0,0,0,0,6,6,6,6,5,5,5, + 5,5,5,0,0,6,6,6,0,0,0,0,6,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,5,5,5, + 5,5,5,5,5,5,5,5,5,5,0xb,0xb,0x17,5,5,5, + 5,5,5,5,5,5,5,5,5,5,0xb,0xb,0xb,5,5,5, + 5,5,5,5,5,0x1b,5,5,5,5,5,5,5,6,6,0, + 0,0,0,0xb,0xb,0xb,0xb,0xb,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0, + 0,0,0,0,0,0,0,0,5,5,5,5,5,5,0,0, + 0,0x17,0x17,0x17,0x17,0x17,0x17,0x17,5,5,5,5,5,5,0,0, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,5,5,5,0,0,0,0,0, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,5,5,0,0,0,0,0,0, + 0,0x17,0x17,0x17,0x17,0,0,0,1,1,1,0,0,0,0,0, + 0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0, + 0,0,0xb,0xb,0xb,0xb,0xb,0xb,5,5,5,5,6,6,6,6, + 0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, + 5,5,0,6,6,0x13,0,0,0xb,0xb,0xb,0xb,0xb,0xb,0xb,5, + 0,0,0,0,0,0,0,0,6,0xb,0xb,0xb,0xb,0x17,0x17,0x17, + 0x17,0x17,0,0,0,0,0,0,5,5,6,6,6,6,0x17,0x17, + 0x17,0x17,0,0,0,0,0,0,5,5,5,5,5,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0,0,0,0,8,6,8,5,5,5,5,5, + 5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0,0,0xb,0xb,0xb,0xb,0xb,0xb,9,9, + 9,9,9,9,9,9,9,9,6,5,5,6,6,5,0,0, + 0,0,0,0,0,0,0,6,8,8,8,6,6,6,6,8, + 8,6,6,0x17,0x17,0x10,0x17,0x17,6,0,0,0,0,0,0,0, + 0,0,0,0x10,0,0,5,5,5,5,5,5,5,6,6,6, + 6,6,8,6,6,6,6,6,0,9,9,9,9,9,9,9, + 9,9,9,0x17,0x17,0x17,0x17,5,8,8,5,0,0,0,0,0, + 0,0,0,5,5,5,6,0x17,0x17,5,0,0,0,0,0,0, + 0,0,0,5,5,5,8,8,8,6,6,6,6,6,6,6, + 6,6,8,5,5,5,5,0x17,0x17,0x17,0x17,6,6,6,6,0x17, + 8,6,9,9,9,9,9,9,9,9,9,9,5,0x17,5,0x17, + 0x17,0x17,0,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0,0,0,0,0,0,0,0,0,0,0,5,5,5, + 5,5,5,5,5,5,5,5,5,8,8,8,6,6,8,8, + 6,8,6,6,0x17,0x17,0x17,0x17,0x17,0x17,6,0,5,5,5,5, + 5,5,5,0,5,0,5,5,5,5,0,5,5,5,5,5, + 5,5,5,5,0x17,0,0,0,0,0,0,8,8,8,6,6, + 6,6,6,6,6,6,0,0,0,0,0,6,6,8,8,0, + 5,5,5,5,5,5,5,5,0,0,5,0,5,5,0,5, + 5,5,5,5,0,6,6,5,8,8,6,8,8,8,8,0, + 0,8,8,0,0,8,8,8,0,0,5,0,0,0,0,0, + 0,8,0,0,0,0,0,5,5,5,8,8,0,0,6,6, + 6,6,6,6,6,0,0,0,5,5,5,5,5,8,8,8, + 6,6,6,6,6,6,6,6,8,8,6,6,6,8,6,5, + 5,5,5,0x17,0x17,0x17,0x17,0x17,9,9,9,9,9,9,9,9, + 9,9,0x17,0x17,0,0x17,6,5,8,8,8,6,6,6,6,6, + 6,8,6,8,8,8,8,6,8,6,6,5,5,0x17,5,0, + 0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,8,8,6,6,6,6,0,0,8,8, + 8,8,6,6,8,6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,5,5,5,5,6,6,0,0,8,8,8, + 6,6,6,6,6,6,6,6,8,8,6,8,6,0x17,0x17,0x17, + 5,0,0,0,0,0,0,0,0,0,0,0,0x17,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0,0,0,5,5,5,5, + 5,5,5,5,5,5,5,6,8,6,8,8,6,6,6,6, + 6,6,8,6,5,0x17,0,0,0,0,0,0,8,8,6,6, + 6,6,8,6,6,6,6,6,0,0,0,0,9,9,9,9, + 9,9,9,9,9,9,0xb,0xb,0x17,0x17,0x17,0x1b,6,6,6,6, + 6,6,6,6,8,6,6,0x17,0,0,0,0,0xb,0xb,0xb,0, + 0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5, + 5,5,0,0,5,0,0,5,5,5,5,0,5,5,0,5, + 5,5,5,5,5,5,5,8,8,8,8,8,8,0,8,8, + 0,0,6,6,8,6,5,8,5,8,6,0x17,0x17,0x17,0,0, + 0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,0, + 0,5,5,5,5,5,5,8,8,8,6,6,6,6,0,0, + 6,6,8,8,8,8,6,5,0x17,5,8,0,0,0,0,0, + 0,0,0,0,0,0,5,6,6,6,6,6,6,6,6,6, + 6,5,5,5,5,5,6,6,6,6,6,6,8,5,6,6, + 6,6,0x17,0x17,0x17,0x17,0x17,0x17,0x17,6,0,0,0,0,0,0, + 0,0,5,6,6,6,6,6,6,8,8,6,6,6,5,5, + 5,5,6,6,6,6,6,6,6,8,6,6,0x17,0x17,0x17,5, + 0x17,0x17,0x17,0,0,0,0,0,0,0,0,0,0,0,0,0, + 6,6,6,6,6,6,6,0,6,6,6,6,6,6,8,6, + 5,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0,0,0,0,0, + 6,6,6,6,6,6,6,6,0,8,6,6,6,6,6,6, + 8,6,6,8,6,6,0,0,0,0,0,0,0,0,0,5, + 6,6,6,6,6,6,0,0,0,6,0,6,6,0,6,6, + 6,6,6,6,5,6,0,0,0,0,0,0,0,0,5,5, + 5,5,5,5,0,5,5,0,5,5,5,5,5,5,5,5, + 5,5,8,8,8,8,8,0,6,6,0,8,8,6,8,6, + 5,0,0,0,0,0,0,0,5,5,5,6,6,8,8,0x17, + 0x17,0,0,0,0,0,0,0,0xb,0xb,0xb,0xb,0xb,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x19,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0x17,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, + 0xa,0xa,0xa,0xa,0,0x17,0x17,0x17,0x17,0x17,0,0,0,0,0,0, + 0,0,0,0,0,5,0x17,0x17,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0,0, + 0,0,0,0,0,6,6,6,6,6,0x17,0,0,0,0,0, + 0,0,0,0,0,6,6,6,6,6,6,6,0x17,0x17,0x17,0x17, + 0x17,0x1b,0x1b,0x1b,0x1b,4,4,4,4,0x17,0x1b,0,0,0,0,0, + 0,0,0,0,0,9,9,9,9,9,9,9,9,9,9,0, + 0xb,0xb,0xb,0xb,0xb,0,5,5,5,5,5,5,5,5,5,5, + 5,5,5,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0x17,0x17,0x17,0x17,0,0, + 0,0,0,5,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,0,0,0,0,0,0,0,6,6,6,4,4, + 4,4,4,4,4,4,4,4,4,4,4,0x17,4,6,0,0, + 0,0,0,0,0,0,0,0,0,8,8,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,4,4,4,4,0,4,4, + 4,4,4,4,4,0,4,4,0,0,0,0,5,5,5,5, + 0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5, + 5,5,0,0,0x1b,6,6,0x17,0x10,0x10,0x10,0x10,0,0,0,0, + 0,0,0,0,0,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0, + 0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,8,8,6,6,6,0x1b,0x1b,0x1b, + 8,8,8,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,6,6,6,6,6, + 0x1b,0x1b,6,6,6,6,6,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,6,6,6,6,0x1b,0x1b,6,6,6,0x1b,0,0,0, + 0,0,0,0,0,0,0,0xb,0xb,0xb,0xb,0,0,0,0,0, + 0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, + 2,2,2,1,0,1,1,0,0,1,0,0,1,1,0,0, + 1,1,1,1,0,1,1,1,1,1,1,2,2,2,2,0, + 2,0,2,2,2,2,1,1,0,1,1,1,1,0,0,1, + 1,1,1,1,0,1,1,1,1,1,1,1,0,2,2,2, + 2,2,2,2,2,1,1,0,1,1,1,1,0,1,1,1, + 1,1,0,1,0,0,0,1,1,1,1,1,1,0,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1, + 2,2,2,2,2,2,0,0,1,1,1,1,1,1,1,1, + 0x18,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1, + 1,1,1,1,1,1,1,1,1,1,0x18,2,2,2,2,2, + 0x18,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1, + 0x18,2,2,2,2,2,2,0x18,2,2,2,2,2,2,1,2, + 0,0,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,6,6,6,6,6,6,6,0x1b,0x1b,0x1b,0x1b,6,6,6, + 6,6,6,6,6,6,6,6,6,6,0x1b,0x1b,0x1b,0x1b,0x1b,6, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,6,0x1b,0x1b,0x17,0x17,0x17, + 0x17,0x17,0,0,0,0,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,0,6,6,6,6,6,6,6,6,6,0, + 0,6,6,6,6,6,0,6,6,0,6,6,6,6,6,0, + 0,0,0,0,6,6,6,6,6,6,6,4,4,4,4,4, + 4,4,0,0,9,9,9,9,9,9,9,9,9,9,0,0, + 0,0,5,0x1b,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,6,0,9,9,9,9,9,9,9,9,9,9,0,0, + 0,0,0,0x19,5,5,5,5,5,5,5,0,5,5,5,5, + 0,5,5,0,5,5,5,5,5,0,0,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,2,2,2,2,6,6,6,6,6,6,6,4, + 0,0,0,0,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0x1b,0xb,0xb,0xb,0x19,0xb,0xb,0xb,0xb,0,0,0,0,0,0,0, + 0,0,0,0,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0x1b,0xb,0,5,5,0,5,0,0,5,0,5,5,5, + 5,5,5,5,0,5,5,5,5,0,5,0,5,0,0,0, + 0,5,0,0,0,0,5,0,5,0,5,0,5,5,5,0, + 5,5,0,5,0,0,5,0,5,0,5,0,5,0,5,5, + 0,5,0,0,5,5,5,5,0,5,5,5,5,0,5,5, + 5,5,0,5,0,5,5,5,0,5,5,5,5,5,0,5, + 5,5,5,5,0x18,0x18,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0,0,0x1b,0x1b, + 0x1b,0x1b,0x1b,0,0,0,0x1b,0x1b,0x1b,0x1b,0x1b,0,0,0,0x1b,0x1b, + 0x1b,0,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0,0x10, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0,0,0,0 + ] +); + +pub static HEADER: CodePointTrieHeader = CodePointTrieHeader { + high_start: 0x110000, + shifted12_high_start: 0x110, + trie_type: TrieType::Small, + index3_null_offset: 0x767, + data_null_offset: 0xd18, + null_value: 0x0, +}; diff --git a/deps/crates/vendor/icu_collections/benches/tries/mod.rs b/deps/crates/vendor/icu_collections/benches/tries/mod.rs new file mode 100644 index 00000000000000..576516da5e4ff2 --- /dev/null +++ b/deps/crates/vendor/icu_collections/benches/tries/mod.rs @@ -0,0 +1,6 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +pub mod gc_fast; +pub mod gc_small; diff --git a/deps/crates/vendor/icu_collections/examples/unicode_bmp_blocks_selector.rs b/deps/crates/vendor/icu_collections/examples/unicode_bmp_blocks_selector.rs new file mode 100644 index 00000000000000..c29f1d25000564 --- /dev/null +++ b/deps/crates/vendor/icu_collections/examples/unicode_bmp_blocks_selector.rs @@ -0,0 +1,71 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +// An example application which uses icu_uniset to test what blocks of +// Basic Multilingual Plane a character belongs to. +// +// In this example we use `CodePointInversionListBuilder` to construct just the first +// two blocks of the first plane, and use an instance of a `BMPBlockSelector` +// to retrieve which of those blocks each character of a string belongs to. +// +// This is a simple example of the API use and is severely oversimplified +// compared to real Unicode block selection. + +#![no_main] // https://github.com/unicode-org/icu4x/issues/395 +icu_benchmark_macros::instrument!(); +use icu_benchmark_macros::println; + +use icu_collections::codepointinvlist::{CodePointInversionList, CodePointInversionListBuilder}; +use std::ops::RangeInclusive; + +#[derive(Copy, Clone, Debug)] +enum BmpBlock { + Basic, + Latin1Supplement, + Unknown, +} + +const BLOCKS: [(BmpBlock, RangeInclusive); 2] = [ + (BmpBlock::Basic, '\u{0000}'..='\u{007F}'), + (BmpBlock::Latin1Supplement, '\u{0080}'..='\u{00FF}'), +]; + +struct BmpBlockSelector { + blocks: [(BmpBlock, CodePointInversionList<'static>); 2], +} + +impl BmpBlockSelector { + pub fn new() -> BmpBlockSelector { + BmpBlockSelector { + blocks: BLOCKS.map(|(ch, range)| { + (ch, { + let mut builder = CodePointInversionListBuilder::new(); + builder.add_range(range); + builder.build() + }) + }), + } + } + + pub fn select(&self, input: char) -> BmpBlock { + for (block, set) in &self.blocks { + if set.contains(input) { + return *block; + } + } + BmpBlock::Unknown + } +} + +fn main() { + let selector = BmpBlockSelector::new(); + + let sample = "Welcome to MyName©®, Алексей!"; + + println!("\n====== Unicode BMP Block Selector example ============"); + for ch in sample.chars() { + let block = selector.select(ch); + println!("{ch}: {block:#?}"); + } +} diff --git a/deps/crates/vendor/icu_collections/src/char16trie/mod.rs b/deps/crates/vendor/icu_collections/src/char16trie/mod.rs new file mode 100644 index 00000000000000..1a4b66b9471ccd --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/char16trie/mod.rs @@ -0,0 +1,44 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module provides a data structure for a space-efficient and time-efficient lookup of +//! sequences of 16-bit units (commonly but not necessarily UTF-16 code units) +//! which map to integer values. +//! +//! It is an implementation of the existing [ICU4C UCharsTrie](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1UCharsTrie.html) +//! / [ICU4J CharsTrie](https://unicode-org.github.io/icu-docs/apidoc/released/icu4j/com/ibm/icu/util/CharsTrie.html) API. +//! +//! ## Architecture +//! +//! ICU4X [`Char16Trie`] is designed to provide a read-only view of `UCharsTrie` data that is exported from ICU4C. +//! +//! ## Examples +//! +//! ### Querying a `Char16Trie` +//! +//! ```rust +//! use icu::collections::char16trie::{Char16Trie, TrieResult}; +//! use zerovec::ZeroVec; +//! +//! // A Char16Trie containing the ASCII characters mapping 'a' to 1 and 'ab' +//! // to 100. +//! let trie_data = [48, 97, 176, 98, 32868]; +//! let trie = Char16Trie::new(ZeroVec::from_slice_or_alloc(&trie_data)); +//! +//! let mut iter = trie.iter(); +//! let res = iter.next('a'); +//! assert_eq!(res, TrieResult::Intermediate(1)); +//! let res = iter.next('b'); +//! assert_eq!(res, TrieResult::FinalValue(100)); +//! let res = iter.next('c'); +//! assert_eq!(res, TrieResult::NoMatch); +//! ``` +//! +//! [`ICU4X`]: ../icu/index.html + +mod trie; + +pub use trie::Char16Trie; +pub use trie::Char16TrieIterator; +pub use trie::TrieResult; diff --git a/deps/crates/vendor/icu_collections/src/char16trie/trie.rs b/deps/crates/vendor/icu_collections/src/char16trie/trie.rs new file mode 100644 index 00000000000000..1d48307957c3ce --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/char16trie/trie.rs @@ -0,0 +1,490 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use zerofrom::ZeroFrom; +use zerovec::{ZeroSlice, ZeroVec}; + +// Match-node lead unit values, after masking off intermediate-value bits: + +// 00..0f: Branch node. If node!=0 then the length is node+1, otherwise +// the length is one more than the next byte. + +// For a branch sub-node with at most this many entries, we drop down +// to a linear search. +const MAX_BRANCH_LINEAR_SUB_NODE_LENGTH: usize = 5; + +// 0030..003f: Linear-match node, match 1..16 units and continue reading the next node. +const MIN_LINEAR_MATCH: u16 = 0x30; +const MAX_LINEAR_MATCH_LENGTH: u16 = 0x10; + +// Match-node lead unit bits 14..6 for the optional intermediate value. +// If these bits are 0, then there is no intermediate value. +// Otherwise, see the *NodeValue* constants below. +const MIN_VALUE_LEAD: u16 = MIN_LINEAR_MATCH + MAX_LINEAR_MATCH_LENGTH; // 0x40 +const NODE_TYPE_MASK: u16 = MIN_VALUE_LEAD - 1; // 0x003f + +// A final-value node has bit 15 set. +const VALUE_IS_FINAL: u16 = 0x8000; + +// Compact value: After testing bit 0, shift right by 15 and then use the following thresholds. +const MAX_ONE_UNIT_VALUE: u16 = 0x3fff; + +const MIN_TWO_UNIT_VALUE_LEAD: u16 = MAX_ONE_UNIT_VALUE + 1; // 0x4000 + +const MAX_ONE_UNIT_NODE_VALUE: u16 = 0xff; + +const MIN_TWO_UNIT_NODE_VALUE_LEAD: u16 = MIN_VALUE_LEAD + ((MAX_ONE_UNIT_NODE_VALUE + 1) << 6); // 0x4040 + +const THREE_UNIT_NODE_VALUE_LEAD: u16 = 0x7fc0; + +const THREE_UNIT_VALUE_LEAD: u16 = 0x7fff; + +// Compact delta integers. +const MAX_ONE_UNIT_DELTA: u16 = 0xfbff; +const MIN_TWO_UNIT_DELTA_LEAD: u16 = MAX_ONE_UNIT_DELTA + 1; // 0xfc00 +const THREE_UNIT_DELTA_LEAD: u16 = 0xffff; + +fn skip_value(pos: usize, lead: u16) -> usize { + if lead < MIN_TWO_UNIT_VALUE_LEAD { + pos + } else if lead < THREE_UNIT_VALUE_LEAD { + pos + 1 + } else { + pos + 2 + } +} + +fn skip_node_value(pos: usize, lead: u16) -> usize { + if lead < MIN_TWO_UNIT_NODE_VALUE_LEAD { + pos + } else if lead < THREE_UNIT_NODE_VALUE_LEAD { + pos + 1 + } else { + pos + 2 + } +} + +/// This struct represents a de-serialized `Char16Trie` that was exported from +/// ICU binary data. +/// +/// Light-weight, non-const reader class for a `CharsTrie`. Traverses a +/// char-serialized data structure with minimal state, for mapping 16-bit-unit +/// sequences to non-negative integer values. +/// +/// For more information: +/// - [ICU4C UCharsTrie](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1UCharsTrie.html) +/// - [ICU4J CharsTrie](https://unicode-org.github.io/icu-docs/apidoc/released/icu4j/com/ibm/icu/util/CharsTrie.html) API. +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "databake", derive(databake::Bake))] +#[cfg_attr(feature = "databake", databake(path = icu_collections::char16trie))] +#[derive(Clone, Debug, PartialEq, Eq, ZeroFrom)] +pub struct Char16Trie<'data> { + /// An array of u16 containing the trie data. + #[cfg_attr(feature = "serde", serde(borrow))] + #[doc(hidden)] // #2417 + pub data: ZeroVec<'data, u16>, +} + +impl<'data> Char16Trie<'data> { + /// Returns a new [`Char16Trie`] with ownership of the provided data. + pub fn new(data: ZeroVec<'data, u16>) -> Self { + Self { data } + } + + /// Returns a new [`Char16TrieIterator`] backed by borrowed data from the `trie` data + pub fn iter(&self) -> Char16TrieIterator { + Char16TrieIterator::new(&self.data) + } +} + +/// This struct represents an iterator over a [`Char16Trie`]. +#[derive(Clone)] +pub struct Char16TrieIterator<'a> { + /// A reference to the Char16Trie data to iterate over. + trie: &'a ZeroSlice, + /// Index of next trie unit to read, or `None` if there are no more matches. + pos: Option, + /// Remaining length of a linear-match node, minus 1, or `None` if not in + /// such a node. + remaining_match_length: Option, +} + +/// An enum representing the return value from a lookup in [`Char16Trie`]. +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum TrieResult { + /// The input unit(s) did not continue a matching string. + /// Once `next()` returns `TrieResult::NoMatch`, all further calls to `next()` + /// will also return `TrieResult::NoMatch`. + NoMatch, + /// The input unit(s) matched a string but there is no value for the string + /// so far. (It is a prefix of a longer string.) + NoValue, + /// The input unit(s) continued a matching string and there is a value for + /// the string so far. No further input byte/unit can continue a matching + /// string. + FinalValue(i32), + /// The input unit(s) continued a matching string and there is a value for + /// the string so far. Another input byte/unit can continue a matching + /// string. + Intermediate(i32), +} + +// Get the lead surrogate (0xd800..0xdbff) for a +// supplementary code point (0x10000..0x10ffff). +// @param supplementary 32-bit code point (U+10000..U+10ffff) +// @return lead surrogate (U+d800..U+dbff) for supplementary +fn u16_lead(supplementary: i32) -> u16 { + (((supplementary) >> 10) + 0xd7c0) as u16 +} + +// Get the trail surrogate (0xdc00..0xdfff) for a +// supplementary code point (0x10000..0x10ffff). +// @param supplementary 32-bit code point (U+10000..U+10ffff) +// @return trail surrogate (U+dc00..U+dfff) for supplementary +fn u16_tail(supplementary: i32) -> u16 { + (((supplementary) & 0x3ff) | 0xdc00) as u16 +} + +/// A macro that takes an `Option` argument and either unwraps it if it has a value or +/// causes the function to return `TrieResult::NoMatch` if there is no value. +/// This could perhaps be done with `std::ops::Try` once stabilized. +macro_rules! trie_unwrap { + ($option:expr) => { + match $option { + Some(x) => x, + None => { + // Unexpected + debug_assert!(false); + return TrieResult::NoMatch; + } + } + }; +} + +impl<'a> Char16TrieIterator<'a> { + /// Returns a new [`Char16TrieIterator`] backed by borrowed data for the `trie` array + pub fn new(trie: &'a ZeroSlice) -> Self { + Self { + trie, + pos: Some(0), + remaining_match_length: None, + } + } + + /// Traverses the trie from the current state for this input char. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::char16trie::{Char16Trie, TrieResult}; + /// use zerovec::ZeroVec; + /// + /// // A Char16Trie containing the ASCII characters 'a' and 'b'. + /// let trie_data = [48, 97, 176, 98, 32868]; + /// let trie = Char16Trie::new(ZeroVec::from_slice_or_alloc(&trie_data)); + /// + /// let mut iter = trie.iter(); + /// let res = iter.next('a'); + /// assert_eq!(res, TrieResult::Intermediate(1)); + /// let res = iter.next('b'); + /// assert_eq!(res, TrieResult::FinalValue(100)); + /// let res = iter.next('c'); + /// assert_eq!(res, TrieResult::NoMatch); + /// ``` + pub fn next(&mut self, c: char) -> TrieResult { + if (c as u32) <= 0xffff { + self.next16(c as u16) + } else { + match self.next16(u16_lead(c as i32)) { + TrieResult::NoValue | TrieResult::Intermediate(_) => { + self.next16(u16_tail(c as i32)) + } + _ => TrieResult::NoMatch, + } + } + } + + /// Traverses the trie from the current state for this input char. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::char16trie::{Char16Trie, TrieResult}; + /// use zerovec::ZeroVec; + /// + /// // A Char16Trie containing the ASCII characters 'a' and 'b'. + /// let trie_data = [48, 97, 176, 98, 32868]; + /// let trie = Char16Trie::new(ZeroVec::from_slice_or_alloc(&trie_data)); + /// + /// let mut iter = trie.iter(); + /// let res = iter.next('a'); + /// assert_eq!(res, TrieResult::Intermediate(1)); + /// let res = iter.next('b'); + /// assert_eq!(res, TrieResult::FinalValue(100)); + /// let res = iter.next('c'); + /// assert_eq!(res, TrieResult::NoMatch); + /// ``` + pub fn next32(&mut self, c: u32) -> TrieResult { + if c <= 0xffff { + self.next16(c as u16) + } else { + match self.next16(u16_lead(c as i32)) { + TrieResult::NoValue | TrieResult::Intermediate(_) => { + self.next16(u16_tail(c as i32)) + } + _ => TrieResult::NoMatch, + } + } + } + + /// Traverses the trie from the current state for this input char. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::char16trie::{Char16Trie, TrieResult}; + /// use zerovec::ZeroVec; + /// + /// // A Char16Trie containing the ASCII characters 'a' and 'b'. + /// let trie_data = [48, 97, 176, 98, 32868]; + /// let trie = Char16Trie::new(ZeroVec::from_slice_or_alloc(&trie_data)); + /// + /// let mut iter = trie.iter(); + /// let res = iter.next16('a' as u16); + /// assert_eq!(res, TrieResult::Intermediate(1)); + /// let res = iter.next16('b' as u16); + /// assert_eq!(res, TrieResult::FinalValue(100)); + /// let res = iter.next16('c' as u16); + /// assert_eq!(res, TrieResult::NoMatch); + /// ``` + pub fn next16(&mut self, c: u16) -> TrieResult { + let mut pos = match self.pos { + Some(p) => p, + None => return TrieResult::NoMatch, + }; + if let Some(length) = self.remaining_match_length { + // Remaining part of a linear-match node + if c == trie_unwrap!(self.trie.get(pos)) { + pos += 1; + self.pos = Some(pos); + if length == 0 { + self.remaining_match_length = None; + let node = trie_unwrap!(self.trie.get(pos)); + if node >= MIN_VALUE_LEAD { + return self.value_result(pos); + } + } else { + self.remaining_match_length = Some(length - 1); + } + return TrieResult::NoValue; + } + self.stop(); + TrieResult::NoMatch + } else { + self.next_impl(pos, c) + } + } + + fn branch_next(&mut self, pos: usize, length: usize, in_unit: u16) -> TrieResult { + let mut pos = pos; + let mut length = length; + if length == 0 { + length = trie_unwrap!(self.trie.get(pos)) as usize; + pos += 1; + } + length += 1; + + // The length of the branch is the number of units to select from. + // The data structure encodes a binary search. + while length > MAX_BRANCH_LINEAR_SUB_NODE_LENGTH { + if in_unit < trie_unwrap!(self.trie.get(pos)) { + length >>= 1; + pos = trie_unwrap!(self.jump_by_delta(pos + 1)); + } else { + length = length - (length >> 1); + pos = trie_unwrap!(self.skip_delta(pos + 1)); + } + } + // Drop down to linear search for the last few bytes. + // length>=2 because the loop body above sees length>kMaxBranchLinearSubNodeLength>=3 + // and divides length by 2. + loop { + if in_unit == trie_unwrap!(self.trie.get(pos)) { + pos += 1; + let mut node = trie_unwrap!(self.trie.get(pos)); + if node & VALUE_IS_FINAL != 0 { + self.pos = Some(pos); + return self.value_result(pos); + } + // Use the non-final value as the jump delta. + pos += 1; + + if node < MIN_TWO_UNIT_VALUE_LEAD { + pos += node as usize; + } else if node < THREE_UNIT_VALUE_LEAD { + pos += (((node - MIN_TWO_UNIT_VALUE_LEAD) as u32) << 16) as usize + | trie_unwrap!(self.trie.get(pos)) as usize; + pos += 1; + } else { + pos += ((trie_unwrap!(self.trie.get(pos)) as usize) << 16) + | trie_unwrap!(self.trie.get(pos + 1)) as usize; + pos += 2; + } + node = trie_unwrap!(self.trie.get(pos)); + self.pos = Some(pos); + + if node >= MIN_VALUE_LEAD { + return self.value_result(pos); + } + return TrieResult::NoValue; + } + length -= 1; + pos = trie_unwrap!(self.skip_value(pos + 1)); + if length <= 1 { + break; + } + } + + if in_unit == trie_unwrap!(self.trie.get(pos)) { + pos += 1; + self.pos = Some(pos); + let node = trie_unwrap!(self.trie.get(pos)); + if node >= MIN_VALUE_LEAD { + return self.value_result(pos); + } + TrieResult::NoValue + } else { + self.stop(); + TrieResult::NoMatch + } + } + + fn next_impl(&mut self, pos: usize, in_unit: u16) -> TrieResult { + let mut node = trie_unwrap!(self.trie.get(pos)); + let mut pos = pos + 1; + loop { + if node < MIN_LINEAR_MATCH { + return self.branch_next(pos, node as usize, in_unit); + } else if node < MIN_VALUE_LEAD { + // Match the first of length+1 units. + let length = node - MIN_LINEAR_MATCH; + if in_unit == trie_unwrap!(self.trie.get(pos)) { + pos += 1; + if length == 0 { + self.remaining_match_length = None; + self.pos = Some(pos); + node = trie_unwrap!(self.trie.get(pos)); + if node >= MIN_VALUE_LEAD { + return self.value_result(pos); + } + return TrieResult::NoValue; + } + self.remaining_match_length = Some(length as usize - 1); + self.pos = Some(pos); + return TrieResult::NoValue; + } + // No match + break; + } else if (node & VALUE_IS_FINAL) != 0 { + // No further matching units. + break; + } else { + // Skip intermediate value. + pos = skip_node_value(pos, node); + node &= NODE_TYPE_MASK; + } + } + self.stop(); + TrieResult::NoMatch + } + + fn stop(&mut self) { + self.pos = None; + } + + #[inline(always)] // 1 call site and we want the Option to go away + fn jump_by_delta(&self, pos: usize) -> Option { + let delta = self.trie.get(pos)?; + let v = if delta < MIN_TWO_UNIT_DELTA_LEAD { + // nothing to do + pos + 1 + delta as usize + } else if delta == THREE_UNIT_DELTA_LEAD { + let delta = + ((self.trie.get(pos + 1)? as usize) << 16) | (self.trie.get(pos + 2)? as usize); + pos + delta + 3 + } else { + let delta = (((delta - MIN_TWO_UNIT_DELTA_LEAD) as usize) << 16) + | (self.trie.get(pos + 1)? as usize); + pos + delta + 2 + }; + Some(v) + } + + #[inline(always)] // 1 call site and we want the Option to go away + fn skip_value(&self, pos: usize) -> Option { + let lead_unit = self.trie.get(pos)?; + Some(skip_value(pos + 1, lead_unit & 0x7fff)) + } + + #[inline(always)] // 1 call site and we want the Option to go away + fn skip_delta(&self, pos: usize) -> Option { + let delta = self.trie.get(pos)?; + let v = if delta < MIN_TWO_UNIT_DELTA_LEAD { + pos + 1 + } else if delta == THREE_UNIT_DELTA_LEAD { + pos + 3 + } else { + pos + 2 + }; + Some(v) + } + + fn value_result(&self, pos: usize) -> TrieResult { + match self.get_value(pos) { + Some(result) => result, + None => { + // Unexpected + debug_assert!(false); + TrieResult::NoMatch + } + } + } + + #[inline(always)] // 1 call site and we want the Option to go away + fn get_value(&self, pos: usize) -> Option { + let lead_unit = self.trie.get(pos)?; + if lead_unit & VALUE_IS_FINAL == VALUE_IS_FINAL { + self.read_value(pos + 1, lead_unit & 0x7fff) + .map(TrieResult::FinalValue) + } else { + self.read_node_value(pos + 1, lead_unit) + .map(TrieResult::Intermediate) + } + } + + #[inline(always)] // 1 call site and we want the Option to go away + fn read_value(&self, pos: usize, lead_unit: u16) -> Option { + let v = if lead_unit < MIN_TWO_UNIT_VALUE_LEAD { + lead_unit.into() + } else if lead_unit < THREE_UNIT_VALUE_LEAD { + (((lead_unit - MIN_TWO_UNIT_VALUE_LEAD) as i32) << 16) | self.trie.get(pos)? as i32 + } else { + ((self.trie.get(pos)? as i32) << 16) | self.trie.get(pos + 1)? as i32 + }; + Some(v) + } + + #[inline(always)] // 1 call site and we want the Option to go away + fn read_node_value(&self, pos: usize, lead_unit: u16) -> Option { + let v = if lead_unit < (MIN_TWO_UNIT_NODE_VALUE_LEAD) { + ((lead_unit >> 6) - 1).into() + } else if lead_unit < THREE_UNIT_NODE_VALUE_LEAD { + ((((lead_unit & 0x7fc0) - MIN_TWO_UNIT_NODE_VALUE_LEAD) as i32) << 10) + | self.trie.get(pos)? as i32 + } else { + ((self.trie.get(pos)? as i32) << 16) | self.trie.get(pos + 1)? as i32 + }; + Some(v) + } +} diff --git a/deps/crates/vendor/icu_collections/src/codepointinvlist/builder.rs b/deps/crates/vendor/icu_collections/src/codepointinvlist/builder.rs new file mode 100644 index 00000000000000..f5b019dd58ff08 --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/codepointinvlist/builder.rs @@ -0,0 +1,986 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use alloc::vec; +use alloc::vec::Vec; +use core::{char, cmp::Ordering, ops::RangeBounds}; +use potential_utf::PotentialCodePoint; + +use crate::codepointinvlist::{utils::deconstruct_range, CodePointInversionList}; +use zerovec::{ule::AsULE, ZeroVec}; + +/// A builder for [`CodePointInversionList`]. +/// +/// Provides exposure to builder functions and conversion to [`CodePointInversionList`] +#[derive(Default)] +pub struct CodePointInversionListBuilder { + // A sorted list of even length, with values <= char::MAX + 1 + intervals: Vec, +} + +impl CodePointInversionListBuilder { + /// Returns empty [`CodePointInversionListBuilder`] + pub const fn new() -> Self { + Self { intervals: vec![] } + } + + /// Returns a [`CodePointInversionList`] and consumes the [`CodePointInversionListBuilder`] + pub fn build(self) -> CodePointInversionList<'static> { + let inv_list: ZeroVec = self + .intervals + .into_iter() + .map(PotentialCodePoint::from_u24) + .collect(); + #[allow(clippy::unwrap_used)] // by invariant + CodePointInversionList::try_from_inversion_list(inv_list).unwrap() + } + + /// Abstraction for adding/removing a range from start..end + /// + /// If add is true add, else remove + fn add_remove_middle(&mut self, start: u32, end: u32, add: bool) { + if start >= end || end > char::MAX as u32 + 1 { + return; + } + let start_res = self.intervals.binary_search(&start); + let end_res = self.intervals.binary_search(&end); + let mut start_ind = start_res.unwrap_or_else(|x| x); + let mut end_ind = end_res.unwrap_or_else(|x| x); + let start_pos_check = (start_ind % 2 == 0) == add; + let end_pos_check = (end_ind % 2 == 0) == add; + let start_eq_end = start_ind == end_ind; + + #[allow(clippy::indexing_slicing)] // all indices are binary search results + if start_eq_end && start_pos_check && end_res.is_err() { + self.intervals.splice(start_ind..end_ind, [start, end]); + } else { + if start_pos_check { + self.intervals[start_ind] = start; + start_ind += 1; + } + if end_pos_check { + if end_res.is_ok() { + end_ind += 1; + } else { + end_ind -= 1; + self.intervals[end_ind] = end; + } + } + if start_ind < end_ind { + self.intervals.drain(start_ind..end_ind); + } + } + } + + /// Add the range to the [`CodePointInversionListBuilder`] + /// + /// Accomplishes this through binary search for the start and end indices and merges intervals + /// in between with inplace memory. Performs `O(1)` operation if adding to end of list, and `O(N)` otherwise, + /// where `N` is the number of endpoints. + fn add(&mut self, start: u32, end: u32) { + if start >= end { + return; + } + if self.intervals.is_empty() { + self.intervals.extend_from_slice(&[start, end]); + return; + } + self.add_remove_middle(start, end, true); + } + + /// Add the character to the [`CodePointInversionListBuilder`] + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionListBuilder; + /// let mut builder = CodePointInversionListBuilder::new(); + /// builder.add_char('a'); + /// let check = builder.build(); + /// assert_eq!(check.iter_chars().next(), Some('a')); + /// ``` + pub fn add_char(&mut self, c: char) { + let to_add = c as u32; + self.add(to_add, to_add + 1); + } + + /// Add the code point value to the [`CodePointInversionListBuilder`] + /// + /// Note: Even though [`u32`] and [`prim@char`] in Rust are non-negative 4-byte + /// values, there is an important difference. A [`u32`] can take values up to + /// a very large integer value, while a [`prim@char`] in Rust is defined to be in + /// the range from 0 to the maximum valid Unicode Scalar Value. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionListBuilder; + /// let mut builder = CodePointInversionListBuilder::new(); + /// builder.add32(0x41); + /// let check = builder.build(); + /// assert!(check.contains32(0x41)); + /// ``` + pub fn add32(&mut self, c: u32) { + if c <= char::MAX as u32 { + // we already know 0 <= c because c: u32 + self.add(c, c + 1); + } + } + + /// Add the range of characters to the [`CodePointInversionListBuilder`] + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionListBuilder; + /// let mut builder = CodePointInversionListBuilder::new(); + /// builder.add_range('A'..='Z'); + /// let check = builder.build(); + /// assert_eq!(check.iter_chars().next(), Some('A')); + /// ``` + pub fn add_range(&mut self, range: impl RangeBounds) { + let (start, end) = deconstruct_range(range); + self.add(start, end); + } + + /// Add the range of characters, represented as u32, to the [`CodePointInversionListBuilder`] + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionListBuilder; + /// let mut builder = CodePointInversionListBuilder::new(); + /// builder.add_range32(0xd800..=0xdfff); + /// let check = builder.build(); + /// assert!(check.contains32(0xd900)); + /// ``` + pub fn add_range32(&mut self, range: impl RangeBounds) { + let (start, end) = deconstruct_range(range); + // Sets that include char::MAX need to allow an end value of MAX + 1 + if start <= end && end <= char::MAX as u32 + 1 { + self.add(start, end); + } + } + + /// Add the [`CodePointInversionList`] reference to the [`CodePointInversionListBuilder`] + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::{ + /// CodePointInversionList, CodePointInversionListBuilder, + /// }; + /// let mut builder = CodePointInversionListBuilder::new(); + /// let set = CodePointInversionList::try_from_u32_inversion_list_slice(&[ + /// 0x41, 0x4C, + /// ]) + /// .unwrap(); + /// builder.add_set(&set); + /// let check = builder.build(); + /// assert_eq!(check.iter_chars().next(), Some('A')); + /// ``` + #[allow(unused_assignments)] + pub fn add_set(&mut self, set: &CodePointInversionList) { + #[allow(clippy::indexing_slicing)] // chunks + set.as_inversion_list() + .as_ule_slice() + .chunks(2) + .for_each(|pair| { + self.add( + u32::from(PotentialCodePoint::from_unaligned(pair[0])), + u32::from(PotentialCodePoint::from_unaligned(pair[1])), + ) + }); + } + + /// Removes the range from the [`CodePointInversionListBuilder`] + /// + /// Performs binary search to find start and end affected intervals, then removes in an `O(N)` fashion + /// where `N` is the number of endpoints, with in-place memory. + fn remove(&mut self, start: u32, end: u32) { + if start >= end || self.intervals.is_empty() { + return; + } + if let Some(&last) = self.intervals.last() { + #[allow(clippy::indexing_slicing)] + // by invariant, if we have a last we have a (different) first + if start <= self.intervals[0] && end >= last { + self.intervals.clear(); + } else { + self.add_remove_middle(start, end, false); + } + } + } + + /// Remove the character from the [`CodePointInversionListBuilder`] + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionListBuilder; + /// let mut builder = CodePointInversionListBuilder::new(); + /// builder.add_range('A'..='Z'); + /// builder.remove_char('A'); + /// let check = builder.build(); + /// assert_eq!(check.iter_chars().next(), Some('B')); + pub fn remove_char(&mut self, c: char) { + self.remove32(c as u32) + } + + /// See [`Self::remove_char`] + pub fn remove32(&mut self, c: u32) { + self.remove(c, c + 1); + } + + /// Remove the range of characters from the [`CodePointInversionListBuilder`] + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionListBuilder; + /// let mut builder = CodePointInversionListBuilder::new(); + /// builder.add_range('A'..='Z'); + /// builder.remove_range('A'..='C'); + /// let check = builder.build(); + /// assert_eq!(check.iter_chars().next(), Some('D')); + pub fn remove_range(&mut self, range: impl RangeBounds) { + let (start, end) = deconstruct_range(range); + self.remove(start, end); + } + + /// See [`Self::remove_range`] + pub fn remove_range32(&mut self, range: impl RangeBounds) { + let (start, end) = deconstruct_range(range); + self.remove(start, end); + } + + /// Remove the [`CodePointInversionList`] from the [`CodePointInversionListBuilder`] + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::{CodePointInversionList, CodePointInversionListBuilder}; + /// let mut builder = CodePointInversionListBuilder::new(); + /// let set = CodePointInversionList::try_from_u32_inversion_list_slice(&[0x41, 0x46]).unwrap(); + /// builder.add_range('A'..='Z'); + /// builder.remove_set(&set); // removes 'A'..='E' + /// let check = builder.build(); + /// assert_eq!(check.iter_chars().next(), Some('F')); + #[allow(clippy::indexing_slicing)] // chunks + pub fn remove_set(&mut self, set: &CodePointInversionList) { + set.as_inversion_list() + .as_ule_slice() + .chunks(2) + .for_each(|pair| { + self.remove( + u32::from(PotentialCodePoint::from_unaligned(pair[0])), + u32::from(PotentialCodePoint::from_unaligned(pair[1])), + ) + }); + } + + /// Retain the specified character in the [`CodePointInversionListBuilder`] if it exists + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionListBuilder; + /// let mut builder = CodePointInversionListBuilder::new(); + /// builder.add_range('A'..='Z'); + /// builder.retain_char('A'); + /// let set = builder.build(); + /// let mut check = set.iter_chars(); + /// assert_eq!(check.next(), Some('A')); + /// assert_eq!(check.next(), None); + /// ``` + pub fn retain_char(&mut self, c: char) { + self.retain32(c as u32) + } + + /// See [`Self::retain_char`] + pub fn retain32(&mut self, c: u32) { + self.remove(0, c); + self.remove(c + 1, (char::MAX as u32) + 1); + } + + /// Retain the range of characters located within the [`CodePointInversionListBuilder`] + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionListBuilder; + /// let mut builder = CodePointInversionListBuilder::new(); + /// builder.add_range('A'..='Z'); + /// builder.retain_range('A'..='B'); + /// let set = builder.build(); + /// let mut check = set.iter_chars(); + /// assert_eq!(check.next(), Some('A')); + /// assert_eq!(check.next(), Some('B')); + /// assert_eq!(check.next(), None); + /// ``` + pub fn retain_range(&mut self, range: impl RangeBounds) { + let (start, end) = deconstruct_range(range); + self.remove(0, start); + self.remove(end, (char::MAX as u32) + 1); + } + + /// See [`Self::retain_range`] + pub fn retain_range32(&mut self, range: impl RangeBounds) { + let (start, end) = deconstruct_range(range); + self.remove(0, start); + self.remove(end, (char::MAX as u32) + 1); + } + + /// Retain the elements in the specified set within the [`CodePointInversionListBuilder`] + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::{ + /// CodePointInversionList, CodePointInversionListBuilder, + /// }; + /// let mut builder = CodePointInversionListBuilder::new(); + /// let set = + /// CodePointInversionList::try_from_u32_inversion_list_slice(&[65, 70]) + /// .unwrap(); + /// builder.add_range('A'..='Z'); + /// builder.retain_set(&set); // retains 'A'..='E' + /// let check = builder.build(); + /// assert!(check.contains('A')); + /// assert!(!check.contains('G')); + /// ``` + #[allow(clippy::indexing_slicing)] // chunks + pub fn retain_set(&mut self, set: &CodePointInversionList) { + let mut prev = 0; + for pair in set.as_inversion_list().as_ule_slice().chunks(2) { + let range_start = u32::from(PotentialCodePoint::from_unaligned(pair[0])); + let range_limit = u32::from(PotentialCodePoint::from_unaligned(pair[1])); + self.remove(prev, range_start); + prev = range_limit; + } + self.remove(prev, (char::MAX as u32) + 1); + } + + /// Computes the complement of the argument, adding any elements that do not yet exist in the builder, + /// and removing any elements that already exist in the builder. See public functions for examples. + /// + /// Performs in `O(B + S)`, where `B` is the number of endpoints in the Builder, and `S` is the number + /// of endpoints in the argument. + fn complement_list(&mut self, set_iter: impl IntoIterator) { + let mut res: Vec = vec![]; // not the biggest fan of having to allocate new memory + let mut ai = self.intervals.iter(); + let mut bi = set_iter.into_iter(); + let mut a = ai.next(); + let mut b = bi.next(); + while let (Some(c), Some(d)) = (a, b) { + match c.cmp(&d) { + Ordering::Less => { + res.push(*c); + a = ai.next(); + } + Ordering::Greater => { + res.push(d); + b = bi.next(); + } + Ordering::Equal => { + a = ai.next(); + b = bi.next(); + } + } + } + if let Some(c) = a { + res.push(*c) + } + if let Some(d) = b { + res.push(d) + } + res.extend(ai); + res.extend(bi); + self.intervals = res; + } + + /// Computes the complement of the builder, inverting the builder (any elements in the builder are removed, + /// while any elements not in the builder are added) + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::{ + /// CodePointInversionList, CodePointInversionListBuilder, + /// }; + /// let mut builder = CodePointInversionListBuilder::new(); + /// let set = CodePointInversionList::try_from_u32_inversion_list_slice(&[ + /// 0x0, + /// 0x41, + /// 0x46, + /// (std::char::MAX as u32) + 1, + /// ]) + /// .unwrap(); + /// builder.add_set(&set); + /// builder.complement(); + /// let check = builder.build(); + /// assert_eq!(check.iter_chars().next(), Some('A')); + /// ``` + pub fn complement(&mut self) { + if !self.intervals.is_empty() { + #[allow(clippy::indexing_slicing)] // by invariant + if self.intervals[0] == 0 { + self.intervals.drain(0..1); + } else { + self.intervals.insert(0, 0); + } + if self.intervals.last() == Some(&(char::MAX as u32 + 1)) { + self.intervals.pop(); + } else { + self.intervals.push(char::MAX as u32 + 1); + } + } else { + self.intervals + .extend_from_slice(&[0, (char::MAX as u32 + 1)]); + } + } + + /// Complements the character in the builder, adding it if not in the builder, and removing it otherwise. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionListBuilder; + /// let mut builder = CodePointInversionListBuilder::new(); + /// builder.add_range('A'..='D'); + /// builder.complement_char('A'); + /// builder.complement_char('E'); + /// let check = builder.build(); + /// assert!(check.contains('E')); + /// assert!(!check.contains('A')); + /// ``` + pub fn complement_char(&mut self, c: char) { + self.complement32(c as u32); + } + + /// See [`Self::complement_char`] + pub fn complement32(&mut self, c: u32) { + self.complement_list([c, c + 1]); + } + + /// Complements the range in the builder, adding any elements in the range if not in the builder, and + /// removing them otherwise. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionListBuilder; + /// let mut builder = CodePointInversionListBuilder::new(); + /// builder.add_range('A'..='D'); + /// builder.complement_range('C'..='F'); + /// let check = builder.build(); + /// assert!(check.contains('F')); + /// assert!(!check.contains('C')); + /// ``` + pub fn complement_range(&mut self, range: impl RangeBounds) { + let (start, end) = deconstruct_range(range); + self.complement_list([start, end]); + } + + /// See [`Self::complement_range`] + pub fn complement_range32(&mut self, range: impl RangeBounds) { + let (start, end) = deconstruct_range(range); + self.complement_list([start, end]); + } + + /// Complements the set in the builder, adding any elements in the set if not in the builder, and + /// removing them otherwise. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::{ + /// CodePointInversionList, CodePointInversionListBuilder, + /// }; + /// let mut builder = CodePointInversionListBuilder::new(); + /// let set = CodePointInversionList::try_from_u32_inversion_list_slice(&[ + /// 0x41, 0x46, 0x4B, 0x5A, + /// ]) + /// .unwrap(); + /// builder.add_range('C'..='N'); // 67 - 78 + /// builder.complement_set(&set); + /// let check = builder.build(); + /// assert!(check.contains('Q')); // 81 + /// assert!(!check.contains('N')); // 78 + /// ``` + pub fn complement_set(&mut self, set: &CodePointInversionList) { + let inv_list_iter_owned = set.as_inversion_list().iter().map(u32::from); + self.complement_list(inv_list_iter_owned); + } + + /// Returns whether the build is empty. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionListBuilder; + /// let mut builder = CodePointInversionListBuilder::new(); + /// let check = builder.build(); + /// assert!(check.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { + self.intervals.is_empty() + } +} + +#[cfg(test)] +mod tests { + use super::{CodePointInversionList, CodePointInversionListBuilder}; + use core::char; + + fn generate_tester(ex: &[u32]) -> CodePointInversionListBuilder { + let check = CodePointInversionList::try_from_u32_inversion_list_slice(ex).unwrap(); + let mut builder = CodePointInversionListBuilder::new(); + builder.add_set(&check); + builder + } + + #[test] + fn test_new() { + let ex = CodePointInversionListBuilder::new(); + assert!(ex.intervals.is_empty()); + } + + #[test] + fn test_build() { + let mut builder = CodePointInversionListBuilder::new(); + builder.add(0x41, 0x42); + let check: CodePointInversionList = builder.build(); + assert_eq!(check.iter_chars().next(), Some('A')); + } + + #[test] + fn test_empty_build() { + let builder = CodePointInversionListBuilder::new(); + let check: CodePointInversionList = builder.build(); + assert!(check.is_empty()); + } + + #[test] + fn test_add_to_empty() { + let mut builder = CodePointInversionListBuilder::new(); + builder.add(0x0, 0xA); + assert_eq!(builder.intervals, [0x0, 0xA]); + } + + #[test] + fn test_add_invalid() { + let mut builder = CodePointInversionListBuilder::new(); + builder.add(0x0, 0x0); + builder.add(0x5, 0x0); + assert!(builder.intervals.is_empty()); + } + + #[test] + fn test_add_to_start() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(0x0, 0x5); + let expected = [0x0, 0x5, 0xA, 0x14, 0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_to_start_overlap() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(0x0, 0xE); + let expected = [0x0, 0x14, 0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_to_end() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(0x3C, 0x46); + let expected = [0xA, 0x14, 0x28, 0x32, 60, 70]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_to_end_overlap() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(0x2B, 0x46); + let expected = [0xA, 0x14, 0x28, 0x46]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_to_middle_no_overlap() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(0x19, 0x1B); + let expected = [0xA, 0x14, 0x19, 0x1B, 0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_to_middle_inside() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(0xA, 0x14); + let expected = [0xA, 0x14, 0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_to_middle_left_overlap() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(0xF, 0x19); + let expected = [0xA, 0x19, 0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_to_middle_right_overlap() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(0x1E, 0x28); + let expected = [0xA, 0x14, 0x1E, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_to_full_encompass() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(0x0, 0x3C); + let expected = [0x0, 0x3C]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_to_partial_encompass() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(0x0, 0x23); + let expected = [0x0, 0x23, 0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_aligned_front() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(5, 10); + let expected = [5, 0x14, 0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_aligned_back() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(0x32, 0x37); + let expected = [0xA, 0x14, 0x28, 0x37]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_aligned_start_middle() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(0x14, 0x19); + let expected = [0xA, 0x19, 0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_aligned_end_middle() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(0x23, 0x28); + let expected = [0xA, 0x14, 0x23, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_aligned_in_between_end() { + let mut builder = generate_tester(&[0xA, 0x14, 0x1E, 0x28, 0x32, 0x3C]); + builder.add(0xF, 0x1E); + let expected = [0xA, 0x28, 0x32, 0x3C]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_aligned_in_between_start() { + let mut builder = generate_tester(&[0xA, 0x14, 0x1E, 0x28, 0x32, 0x3C]); + builder.add(20, 35); + let expected = [0xA, 0x28, 0x32, 0x3C]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_adjacent_ranges() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.add(0x13, 0x14); + builder.add(0x14, 0x15); + builder.add(0x15, 0x16); + let expected = [0xA, 0x16, 0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_codepointinversionlist() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + let check = CodePointInversionList::try_from_u32_inversion_list_slice(&[ + 0x5, 0xA, 0x16, 0x21, 0x2C, 0x33, + ]) + .unwrap(); + builder.add_set(&check); + let expected = [0x5, 0x14, 0x16, 0x21, 0x28, 0x33]; + assert_eq!(builder.intervals, expected); + } + #[test] + fn test_add_char() { + let mut builder = CodePointInversionListBuilder::new(); + builder.add_char('a'); + let expected = [0x61, 0x62]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_range() { + let mut builder = CodePointInversionListBuilder::new(); + builder.add_range('A'..='Z'); + let expected = [0x41, 0x5B]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_range32() { + let mut builder = CodePointInversionListBuilder::new(); + builder.add_range32(0xd800..=0xdfff); + let expected = [0xd800, 0xe000]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_add_invalid_range() { + let mut builder = CodePointInversionListBuilder::new(); + builder.add_range('Z'..='A'); + assert!(builder.intervals.is_empty()); + } + + #[test] + fn test_remove_empty() { + let mut builder = CodePointInversionListBuilder::new(); + builder.remove(0x0, 0xA); + assert!(builder.intervals.is_empty()); + } + + #[test] + fn test_remove_entire_builder() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.remove(0xA, 0x32); + assert!(builder.intervals.is_empty()); + } + + #[test] + fn test_remove_entire_range() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.remove(0xA, 0x14); + let expected = [0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_remove_partial_range_left() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.remove(0xA, 0x2B); + let expected = [0x2B, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_remove_ne_range() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.remove(0x14, 0x28); + let expected = [0xA, 0x14, 0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_remove_partial_range_right() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.remove(0xF, 0x37); + let expected = [0xA, 0xF]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_remove_middle_range() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.remove(0xC, 0x12); + let expected = [0xA, 0xC, 0x12, 0x14, 0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_remove_ne_middle_range() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.remove(0x19, 0x1B); + let expected = [0xA, 0x14, 0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_remove_encompassed_range() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32, 70, 80]); + builder.remove(0x19, 0x37); + let expected = [0xA, 0x14, 0x46, 0x50]; + assert_eq!(builder.intervals, expected); + } + #[test] + fn test_remove_adjacent_ranges() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.remove(0x27, 0x28); + builder.remove(0x28, 0x29); + builder.remove(0x29, 0x2A); + let expected = [0xA, 0x14, 0x2A, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_remove_char() { + let mut builder = generate_tester(&[0x41, 0x46]); + builder.remove_char('A'); // 65 + let expected = [0x42, 0x46]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_remove_range() { + let mut builder = generate_tester(&[0x41, 0x5A]); + builder.remove_range('A'..'L'); // 65 - 76 + let expected = [0x4C, 0x5A]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_remove_set() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32, 70, 80]); + let remove = + CodePointInversionList::try_from_u32_inversion_list_slice(&[0xA, 0x14, 0x2D, 0x4B]) + .unwrap(); + builder.remove_set(&remove); + let expected = [0x28, 0x2D, 0x4B, 0x50]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_retain_char() { + let mut builder = generate_tester(&[0x41, 0x5A]); + builder.retain_char('A'); // 65 + let expected = [0x41, 0x42]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_retain_range() { + let mut builder = generate_tester(&[0x41, 0x5A]); + builder.retain_range('C'..'F'); // 67 - 70 + let expected = [0x43, 0x46]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_retain_range_empty() { + let mut builder = generate_tester(&[0x41, 0x46]); + builder.retain_range('F'..'Z'); + assert!(builder.intervals.is_empty()); + } + + #[test] + fn test_retain_set() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32, 70, 80]); + let retain = CodePointInversionList::try_from_u32_inversion_list_slice(&[ + 0xE, 0x14, 0x19, 0x37, 0x4D, 0x51, + ]) + .unwrap(); + builder.retain_set(&retain); + let expected = [0xE, 0x14, 0x28, 0x32, 0x4D, 0x50]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_complement() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.complement(); + let expected = [0x0, 0xA, 0x14, 0x28, 0x32, (char::MAX as u32) + 1]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_complement_empty() { + let mut builder = generate_tester(&[]); + builder.complement(); + let expected = [0x0, (char::MAX as u32) + 1]; + assert_eq!(builder.intervals, expected); + + builder.complement(); + let expected: [u32; 0] = []; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_complement_zero_max() { + let mut builder = generate_tester(&[0x0, 0xA, 0x5A, (char::MAX as u32) + 1]); + builder.complement(); + let expected = [0xA, 0x5A]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_complement_interior() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.complement_list([0xE, 0x14]); + let expected = [0xA, 0xE, 0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_complement_exterior() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.complement_list([0x19, 0x23]); + let expected = [0xA, 0x14, 0x19, 0x23, 0x28, 0x32]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_complement_larger_list() { + let mut builder = generate_tester(&[0xA, 0x14, 0x28, 0x32]); + builder.complement_list([0x1E, 0x37, 0x3C, 0x46]); + let expected = [0xA, 0x14, 0x1E, 0x28, 0x32, 0x37, 0x3C, 0x46]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_complement_char() { + let mut builder = generate_tester(&[0x41, 0x4C]); // A - K + builder.complement_char('A'); + builder.complement_char('L'); + let expected = [0x42, 0x4D]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_complement_range() { + let mut builder = generate_tester(&[0x46, 0x4C]); // F - K + builder.complement_range('A'..='Z'); + let expected = [0x41, 0x46, 0x4C, 0x5B]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_complement_set() { + let mut builder = generate_tester(&[0x43, 0x4E]); + let set = + CodePointInversionList::try_from_u32_inversion_list_slice(&[0x41, 0x46, 0x4B, 0x5A]) + .unwrap(); + builder.complement_set(&set); + let expected = [0x41, 0x43, 0x46, 0x4B, 0x4E, 0x5A]; + assert_eq!(builder.intervals, expected); + } + + #[test] + fn test_is_empty() { + let builder = CodePointInversionListBuilder::new(); + assert!(builder.is_empty()); + } +} diff --git a/deps/crates/vendor/icu_collections/src/codepointinvlist/conversions.rs b/deps/crates/vendor/icu_collections/src/codepointinvlist/conversions.rs new file mode 100644 index 00000000000000..9e4cb380c7b41f --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/codepointinvlist/conversions.rs @@ -0,0 +1,180 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use core::iter::FromIterator; +use core::{ + convert::TryFrom, + ops::{Range, RangeBounds, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive}, +}; + +use super::RangeError; +use crate::codepointinvlist::utils::deconstruct_range; +use crate::codepointinvlist::CodePointInversionList; +use crate::codepointinvlist::CodePointInversionListBuilder; +use potential_utf::PotentialCodePoint; +use zerovec::ZeroVec; + +fn try_from_range<'data>( + range: impl RangeBounds, +) -> Result, RangeError> { + let (from, till) = deconstruct_range(range); + if from < till { + let set = [ + PotentialCodePoint::from_u24(from), + PotentialCodePoint::from_u24(till), + ]; + let inv_list: ZeroVec = ZeroVec::alloc_from_slice(&set); + #[allow(clippy::unwrap_used)] // valid + Ok(CodePointInversionList::try_from_inversion_list(inv_list).unwrap()) + } else { + Err(RangeError(from, till)) + } +} + +impl TryFrom> for CodePointInversionList<'_> { + type Error = RangeError; + + fn try_from(range: Range) -> Result { + try_from_range(range) + } +} + +impl TryFrom> for CodePointInversionList<'_> { + type Error = RangeError; + + fn try_from(range: RangeFrom) -> Result { + try_from_range(range) + } +} + +impl TryFrom for CodePointInversionList<'_> { + type Error = RangeError; + + fn try_from(_: RangeFull) -> Result { + Ok(Self::all()) + } +} + +impl TryFrom> for CodePointInversionList<'_> { + type Error = RangeError; + + fn try_from(range: RangeInclusive) -> Result { + try_from_range(range) + } +} + +impl TryFrom> for CodePointInversionList<'_> { + type Error = RangeError; + + fn try_from(range: RangeTo) -> Result { + try_from_range(range) + } +} + +impl TryFrom> for CodePointInversionList<'_> { + type Error = RangeError; + + fn try_from(range: RangeToInclusive) -> Result { + try_from_range(range) + } +} + +impl FromIterator> for CodePointInversionList<'_> { + fn from_iter>>(iter: I) -> Self { + let mut builder = CodePointInversionListBuilder::new(); + for range in iter { + builder.add_range32(range); + } + builder.build() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::codepointinvlist::CodePointInversionList; + use core::{char, convert::TryFrom}; + + #[test] + fn test_try_from_range() { + let check: Vec = CodePointInversionList::try_from('A'..'B') + .unwrap() + .iter_chars() + .collect(); + assert_eq!(vec!['A'], check); + } + + #[test] + fn test_try_from_range_error() { + let check = CodePointInversionList::try_from('A'..'A'); + assert!(matches!(check, Err(RangeError(65, 65)))); + } + + #[test] + fn test_try_from_range_inclusive() { + let check: Vec = CodePointInversionList::try_from('A'..='A') + .unwrap() + .iter_chars() + .collect(); + assert_eq!(vec!['A'], check); + } + + #[test] + fn test_try_from_range_inclusive_err() { + let check = CodePointInversionList::try_from('B'..'A'); + assert!(matches!(check, Err(RangeError(66, 65)))); + } + + #[test] + fn test_try_from_range_from() { + let uset = CodePointInversionList::try_from('A'..).unwrap(); + let check: usize = uset.size(); + let expected: usize = (char::MAX as usize) + 1 - 65; + assert_eq!(expected, check); + } + + #[test] + fn test_try_from_range_to() { + let uset = CodePointInversionList::try_from(..'A').unwrap(); + let check: usize = uset.size(); + let expected: usize = 65; + assert_eq!(expected, check); + } + + #[test] + fn test_try_from_range_to_err() { + let check = CodePointInversionList::try_from(..(0x0 as char)); + assert!(matches!(check, Err(RangeError(0, 0)))); + } + + #[test] + fn test_try_from_range_to_inclusive() { + let uset = CodePointInversionList::try_from(..='A').unwrap(); + let check: usize = uset.size(); + let expected: usize = 66; + assert_eq!(expected, check); + } + + #[test] + fn test_try_from_range_full() { + let uset = CodePointInversionList::try_from(..).unwrap(); + let check: usize = uset.size(); + let expected: usize = (char::MAX as usize) + 1; + assert_eq!(expected, check); + } + + #[test] + fn test_from_range_iterator() { + let ranges = [ + 0..=0x3FFF, + 0x4000..=0x7FFF, + 0x8000..=0xBFFF, + 0xC000..=0xFFFF, + ]; + let expected = + CodePointInversionList::try_from_u32_inversion_list_slice(&[0x0, 0x1_0000]).unwrap(); + let actual = CodePointInversionList::from_iter(ranges); + assert_eq!(expected, actual); + } +} diff --git a/deps/crates/vendor/icu_collections/src/codepointinvlist/cpinvlist.rs b/deps/crates/vendor/icu_collections/src/codepointinvlist/cpinvlist.rs new file mode 100644 index 00000000000000..3b63ff365d3a79 --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/codepointinvlist/cpinvlist.rs @@ -0,0 +1,1064 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +#[cfg(feature = "serde")] +use alloc::format; +#[cfg(feature = "serde")] +use alloc::string::String; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +use core::{char, ops::RangeBounds, ops::RangeInclusive}; +use potential_utf::PotentialCodePoint; +use yoke::Yokeable; +use zerofrom::ZeroFrom; +use zerovec::{ule::AsULE, zerovec, ZeroVec}; + +use super::InvalidSetError; +use crate::codepointinvlist::utils::{deconstruct_range, is_valid_zv}; + +/// Represents the end code point of the Basic Multilingual Plane range, starting from code point 0, inclusive +const BMP_MAX: u32 = 0xFFFF; + +/// Represents the inversion list for a set of all code points in the Basic Multilingual Plane. +const BMP_INV_LIST_VEC: ZeroVec = zerovec!(PotentialCodePoint; PotentialCodePoint::to_unaligned; [PotentialCodePoint::from_u24(0x0), PotentialCodePoint::from_u24(BMP_MAX + 1)]); + +/// Represents the inversion list for all of the code points in the Unicode range. +const ALL_VEC: ZeroVec = zerovec!(PotentialCodePoint; PotentialCodePoint::to_unaligned; [PotentialCodePoint::from_u24(0x0), PotentialCodePoint::from_u24((char::MAX as u32) + 1)]); + +/// A membership wrapper for [`CodePointInversionList`]. +/// +/// Provides exposure to membership functions and constructors from serialized `CodePointSet`s (sets of code points) +/// and predefined ranges. +#[zerovec::make_varule(CodePointInversionListULE)] +#[zerovec::skip_derive(Ord)] +#[zerovec::derive(Debug)] +#[derive(Debug, Eq, PartialEq, Clone, Yokeable, ZeroFrom)] +#[cfg_attr(not(feature = "alloc"), zerovec::skip_derive(ZeroMapKV, ToOwned))] +pub struct CodePointInversionList<'data> { + // If we wanted to use an array to keep the memory on the stack, there is an unsafe nightly feature + // https://doc.rust-lang.org/nightly/core/array/trait.FixedSizeArray.html + // Allows for traits of fixed size arrays + + // Implements an [inversion list.](https://en.wikipedia.org/wiki/Inversion_list) + inv_list: ZeroVec<'data, PotentialCodePoint>, + size: u32, +} + +#[cfg(feature = "serde")] +impl<'de: 'a, 'a> serde::Deserialize<'de> for CodePointInversionList<'a> { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + use serde::de::Error; + + let parsed_inv_list = if deserializer.is_human_readable() { + let parsed_strings = Vec::>::deserialize(deserializer)?; + let mut inv_list = ZeroVec::new_owned(Vec::with_capacity(parsed_strings.len() * 2)); + for range in parsed_strings { + fn internal(range: &str) -> Option<(u32, u32)> { + let (start, range) = UnicodeCodePoint::parse(range)?; + if range.is_empty() { + return Some((start.0, start.0)); + } + let (hyphen, range) = UnicodeCodePoint::parse(range)?; + if hyphen.0 != '-' as u32 { + return None; + } + let (end, range) = UnicodeCodePoint::parse(range)?; + range.is_empty().then_some((start.0, end.0)) + } + let (start, end) = internal(&range).ok_or_else(|| Error::custom(format!( + "Cannot deserialize invalid inversion list for CodePointInversionList: {range:?}" + )))?; + inv_list.with_mut(|v| { + v.push(PotentialCodePoint::from_u24(start).to_unaligned()); + v.push(PotentialCodePoint::from_u24(end + 1).to_unaligned()); + }); + } + inv_list + } else { + ZeroVec::::deserialize(deserializer)? + }; + CodePointInversionList::try_from_inversion_list(parsed_inv_list).map_err(|e| { + Error::custom(format!( + "Cannot deserialize invalid inversion list for CodePointInversionList: {e:?}" + )) + }) + } +} + +#[cfg(feature = "databake")] +impl databake::Bake for CodePointInversionList<'_> { + fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream { + env.insert("icu_collections"); + let inv_list = self.inv_list.bake(env); + let size = self.size.bake(env); + // Safe because our parts are safe. + databake::quote! { unsafe { + #[allow(unused_unsafe)] + icu_collections::codepointinvlist::CodePointInversionList::from_parts_unchecked(#inv_list, #size) + }} + } +} + +#[cfg(feature = "databake")] +impl databake::BakeSize for CodePointInversionList<'_> { + fn borrows_size(&self) -> usize { + self.inv_list.borrows_size() + } +} + +#[cfg(feature = "serde")] +#[derive(Debug, Copy, Clone)] +struct UnicodeCodePoint(u32); + +#[cfg(feature = "serde")] +impl UnicodeCodePoint { + fn from_u32(cp: u32) -> Result { + if cp <= char::MAX as u32 { + Ok(Self(cp)) + } else { + Err(format!("Not a Unicode code point {}", cp)) + } + } + + fn parse(value: &str) -> Option<(Self, &str)> { + Some(if let Some(hex) = value.strip_prefix("U+") { + let (escape, remainder) = (hex.get(..4)?, hex.get(4..)?); + (Self(u32::from_str_radix(escape, 16).ok()?), remainder) + } else { + let c = value.chars().next()?; + (Self(c as u32), value.get(c.len_utf8()..)?) + }) + } +} + +#[cfg(feature = "serde")] +impl core::fmt::Display for UnicodeCodePoint { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self.0 { + s @ 0xD800..=0xDFFF => write!(f, "U+{s:X}"), + // char should be in range by construction but this code is not so performance-sensitive + // so we just use the replacement character + c => write!( + f, + "{}", + char::from_u32(c).unwrap_or(char::REPLACEMENT_CHARACTER) + ), + } + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for CodePointInversionList<'_> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + if serializer.is_human_readable() { + use serde::ser::Error; + use serde::ser::SerializeSeq; + let mut seq = serializer.serialize_seq(Some(self.inv_list.len() / 2))?; + for range in self.iter_ranges() { + let start = UnicodeCodePoint::from_u32(*range.start()).map_err(S::Error::custom)?; + if range.start() == range.end() { + seq.serialize_element(&format!("{start}"))?; + } else { + let end = UnicodeCodePoint::from_u32(*range.end()).map_err(S::Error::custom)?; + seq.serialize_element(&format!("{start}-{end}",))?; + } + } + seq.end() + } else { + // Note: serde(flatten) currently does not promote a struct field of type Vec + // to replace the struct when serializing. The error message from the default + // serialization is: "can only flatten structs and maps (got a sequence)". + self.inv_list.serialize(serializer) + } + } +} + +impl<'data> CodePointInversionList<'data> { + /// Returns a new [`CodePointInversionList`] from an [inversion list](https://en.wikipedia.org/wiki/Inversion_list) + /// represented as a [`ZeroVec`]`<`[`PotentialCodePoint`]`>` of code points. + /// + /// The inversion list must be of even length, sorted ascending non-overlapping, + /// and within the bounds of `0x0 -> 0x10FFFF` inclusive, and end points being exclusive. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// use icu::collections::codepointinvlist::InvalidSetError; + /// use potential_utf::PotentialCodePoint; + /// use zerovec::ZeroVec; + /// + /// let valid = [0x0, 0x10000]; + /// let inv_list: ZeroVec = valid + /// .into_iter() + /// .map(PotentialCodePoint::from_u24) + /// .collect(); + /// let result = CodePointInversionList::try_from_inversion_list(inv_list); + /// assert!(matches!(result, CodePointInversionList)); + /// + /// let invalid = vec![0x0, 0x80, 0x3]; + /// let inv_list: ZeroVec = invalid + /// .iter() + /// .copied() + /// .map(PotentialCodePoint::from_u24) + /// .collect(); + /// let result = CodePointInversionList::try_from_inversion_list(inv_list); + /// assert!(matches!(result, Err(InvalidSetError(_)))); + /// if let Err(InvalidSetError(actual)) = result { + /// assert_eq!( + /// &invalid, + /// &actual.into_iter().map(u32::from).collect::>() + /// ); + /// } + /// ``` + pub fn try_from_inversion_list( + inv_list: ZeroVec<'data, PotentialCodePoint>, + ) -> Result { + #[allow(clippy::indexing_slicing)] // chunks + if is_valid_zv(&inv_list) { + let size = inv_list + .as_ule_slice() + .chunks(2) + .map(|end_points| { + u32::from(::from_unaligned(end_points[1])) + - u32::from(::from_unaligned(end_points[0])) + }) + .sum::(); + Ok(Self { inv_list, size }) + } else { + Err(InvalidSetError( + #[cfg(feature = "alloc")] + inv_list.to_vec(), + )) + } + } + + /// Safety: no actual safety invariants, however has correctness invariants + #[doc(hidden)] // databake internal + pub const unsafe fn from_parts_unchecked( + inv_list: ZeroVec<'data, PotentialCodePoint>, + size: u32, + ) -> Self { + Self { inv_list, size } + } + + /// Returns a new, fully-owned [`CodePointInversionList`] by cloning an [inversion list](https://en.wikipedia.org/wiki/Inversion_list) + /// represented as a slice of [`PotentialCodePoint`] code points. + /// + /// The inversion list must be of even length, sorted ascending non-overlapping, + /// and within the bounds of `0x0 -> 0x10FFFF` inclusive, and end points being exclusive. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// + /// let bmp_list = &[0x0, 0x10000]; + /// let smp_list = &[0x10000, 0x20000]; + /// let sip_list = &[0x20000, 0x30000]; + /// + /// let lists: Vec = + /// [&bmp_list[..], smp_list, sip_list] + /// .into_iter() + /// .map(|l| { + /// CodePointInversionList::try_from_u32_inversion_list_slice(l) + /// .unwrap() + /// }) + /// .collect(); + /// + /// let bmp = &lists[0]; + /// assert!(bmp.contains32(0xFFFF)); + /// assert!(!bmp.contains32(0x10000)); + /// + /// assert!(!lists.iter().any(|set| set.contains32(0x40000))); + /// ``` + #[cfg(feature = "alloc")] + pub fn try_from_u32_inversion_list_slice(inv_list: &[u32]) -> Result { + let inv_list_zv: ZeroVec = inv_list + .iter() + .copied() + .map(PotentialCodePoint::from_u24) + .collect(); + CodePointInversionList::try_from_inversion_list(inv_list_zv) + } + + /// Attempts to convert this list into a fully-owned one. No-op if already fully owned + #[cfg(feature = "alloc")] + pub fn into_owned(self) -> CodePointInversionList<'static> { + CodePointInversionList { + inv_list: self.inv_list.into_owned(), + size: self.size, + } + } + + /// Returns an owned inversion list representing the current [`CodePointInversionList`] + #[cfg(feature = "alloc")] + pub fn get_inversion_list_vec(&self) -> Vec { + self.as_inversion_list().iter().map(u32::from).collect() + } + + /// Returns [`CodePointInversionList`] spanning entire Unicode range + /// + /// The range spans from `0x0 -> 0x10FFFF` inclusive. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// + /// let expected = [0x0, (char::MAX as u32) + 1]; + /// assert_eq!( + /// CodePointInversionList::all().get_inversion_list_vec(), + /// expected + /// ); + /// assert_eq!( + /// CodePointInversionList::all().size(), + /// (expected[1] - expected[0]) as usize + /// ); + /// ``` + pub fn all() -> Self { + Self { + inv_list: ALL_VEC, + size: (char::MAX as u32) + 1, + } + } + + /// Returns [`CodePointInversionList`] spanning BMP range + /// + /// The range spans from `0x0 -> 0xFFFF` inclusive. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// + /// const BMP_MAX: u32 = 0xFFFF; + /// + /// let expected = [0x0, BMP_MAX + 1]; + /// assert_eq!( + /// CodePointInversionList::bmp().get_inversion_list_vec(), + /// expected + /// ); + /// assert_eq!( + /// CodePointInversionList::bmp().size(), + /// (expected[1] - expected[0]) as usize + /// ); + /// ``` + pub fn bmp() -> Self { + Self { + inv_list: BMP_INV_LIST_VEC, + size: BMP_MAX + 1, + } + } + + /// Returns the inversion list as a slice + /// + /// Public only to the crate, not exposed to public + #[cfg(feature = "alloc")] + pub(crate) fn as_inversion_list(&self) -> &ZeroVec { + &self.inv_list + } + + /// Yields an [`Iterator`] going through the character set in the [`CodePointInversionList`] + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// let example_list = [0x41, 0x44, 0x45, 0x46]; + /// let example = CodePointInversionList::try_from_u32_inversion_list_slice( + /// &example_list, + /// ) + /// .unwrap(); + /// let mut ex_iter_chars = example.iter_chars(); + /// assert_eq!(Some('A'), ex_iter_chars.next()); + /// assert_eq!(Some('B'), ex_iter_chars.next()); + /// assert_eq!(Some('C'), ex_iter_chars.next()); + /// assert_eq!(Some('E'), ex_iter_chars.next()); + /// assert_eq!(None, ex_iter_chars.next()); + /// ``` + pub fn iter_chars(&self) -> impl Iterator + '_ { + #[allow(clippy::indexing_slicing)] // chunks + self.inv_list + .as_ule_slice() + .chunks(2) + .flat_map(|pair| { + u32::from(PotentialCodePoint::from_unaligned(pair[0])) + ..u32::from(PotentialCodePoint::from_unaligned(pair[1])) + }) + .filter_map(char::from_u32) + } + + /// Yields an [`Iterator`] returning the ranges of the code points that are + /// included in the [`CodePointInversionList`] + /// + /// Ranges are returned as [`RangeInclusive`], which is inclusive of its + /// `end` bound value. An end-inclusive behavior matches the ICU4C/J + /// behavior of ranges, ex: `CodePointInversionList::contains(UChar32 start, UChar32 end)`. + /// + /// # Example + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// let example_list = [0x41, 0x44, 0x45, 0x46]; + /// let example = CodePointInversionList::try_from_u32_inversion_list_slice( + /// &example_list, + /// ) + /// .unwrap(); + /// let mut example_iter_ranges = example.iter_ranges(); + /// assert_eq!(Some(0x41..=0x43), example_iter_ranges.next()); + /// assert_eq!(Some(0x45..=0x45), example_iter_ranges.next()); + /// assert_eq!(None, example_iter_ranges.next()); + /// ``` + pub fn iter_ranges(&self) -> impl ExactSizeIterator> + '_ { + #[allow(clippy::indexing_slicing)] // chunks + self.inv_list.as_ule_slice().chunks(2).map(|pair| { + let range_start = u32::from(PotentialCodePoint::from_unaligned(pair[0])); + let range_limit = u32::from(PotentialCodePoint::from_unaligned(pair[1])); + range_start..=(range_limit - 1) + }) + } + + /// Yields an [`Iterator`] returning the ranges of the code points that are + /// *not* included in the [`CodePointInversionList`] + /// + /// Ranges are returned as [`RangeInclusive`], which is inclusive of its + /// `end` bound value. An end-inclusive behavior matches the ICU4C/J + /// behavior of ranges, ex: `CodePointInversionList::contains(UChar32 start, UChar32 end)`. + /// + /// # Example + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// let example_list = [0x41, 0x44, 0x45, 0x46]; + /// let example = CodePointInversionList::try_from_u32_inversion_list_slice( + /// &example_list, + /// ) + /// .unwrap(); + /// let mut example_iter_ranges = example.iter_ranges_complemented(); + /// assert_eq!(Some(0..=0x40), example_iter_ranges.next()); + /// assert_eq!(Some(0x44..=0x44), example_iter_ranges.next()); + /// assert_eq!(Some(0x46..=char::MAX as u32), example_iter_ranges.next()); + /// assert_eq!(None, example_iter_ranges.next()); + /// ``` + pub fn iter_ranges_complemented(&self) -> impl Iterator> + '_ { + let inv_ule = self.inv_list.as_ule_slice(); + let middle = inv_ule.get(1..inv_ule.len() - 1).unwrap_or(&[]); + let beginning = if let Some(first) = self.inv_list.first() { + let first = u32::from(first); + if first == 0 { + None + } else { + Some(0..=first - 1) + } + } else { + None + }; + let end = if let Some(last) = self.inv_list.last() { + let last = u32::from(last); + if last == char::MAX as u32 { + None + } else { + Some(last..=char::MAX as u32) + } + } else { + None + }; + #[allow(clippy::indexing_slicing)] // chunks + let chunks = middle.chunks(2).map(|pair| { + let range_start = u32::from(PotentialCodePoint::from_unaligned(pair[0])); + let range_limit = u32::from(PotentialCodePoint::from_unaligned(pair[1])); + range_start..=(range_limit - 1) + }); + beginning.into_iter().chain(chunks).chain(end) + } + + /// Returns the number of ranges contained in this [`CodePointInversionList`] + pub fn get_range_count(&self) -> usize { + self.inv_list.len() / 2 + } + + /// Returns a specific range contained in this [`CodePointInversionList`] by index. + /// Intended for use in FFI. + pub fn get_nth_range(&self, idx: usize) -> Option> { + let start_idx = idx * 2; + let end_idx = start_idx + 1; + let start = u32::from(self.inv_list.get(start_idx)?); + let end = u32::from(self.inv_list.get(end_idx)?); + Some(start..=(end - 1)) + } + + /// Returns the number of elements of the [`CodePointInversionList`] + pub fn size(&self) -> usize { + if self.is_empty() { + return 0; + } + self.size as usize + } + + /// Returns whether or not the [`CodePointInversionList`] is empty + pub fn is_empty(&self) -> bool { + self.inv_list.is_empty() + } + + /// Wrapper for contains + /// + /// Returns an [`Option`] as to whether or not it is possible for the query to be contained. + /// The value in the [`Option`] is the start index of the range that contains the query. + fn contains_query(&self, query: u32) -> Option { + let query = PotentialCodePoint::try_from(query).ok()?; + match self.inv_list.binary_search(&query) { + Ok(pos) => { + if pos % 2 == 0 { + Some(pos) + } else { + None + } + } + Err(pos) => { + if pos % 2 != 0 && pos < self.inv_list.len() { + Some(pos - 1) + } else { + None + } + } + } + } + + /// Checks to see the query is in the [`CodePointInversionList`] + /// + /// Runs a binary search in `O(log(n))` where `n` is the number of start and end points + /// in the set using [`core`] implementation + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// let example_list = [0x41, 0x43, 0x44, 0x45]; + /// let example = CodePointInversionList::try_from_u32_inversion_list_slice( + /// &example_list, + /// ) + /// .unwrap(); + /// assert!(example.contains('A')); + /// assert!(!example.contains('C')); + /// ``` + pub fn contains(&self, query: char) -> bool { + self.contains_query(query as u32).is_some() + } + + /// Checks to see the unsigned int is in the [`CodePointInversionList::all()`](CodePointInversionList::all()) + /// + /// Note: Even though [`u32`] and [`prim@char`] in Rust are non-negative 4-byte + /// values, there is an important difference. A [`u32`] can take values up to + /// a very large integer value, while a [`prim@char`] in Rust is defined to be in + /// the range from 0 to the maximum valid Unicode Scalar Value. + /// + /// Runs a binary search in `O(log(n))` where `n` is the number of start and end points + /// in the set using [`core`] implementation + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// let example_list = [0x41, 0x43, 0x44, 0x45]; + /// let example = CodePointInversionList::try_from_u32_inversion_list_slice( + /// &example_list, + /// ) + /// .unwrap(); + /// assert!(example.contains32(0x41)); + /// assert!(!example.contains32(0x43)); + /// ``` + pub fn contains32(&self, query: u32) -> bool { + self.contains_query(query).is_some() + } + + /// Checks to see if the range is in the [`CodePointInversionList`] + /// + /// Runs a binary search in `O(log(n))` where `n` is the number of start and end points + /// in the set using [`Vec`] implementation. Only runs the search once on the `start` + /// parameter, while the `end` parameter is checked in a single `O(1)` step. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// let example_list = [0x41, 0x43, 0x44, 0x45]; + /// let example = CodePointInversionList::try_from_u32_inversion_list_slice( + /// &example_list, + /// ) + /// .unwrap(); + /// assert!(example.contains_range('A'..'C')); + /// assert!(example.contains_range('A'..='B')); + /// assert!(!example.contains_range('A'..='C')); + /// ``` + /// + /// Surrogate points (`0xD800 -> 0xDFFF`) will return [`false`] if the Range contains them but the + /// [`CodePointInversionList`] does not. + /// + /// Note: when comparing to ICU4C/J, keep in mind that `Range`s in Rust are + /// constructed inclusive of start boundary and exclusive of end boundary. + /// The ICU4C/J `CodePointInversionList::contains(UChar32 start, UChar32 end)` method + /// differs by including the end boundary. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// use std::char; + /// let check = + /// char::from_u32(0xD7FE).unwrap()..char::from_u32(0xE001).unwrap(); + /// let example_list = [0xD7FE, 0xD7FF, 0xE000, 0xE001]; + /// let example = CodePointInversionList::try_from_u32_inversion_list_slice( + /// &example_list, + /// ) + /// .unwrap(); + /// assert!(!example.contains_range(check)); + /// ``` + pub fn contains_range(&self, range: impl RangeBounds) -> bool { + let (from, till) = deconstruct_range(range); + if from >= till { + return false; + } + match self.contains_query(from) { + Some(pos) => { + if let Some(x) = self.inv_list.get(pos + 1) { + (till) <= x.into() + } else { + debug_assert!( + false, + "Inversion list query should not return out of bounds index" + ); + false + } + } + None => false, + } + } + + /// Check if the calling [`CodePointInversionList`] contains all the characters of the given [`CodePointInversionList`] + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// let example_list = [0x41, 0x46, 0x55, 0x5B]; // A - E, U - Z + /// let example = CodePointInversionList::try_from_u32_inversion_list_slice( + /// &example_list, + /// ) + /// .unwrap(); + /// let a_to_d = CodePointInversionList::try_from_u32_inversion_list_slice(&[ + /// 0x41, 0x45, + /// ]) + /// .unwrap(); + /// let f_to_t = CodePointInversionList::try_from_u32_inversion_list_slice(&[ + /// 0x46, 0x55, + /// ]) + /// .unwrap(); + /// let r_to_x = CodePointInversionList::try_from_u32_inversion_list_slice(&[ + /// 0x52, 0x58, + /// ]) + /// .unwrap(); + /// assert!(example.contains_set(&a_to_d)); // contains all + /// assert!(!example.contains_set(&f_to_t)); // contains none + /// assert!(!example.contains_set(&r_to_x)); // contains some + /// ``` + pub fn contains_set(&self, set: &Self) -> bool { + if set.size() > self.size() { + return false; + } + + let mut set_ranges = set.iter_ranges(); + let mut check_elem = set_ranges.next(); + + let ranges = self.iter_ranges(); + for range in ranges { + match check_elem { + Some(ref check_range) => { + if check_range.start() >= range.start() + && check_range.end() <= &(range.end() + 1) + { + check_elem = set_ranges.next(); + } + } + _ => break, + } + } + check_elem.is_none() + } + + /// Returns the end of the initial substring where the characters are either contained/not contained + /// in the set. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// let example_list = [0x41, 0x44]; // {A, B, C} + /// let example = CodePointInversionList::try_from_u32_inversion_list_slice( + /// &example_list, + /// ) + /// .unwrap(); + /// assert_eq!(example.span("CABXYZ", true), 3); + /// assert_eq!(example.span("XYZC", false), 3); + /// assert_eq!(example.span("XYZ", true), 0); + /// assert_eq!(example.span("ABC", false), 0); + /// ``` + pub fn span(&self, span_str: &str, contained: bool) -> usize { + span_str + .chars() + .take_while(|&x| self.contains(x) == contained) + .count() + } + + /// Returns the start of the trailing substring (starting from end of string) where the characters are + /// either contained/not contained in the set. Returns the length of the string if no valid return. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// let example_list = [0x41, 0x44]; // {A, B, C} + /// let example = CodePointInversionList::try_from_u32_inversion_list_slice( + /// &example_list, + /// ) + /// .unwrap(); + /// assert_eq!(example.span_back("XYZCAB", true), 3); + /// assert_eq!(example.span_back("ABCXYZ", true), 6); + /// assert_eq!(example.span_back("CABXYZ", false), 3); + /// ``` + pub fn span_back(&self, span_str: &str, contained: bool) -> usize { + span_str.len() + - span_str + .chars() + .rev() + .take_while(|&x| self.contains(x) == contained) + .count() + } +} + +#[cfg(test)] +mod tests { + use super::{CodePointInversionList, InvalidSetError}; + use std::{char, vec::Vec}; + use zerovec::ZeroVec; + + #[test] + fn test_codepointinversionlist_try_from_vec() { + let ex = vec![0x2, 0x3, 0x4, 0x5]; + let check = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + assert_eq!(ex, check.get_inversion_list_vec()); + assert_eq!(2, check.size()); + } + + #[test] + fn test_codepointinversionlist_try_from_vec_error() { + let check = vec![0x1, 0x1, 0x2, 0x3, 0x4]; + let set = CodePointInversionList::try_from_u32_inversion_list_slice(&check); + assert!(matches!(set, Err(InvalidSetError(_)))); + if let Err(InvalidSetError(actual)) = set { + assert_eq!( + &check, + &actual.into_iter().map(u32::from).collect::>() + ); + } + } + + // CodePointInversionList membership functions + #[test] + fn test_codepointinversionlist_contains_query() { + let ex = vec![0x41, 0x46, 0x4B, 0x55]; + let check = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + assert!(check.contains_query(0x40).is_none()); + assert_eq!(check.contains_query(0x41).unwrap(), 0); + assert_eq!(check.contains_query(0x44).unwrap(), 0); + assert!(check.contains_query(0x46).is_none()); + assert_eq!(check.contains_query(0x4C).unwrap(), 2); + assert!(check.contains_query(0x56).is_none()); + } + + #[test] + fn test_codepointinversionlist_contains() { + let ex = vec![0x2, 0x5, 0xA, 0xF]; + let check = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + assert!(check.contains(0x2 as char)); + assert!(check.contains(0x4 as char)); + assert!(check.contains(0xA as char)); + assert!(check.contains(0xE as char)); + } + + #[test] + fn test_codepointinversionlist_contains_false() { + let ex = vec![0x2, 0x5, 0xA, 0xF]; + let check = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + assert!(!check.contains(0x1 as char)); + assert!(!check.contains(0x5 as char)); + assert!(!check.contains(0x9 as char)); + assert!(!check.contains(0xF as char)); + assert!(!check.contains(0x10 as char)); + } + + #[test] + fn test_codepointinversionlist_contains_range() { + let ex = vec![0x41, 0x46, 0x4B, 0x55]; + let check = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + assert!(check.contains_range('A'..='E')); // 65 - 69 + assert!(check.contains_range('C'..'D')); // 67 - 67 + assert!(check.contains_range('L'..'P')); // 76 - 80 + assert!(!check.contains_range('L'..='U')); // 76 - 85 + } + + #[test] + fn test_codepointinversionlist_contains_range_false() { + let ex = vec![0x41, 0x46, 0x4B, 0x55]; + let check = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + assert!(!check.contains_range('!'..'A')); // 33 - 65 + assert!(!check.contains_range('F'..'K')); // 70 - 74 + assert!(!check.contains_range('U'..)); // 85 - .. + } + + #[test] + fn test_codepointinversionlist_contains_range_invalid() { + let check = CodePointInversionList::all(); + assert!(!check.contains_range('A'..'!')); // 65 - 33 + assert!(!check.contains_range('A'..'A')); // 65 - 65 + } + + #[test] + fn test_codepointinversionlist_contains_set_u() { + let ex = vec![0xA, 0x14, 0x28, 0x32, 0x46, 0x50, 0x64, 0x6E]; + let u = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + let inside = vec![0xF, 0x14, 0x2C, 0x31, 0x46, 0x50, 0x64, 0x6D]; + let s = CodePointInversionList::try_from_u32_inversion_list_slice(&inside).unwrap(); + assert!(u.contains_set(&s)); + } + + #[test] + fn test_codepointinversionlist_contains_set_u_false() { + let ex = vec![0xA, 0x14, 0x28, 0x32, 0x46, 0x50, 0x64, 0x78]; + let u = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + let outside = vec![0x0, 0xA, 0x16, 0x2C, 0x32, 0x46, 0x4F, 0x51, 0x6D, 0x6F]; + let s = CodePointInversionList::try_from_u32_inversion_list_slice(&outside).unwrap(); + assert!(!u.contains_set(&s)); + } + + #[test] + fn test_codepointinversionlist_size() { + let ex = vec![0x2, 0x5, 0xA, 0xF]; + let check = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + assert_eq!(8, check.size()); + let check = CodePointInversionList::all(); + let expected = (char::MAX as u32) + 1; + assert_eq!(expected as usize, check.size()); + let inv_list_vec = vec![]; + let check = CodePointInversionList { + inv_list: ZeroVec::from_slice_or_alloc(&inv_list_vec), + size: 0, + }; + assert_eq!(check.size(), 0); + } + + #[test] + fn test_codepointinversionlist_is_empty() { + let inv_list_vec = vec![]; + let check = CodePointInversionList { + inv_list: ZeroVec::from_slice_or_alloc(&inv_list_vec), + size: 0, + }; + assert!(check.is_empty()); + } + + #[test] + fn test_codepointinversionlist_is_not_empty() { + let check = CodePointInversionList::all(); + assert!(!check.is_empty()); + } + + #[test] + fn test_codepointinversionlist_iter_chars() { + let ex = vec![0x41, 0x44, 0x45, 0x46, 0xD800, 0xD801]; + let check = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + let mut iter = check.iter_chars(); + assert_eq!(Some('A'), iter.next()); + assert_eq!(Some('B'), iter.next()); + assert_eq!(Some('C'), iter.next()); + assert_eq!(Some('E'), iter.next()); + assert_eq!(None, iter.next()); + } + + #[test] + fn test_codepointinversionlist_iter_ranges() { + let ex = vec![0x41, 0x44, 0x45, 0x46, 0xD800, 0xD801]; + let set = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + let mut ranges = set.iter_ranges(); + assert_eq!(Some(0x41..=0x43), ranges.next()); + assert_eq!(Some(0x45..=0x45), ranges.next()); + assert_eq!(Some(0xD800..=0xD800), ranges.next()); + assert_eq!(None, ranges.next()); + } + + #[test] + fn test_codepointinversionlist_iter_ranges_exactsizeiter_trait() { + let ex = vec![0x41, 0x44, 0x45, 0x46, 0xD800, 0xD801]; + let set = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + let ranges = set.iter_ranges(); + assert_eq!(3, ranges.len()); + } + + #[test] + fn test_codepointinversionlist_range_count() { + let ex = vec![0x41, 0x44, 0x45, 0x46, 0xD800, 0xD801]; + let set = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + assert_eq!(3, set.get_range_count()); + } + + #[test] + fn test_codepointinversionlist_get_nth_range() { + let ex = vec![0x41, 0x44, 0x45, 0x46, 0xD800, 0xD801]; + let set = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + assert_eq!(Some(0x41..=0x43), set.get_nth_range(0)); + assert_eq!(Some(0x45..=0x45), set.get_nth_range(1)); + assert_eq!(Some(0xD800..=0xD800), set.get_nth_range(2)); + assert_eq!(None, set.get_nth_range(3)); + } + + // Range cannot represent the upper bound (non-inclusive) for + // char::MAX, whereas Range can. + #[test] + fn test_codepointinversionlist_iter_ranges_with_max_code_point() { + let ex = vec![0x80, (char::MAX as u32) + 1]; + let set = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + let mut ranges = set.iter_ranges(); + assert_eq!(Some(0x80..=(char::MAX as u32)), ranges.next()); + assert_eq!(None, ranges.next()); + } + + #[test] + fn test_codepointinversionlist_span_contains() { + let ex = vec![0x41, 0x44, 0x46, 0x4B]; // A - D, F - K + let check = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + assert_eq!(check.span("ABCDE", true), 3); + assert_eq!(check.span("E", true), 0); + } + + #[test] + fn test_codepointinversionlist_span_does_not_contain() { + let ex = vec![0x41, 0x44, 0x46, 0x4B]; // A - D, F - K + let check = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + assert_eq!(check.span("DEF", false), 2); + assert_eq!(check.span("KLMA", false), 3); + } + + #[test] + fn test_codepointinversionlist_span_back_contains() { + let ex = vec![0x41, 0x44, 0x46, 0x4B]; // A - D, F - K + let check = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + assert_eq!(check.span_back("XYZABFH", true), 3); + assert_eq!(check.span_back("ABCXYZ", true), 6); + } + + #[test] + fn test_codepointinversionlist_span_back_does_not_contain() { + let ex = vec![0x41, 0x44, 0x46, 0x4B]; // A - D, F - K + let check = CodePointInversionList::try_from_u32_inversion_list_slice(&ex).unwrap(); + assert_eq!(check.span_back("ABCXYZ", false), 3); + assert_eq!(check.span_back("XYZABC", false), 6); + } + + #[test] + fn test_uniset_to_inv_list() { + let inv_list = [ + 0x9, 0xE, 0x20, 0x21, 0x85, 0x86, 0xA0, 0xA1, 0x1626, 0x1627, 0x2000, 0x2003, 0x2028, + 0x202A, 0x202F, 0x2030, 0x205F, 0x2060, 0x3000, 0x3001, + ]; + let s: CodePointInversionList = + CodePointInversionList::try_from_u32_inversion_list_slice(&inv_list).unwrap(); + let round_trip_inv_list = s.get_inversion_list_vec(); + assert_eq!( + round_trip_inv_list.into_iter().collect::>(), + inv_list + ); + } + + #[test] + fn test_serde_serialize() { + let inv_list = [0x41, 0x46, 0x4B, 0x55]; + let uniset = CodePointInversionList::try_from_u32_inversion_list_slice(&inv_list).unwrap(); + let json_str = serde_json::to_string(&uniset).unwrap(); + assert_eq!(json_str, r#"["A-E","K-T"]"#); + } + + #[test] + fn test_serde_serialize_surrogates() { + let inv_list = [0xDFAB, 0xDFFF]; + let uniset = CodePointInversionList::try_from_u32_inversion_list_slice(&inv_list).unwrap(); + let json_str = serde_json::to_string(&uniset).unwrap(); + assert_eq!(json_str, r#"["U+DFAB-U+DFFE"]"#); + } + + #[test] + fn test_serde_deserialize() { + let inv_list_str = r#"["A-E","K-T"]"#; + let exp_inv_list = [0x41, 0x46, 0x4B, 0x55]; + let exp_uniset = + CodePointInversionList::try_from_u32_inversion_list_slice(&exp_inv_list).unwrap(); + let act_uniset: CodePointInversionList = serde_json::from_str(inv_list_str).unwrap(); + assert_eq!(act_uniset, exp_uniset); + } + + #[test] + fn test_serde_deserialize_surrogates() { + let inv_list_str = r#"["U+DFAB-U+DFFE"]"#; + let exp_inv_list = [0xDFAB, 0xDFFF]; + let exp_uniset = + CodePointInversionList::try_from_u32_inversion_list_slice(&exp_inv_list).unwrap(); + let act_uniset: CodePointInversionList = serde_json::from_str(inv_list_str).unwrap(); + assert_eq!(act_uniset, exp_uniset); + } + + #[test] + fn test_serde_deserialize_invalid() { + assert!(serde_json::from_str::("[65,70,98775,85]").is_err()); + assert!(serde_json::from_str::("[65,70,U+FFFFFFFFFF,85]").is_err()); + } + + #[test] + fn test_serde_with_postcard_roundtrip() -> Result<(), postcard::Error> { + let set = CodePointInversionList::bmp(); + let set_serialized: Vec = postcard::to_allocvec(&set).unwrap(); + let set_deserialized: CodePointInversionList = + postcard::from_bytes::(&set_serialized)?; + + assert_eq!(&set, &set_deserialized); + assert!(!set_deserialized.inv_list.is_owned()); + + Ok(()) + } + + #[test] + fn databake() { + databake::test_bake!( + CodePointInversionList<'static>, + const, + unsafe { + #[allow(unused_unsafe)] + crate::codepointinvlist::CodePointInversionList::from_parts_unchecked( + unsafe { + zerovec::ZeroVec::from_bytes_unchecked( + b"0\0\0\0:\0\0\0A\0\0\0G\0\0\0a\0\0\0g\0\0\0", + ) + }, + 22u32, + ) + }, + icu_collections, + [zerovec], + ); + } +} diff --git a/deps/crates/vendor/icu_collections/src/codepointinvlist/mod.rs b/deps/crates/vendor/icu_collections/src/codepointinvlist/mod.rs new file mode 100644 index 00000000000000..be4986a301d3c2 --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/codepointinvlist/mod.rs @@ -0,0 +1,82 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module provides necessary functionality for highly efficient querying of sets of Unicode characters. +//! +//! It is an implementation of the code point portion of the existing +//! [ICU4C UnicodeSet API](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1UnicodeSet.html). +//! +//! # Architecture +//! ICU4X [`CodePointInversionList`] is split up into independent levels, with [`CodePointInversionList`] representing the membership/query API, +//! and [`CodePointInversionListBuilder`] representing the builder API. +//! +//! # Examples: +//! +//! ## Creating a `CodePointInversionList` +//! +//! `CodePointSets` are created from either serialized [`CodePointSets`](CodePointInversionList), +//! represented by [inversion lists](http://userguide.icu-project.org/strings/properties), +//! the [`CodePointInversionListBuilder`], or from the Properties API. +//! +//! ``` +//! use icu::collections::codepointinvlist::{ +//! CodePointInversionList, CodePointInversionListBuilder, +//! }; +//! +//! let mut builder = CodePointInversionListBuilder::new(); +//! builder.add_range('A'..='Z'); +//! let set: CodePointInversionList = builder.build(); +//! +//! assert!(set.contains('A')); +//! ``` +//! +//! ## Querying a `CodePointInversionList` +//! +//! Currently, you can check if a character/range of characters exists in the [`CodePointInversionList`], or iterate through the characters. +//! +//! ``` +//! use icu::collections::codepointinvlist::{ +//! CodePointInversionList, CodePointInversionListBuilder, +//! }; +//! +//! let mut builder = CodePointInversionListBuilder::new(); +//! builder.add_range('A'..='Z'); +//! let set: CodePointInversionList = builder.build(); +//! +//! assert!(set.contains('A')); +//! assert!(set.contains_range('A'..='C')); +//! assert_eq!(set.iter_chars().next(), Some('A')); +//! ``` +//! +//! [`ICU4X`]: ../icu/index.html + +#![warn(missing_docs)] + +extern crate alloc; + +#[cfg(feature = "alloc")] +#[macro_use] +mod builder; +#[cfg(feature = "alloc")] +mod conversions; +mod cpinvlist; +mod utils; + +#[cfg(feature = "alloc")] +pub use builder::CodePointInversionListBuilder; +pub use cpinvlist::CodePointInversionList; +pub use cpinvlist::CodePointInversionListULE; +use displaydoc::Display; + +#[derive(Display, Debug)] +/// A CodePointInversionList was constructed with an invalid inversion list +#[cfg_attr(feature = "alloc", displaydoc("Invalid set: {0:?}"))] +pub struct InvalidSetError( + #[cfg(feature = "alloc")] pub alloc::vec::Vec, +); + +/// A CodePointInversionList was constructed from an invalid range +#[derive(Display, Debug)] +#[displaydoc("Invalid range: {0}..{1}")] +pub struct RangeError(pub u32, pub u32); diff --git a/deps/crates/vendor/icu_collections/src/codepointinvlist/utils.rs b/deps/crates/vendor/icu_collections/src/codepointinvlist/utils.rs new file mode 100644 index 00000000000000..525b02ffd116f1 --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/codepointinvlist/utils.rs @@ -0,0 +1,118 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use core::{ + char, + ops::{Bound::*, RangeBounds}, +}; +use potential_utf::PotentialCodePoint; +use zerovec::ule::AsULE; +use zerovec::ZeroVec; + +/// Returns whether the vector is sorted ascending non inclusive, of even length, +/// and within the bounds of `0x0 -> 0x10FFFF + 1` inclusive. +#[allow(clippy::indexing_slicing)] // windows +#[allow(clippy::unwrap_used)] // by is_empty check +pub fn is_valid_zv(inv_list_zv: &ZeroVec<'_, PotentialCodePoint>) -> bool { + inv_list_zv.is_empty() + || (inv_list_zv.len() % 2 == 0 + && inv_list_zv.as_ule_slice().windows(2).all(|chunk| { + ::from_unaligned(chunk[0]) + < ::from_unaligned(chunk[1]) + }) + && u32::from(inv_list_zv.last().unwrap()) <= char::MAX as u32 + 1) +} + +/// Returns start (inclusive) and end (exclusive) bounds of [`RangeBounds`] +pub fn deconstruct_range(range: impl RangeBounds) -> (u32, u32) +where + T: Into + Copy, +{ + let from = match range.start_bound() { + Included(b) => (*b).into(), + Excluded(_) => unreachable!(), + Unbounded => 0, + }; + let till = match range.end_bound() { + Included(b) => (*b).into() + 1, + Excluded(b) => (*b).into(), + Unbounded => (char::MAX as u32) + 1, + }; + (from, till) +} + +#[cfg(test)] +mod tests { + use super::{deconstruct_range, is_valid_zv, PotentialCodePoint}; + use core::char; + use zerovec::ZeroVec; + + fn make_zv(slice: &[u32]) -> ZeroVec { + slice + .iter() + .copied() + .map(PotentialCodePoint::from_u24) + .collect() + } + #[test] + fn test_is_valid_zv() { + let check = make_zv(&[0x2, 0x3, 0x4, 0x5]); + assert!(is_valid_zv(&check)); + } + + #[test] + fn test_is_valid_zv_empty() { + let check = make_zv(&[]); + assert!(is_valid_zv(&check)); + } + + #[test] + fn test_is_valid_zv_overlapping() { + let check = make_zv(&[0x2, 0x5, 0x4, 0x6]); + assert!(!is_valid_zv(&check)); + } + + #[test] + fn test_is_valid_zv_out_of_order() { + let check = make_zv(&[0x5, 0x4, 0x5, 0x6, 0x7]); + assert!(!is_valid_zv(&check)); + } + + #[test] + fn test_is_valid_zv_duplicate() { + let check = make_zv(&[0x1, 0x2, 0x3, 0x3, 0x5]); + assert!(!is_valid_zv(&check)); + } + + #[test] + fn test_is_valid_zv_odd() { + let check = make_zv(&[0x1, 0x2, 0x3, 0x4, 0x5]); + assert!(!is_valid_zv(&check)); + } + + #[test] + fn test_is_valid_zv_out_of_range() { + let check = make_zv(&[0x1, 0x2, 0x3, 0x4, (char::MAX as u32) + 1]); + assert!(!is_valid_zv(&check)); + } + + // deconstruct_range + + #[test] + fn test_deconstruct_range() { + let expected = (0x41, 0x45); + let check = deconstruct_range('A'..'E'); // Range + assert_eq!(check, expected); + let check = deconstruct_range('A'..='D'); // Range Inclusive + assert_eq!(check, expected); + let check = deconstruct_range('A'..); // Range From + assert_eq!(check, (0x41, (char::MAX as u32) + 1)); + let check = deconstruct_range(..'A'); // Range To + assert_eq!(check, (0x0, 0x41)); + let check = deconstruct_range(..='A'); // Range To Inclusive + assert_eq!(check, (0x0, 0x42)); + let check = deconstruct_range::(..); // Range Full + assert_eq!(check, (0x0, (char::MAX as u32) + 1)); + } +} diff --git a/deps/crates/vendor/icu_collections/src/codepointinvliststringlist/mod.rs b/deps/crates/vendor/icu_collections/src/codepointinvliststringlist/mod.rs new file mode 100644 index 00000000000000..2562cc5bc69512 --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/codepointinvliststringlist/mod.rs @@ -0,0 +1,384 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module provides functionality for querying of sets of Unicode code points and strings. +//! +//! It depends on [`CodePointInversionList`] to efficiently represent Unicode code points, while +//! it also maintains a list of strings in the set. +//! +//! It is an implementation of the existing [ICU4C UnicodeSet API](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1UnicodeSet.html). + +#[cfg(feature = "alloc")] +use crate::codepointinvlist::CodePointInversionListBuilder; +use crate::codepointinvlist::{CodePointInversionList, CodePointInversionListULE}; +#[cfg(feature = "alloc")] +use alloc::string::{String, ToString}; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +use displaydoc::Display; +use yoke::Yokeable; +use zerofrom::ZeroFrom; +use zerovec::{VarZeroSlice, VarZeroVec}; + +/// A data structure providing a concrete implementation of a set of code points and strings, +/// using an inversion list for the code points. +/// +/// This is what ICU4C calls a `UnicodeSet`. +#[zerovec::make_varule(CodePointInversionListAndStringListULE)] +#[zerovec::skip_derive(Ord)] +#[zerovec::derive(Debug)] +#[derive(Debug, Eq, PartialEq, Clone, Yokeable, ZeroFrom)] +#[cfg_attr(not(feature = "alloc"), zerovec::skip_derive(ZeroMapKV, ToOwned))] +// Valid to auto-derive Deserialize because the invariants are weakly held +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", zerovec::derive(Serialize, Deserialize, Debug))] +pub struct CodePointInversionListAndStringList<'data> { + #[cfg_attr(feature = "serde", serde(borrow))] + #[zerovec::varule(CodePointInversionListULE)] + cp_inv_list: CodePointInversionList<'data>, + // Invariants (weakly held): + // - no input string is length 1 (a length 1 string should be a single code point) + // - the string list is sorted + // - the elements in the string list are unique + #[cfg_attr(feature = "serde", serde(borrow))] + str_list: VarZeroVec<'data, str>, +} + +#[cfg(feature = "databake")] +impl databake::Bake for CodePointInversionListAndStringList<'_> { + fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream { + env.insert("icu_collections"); + let cp_inv_list = self.cp_inv_list.bake(env); + let str_list = self.str_list.bake(env); + // Safe because our parts are safe. + databake::quote! { + icu_collections::codepointinvliststringlist::CodePointInversionListAndStringList::from_parts_unchecked(#cp_inv_list, #str_list) + } + } +} + +#[cfg(feature = "databake")] +impl databake::BakeSize for CodePointInversionListAndStringList<'_> { + fn borrows_size(&self) -> usize { + self.cp_inv_list.borrows_size() + self.str_list.borrows_size() + } +} + +impl<'data> CodePointInversionListAndStringList<'data> { + /// Returns a new [`CodePointInversionListAndStringList`] from both a [`CodePointInversionList`] for the + /// code points and a [`VarZeroVec`]`<`[`str`]`>` of strings. + pub fn try_from( + cp_inv_list: CodePointInversionList<'data>, + str_list: VarZeroVec<'data, str>, + ) -> Result { + // Verify invariants: + // Do so by using the equivalent of str_list.iter().windows(2) to get + // overlapping windows of size 2. The above putative code is not possible + // because `.windows()` exists on a slice, but VarZeroVec cannot return a slice + // because the non-fixed size elements necessitate at least some type + // of allocation. + { + let mut it = str_list.iter(); + if let Some(mut x) = it.next() { + if x.len() == 1 { + return Err(InvalidStringList::InvalidStringLength( + #[cfg(feature = "alloc")] + x.to_string(), + )); + } + for y in it { + if x.len() == 1 { + return Err(InvalidStringList::InvalidStringLength( + #[cfg(feature = "alloc")] + x.to_string(), + )); + } else if x == y { + return Err(InvalidStringList::StringListNotUnique( + #[cfg(feature = "alloc")] + x.to_string(), + )); + } else if x > y { + return Err(InvalidStringList::StringListNotSorted( + #[cfg(feature = "alloc")] + x.to_string(), + #[cfg(feature = "alloc")] + y.to_string(), + )); + } + + // Next window begins. Update `x` here, `y` will be updated in next loop iteration. + x = y; + } + } + } + + Ok(CodePointInversionListAndStringList { + cp_inv_list, + str_list, + }) + } + + #[doc(hidden)] // databake internal + pub const fn from_parts_unchecked( + cp_inv_list: CodePointInversionList<'data>, + str_list: VarZeroVec<'data, str>, + ) -> Self { + CodePointInversionListAndStringList { + cp_inv_list, + str_list, + } + } + + /// Returns the number of elements in this set (its cardinality). + /// Note than the elements of a set may include both individual + /// codepoints and strings. + pub fn size(&self) -> usize { + self.cp_inv_list.size() + self.str_list.len() + } + + /// Return true if this set contains multi-code point strings or the empty string. + pub fn has_strings(&self) -> bool { + !self.str_list.is_empty() + } + + /// + /// # Examples + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// use icu::collections::codepointinvliststringlist::CodePointInversionListAndStringList; + /// use zerovec::VarZeroVec; + /// + /// let cp_slice = &[0, 0x1_0000, 0x10_FFFF, 0x11_0000]; + /// let cp_list = + /// CodePointInversionList::try_from_u32_inversion_list_slice(cp_slice).unwrap(); + /// let str_slice = &["", "bmp_max", "unicode_max", "zero"]; + /// let str_list = VarZeroVec::::from(str_slice); + /// + /// let cpilsl = CodePointInversionListAndStringList::try_from(cp_list, str_list).unwrap(); + /// + /// assert!(cpilsl.contains_str("bmp_max")); + /// assert!(cpilsl.contains_str("")); + /// assert!(cpilsl.contains_str("A")); + /// assert!(cpilsl.contains_str("ቔ")); // U+1254 ETHIOPIC SYLLABLE QHEE + /// assert!(!cpilsl.contains_str("bazinga!")); + /// ``` + pub fn contains_str(&self, s: &str) -> bool { + let mut chars = s.chars(); + if let Some(first_char) = chars.next() { + if chars.next().is_none() { + return self.contains(first_char); + } + } + self.str_list.binary_search(s).is_ok() + } + + /// + /// # Examples + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// use icu::collections::codepointinvliststringlist::CodePointInversionListAndStringList; + /// use zerovec::VarZeroVec; + /// + /// let cp_slice = &[0, 0x80, 0xFFFF, 0x1_0000, 0x10_FFFF, 0x11_0000]; + /// let cp_list = + /// CodePointInversionList::try_from_u32_inversion_list_slice(cp_slice).unwrap(); + /// let str_slice = &["", "ascii_max", "bmp_max", "unicode_max", "zero"]; + /// let str_list = VarZeroVec::::from(str_slice); + /// + /// let cpilsl = CodePointInversionListAndStringList::try_from(cp_list, str_list).unwrap(); + /// + /// assert!(cpilsl.contains32(0)); + /// assert!(cpilsl.contains32(0x0042)); + /// assert!(!cpilsl.contains32(0x0080)); + /// ``` + pub fn contains32(&self, cp: u32) -> bool { + self.cp_inv_list.contains32(cp) + } + + /// + /// # Examples + /// ``` + /// use icu::collections::codepointinvlist::CodePointInversionList; + /// use icu::collections::codepointinvliststringlist::CodePointInversionListAndStringList; + /// use zerovec::VarZeroVec; + /// + /// let cp_slice = &[0, 0x1_0000, 0x10_FFFF, 0x11_0000]; + /// let cp_list = + /// CodePointInversionList::try_from_u32_inversion_list_slice(cp_slice).unwrap(); + /// let str_slice = &["", "bmp_max", "unicode_max", "zero"]; + /// let str_list = VarZeroVec::::from(str_slice); + /// + /// let cpilsl = CodePointInversionListAndStringList::try_from(cp_list, str_list).unwrap(); + /// + /// assert!(cpilsl.contains('A')); + /// assert!(cpilsl.contains('ቔ')); // U+1254 ETHIOPIC SYLLABLE QHEE + /// assert!(!cpilsl.contains('\u{1_0000}')); + /// assert!(!cpilsl.contains('🨫')); // U+1FA2B NEUTRAL CHESS TURNED QUEEN + pub fn contains(&self, ch: char) -> bool { + self.contains32(ch as u32) + } + + /// Access the underlying [`CodePointInversionList`]. + pub fn code_points(&self) -> &CodePointInversionList<'data> { + &self.cp_inv_list + } + + /// Access the contained strings. + pub fn strings(&self) -> &VarZeroSlice { + &self.str_list + } +} + +#[cfg(feature = "alloc")] +impl<'a> FromIterator<&'a str> for CodePointInversionListAndStringList<'_> { + fn from_iter(it: I) -> Self + where + I: IntoIterator, + { + let mut builder = CodePointInversionListBuilder::new(); + let mut strings = Vec::<&str>::new(); + for s in it { + let mut chars = s.chars(); + if let Some(first_char) = chars.next() { + if chars.next().is_none() { + builder.add_char(first_char); + continue; + } + } + strings.push(s); + } + + // Ensure that the string list is sorted. If not, the binary search that + // is used for `.contains(&str)` will return garbage output. + strings.sort_unstable(); + strings.dedup(); + + let cp_inv_list = builder.build(); + let str_list = VarZeroVec::::from(&strings); + + CodePointInversionListAndStringList { + cp_inv_list, + str_list, + } + } +} + +/// Custom Errors for [`CodePointInversionListAndStringList`]. +#[derive(Display, Debug)] +pub enum InvalidStringList { + /// A string in the string list had an invalid length + #[cfg_attr(feature = "alloc", displaydoc("Invalid string length for string: {0}"))] + InvalidStringLength(#[cfg(feature = "alloc")] String), + /// A string in the string list appears more than once + #[cfg_attr(feature = "alloc", displaydoc("String list has duplicate: {0}"))] + StringListNotUnique(#[cfg(feature = "alloc")] String), + /// Two strings in the string list compare to each other opposite of sorted order + #[cfg_attr( + feature = "alloc", + displaydoc("Strings in string list not in sorted order: ({0}, {1})") + )] + StringListNotSorted( + #[cfg(feature = "alloc")] String, + #[cfg(feature = "alloc")] String, + ), +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_size_has_strings() { + let cp_slice = &[0, 1, 0x7F, 0x80, 0xFFFF, 0x1_0000, 0x10_FFFF, 0x11_0000]; + let cp_list = CodePointInversionList::try_from_u32_inversion_list_slice(cp_slice).unwrap(); + let str_slice = &["ascii_max", "bmp_max", "unicode_max", "zero"]; + let str_list = VarZeroVec::::from(str_slice); + + let cpilsl = CodePointInversionListAndStringList::try_from(cp_list, str_list).unwrap(); + + assert!(cpilsl.has_strings()); + assert_eq!(8, cpilsl.size()); + } + + #[test] + fn test_empty_string_allowed() { + let cp_slice = &[0, 1, 0x7F, 0x80, 0xFFFF, 0x1_0000, 0x10_FFFF, 0x11_0000]; + let cp_list = CodePointInversionList::try_from_u32_inversion_list_slice(cp_slice).unwrap(); + let str_slice = &["", "ascii_max", "bmp_max", "unicode_max", "zero"]; + let str_list = VarZeroVec::::from(str_slice); + + let cpilsl = CodePointInversionListAndStringList::try_from(cp_list, str_list).unwrap(); + + assert!(cpilsl.has_strings()); + assert_eq!(9, cpilsl.size()); + } + + #[test] + fn test_invalid_string() { + let cp_slice = &[0, 1]; + let cp_list = CodePointInversionList::try_from_u32_inversion_list_slice(cp_slice).unwrap(); + let str_slice = &["a"]; + let str_list = VarZeroVec::::from(str_slice); + + let cpilsl = CodePointInversionListAndStringList::try_from(cp_list, str_list); + + assert!(matches!( + cpilsl, + Err(InvalidStringList::InvalidStringLength(_)) + )); + } + + #[test] + fn test_invalid_string_list_has_duplicate() { + let cp_slice = &[0, 1]; + let cp_list = CodePointInversionList::try_from_u32_inversion_list_slice(cp_slice).unwrap(); + let str_slice = &["abc", "abc"]; + let str_list = VarZeroVec::::from(str_slice); + + let cpilsl = CodePointInversionListAndStringList::try_from(cp_list, str_list); + + assert!(matches!( + cpilsl, + Err(InvalidStringList::StringListNotUnique(_)) + )); + } + + #[test] + fn test_invalid_string_list_not_sorted() { + let cp_slice = &[0, 1]; + let cp_list = CodePointInversionList::try_from_u32_inversion_list_slice(cp_slice).unwrap(); + let str_slice = &["xyz", "abc"]; + let str_list = VarZeroVec::::from(str_slice); + + let cpilsl = CodePointInversionListAndStringList::try_from(cp_list, str_list); + + assert!(matches!( + cpilsl, + Err(InvalidStringList::StringListNotSorted(_, _)) + )); + } + + #[test] + fn test_from_iter_invariants() { + let in_strs_1 = ["a", "abc", "xyz", "abc"]; + let in_strs_2 = ["xyz", "abc", "a", "abc"]; + + let cpilsl_1 = CodePointInversionListAndStringList::from_iter(in_strs_1); + let cpilsl_2 = CodePointInversionListAndStringList::from_iter(in_strs_2); + + assert_eq!(cpilsl_1, cpilsl_2); + + assert!(cpilsl_1.has_strings()); + assert!(cpilsl_1.contains_str("abc")); + assert!(cpilsl_1.contains_str("xyz")); + assert!(!cpilsl_1.contains_str("def")); + + assert_eq!(1, cpilsl_1.cp_inv_list.size()); + assert!(cpilsl_1.contains('a')); + assert!(!cpilsl_1.contains('0')); + assert!(!cpilsl_1.contains('q')); + + assert_eq!(3, cpilsl_1.size()); + } +} diff --git a/deps/crates/vendor/icu_collections/src/codepointtrie/cptrie.rs b/deps/crates/vendor/icu_collections/src/codepointtrie/cptrie.rs new file mode 100644 index 00000000000000..8a79032afbecfd --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/codepointtrie/cptrie.rs @@ -0,0 +1,1345 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::codepointtrie::error::Error; +use crate::codepointtrie::impl_const::*; + +#[cfg(feature = "alloc")] +use crate::codepointinvlist::CodePointInversionList; +use core::char::CharTryFromError; +use core::convert::Infallible; +use core::convert::TryFrom; +use core::fmt::Display; +#[cfg(feature = "alloc")] +use core::iter::FromIterator; +use core::num::TryFromIntError; +use core::ops::RangeInclusive; +use yoke::Yokeable; +use zerofrom::ZeroFrom; +#[cfg(feature = "alloc")] +use zerovec::ule::UleError; +use zerovec::ZeroVec; + +/// The type of trie represents whether the trie has an optimization that +/// would make it smaller or faster. +/// +/// Regarding performance, a trie being a small or fast type affects the number of array lookups +/// needed for code points in the range `[0x1000, 0x10000)`. In this range, `Small` tries use 4 array lookups, +/// while `Fast` tries use 2 array lookups. +/// Code points before the interval (in `[0, 0x1000)`) will always use 2 array lookups. +/// Code points after the interval (in `[0x10000, 0x10FFFF]`) will always use 4 array lookups. +/// +/// Regarding size, `Fast` type tries are larger than `Small` type tries because the minimum size of +/// the index array is larger. The minimum size is the "fast max" limit, which is the limit of the range +/// of code points with 2 array lookups. +/// +/// See the document [Unicode Properties and Code Point Tries in ICU4X](https://github.com/unicode-org/icu4x/blob/main/documents/design/properties_code_point_trie.md). +/// +/// Also see [`UCPTrieType`](https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/ucptrie_8h.html) in ICU4C. +#[derive(Clone, Copy, PartialEq, Debug, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "databake", derive(databake::Bake))] +#[cfg_attr(feature = "databake", databake(path = icu_collections::codepointtrie))] +pub enum TrieType { + /// Represents the "fast" type code point tries for the + /// [`TrieType`] trait. The "fast max" limit is set to `0xffff`. + Fast = 0, + /// Represents the "small" type code point tries for the + /// [`TrieType`] trait. The "fast max" limit is set to `0x0fff`. + Small = 1, +} + +// TrieValue trait + +// AsULE is AsUnalignedLittleEndian, i.e. "allowed in a zerovec" + +/// A trait representing the values stored in the data array of a [`CodePointTrie`]. +/// This trait is used as a type parameter in constructing a `CodePointTrie`. +/// +/// This trait can be implemented on anything that can be represented as a u32s worth of data. +pub trait TrieValue: Copy + Eq + PartialEq + zerovec::ule::AsULE + 'static { + /// Last-resort fallback value to return if we cannot read data from the trie. + /// + /// In most cases, the error value is read from the last element of the `data` array, + /// this value is used for empty codepointtrie arrays + /// Error type when converting from a u32 to this `TrieValue`. + type TryFromU32Error: Display; + /// A parsing function that is primarily motivated by deserialization contexts. + /// When the serialization type width is smaller than 32 bits, then it is expected + /// that the call site will widen the value to a `u32` first. + fn try_from_u32(i: u32) -> Result; + + /// A method for converting back to a `u32` that can roundtrip through + /// [`Self::try_from_u32()`]. The default implementation of this trait + /// method panics in debug mode and returns 0 in release mode. + /// + /// This method is allowed to have GIGO behavior when fed a value that has + /// no corresponding `u32` (since such values cannot be stored in the trie) + fn to_u32(self) -> u32; +} + +macro_rules! impl_primitive_trie_value { + ($primitive:ty, $error:ty) => { + impl TrieValue for $primitive { + type TryFromU32Error = $error; + fn try_from_u32(i: u32) -> Result { + Self::try_from(i) + } + + fn to_u32(self) -> u32 { + // bitcast when the same size, zero-extend/sign-extend + // when not the same size + self as u32 + } + } + }; +} + +impl_primitive_trie_value!(u8, TryFromIntError); +impl_primitive_trie_value!(u16, TryFromIntError); +impl_primitive_trie_value!(u32, Infallible); +impl_primitive_trie_value!(i8, TryFromIntError); +impl_primitive_trie_value!(i16, TryFromIntError); +impl_primitive_trie_value!(i32, TryFromIntError); +impl_primitive_trie_value!(char, CharTryFromError); + +/// Helper function used by [`get_range`]. Converts occurrences of trie's null +/// value into the provided `null_value`. +/// +/// Note: the ICU version of this helper function uses a `ValueFilter` function +/// to apply a transform on a non-null value. But currently, this implementation +/// stops short of that functionality, and instead leaves the non-null trie value +/// untouched. This is equivalent to having a `ValueFilter` function that is the +/// identity function. +fn maybe_filter_value(value: T, trie_null_value: T, null_value: T) -> T { + if value == trie_null_value { + null_value + } else { + value + } +} + +/// This struct represents a de-serialized [`CodePointTrie`] that was exported from +/// ICU binary data. +/// +/// For more information: +/// - [ICU Site design doc](http://site.icu-project.org/design/struct/utrie) +/// - [ICU User Guide section on Properties lookup](https://unicode-org.github.io/icu/userguide/strings/properties.html#lookup) +// serde impls in crate::serde +#[derive(Debug, Eq, PartialEq, Yokeable, ZeroFrom)] +pub struct CodePointTrie<'trie, T: TrieValue> { + pub(crate) header: CodePointTrieHeader, + pub(crate) index: ZeroVec<'trie, u16>, + pub(crate) data: ZeroVec<'trie, T>, + // serde impl skips this field + #[zerofrom(clone)] // TrieValue is Copy, this allows us to avoid + // a T: ZeroFrom bound + pub(crate) error_value: T, +} + +/// This struct contains the fixed-length header fields of a [`CodePointTrie`]. +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "databake", derive(databake::Bake))] +#[cfg_attr(feature = "databake", databake(path = icu_collections::codepointtrie))] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Yokeable, ZeroFrom)] +pub struct CodePointTrieHeader { + /// The code point of the start of the last range of the trie. A + /// range is defined as a partition of the code point space such that the + /// value in this trie associated with all code points of the same range is + /// the same. + /// + /// For the property value data for many Unicode properties, + /// often times, `high_start` is `U+10000` or lower. In such cases, not + /// reserving space in the `index` array for duplicate values is a large + /// savings. The "highValue" associated with the `high_start` range is + /// stored at the second-to-last position of the `data` array. + /// (See `impl_const::HIGH_VALUE_NEG_DATA_OFFSET`.) + pub high_start: u32, + /// A version of the `high_start` value that is right-shifted 12 spaces, + /// but is rounded up to a multiple `0x1000` for easy testing from UTF-8 + /// lead bytes. + pub shifted12_high_start: u16, + /// Offset for the null block in the "index-3" table of the `index` array. + /// Set to an impossibly high value (e.g., `0xffff`) if there is no + /// dedicated index-3 null block. + pub index3_null_offset: u16, + /// Internal data null block offset, not shifted. + /// Set to an impossibly high value (e.g., `0xfffff`) if there is no + /// dedicated data null block. + pub data_null_offset: u32, + /// The value stored in the trie that represents a null value being + /// associated to a code point. + pub null_value: u32, + /// The enum value representing the type of trie, where trie type is as it + /// is defined in ICU (ex: Fast, Small). + pub trie_type: TrieType, +} + +impl TryFrom for TrieType { + type Error = crate::codepointtrie::error::Error; + + fn try_from(trie_type_int: u8) -> Result { + match trie_type_int { + 0 => Ok(TrieType::Fast), + 1 => Ok(TrieType::Small), + _ => Err(crate::codepointtrie::error::Error::FromDeserialized { + reason: "Cannot parse value for trie_type", + }), + } + } +} + +// Helper macro that turns arithmetic into wrapping-in-release, checked-in-debug arithmetic +// +// This is rustc's default behavior anyway, however some projects like Android deliberately +// enable overflow checks. CodePointTrie::get() is intended to be used in Android bionic which +// cares about codesize and we don't want the pile of panicking infrastructure brought in by overflow +// checks, so we force wrapping in release. +// See #6052 +macro_rules! w( + // Note: these matchers are not perfect since you cannot have an operator after an expr matcher + // Use variables if you need complex first operands. + ($a:tt + $b:expr) => { + { + #[allow(unused_parens)] + let a = $a; + let b = $b; + debug_assert!(a.checked_add(b).is_some()); + $a.wrapping_add($b) + } + }; + ($a:tt - $b:expr) => { + + { + #[allow(unused_parens)] + let a = $a; + let b = $b; + debug_assert!(a.checked_sub(b).is_some()); + $a.wrapping_sub($b) + } + }; + ($a:tt * $b:expr) => { + { + #[allow(unused_parens)] + let a = $a; + let b = $b; + debug_assert!(a.checked_mul(b).is_some()); + $a.wrapping_mul($b) + } + }; +); + +impl<'trie, T: TrieValue> CodePointTrie<'trie, T> { + #[doc(hidden)] // databake internal + pub const fn from_parts( + header: CodePointTrieHeader, + index: ZeroVec<'trie, u16>, + data: ZeroVec<'trie, T>, + error_value: T, + ) -> Self { + Self { + header, + index, + data, + error_value, + } + } + + /// Returns a new [`CodePointTrie`] backed by borrowed data for the `index` + /// array and `data` array, whose data values have width `W`. + pub fn try_new( + header: CodePointTrieHeader, + index: ZeroVec<'trie, u16>, + data: ZeroVec<'trie, T>, + ) -> Result, Error> { + // Validation invariants are not needed here when constructing a new + // `CodePointTrie` because: + // + // - Rust includes the size of a slice (or Vec or similar), which allows it + // to prevent lookups at out-of-bounds indices, whereas in C++, it is the + // programmer's responsibility to keep track of length info. + // - For lookups into collections, Rust guarantees that a fallback value will + // be returned in the case of `.get()` encountering a lookup error, via + // the `Option` type. + // - The `ZeroVec` serializer stores the length of the array along with the + // ZeroVec data, meaning that a deserializer would also see that length info. + + let error_value = data.last().ok_or(Error::EmptyDataVector)?; + let trie: CodePointTrie<'trie, T> = CodePointTrie { + header, + index, + data, + error_value, + }; + Ok(trie) + } + + /// Returns the position in the data array containing the trie's stored + /// error value. + #[inline(always)] // `always` based on normalizer benchmarking + fn trie_error_val_index(&self) -> u32 { + // We use wrapping_sub here to avoid panicky overflow checks. + // len should always be > 1, but if it isn't this will just cause GIGO behavior of producing + // None on `.get()` + debug_assert!(self.data.len() as u32 >= ERROR_VALUE_NEG_DATA_OFFSET); + w!((self.data.len() as u32) - ERROR_VALUE_NEG_DATA_OFFSET) + } + + fn internal_small_index(&self, code_point: u32) -> u32 { + // We use wrapping arithmetic here to avoid overflow checks making their way into binaries + // with overflow checks enabled. Ultimately this code ends up as a checked index, so any + // bugs here will cause GIGO + let mut index1_pos: u32 = code_point >> SHIFT_1; + if self.header.trie_type == TrieType::Fast { + debug_assert!( + FAST_TYPE_FAST_INDEXING_MAX < code_point && code_point < self.header.high_start + ); + index1_pos = w!(index1_pos + BMP_INDEX_LENGTH - OMITTED_BMP_INDEX_1_LENGTH); + } else { + assert!(code_point < self.header.high_start && self.header.high_start > SMALL_LIMIT); + index1_pos = w!(index1_pos + SMALL_INDEX_LENGTH); + } + let index1_val = if let Some(index1_val) = self.index.get(index1_pos as usize) { + index1_val + } else { + return self.trie_error_val_index(); + }; + let index3_block_idx: u32 = + w!((index1_val as u32) + (code_point >> SHIFT_2) & INDEX_2_MASK); + let mut index3_block: u32 = + if let Some(index3_block) = self.index.get(index3_block_idx as usize) { + index3_block as u32 + } else { + return self.trie_error_val_index(); + }; + let mut index3_pos: u32 = (code_point >> SHIFT_3) & INDEX_3_MASK; + let mut data_block: u32; + if index3_block & 0x8000 == 0 { + // 16-bit indexes + data_block = + if let Some(data_block) = self.index.get(w!(index3_block + index3_pos) as usize) { + data_block as u32 + } else { + return self.trie_error_val_index(); + }; + } else { + // 18-bit indexes stored in groups of 9 entries per 8 indexes. + index3_block = w!((index3_block & 0x7fff) + w!((index3_pos & !7) + index3_pos >> 3)); + index3_pos &= 7; + data_block = if let Some(data_block) = self.index.get(index3_block as usize) { + data_block as u32 + } else { + return self.trie_error_val_index(); + }; + data_block = (data_block << w!(2u32 + w!(2u32 * index3_pos))) & 0x30000; + index3_block += 1; + data_block = + if let Some(index3_val) = self.index.get(w!(index3_block + index3_pos) as usize) { + data_block | (index3_val as u32) + } else { + return self.trie_error_val_index(); + }; + } + // Returns data_pos == data_block (offset) + + // portion of code_point bit field for last (4th) lookup + w!(data_block + code_point & SMALL_DATA_MASK) + } + + /// Returns the position in the `data` array for the given code point, + /// where this code point is at or above the fast limit associated for the + /// `trie_type`. We will refer to that limit as "`fastMax`" here. + /// + /// A lookup of the value in the code point trie for a code point in the + /// code point space range [`fastMax`, `high_start`) will be a 4-step + /// lookup: 3 lookups in the `index` array and one lookup in the `data` + /// array. Lookups for code points in the range [`high_start`, + /// `CODE_POINT_MAX`] are short-circuited to be a single lookup, see + /// [`CodePointTrieHeader::high_start`]. + fn small_index(&self, code_point: u32) -> u32 { + if code_point >= self.header.high_start { + w!((self.data.len() as u32) - HIGH_VALUE_NEG_DATA_OFFSET) + } else { + self.internal_small_index(code_point) // helper fn + } + } + + /// Returns the position in the `data` array for the given code point, + /// where this code point is below the fast limit associated for the + /// `trie type`. We will refer to that limit as "`fastMax`" here. + /// + /// A lookup of the value in the code point trie for a code point in the + /// code point space range [0, `fastMax`) will be a 2-step lookup: 1 + /// lookup in the `index` array and one lookup in the `data` array. By + /// design, for trie type `T`, there is an element allocated in the `index` + /// array for each block of code points in [0, `fastMax`), which in + /// turn guarantees that those code points are represented and only need 1 + /// lookup. + #[inline(always)] // `always` based on normalizer benchmarking + fn fast_index(&self, code_point: u32) -> u32 { + let index_array_pos: u32 = code_point >> FAST_TYPE_SHIFT; + let index_array_val: u16 = + if let Some(index_array_val) = self.index.get(index_array_pos as usize) { + index_array_val + } else { + return self.trie_error_val_index(); + }; + let masked_cp = code_point & FAST_TYPE_DATA_MASK; + let index_array_val = index_array_val as u32; + let fast_index_val: u32 = w!(index_array_val + masked_cp); + fast_index_val + } + + /// Returns the value that is associated with `code_point` in this [`CodePointTrie`]. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointtrie::planes; + /// let trie = planes::get_planes_trie(); + /// + /// assert_eq!(0, trie.get32(0x41)); // 'A' as u32 + /// assert_eq!(0, trie.get32(0x13E0)); // 'Ꮰ' as u32 + /// assert_eq!(1, trie.get32(0x10044)); // '𐁄' as u32 + /// ``` + #[inline(always)] // `always` based on normalizer benchmarking + pub fn get32(&self, code_point: u32) -> T { + // If we cannot read from the data array, then return the sentinel value + // self.error_value() for the instance type for T: TrieValue. + self.get32_ule(code_point) + .map(|t| T::from_unaligned(*t)) + .unwrap_or(self.error_value) + } + + /// Returns the value that is associated with `char` in this [`CodePointTrie`]. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointtrie::planes; + /// let trie = planes::get_planes_trie(); + /// + /// assert_eq!(0, trie.get('A')); // 'A' as u32 + /// assert_eq!(0, trie.get('Ꮰ')); // 'Ꮰ' as u32 + /// assert_eq!(1, trie.get('𐁄')); // '𐁄' as u32 + /// ``` + #[inline(always)] + pub fn get(&self, c: char) -> T { + self.get32(u32::from(c)) + } + + /// Returns a reference to the ULE of the value that is associated with `code_point` in this [`CodePointTrie`]. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointtrie::planes; + /// let trie = planes::get_planes_trie(); + /// + /// assert_eq!(Some(&0), trie.get32_ule(0x41)); // 'A' as u32 + /// assert_eq!(Some(&0), trie.get32_ule(0x13E0)); // 'Ꮰ' as u32 + /// assert_eq!(Some(&1), trie.get32_ule(0x10044)); // '𐁄' as u32 + /// ``` + #[inline(always)] // `always` based on normalizer benchmarking + pub fn get32_ule(&self, code_point: u32) -> Option<&T::ULE> { + // All code points up to the fast max limit are represented + // individually in the `index` array to hold their `data` array position, and + // thus only need 2 lookups for a [CodePointTrie::get()](`crate::codepointtrie::CodePointTrie::get`). + // Code points above the "fast max" limit require 4 lookups. + let fast_max = match self.header.trie_type { + TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX, + TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX, + }; + let data_pos: u32 = if code_point <= fast_max { + Self::fast_index(self, code_point) + } else if code_point <= CODE_POINT_MAX { + Self::small_index(self, code_point) + } else { + self.trie_error_val_index() + }; + // Returns the trie value (or trie's error value). + self.data.as_ule_slice().get(data_pos as usize) + } + + /// Converts the [`CodePointTrie`] into one that returns another type of the same size. + /// + /// Borrowed data remains borrowed, and owned data remains owned. + /// + /// If the old and new types are not the same size, use + /// [`CodePointTrie::try_alloc_map_value`]. + /// + /// # Panics + /// + /// Panics if `T` and `P` are different sizes. + /// + /// More specifically, panics if [`ZeroVec::try_into_converted()`] panics when converting + /// `ZeroVec` into `ZeroVec

`, which happens if `T::ULE` and `P::ULE` differ in size. + /// + /// # Examples + /// + /// ```no_run + /// use icu::collections::codepointtrie::planes; + /// use icu::collections::codepointtrie::CodePointTrie; + /// + /// let planes_trie_u8: CodePointTrie = planes::get_planes_trie(); + /// let planes_trie_i8: CodePointTrie = + /// planes_trie_u8.try_into_converted().expect("infallible"); + /// + /// assert_eq!(planes_trie_i8.get32(0x30000), 3); + /// ``` + #[cfg(feature = "alloc")] + pub fn try_into_converted

(self) -> Result, UleError> + where + P: TrieValue, + { + let converted_data = self.data.try_into_converted()?; + let error_ule = self.error_value.to_unaligned(); + let slice = &[error_ule]; + let error_vec = ZeroVec::::new_borrowed(slice); + let error_converted = error_vec.try_into_converted::

()?; + #[allow(clippy::expect_used)] // we know this cannot fail + Ok(CodePointTrie { + header: self.header, + index: self.index, + data: converted_data, + error_value: error_converted + .get(0) + .expect("vector known to have one element"), + }) + } + + /// Maps the [`CodePointTrie`] into one that returns a different type. + /// + /// This function returns owned data. + /// + /// If the old and new types are the same size, use the more efficient + /// [`CodePointTrie::try_into_converted`]. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointtrie::planes; + /// use icu::collections::codepointtrie::CodePointTrie; + /// + /// let planes_trie_u8: CodePointTrie = planes::get_planes_trie(); + /// let planes_trie_u16: CodePointTrie = planes_trie_u8 + /// .try_alloc_map_value(TryFrom::try_from) + /// .expect("infallible"); + /// + /// assert_eq!(planes_trie_u16.get32(0x30000), 3); + /// ``` + #[cfg(feature = "alloc")] + pub fn try_alloc_map_value( + &self, + mut f: impl FnMut(T) -> Result, + ) -> Result, E> + where + P: TrieValue, + { + let error_converted = f(self.error_value)?; + let converted_data = self.data.iter().map(f).collect::, E>>()?; + Ok(CodePointTrie { + header: self.header, + index: self.index.clone(), + data: converted_data, + error_value: error_converted, + }) + } + + /// Returns a [`CodePointMapRange`] struct which represents a range of code + /// points associated with the same trie value. The returned range will be + /// the longest stretch of consecutive code points starting at `start` that + /// share this value. + /// + /// This method is designed to use the internal details of + /// the structure of [`CodePointTrie`] to be optimally efficient. This will + /// outperform a naive approach that just uses [`CodePointTrie::get()`]. + /// + /// This method provides lower-level functionality that can be used in the + /// implementation of other methods that are more convenient to the user. + /// To obtain an optimal partition of the code point space for + /// this trie resulting in the fewest number of ranges, see + /// [`CodePointTrie::iter_ranges()`]. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointtrie::planes; + /// + /// let trie = planes::get_planes_trie(); + /// + /// const CODE_POINT_MAX: u32 = 0x10ffff; + /// let start = 0x1_0000; + /// let exp_end = 0x1_ffff; + /// + /// let start_val = trie.get32(start); + /// assert_eq!(trie.get32(exp_end), start_val); + /// assert_ne!(trie.get32(exp_end + 1), start_val); + /// + /// use icu::collections::codepointtrie::CodePointMapRange; + /// + /// let cpm_range: CodePointMapRange = trie.get_range(start).unwrap(); + /// + /// assert_eq!(cpm_range.range.start(), &start); + /// assert_eq!(cpm_range.range.end(), &exp_end); + /// assert_eq!(cpm_range.value, start_val); + /// + /// // `start` can be any code point, whether or not it lies on the boundary + /// // of a maximally large range that still contains `start` + /// + /// let submaximal_1_start = start + 0x1234; + /// let submaximal_1 = trie.get_range(submaximal_1_start).unwrap(); + /// assert_eq!(submaximal_1.range.start(), &0x1_1234); + /// assert_eq!(submaximal_1.range.end(), &0x1_ffff); + /// assert_eq!(submaximal_1.value, start_val); + /// + /// let submaximal_2_start = start + 0xffff; + /// let submaximal_2 = trie.get_range(submaximal_2_start).unwrap(); + /// assert_eq!(submaximal_2.range.start(), &0x1_ffff); + /// assert_eq!(submaximal_2.range.end(), &0x1_ffff); + /// assert_eq!(submaximal_2.value, start_val); + /// ``` + pub fn get_range(&self, start: u32) -> Option> { + // Exit early if the start code point is out of range, or if it is + // in the last range of code points in high_start..=CODE_POINT_MAX + // (start- and end-inclusive) that all share the same trie value. + if CODE_POINT_MAX < start { + return None; + } + if start >= self.header.high_start { + let di: usize = self.data.len() - (HIGH_VALUE_NEG_DATA_OFFSET as usize); + let value: T = self.data.get(di)?; + return Some(CodePointMapRange { + range: start..=CODE_POINT_MAX, + value, + }); + } + + let null_value: T = T::try_from_u32(self.header.null_value).ok()?; + + let mut prev_i3_block: u32 = u32::MAX; // using u32::MAX (instead of -1 as an i32 in ICU) + let mut prev_block: u32 = u32::MAX; // using u32::MAX (instead of -1 as an i32 in ICU) + let mut c: u32 = start; + let mut trie_value: T = self.error_value(); + let mut value: T = self.error_value(); + let mut have_value: bool = false; + + loop { + let i3_block: u32; + let mut i3: u32; + let i3_block_length: u32; + let data_block_length: u32; + + // Initialize values before beginning the iteration in the subsequent + // `loop` block. In particular, use the "i3*" local variables + // (representing the `index` array position's offset + increment + // for a 3rd-level trie lookup) to help initialize the data block + // variable `block` in the loop for the `data` array. + // + // When a lookup code point is <= the trie's *_FAST_INDEXING_MAX that + // corresponds to its `trie_type`, the lookup only takes 2 steps + // (once into the `index`, once into the `data` array); otherwise, + // takes 4 steps (3 iterative lookups into the `index`, once more + // into the `data` array). So for convenience's sake, when we have the + // 2-stage lookup, reuse the "i3*" variable names for the first lookup. + if c <= 0xffff + && (self.header.trie_type == TrieType::Fast || c <= SMALL_TYPE_FAST_INDEXING_MAX) + { + i3_block = 0; + i3 = c >> FAST_TYPE_SHIFT; + i3_block_length = if self.header.trie_type == TrieType::Fast { + BMP_INDEX_LENGTH + } else { + SMALL_INDEX_LENGTH + }; + data_block_length = FAST_TYPE_DATA_BLOCK_LENGTH; + } else { + // Use the multi-stage index. + let mut i1: u32 = c >> SHIFT_1; + if self.header.trie_type == TrieType::Fast { + debug_assert!(0xffff < c && c < self.header.high_start); + i1 = i1 + BMP_INDEX_LENGTH - OMITTED_BMP_INDEX_1_LENGTH; + } else { + debug_assert!( + c < self.header.high_start && self.header.high_start > SMALL_LIMIT + ); + i1 += SMALL_INDEX_LENGTH; + } + let i2: u16 = self.index.get(i1 as usize)?; + let i3_block_idx: u32 = (i2 as u32) + ((c >> SHIFT_2) & INDEX_2_MASK); + i3_block = if let Some(i3b) = self.index.get(i3_block_idx as usize) { + i3b as u32 + } else { + return None; + }; + if i3_block == prev_i3_block && (c - start) >= CP_PER_INDEX_2_ENTRY { + // The index-3 block is the same as the previous one, and filled with value. + debug_assert!((c & (CP_PER_INDEX_2_ENTRY - 1)) == 0); + c += CP_PER_INDEX_2_ENTRY; + + if c >= self.header.high_start { + break; + } else { + continue; + } + } + prev_i3_block = i3_block; + if i3_block == self.header.index3_null_offset as u32 { + // This is the index-3 null block. + // All of the `data` array blocks pointed to by the values + // in this block of the `index` 3rd-stage subarray will + // contain this trie's null_value. So if we are in the middle + // of a range, end it and return early, otherwise start a new + // range of null values. + if have_value { + if null_value != value { + return Some(CodePointMapRange { + range: start..=(c - 1), + value, + }); + } + } else { + trie_value = T::try_from_u32(self.header.null_value).ok()?; + value = null_value; + have_value = true; + } + prev_block = self.header.data_null_offset; + c = (c + CP_PER_INDEX_2_ENTRY) & !(CP_PER_INDEX_2_ENTRY - 1); + + if c >= self.header.high_start { + break; + } else { + continue; + } + } + i3 = (c >> SHIFT_3) & INDEX_3_MASK; + i3_block_length = INDEX_3_BLOCK_LENGTH; + data_block_length = SMALL_DATA_BLOCK_LENGTH; + } + + // Enumerate data blocks for one index-3 block. + loop { + let mut block: u32; + if (i3_block & 0x8000) == 0 { + block = if let Some(b) = self.index.get((i3_block + i3) as usize) { + b as u32 + } else { + return None; + }; + } else { + // 18-bit indexes stored in groups of 9 entries per 8 indexes. + let mut group: u32 = (i3_block & 0x7fff) + (i3 & !7) + (i3 >> 3); + let gi: u32 = i3 & 7; + let gi_val: u32 = if let Some(giv) = self.index.get(group as usize) { + giv.into() + } else { + return None; + }; + block = (gi_val << (2 + (2 * gi))) & 0x30000; + group += 1; + let ggi_val: u32 = if let Some(ggiv) = self.index.get((group + gi) as usize) { + ggiv as u32 + } else { + return None; + }; + block |= ggi_val; + } + + // If our previous and current return values of the 3rd-stage `index` + // lookup yield the same `data` block offset, and if we already know that + // the entire `data` block / subarray starting at that offset stores + // `value` and nothing else, then we can extend our range by the length + // of a data block and continue. + // Otherwise, we have to iterate over the values stored in the + // new data block to see if they differ from `value`. + if block == prev_block && (c - start) >= data_block_length { + // The block is the same as the previous one, and filled with value. + debug_assert!((c & (data_block_length - 1)) == 0); + c += data_block_length; + } else { + let data_mask: u32 = data_block_length - 1; + prev_block = block; + if block == self.header.data_null_offset { + // This is the data null block. + // If we are in the middle of a range, end it and + // return early, otherwise start a new range of null + // values. + if have_value { + if null_value != value { + return Some(CodePointMapRange { + range: start..=(c - 1), + value, + }); + } + } else { + trie_value = T::try_from_u32(self.header.null_value).ok()?; + value = null_value; + have_value = true; + } + c = (c + data_block_length) & !data_mask; + } else { + let mut di: u32 = block + (c & data_mask); + let mut trie_value_2: T = self.data.get(di as usize)?; + if have_value { + if trie_value_2 != trie_value { + if maybe_filter_value( + trie_value_2, + T::try_from_u32(self.header.null_value).ok()?, + null_value, + ) != value + { + return Some(CodePointMapRange { + range: start..=(c - 1), + value, + }); + } + // `trie_value` stores the previous value that was retrieved + // from the trie. + // `value` stores the value associated for the range (return + // value) that we are currently building, which is computed + // as a transformation by applying maybe_filter_value() + // to the trie value. + // The current trie value `trie_value_2` within this data block + // differs here from the previous value in `trie_value`. + // But both map to `value` after applying `maybe_filter_value`. + // It is not clear whether the previous or the current trie value + // (or neither) is more likely to match potential subsequent trie + // values that would extend the range by mapping to `value`. + // On the assumption of locality -- often times consecutive + // characters map to the same trie values -- remembering the new + // one might make it faster to extend this range further + // (by increasing the chance that the next `trie_value_2 != + // trie_value` test will be false). + trie_value = trie_value_2; // may or may not help + } + } else { + trie_value = trie_value_2; + value = maybe_filter_value( + trie_value_2, + T::try_from_u32(self.header.null_value).ok()?, + null_value, + ); + have_value = true; + } + + c += 1; + while (c & data_mask) != 0 { + di += 1; + trie_value_2 = self.data.get(di as usize)?; + if trie_value_2 != trie_value { + if maybe_filter_value( + trie_value_2, + T::try_from_u32(self.header.null_value).ok()?, + null_value, + ) != value + { + return Some(CodePointMapRange { + range: start..=(c - 1), + value, + }); + } + // `trie_value` stores the previous value that was retrieved + // from the trie. + // `value` stores the value associated for the range (return + // value) that we are currently building, which is computed + // as a transformation by applying maybe_filter_value() + // to the trie value. + // The current trie value `trie_value_2` within this data block + // differs here from the previous value in `trie_value`. + // But both map to `value` after applying `maybe_filter_value`. + // It is not clear whether the previous or the current trie value + // (or neither) is more likely to match potential subsequent trie + // values that would extend the range by mapping to `value`. + // On the assumption of locality -- often times consecutive + // characters map to the same trie values -- remembering the new + // one might make it faster to extend this range further + // (by increasing the chance that the next `trie_value_2 != + // trie_value` test will be false). + trie_value = trie_value_2; // may or may not help + } + + c += 1; + } + } + } + + i3 += 1; + if i3 >= i3_block_length { + break; + } + } + + if c >= self.header.high_start { + break; + } + } + + debug_assert!(have_value); + + // Now that c >= high_start, compare `value` to `high_value` to see + // if we can merge our current range with the high_value range + // high_start..=CODE_POINT_MAX (start- and end-inclusive), otherwise + // stop at high_start - 1. + let di: u32 = self.data.len() as u32 - HIGH_VALUE_NEG_DATA_OFFSET; + let high_value: T = self.data.get(di as usize)?; + if maybe_filter_value( + high_value, + T::try_from_u32(self.header.null_value).ok()?, + null_value, + ) != value + { + c -= 1; + } else { + c = CODE_POINT_MAX; + } + Some(CodePointMapRange { + range: start..=c, + value, + }) + } + + /// Yields an [`Iterator`] returning ranges of consecutive code points that + /// share the same value in the [`CodePointTrie`], as given by + /// [`CodePointTrie::get_range()`]. + /// + /// # Examples + /// + /// ``` + /// use core::ops::RangeInclusive; + /// use icu::collections::codepointtrie::planes; + /// use icu::collections::codepointtrie::CodePointMapRange; + /// + /// let planes_trie = planes::get_planes_trie(); + /// + /// let mut ranges = planes_trie.iter_ranges(); + /// + /// for plane in 0..=16 { + /// let exp_start = plane * 0x1_0000; + /// let exp_end = exp_start + 0xffff; + /// assert_eq!( + /// ranges.next(), + /// Some(CodePointMapRange { + /// range: exp_start..=exp_end, + /// value: plane as u8 + /// }) + /// ); + /// } + /// + /// // Hitting the end of the iterator returns `None`, as will subsequent + /// // calls to .next(). + /// assert_eq!(ranges.next(), None); + /// assert_eq!(ranges.next(), None); + /// ``` + pub fn iter_ranges(&self) -> CodePointMapRangeIterator { + let init_range = Some(CodePointMapRange { + range: u32::MAX..=u32::MAX, + value: self.error_value(), + }); + CodePointMapRangeIterator:: { + cpt: self, + cpm_range: init_range, + } + } + + /// Yields an [`Iterator`] returning the ranges of the code points whose values + /// match `value` in the [`CodePointTrie`]. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointtrie::planes; + /// + /// let trie = planes::get_planes_trie(); + /// + /// let plane_val = 2; + /// let mut sip_range_iter = trie.iter_ranges_for_value(plane_val as u8); + /// + /// let start = plane_val * 0x1_0000; + /// let end = start + 0xffff; + /// + /// let sip_range = sip_range_iter.next() + /// .expect("Plane 2 (SIP) should exist in planes data"); + /// assert_eq!(start..=end, sip_range); + /// + /// assert!(sip_range_iter.next().is_none()); + pub fn iter_ranges_for_value( + &self, + value: T, + ) -> impl Iterator> + '_ { + self.iter_ranges() + .filter(move |cpm_range| cpm_range.value == value) + .map(|cpm_range| cpm_range.range) + } + + /// Yields an [`Iterator`] returning the ranges of the code points after passing + /// the value through a mapping function. + /// + /// This is preferable to calling `.get_ranges().map()` since it will coalesce + /// adjacent ranges into one. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointtrie::planes; + /// + /// let trie = planes::get_planes_trie(); + /// + /// let plane_val = 2; + /// let mut sip_range_iter = trie.iter_ranges_mapped(|value| value != plane_val as u8).filter(|range| range.value); + /// + /// let end = plane_val * 0x1_0000 - 1; + /// + /// let sip_range = sip_range_iter.next() + /// .expect("Complemented planes data should have at least one entry"); + /// assert_eq!(0..=end, sip_range.range); + pub fn iter_ranges_mapped<'a, U: Eq + 'a>( + &'a self, + mut map: impl FnMut(T) -> U + Copy + 'a, + ) -> impl Iterator> + 'a { + crate::iterator_utils::RangeListIteratorCoalescer::new(self.iter_ranges().map( + move |range| CodePointMapRange { + range: range.range, + value: map(range.value), + }, + )) + } + + /// Returns a [`CodePointInversionList`] for the code points that have the given + /// [`TrieValue`] in the trie. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointtrie::planes; + /// + /// let trie = planes::get_planes_trie(); + /// + /// let plane_val = 2; + /// let sip = trie.get_set_for_value(plane_val as u8); + /// + /// let start = plane_val * 0x1_0000; + /// let end = start + 0xffff; + /// + /// assert!(!sip.contains32(start - 1)); + /// assert!(sip.contains32(start)); + /// assert!(sip.contains32(end)); + /// assert!(!sip.contains32(end + 1)); + /// ``` + #[cfg(feature = "alloc")] + pub fn get_set_for_value(&self, value: T) -> CodePointInversionList<'static> { + let value_ranges = self.iter_ranges_for_value(value); + CodePointInversionList::from_iter(value_ranges) + } + + /// Returns the value used as an error value for this trie + #[inline] + pub fn error_value(&self) -> T { + self.error_value + } +} + +#[cfg(feature = "databake")] +impl databake::Bake for CodePointTrie<'_, T> { + fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream { + let header = self.header.bake(env); + let index = self.index.bake(env); + let data = self.data.bake(env); + let error_value = self.error_value.bake(env); + databake::quote! { icu_collections::codepointtrie::CodePointTrie::from_parts(#header, #index, #data, #error_value) } + } +} + +#[cfg(feature = "databake")] +impl databake::BakeSize for CodePointTrie<'_, T> { + fn borrows_size(&self) -> usize { + self.header.borrows_size() + self.index.borrows_size() + self.data.borrows_size() + } +} + +impl> CodePointTrie<'_, T> { + /// Returns the value that is associated with `code_point` for this [`CodePointTrie`] + /// as a `u32`. + /// + /// # Examples + /// + /// ``` + /// use icu::collections::codepointtrie::planes; + /// let trie = planes::get_planes_trie(); + /// + /// let cp = '𑖎' as u32; + /// assert_eq!(cp, 0x1158E); + /// + /// let plane_num: u8 = trie.get32(cp); + /// assert_eq!(trie.get32_u32(cp), plane_num as u32); + /// ``` + // Note: This API method maintains consistency with the corresponding + // original ICU APIs. + pub fn get32_u32(&self, code_point: u32) -> u32 { + self.get32(code_point).into() + } +} + +impl Clone for CodePointTrie<'_, T> +where + ::ULE: Clone, +{ + fn clone(&self) -> Self { + CodePointTrie { + header: self.header, + index: self.index.clone(), + data: self.data.clone(), + error_value: self.error_value, + } + } +} + +/// Represents a range of consecutive code points sharing the same value in a +/// code point map. +/// +/// The start and end of the interval is represented as a +/// `RangeInclusive`, and the value is represented as `T`. +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct CodePointMapRange { + /// Range of code points from start to end (inclusive). + pub range: RangeInclusive, + /// Trie value associated with this range. + pub value: T, +} + +/// A custom [`Iterator`] type specifically for a code point trie that returns +/// [`CodePointMapRange`]s. +pub struct CodePointMapRangeIterator<'a, T: TrieValue> { + cpt: &'a CodePointTrie<'a, T>, + // Initialize `range` to Some(CodePointMapRange{ start: u32::MAX, end: u32::MAX, value: 0}). + // When `range` is Some(...) and has a start value different from u32::MAX, then we have + // returned at least one code point range due to a call to `next()`. + // When `range` == `None`, it means that we have hit the end of iteration. It would occur + // after a call to `next()` returns a None <=> we attempted to call `get_range()` + // with a start code point that is > CODE_POINT_MAX. + cpm_range: Option>, +} + +impl Iterator for CodePointMapRangeIterator<'_, T> { + type Item = CodePointMapRange; + + fn next(&mut self) -> Option { + self.cpm_range = match &self.cpm_range { + Some(cpmr) => { + if *cpmr.range.start() == u32::MAX { + self.cpt.get_range(0) + } else { + self.cpt.get_range(cpmr.range.end() + 1) + } + } + None => None, + }; + // Note: Clone is cheap. We can't Copy because RangeInclusive does not impl Copy. + self.cpm_range.clone() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::codepointtrie::planes; + use alloc::vec::Vec; + + #[test] + #[cfg(feature = "serde")] + fn test_serde_with_postcard_roundtrip() -> Result<(), postcard::Error> { + let trie = crate::codepointtrie::planes::get_planes_trie(); + let trie_serialized: Vec = postcard::to_allocvec(&trie).unwrap(); + + // Assert an expected (golden data) version of the serialized trie. + const EXP_TRIE_SERIALIZED: &[u8] = &[ + 128, 128, 64, 128, 2, 2, 0, 0, 1, 160, 18, 0, 0, 64, 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, 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, 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, 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, 136, + 2, 144, 2, 144, 2, 144, 2, 176, 2, 176, 2, 176, 2, 176, 2, 208, 2, 208, 2, 208, 2, 208, + 2, 240, 2, 240, 2, 240, 2, 240, 2, 16, 3, 16, 3, 16, 3, 16, 3, 48, 3, 48, 3, 48, 3, 48, + 3, 80, 3, 80, 3, 80, 3, 80, 3, 112, 3, 112, 3, 112, 3, 112, 3, 144, 3, 144, 3, 144, 3, + 144, 3, 176, 3, 176, 3, 176, 3, 176, 3, 208, 3, 208, 3, 208, 3, 208, 3, 240, 3, 240, 3, + 240, 3, 240, 3, 16, 4, 16, 4, 16, 4, 16, 4, 48, 4, 48, 4, 48, 4, 48, 4, 80, 4, 80, 4, + 80, 4, 80, 4, 112, 4, 112, 4, 112, 4, 112, 4, 0, 0, 16, 0, 32, 0, 48, 0, 64, 0, 80, 0, + 96, 0, 112, 0, 0, 0, 16, 0, 32, 0, 48, 0, 0, 0, 16, 0, 32, 0, 48, 0, 0, 0, 16, 0, 32, + 0, 48, 0, 0, 0, 16, 0, 32, 0, 48, 0, 0, 0, 16, 0, 32, 0, 48, 0, 0, 0, 16, 0, 32, 0, 48, + 0, 0, 0, 16, 0, 32, 0, 48, 0, 0, 0, 16, 0, 32, 0, 48, 0, 128, 0, 128, 0, 128, 0, 128, + 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, + 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, + 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, + 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, + 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, + 0, 144, 0, 144, 0, 144, 0, 144, 0, 144, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, + 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, + 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, 0, 160, + 0, 160, 0, 160, 0, 160, 0, 160, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, + 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, + 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, 0, 176, + 0, 176, 0, 176, 0, 176, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, + 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, + 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, 0, 192, + 0, 192, 0, 192, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, + 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, + 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, 0, 208, + 0, 208, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, + 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, + 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, 0, 224, + 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, + 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, + 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 240, 0, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, + 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, + 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 32, 1, 32, 1, 32, 1, + 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, + 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, + 32, 1, 32, 1, 32, 1, 32, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, + 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, + 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 64, 1, 64, + 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, + 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, + 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, + 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, + 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, + 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, + 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, + 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 128, 0, 136, 0, 136, 0, 136, 0, 136, + 0, 136, 0, 136, 0, 136, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, + 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, + 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, + 168, 0, 168, 0, 168, 0, 168, 0, 168, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, + 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, + 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, + 200, 0, 200, 0, 200, 0, 200, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, + 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, + 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, 232, 0, + 232, 0, 232, 0, 232, 0, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, + 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, + 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, + 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, + 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, + 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, + 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, + 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 104, 1, 104, 1, 104, 1, 104, 1, + 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, + 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, + 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 104, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, + 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, + 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, + 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, + 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, + 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, + 168, 1, 168, 1, 168, 1, 168, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, + 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, + 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, 200, 1, + 200, 1, 200, 1, 200, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, + 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, + 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, 232, 1, + 232, 1, 232, 1, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, + 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, + 2, 8, 2, 8, 2, 8, 2, 8, 2, 8, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, + 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, + 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 40, 2, 72, + 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, + 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, + 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 72, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, + 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, + 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, + 104, 2, 104, 2, 104, 2, 104, 2, 104, 2, 244, 2, 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, 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, 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, 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, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 0, + ]; + assert_eq!(trie_serialized, EXP_TRIE_SERIALIZED); + + let trie_deserialized = postcard::from_bytes::>(&trie_serialized)?; + + assert_eq!(&trie.index, &trie_deserialized.index); + assert_eq!(&trie.data, &trie_deserialized.data); + + assert!(!trie_deserialized.index.is_owned()); + assert!(!trie_deserialized.data.is_owned()); + + Ok(()) + } + + #[test] + fn test_get_range() { + let planes_trie = planes::get_planes_trie(); + + let first_range: Option> = planes_trie.get_range(0x0); + assert_eq!( + first_range, + Some(CodePointMapRange { + range: 0x0..=0xffff, + value: 0 + }) + ); + + let second_range: Option> = planes_trie.get_range(0x1_0000); + assert_eq!( + second_range, + Some(CodePointMapRange { + range: 0x10000..=0x1ffff, + value: 1 + }) + ); + + let penultimate_range: Option> = planes_trie.get_range(0xf_0000); + assert_eq!( + penultimate_range, + Some(CodePointMapRange { + range: 0xf_0000..=0xf_ffff, + value: 15 + }) + ); + + let last_range: Option> = planes_trie.get_range(0x10_0000); + assert_eq!( + last_range, + Some(CodePointMapRange { + range: 0x10_0000..=0x10_ffff, + value: 16 + }) + ); + } + + #[test] + fn databake() { + databake::test_bake!( + CodePointTrie<'static, u32>, + const, + crate::codepointtrie::CodePointTrie::from_parts( + crate::codepointtrie::CodePointTrieHeader { + high_start: 1u32, + shifted12_high_start: 2u16, + index3_null_offset: 3u16, + data_null_offset: 4u32, + null_value: 5u32, + trie_type: crate::codepointtrie::TrieType::Small, + }, + zerovec::ZeroVec::new(), + zerovec::ZeroVec::new(), + 0u32, + ), + icu_collections, + [zerovec], + ); + } +} diff --git a/deps/crates/vendor/icu_collections/src/codepointtrie/error.rs b/deps/crates/vendor/icu_collections/src/codepointtrie/error.rs new file mode 100644 index 00000000000000..4cd157fc3f2762 --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/codepointtrie/error.rs @@ -0,0 +1,24 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! Custom error type(s) for the parent module. + +use displaydoc::Display; + +/// A custom error type for [`CodePointTrie`](super::CodePointTrie). +#[derive(Copy, Clone, Display, Debug, PartialEq)] +#[non_exhaustive] +pub enum Error { + /// Could not construct [`CodePointTrie`](super::CodePointTrie) from deserialized values + #[displaydoc("Could not construct CodePointTrie from deserialized values: {reason}")] + FromDeserialized { + /// Reason for inability to deserialize values. + reason: &'static str, + }, + /// [`CodePointTrie`](super::CodePointTrie) must be constructed from data vector with at least one element + #[displaydoc("CodePointTrie must be constructed from data vector with at least one element")] + EmptyDataVector, +} + +impl core::error::Error for Error {} diff --git a/deps/crates/vendor/icu_collections/src/codepointtrie/impl_const.rs b/deps/crates/vendor/icu_collections/src/codepointtrie/impl_const.rs new file mode 100644 index 00000000000000..61e4f2746dedac --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/codepointtrie/impl_const.rs @@ -0,0 +1,76 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +pub const FAST_TYPE_SHIFT: i32 = 6; + +/// Number of entries in a data block for code points below the fast limit. 64=0x40 +pub const FAST_TYPE_DATA_BLOCK_LENGTH: u32 = 1 << FAST_TYPE_SHIFT; + +/// Mask for getting the lower bits for the in-fast-data-block offset. +pub const FAST_TYPE_DATA_MASK: u32 = FAST_TYPE_DATA_BLOCK_LENGTH - 1; + +/// Fast indexing limit for "fast"-type trie +pub const FAST_TYPE_FAST_INDEXING_MAX: u32 = 0xffff; + +/// Fast indexing limit for "small"-type trie +pub const SMALL_TYPE_FAST_INDEXING_MAX: u32 = 0xfff; + +/// Offset from dataLength (to be subtracted) for fetching the +/// value returned for out-of-range code points and ill-formed UTF-8/16. +pub const ERROR_VALUE_NEG_DATA_OFFSET: u32 = 1; + +/// Offset from dataLength (to be subtracted) for fetching the +/// value returned for code points highStart..U+10FFFF. +pub const HIGH_VALUE_NEG_DATA_OFFSET: u32 = 2; + +/// The length of the BMP index table. 1024=0x400 +pub const BMP_INDEX_LENGTH: u32 = 0x10000 >> FAST_TYPE_SHIFT; + +pub const SMALL_LIMIT: u32 = 0x1000; + +pub const SMALL_INDEX_LENGTH: u32 = SMALL_LIMIT >> FAST_TYPE_SHIFT; + +/// Shift size for getting the index-3 table offset. +pub const SHIFT_3: u32 = 4; + +/// Shift size for getting the index-2 table offset. +pub const SHIFT_2: u32 = 5 + SHIFT_3; + +/// Shift size for getting the index-1 table offset. +pub const SHIFT_1: u32 = 5 + SHIFT_2; + +/// Difference between two shift sizes, +/// for getting an index-2 offset from an index-3 offset. 5=9-4 +pub const SHIFT_2_3: u32 = SHIFT_2 - SHIFT_3; + +/// Difference between two shift sizes, +/// for getting an index-1 offset from an index-2 offset. 5=14-9 +pub const SHIFT_1_2: u32 = SHIFT_1 - SHIFT_2; + +/// Number of index-1 entries for the BMP. (4) +/// This part of the index-1 table is omitted from the serialized form. +pub const OMITTED_BMP_INDEX_1_LENGTH: u32 = 0x10000 >> SHIFT_1; + +/// Number of entries in an index-2 block. 32=0x20 +pub const INDEX_2_BLOCK_LENGTH: u32 = 1 << SHIFT_1_2; + +/// Mask for getting the lower bits for the in-index-2-block offset. +pub const INDEX_2_MASK: u32 = INDEX_2_BLOCK_LENGTH - 1; + +/// Number of code points per index-2 table entry. 512=0x200 +pub const CP_PER_INDEX_2_ENTRY: u32 = 1 << SHIFT_2; + +/// Number of entries in an index-3 block. 32=0x20 +pub const INDEX_3_BLOCK_LENGTH: u32 = 1 << SHIFT_2_3; + +/// Mask for getting the lower bits for the in-index-3-block offset. +pub const INDEX_3_MASK: u32 = INDEX_3_BLOCK_LENGTH - 1; + +/// Number of entries in a small data block. 16=0x10 +pub const SMALL_DATA_BLOCK_LENGTH: u32 = 1 << SHIFT_3; + +/// Mask for getting the lower bits for the in-small-data-block offset. +pub const SMALL_DATA_MASK: u32 = SMALL_DATA_BLOCK_LENGTH - 1; + +pub const CODE_POINT_MAX: u32 = 0x10ffff; diff --git a/deps/crates/vendor/icu_collections/src/codepointtrie/mod.rs b/deps/crates/vendor/icu_collections/src/codepointtrie/mod.rs new file mode 100644 index 00000000000000..970eab4fbfd570 --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/codepointtrie/mod.rs @@ -0,0 +1,51 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module provides a data structure for an time-efficient lookup of values +//! associated to code points. +//! +//! It is an implementation of the existing [ICU4C UCPTrie](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/ucptrie_8h.html) +//! / [ICU4J CodePointTrie](https://unicode-org.github.io/icu-docs/apidoc/dev/icu4j/) API. +//! +//! # Architecture +//! +//! ICU4X [`CodePointTrie`] is designed to provide a read-only view of [`CodePointTrie`] data that is exported +//! from ICU4C. Detailed information about the design of the data structure can be found in the documentation +//! for the [`CodePointTrie`] struct. +//! +//! # Examples +//! +//! ## Querying a `CodePointTrie` +//! +//! ``` +//! use icu::collections::codepointtrie::planes; +//! let trie = planes::get_planes_trie(); +//! +//! assert_eq!(0, trie.get32(0x41)); // 'A' as u32 +//! assert_eq!(0, trie.get32(0x13E0)); // 'Ꮰ' as u32 +//! assert_eq!(1, trie.get32(0x10044)); // '𐁄' as u32 +//! ``` +//! +//! [`ICU4X`]: ../icu/index.html + +extern crate alloc; + +mod cptrie; +mod error; +mod impl_const; +pub mod planes; + +#[cfg(feature = "serde")] +pub mod toml; + +#[cfg(feature = "serde")] +mod serde; + +pub use cptrie::CodePointMapRange; +pub use cptrie::CodePointMapRangeIterator; +pub use cptrie::CodePointTrie; +pub use cptrie::CodePointTrieHeader; +pub use cptrie::TrieType; +pub use cptrie::TrieValue; +pub use error::Error as CodePointTrieError; diff --git a/deps/crates/vendor/icu_collections/src/codepointtrie/planes.rs b/deps/crates/vendor/icu_collections/src/codepointtrie/planes.rs new file mode 100644 index 00000000000000..70ab1629d8b731 --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/codepointtrie/planes.rs @@ -0,0 +1,296 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! Sample data for [`CodePointTrie`] that returns the code point's plane number. + +use crate::codepointtrie::cptrie::*; +use zerovec::ZeroVec; + +const INDEX_ARRAY_AS_BYTES: &[u8] = &[ + 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x88, 0x2, 0x90, 0x2, + 0x90, 0x2, 0x90, 0x2, 0xb0, 0x2, 0xb0, 0x2, 0xb0, 0x2, 0xb0, 0x2, 0xd0, 0x2, 0xd0, 0x2, 0xd0, + 0x2, 0xd0, 0x2, 0xf0, 0x2, 0xf0, 0x2, 0xf0, 0x2, 0xf0, 0x2, 0x10, 0x3, 0x10, 0x3, 0x10, 0x3, + 0x10, 0x3, 0x30, 0x3, 0x30, 0x3, 0x30, 0x3, 0x30, 0x3, 0x50, 0x3, 0x50, 0x3, 0x50, 0x3, 0x50, + 0x3, 0x70, 0x3, 0x70, 0x3, 0x70, 0x3, 0x70, 0x3, 0x90, 0x3, 0x90, 0x3, 0x90, 0x3, 0x90, 0x3, + 0xb0, 0x3, 0xb0, 0x3, 0xb0, 0x3, 0xb0, 0x3, 0xd0, 0x3, 0xd0, 0x3, 0xd0, 0x3, 0xd0, 0x3, 0xf0, + 0x3, 0xf0, 0x3, 0xf0, 0x3, 0xf0, 0x3, 0x10, 0x4, 0x10, 0x4, 0x10, 0x4, 0x10, 0x4, 0x30, 0x4, + 0x30, 0x4, 0x30, 0x4, 0x30, 0x4, 0x50, 0x4, 0x50, 0x4, 0x50, 0x4, 0x50, 0x4, 0x70, 0x4, 0x70, + 0x4, 0x70, 0x4, 0x70, 0x4, 0x0, 0x0, 0x10, 0x0, 0x20, 0x0, 0x30, 0x0, 0x40, 0x0, 0x50, 0x0, + 0x60, 0x0, 0x70, 0x0, 0x0, 0x0, 0x10, 0x0, 0x20, 0x0, 0x30, 0x0, 0x0, 0x0, 0x10, 0x0, 0x20, + 0x0, 0x30, 0x0, 0x0, 0x0, 0x10, 0x0, 0x20, 0x0, 0x30, 0x0, 0x0, 0x0, 0x10, 0x0, 0x20, 0x0, + 0x30, 0x0, 0x0, 0x0, 0x10, 0x0, 0x20, 0x0, 0x30, 0x0, 0x0, 0x0, 0x10, 0x0, 0x20, 0x0, 0x30, + 0x0, 0x0, 0x0, 0x10, 0x0, 0x20, 0x0, 0x30, 0x0, 0x0, 0x0, 0x10, 0x0, 0x20, 0x0, 0x30, 0x0, + 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, + 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, + 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, + 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x80, 0x0, 0x90, 0x0, 0x90, 0x0, + 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, + 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, + 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, + 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0x90, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, + 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, + 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, + 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xa0, + 0x0, 0xa0, 0x0, 0xa0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, + 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, + 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, + 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, 0x0, 0xb0, + 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, + 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, + 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, + 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xc0, 0x0, 0xd0, 0x0, 0xd0, + 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, + 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, + 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, + 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, + 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, + 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, + 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, + 0xe0, 0x0, 0xe0, 0x0, 0xe0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, + 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, + 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, + 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, 0xf0, 0x0, + 0xf0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, + 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, + 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, + 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, + 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, + 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, + 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, 0x10, 0x1, + 0x10, 0x1, 0x10, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, + 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, + 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, + 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, 0x20, 0x1, + 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, + 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, + 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, + 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x30, 0x1, 0x40, 0x1, 0x40, 0x1, + 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, + 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, + 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, + 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x40, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, + 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, + 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, + 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, 0x1, 0x50, + 0x1, 0x50, 0x1, 0x50, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, + 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, + 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, + 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, 0x1, 0x60, + 0x1, 0x80, 0x0, 0x88, 0x0, 0x88, 0x0, 0x88, 0x0, 0x88, 0x0, 0x88, 0x0, 0x88, 0x0, 0x88, 0x0, + 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, + 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, + 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, + 0x0, 0x2, 0x0, 0x2, 0x0, 0x2, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, + 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, + 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, + 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, + 0xa8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, + 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, + 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, + 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xc8, 0x0, 0xe8, 0x0, + 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, + 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, + 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, + 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0xe8, 0x0, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, + 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, + 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, + 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, 0x8, 0x1, + 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, + 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, + 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, + 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x28, 0x1, 0x48, 0x1, 0x48, 0x1, + 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, + 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, + 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, + 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x48, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, + 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, + 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, + 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, 0x1, 0x68, + 0x1, 0x68, 0x1, 0x68, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, + 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, + 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, + 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, 0x1, 0x88, + 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, + 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, + 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, + 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xa8, 0x1, 0xc8, 0x1, 0xc8, + 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, + 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, + 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, + 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xc8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, + 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, + 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, + 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, + 0xe8, 0x1, 0xe8, 0x1, 0xe8, 0x1, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, + 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, + 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, + 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x28, 0x2, 0x28, 0x2, + 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, + 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, + 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, + 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x28, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, + 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, + 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, + 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, 0x2, 0x48, + 0x2, 0x48, 0x2, 0x48, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, + 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, + 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, + 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, 0x2, 0x68, + 0x2, +]; + +/// Return a [`CodePointTrie`] that returns the Unicode plane number, an +/// integer from 0-16 inclusive, for each code point. +/// +/// This `CodePointTrie` +/// does not actually represent any Unicode property, but it is provided in +/// case it is useful to users of `CodePointTrie` for testing or other +/// purposes. See . +pub fn get_planes_trie() -> CodePointTrie<'static, u8> { + let index_array_as_bytes: &[u8] = INDEX_ARRAY_AS_BYTES; + let data_8_array: &[u8] = &[ + 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, 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, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xb, + 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xc, 0xc, 0xc, + 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xd, 0xd, 0xd, 0xd, 0xd, + 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, + 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, + 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0x10, 0x10, 0x10, 0, + ]; + #[allow(clippy::unwrap_used)] // valid bytes + let index: ZeroVec = ZeroVec::parse_bytes(index_array_as_bytes).unwrap(); + #[allow(clippy::unwrap_used)] // valid bytes + let data: ZeroVec = ZeroVec::parse_bytes(data_8_array).unwrap(); + let high_start = 0x100000; + let shifted12_high_start = 0x100; + let index3_null_offset = 0x2; + let data_null_offset = 0x0; + let null_value = 0x0; + let trie_type = TrieType::Small; + + let trie_header = CodePointTrieHeader { + high_start, + shifted12_high_start, + index3_null_offset, + data_null_offset, + null_value, + trie_type, + }; + + #[allow(clippy::unwrap_used)] // valid data + CodePointTrie::try_new(trie_header, index, data).unwrap() +} + +#[cfg(test)] +mod tests { + use zerovec::ZeroVec; + + const INDEX_ARRAY: &[u16] = &[ + 0, 0x40, 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, 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, 0x288, 0x290, 0x290, 0x290, 0x2b0, 0x2b0, 0x2b0, 0x2b0, 0x2d0, 0x2d0, 0x2d0, + 0x2d0, 0x2f0, 0x2f0, 0x2f0, 0x2f0, 0x310, 0x310, 0x310, 0x310, 0x330, 0x330, 0x330, 0x330, + 0x350, 0x350, 0x350, 0x350, 0x370, 0x370, 0x370, 0x370, 0x390, 0x390, 0x390, 0x390, 0x3b0, + 0x3b0, 0x3b0, 0x3b0, 0x3d0, 0x3d0, 0x3d0, 0x3d0, 0x3f0, 0x3f0, 0x3f0, 0x3f0, 0x410, 0x410, + 0x410, 0x410, 0x430, 0x430, 0x430, 0x430, 0x450, 0x450, 0x450, 0x450, 0x470, 0x470, 0x470, + 0x470, 0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0, 0x10, 0x20, 0x30, 0, 0x10, 0x20, + 0x30, 0, 0x10, 0x20, 0x30, 0, 0x10, 0x20, 0x30, 0, 0x10, 0x20, 0x30, 0, 0x10, 0x20, 0x30, + 0, 0x10, 0x20, 0x30, 0, 0x10, 0x20, 0x30, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, + 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, + 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, + 0xc0, 0xc0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, + 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, + 0xd0, 0xd0, 0xd0, 0xd0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, + 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, + 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, + 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, + 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, + 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, + 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, + 0x110, 0x110, 0x110, 0x110, 0x110, 0x110, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, + 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, + 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x120, 0x130, + 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, + 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, 0x130, + 0x130, 0x130, 0x130, 0x130, 0x130, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, + 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, + 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x140, 0x150, 0x150, + 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, + 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, 0x150, + 0x150, 0x150, 0x150, 0x150, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, + 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, + 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x160, 0x80, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 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, 2, 2, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, + 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, + 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, + 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, + 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, + 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0x108, 0x108, + 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, + 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, + 0x108, 0x108, 0x108, 0x108, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, + 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, + 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x128, 0x148, 0x148, 0x148, + 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, + 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, 0x148, + 0x148, 0x148, 0x148, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, + 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, + 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x168, 0x188, 0x188, 0x188, 0x188, + 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, + 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, 0x188, + 0x188, 0x188, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, + 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, + 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1a8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, + 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, + 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, 0x1c8, + 0x1c8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, + 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, + 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x1e8, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, + 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, + 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, 0x208, + 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, + 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, + 0x228, 0x228, 0x228, 0x228, 0x228, 0x228, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, + 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, + 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x248, 0x268, + 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, + 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, 0x268, + 0x268, 0x268, 0x268, 0x268, 0x268, + ]; + + #[test] + fn test_index_byte_array_literal() { + let index_array_as_bytes: &[u8] = super::INDEX_ARRAY_AS_BYTES; + let index_zv_bytes: ZeroVec = + ZeroVec::parse_bytes(index_array_as_bytes).expect("infallible"); + let index_zv_aligned: ZeroVec = ZeroVec::from_slice_or_alloc(INDEX_ARRAY); + assert_eq!(index_zv_bytes, index_zv_aligned); + } +} diff --git a/deps/crates/vendor/icu_collections/src/codepointtrie/serde.rs b/deps/crates/vendor/icu_collections/src/codepointtrie/serde.rs new file mode 100644 index 00000000000000..74b9e7bb3ed1b6 --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/codepointtrie/serde.rs @@ -0,0 +1,52 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::codepointtrie::{CodePointTrie, CodePointTrieHeader, TrieValue}; +use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; +use zerofrom::ZeroFrom; +use zerovec::ZeroVec; + +#[derive(Serialize, Deserialize)] +pub struct CodePointTrieSerde<'trie, T: TrieValue> { + header: CodePointTrieHeader, + #[serde(borrow)] + index: ZeroVec<'trie, u16>, + #[serde(borrow)] + data: ZeroVec<'trie, T>, +} + +impl Serialize for CodePointTrie<'_, T> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let ser = CodePointTrieSerde { + header: self.header, + index: ZeroFrom::zero_from(&self.index), + data: ZeroFrom::zero_from(&self.data), + }; + ser.serialize(serializer) + } +} + +impl<'de, 'trie, T: TrieValue + Deserialize<'de>> Deserialize<'de> for CodePointTrie<'trie, T> +where + 'de: 'trie, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let de = CodePointTrieSerde::deserialize(deserializer)?; + let error_value = de.data.last().ok_or_else(|| { + D::Error::custom("CodePointTrie vector must have at least one element") + })?; + Ok(CodePointTrie { + header: de.header, + index: de.index, + data: de.data, + error_value, + }) + } +} diff --git a/deps/crates/vendor/icu_collections/src/codepointtrie/toml.rs b/deps/crates/vendor/icu_collections/src/codepointtrie/toml.rs new file mode 100644 index 00000000000000..f8b0f7b4638e1e --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/codepointtrie/toml.rs @@ -0,0 +1,124 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! Utilities for reading CodePointTrie data from TOML files. + +use crate::codepointtrie::error::Error; +use crate::codepointtrie::CodePointTrie; +use crate::codepointtrie::CodePointTrieHeader; +use crate::codepointtrie::TrieType; +use crate::codepointtrie::TrieValue; +use alloc::string::String; +use alloc::vec::Vec; +use core::convert::TryFrom; +use zerovec::ZeroVec; + +/// A Serde-compatible struct for reading serialized [`CodePointTrie`] TOML files +/// generated by ICU4C. +/// +/// Use `TryInto` to convert [`CodePointTrieToml`] to a proper [`CodePointTrie`]. +#[allow(clippy::upper_case_acronyms)] +#[derive(serde::Deserialize)] +pub struct CodePointTrieToml { + #[serde(skip)] + _short_name: String, + #[serde(skip)] + _long_name: String, + #[serde(skip)] + _name: String, + index: Vec, + data_8: Option>, + data_16: Option>, + data_32: Option>, + #[serde(skip)] + _index_length: u32, + #[serde(skip)] + _data_length: u32, + #[serde(rename = "highStart")] + high_start: u32, + #[serde(rename = "shifted12HighStart")] + shifted12_high_start: u16, + #[serde(rename = "type")] + trie_type_enum_val: u8, + #[serde(rename = "valueWidth")] + _value_width_enum_val: u8, + #[serde(rename = "index3NullOffset")] + index3_null_offset: u16, + #[serde(rename = "dataNullOffset")] + data_null_offset: u32, + #[serde(rename = "nullValue")] + null_value: u32, +} + +/// Data slice from a [`CodePointTrie`] TOML. +/// +/// ICU4C exports data as either `u8`, `u16`, or `u32`, which may be converted +/// to other types as appropriate. +#[allow(clippy::exhaustive_enums)] // based on a stable serialized form +pub enum CodePointDataSlice<'a> { + /// A serialized [`CodePointTrie`] data array 8-bit values. + U8(&'a [u8]), + /// A serialized [`CodePointTrie`] data array 16-bit values. + U16(&'a [u16]), + /// A serialized [`CodePointTrie`] data array 32-bit values. + U32(&'a [u32]), +} + +impl CodePointTrieToml { + /// Gets the `index` slice. + pub fn index_slice(&self) -> &[u16] { + self.index.as_slice() + } + + /// Gets the `data` slice. + pub fn data_slice(&self) -> Result { + if let Some(data_8) = &self.data_8 { + Ok(CodePointDataSlice::U8(data_8.as_slice())) + } else if let Some(data_16) = &self.data_16 { + Ok(CodePointDataSlice::U16(data_16.as_slice())) + } else if let Some(data_32) = &self.data_32 { + Ok(CodePointDataSlice::U32(data_32.as_slice())) + } else { + Err(Error::FromDeserialized { + reason: "Did not find data array for CodePointTrie in TOML", + }) + } + } +} + +impl TryFrom<&CodePointTrieToml> for CodePointTrieHeader { + type Error = Error; + + fn try_from(cpt_data: &CodePointTrieToml) -> Result { + let trie_type_enum: TrieType = TrieType::try_from(cpt_data.trie_type_enum_val)?; + Ok(CodePointTrieHeader { + high_start: cpt_data.high_start, + shifted12_high_start: cpt_data.shifted12_high_start, + index3_null_offset: cpt_data.index3_null_offset, + data_null_offset: cpt_data.data_null_offset, + null_value: cpt_data.null_value, + trie_type: trie_type_enum, + }) + } +} + +impl TryFrom<&CodePointTrieToml> for CodePointTrie<'static, T> { + type Error = Error; + + fn try_from(cpt_data: &CodePointTrieToml) -> Result, Self::Error> { + use CodePointDataSlice::*; + let header = CodePointTrieHeader::try_from(cpt_data)?; + let index: ZeroVec = ZeroVec::alloc_from_slice(&cpt_data.index); + let data: Result, T::TryFromU32Error> = match cpt_data.data_slice()? { + U8(s) => s.iter().map(|i| T::try_from_u32(*i as u32)).collect(), + U16(s) => s.iter().map(|i| T::try_from_u32(*i as u32)).collect(), + U32(s) => s.iter().map(|i| T::try_from_u32(*i)).collect(), + }; + + let data = data.map_err(|_| Error::FromDeserialized { + reason: "Could not parse data array to typed array", + })?; + CodePointTrie::::try_new(header, index, data) + } +} diff --git a/deps/crates/vendor/icu_collections/src/iterator_utils.rs b/deps/crates/vendor/icu_collections/src/iterator_utils.rs new file mode 100644 index 00000000000000..701a77eea31da8 --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/iterator_utils.rs @@ -0,0 +1,188 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::codepointtrie::CodePointMapRange; + +/// This is an iterator that coalesces adjacent ranges in an iterator over code +/// point ranges +pub(crate) struct RangeListIteratorCoalescer { + iter: I, + peek: Option>, +} + +impl RangeListIteratorCoalescer +where + I: Iterator>, +{ + pub fn new(iter: I) -> Self { + Self { iter, peek: None } + } +} + +impl Iterator for RangeListIteratorCoalescer +where + I: Iterator>, +{ + type Item = CodePointMapRange; + + fn next(&mut self) -> Option { + // Get the initial range we're working with: either a leftover + // range from last time, or the next range + let mut ret = if let Some(peek) = self.peek.take() { + peek + } else if let Some(next) = self.iter.next() { + next + } else { + // No ranges, exit early + return None; + }; + + // Keep pulling ranges + #[allow(clippy::while_let_on_iterator)] + // can't move the iterator, also we want it to be explicit that we're not draining the iterator + while let Some(next) = self.iter.next() { + if *next.range.start() == ret.range.end() + 1 && next.value == ret.value { + // Range has no gap, coalesce + ret.range = *ret.range.start()..=*next.range.end(); + } else { + // Range has a gap, return what we have so far, update + // peek + self.peek = Some(next); + return Some(ret); + } + } + + // Ran out of elements, exit + Some(ret) + } +} + +#[cfg(test)] +mod tests { + use core::fmt::Debug; + use icu::collections::codepointinvlist::CodePointInversionListBuilder; + use icu::properties::props::{BinaryProperty, EnumeratedProperty}; + use icu::properties::{CodePointMapData, CodePointSetData}; + + fn test_set(name: &str) { + let mut builder = CodePointInversionListBuilder::new(); + let mut builder_complement = CodePointInversionListBuilder::new(); + + for range in CodePointSetData::new::

().iter_ranges() { + builder.add_range32(range) + } + + for range in CodePointSetData::new::

().iter_ranges_complemented() { + builder_complement.add_range32(range) + } + + builder.complement(); + let set1 = builder.build(); + let set2 = builder_complement.build(); + assert_eq!(set1, set2, "Set {name} failed to complement correctly"); + } + + fn test_map(value: T, name: &str) { + let mut builder = CodePointInversionListBuilder::new(); + let mut builder_complement = CodePointInversionListBuilder::new(); + + for range in CodePointMapData::::new().iter_ranges_for_value(value) { + builder.add_range32(range) + } + + for range in CodePointMapData::::new().iter_ranges_for_value_complemented(value) { + builder_complement.add_range32(range) + } + + builder.complement(); + let set1 = builder.build(); + let set2 = builder_complement.build(); + assert_eq!( + set1, set2, + "Map {name} failed to complement correctly with value {value:?}" + ); + } + + #[test] + fn test_complement_sets() { + use icu::properties::props::*; + // Stress test the RangeListIteratorComplementer logic by ensuring it works for + // a whole bunch of binary properties + test_set::("ASCII_Hex_Digit"); + test_set::("Alnum"); + test_set::("Alphabetic"); + test_set::("Bidi_Control"); + test_set::("Bidi_Mirrored"); + test_set::("Blank"); + test_set::("Cased"); + test_set::("Case_Ignorable"); + test_set::("Full_Composition_Exclusion"); + test_set::("Changes_When_Casefolded"); + test_set::("Changes_When_Casemapped"); + test_set::("Changes_When_NFKC_Casefolded"); + test_set::("Changes_When_Lowercased"); + test_set::("Changes_When_Titlecased"); + test_set::("Changes_When_Uppercased"); + test_set::("Dash"); + test_set::("Deprecated"); + test_set::("Default_Ignorable_Code_Point"); + test_set::("Diacritic"); + test_set::("Emoji_Modifier_Base"); + test_set::("Emoji_Component"); + test_set::("Emoji_Modifier"); + test_set::("Emoji"); + test_set::("Emoji_Presentation"); + test_set::("Extender"); + test_set::("Extended_Pictographic"); + test_set::("Graph"); + test_set::("Grapheme_Base"); + test_set::("Grapheme_Extend"); + test_set::("Grapheme_Link"); + test_set::("Hex_Digit"); + test_set::("Hyphen"); + test_set::("Id_Continue"); + test_set::("Ideographic"); + test_set::("Id_Start"); + test_set::("Ids_Binary_Operator"); + test_set::("Ids_Trinary_Operator"); + test_set::("Join_Control"); + test_set::("Logical_Order_Exception"); + test_set::("Lowercase"); + test_set::("Math"); + test_set::("Noncharacter_Code_Point"); + test_set::("NFC_Inert"); + test_set::("NFD_Inert"); + test_set::("NFKC_Inert"); + test_set::("NFKD_Inert"); + test_set::("Pattern_Syntax"); + test_set::("Pattern_White_Space"); + test_set::("Prepended_Concatenation_Mark"); + test_set::("Print"); + test_set::("Quotation_Mark"); + test_set::("Radical"); + test_set::("Regional_Indicator"); + test_set::("Soft_Dotted"); + test_set::("Segment_Starter"); + test_set::("Case_Sensitive"); + test_set::("Sentence_Terminal"); + test_set::("Terminal_Punctuation"); + test_set::("Unified_Ideograph"); + test_set::("Uppercase"); + test_set::("Variation_Selector"); + test_set::("White_Space"); + test_set::("Xdigit"); + test_set::("XID_Continue"); + test_set::("XID_Start"); + } + + #[test] + fn test_complement_maps() { + use icu::properties::props::{GeneralCategory, Script}; + test_map(GeneralCategory::UppercaseLetter, "gc"); + test_map(GeneralCategory::OtherPunctuation, "gc"); + test_map(Script::Devanagari, "script"); + test_map(Script::Latin, "script"); + test_map(Script::Common, "script"); + } +} diff --git a/deps/crates/vendor/icu_collections/src/lib.rs b/deps/crates/vendor/icu_collections/src/lib.rs new file mode 100644 index 00000000000000..a20545d0887ee8 --- /dev/null +++ b/deps/crates/vendor/icu_collections/src/lib.rs @@ -0,0 +1,44 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! Efficient collections for Unicode data. +//! +//! This module is published as its own crate ([`icu_collections`](https://docs.rs/icu_collections/latest/icu_collections/)) +//! and as part of the [`icu`](https://docs.rs/icu/latest/icu/) crate. See the latter for more details on the ICU4X project. +//! +//! ICU4X [`CodePointTrie`](crate::codepointtrie::CodePointTrie) provides a read-only view of `CodePointTrie` data that is exported +//! from ICU4C. Detailed information about the design of the data structure can be found in the documentation +//! for the [`CodePointTrie`](crate::codepointtrie::CodePointTrie) struct. +//! +//! ICU4X [`CodePointInversionList`](`crate::codepointinvlist::CodePointInversionList`) provides necessary functionality for highly efficient querying of sets of Unicode characters. +//! It is an implementation of the existing [ICU4C UnicodeSet API](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1UnicodeSet.html). +//! +//! ICU4X [`Char16Trie`](`crate::char16trie::Char16Trie`) provides a data structure for a space-efficient and time-efficient lookup of +//! sequences of 16-bit units (commonly but not necessarily UTF-16 code units) +//! which map to integer values. +//! It is an implementation of the existing [ICU4C UCharsTrie](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1UCharsTrie.html) +//! / [ICU4J CharsTrie](https://unicode-org.github.io/icu-docs/apidoc/released/icu4j/com/ibm/icu/util/CharsTrie.html) API. + +// https://github.com/unicode-org/icu4x/blob/main/documents/process/boilerplate.md#library-annotations +#![cfg_attr(not(any(test, doc)), no_std)] +#![cfg_attr( + not(test), + deny( + clippy::indexing_slicing, + clippy::unwrap_used, + clippy::expect_used, + clippy::panic + ) +)] +#![warn(missing_docs)] + +#[cfg(feature = "alloc")] +extern crate alloc; + +pub mod char16trie; +pub mod codepointinvlist; +pub mod codepointinvliststringlist; +pub mod codepointtrie; + +pub(crate) mod iterator_utils; diff --git a/deps/crates/vendor/icu_collections/tests/char16trie.rs b/deps/crates/vendor/icu_collections/tests/char16trie.rs new file mode 100644 index 00000000000000..ac0308870c7ff2 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/char16trie.rs @@ -0,0 +1,304 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use icu_collections::char16trie::{Char16Trie, TrieResult}; +use zerovec::ZeroVec; + +#[test] +fn empty() { + let trie_data = toml::from_str::(include_str!("data/char16trie/empty.toml")) + .unwrap() + .ucharstrie + .data; + let trie = Char16Trie::new(ZeroVec::from_slice_or_alloc(trie_data.as_slice())); + let res = trie.iter().next('h'); + assert_eq!(res, TrieResult::NoMatch); +} + +#[test] +fn a() { + let trie_data = toml::from_str::(include_str!("data/char16trie/test_a.toml")) + .unwrap() + .ucharstrie + .data; + let trie = Char16Trie::new(ZeroVec::from_slice_or_alloc(trie_data.as_slice())); + + let mut iter = trie.iter(); + let res = iter.next('h'); + assert_eq!(res, TrieResult::NoMatch); + + let mut iter = trie.iter(); + let res = iter.next('a'); + assert_eq!(res, TrieResult::FinalValue(1)); + let res = iter.next('a'); + assert_eq!(res, TrieResult::NoMatch); +} + +#[test] +fn a_b() { + let trie_data = toml::from_str::(include_str!("data/char16trie/test_a_ab.toml")) + .unwrap() + .ucharstrie + .data; + let trie = Char16Trie::new(ZeroVec::from_slice_or_alloc(trie_data.as_slice())); + + let mut iter = trie.iter(); + let res = iter.next('a'); + assert_eq!(res, TrieResult::Intermediate(1)); + let res = iter.next('a'); + assert_eq!(res, TrieResult::NoMatch); + + let mut iter = trie.iter(); + let res = iter.next('a'); + assert_eq!(res, TrieResult::Intermediate(1)); + let res = iter.next('b'); + assert_eq!(res, TrieResult::FinalValue(100)); + let res = iter.next('b'); + assert_eq!(res, TrieResult::NoMatch); +} + +#[test] +fn shortest_branch() { + let trie_data = + toml::from_str::(include_str!("data/char16trie/test_shortest_branch.toml")) + .unwrap() + .ucharstrie + .data; + let trie = Char16Trie::new(ZeroVec::from_slice_or_alloc(trie_data.as_slice())); + + let mut iter = trie.iter(); + let res = iter.next('a'); + assert_eq!(res, TrieResult::FinalValue(1000)); + let res = iter.next('b'); + assert_eq!(res, TrieResult::NoMatch); + + let mut iter = trie.iter(); + let res = iter.next('b'); + assert_eq!(res, TrieResult::FinalValue(2000)); + let res = iter.next('a'); + assert_eq!(res, TrieResult::NoMatch); +} + +#[test] +fn branches() { + let trie_data = toml::from_str::(include_str!("data/char16trie/test_branches.toml")) + .unwrap() + .ucharstrie + .data; + let trie = Char16Trie::new(ZeroVec::from_slice_or_alloc(trie_data.as_slice())); + + for (query, expected) in [ + ("a", TrieResult::FinalValue(0x10)), + ("cc", TrieResult::FinalValue(0x40)), + ("e", TrieResult::FinalValue(0x100)), + ("ggg", TrieResult::FinalValue(0x400)), + ("i", TrieResult::FinalValue(0x1000)), + ("kkkk", TrieResult::FinalValue(0x4000)), + ("n", TrieResult::FinalValue(0x10000)), + ("ppppp", TrieResult::FinalValue(0x40000)), + ("r", TrieResult::FinalValue(0x100000)), + ("sss", TrieResult::FinalValue(0x200000)), + ("t", TrieResult::FinalValue(0x400000)), + ("uu", TrieResult::FinalValue(0x800000)), + ("vv", TrieResult::FinalValue(0x7fffffff)), + ("zz", TrieResult::FinalValue(-2147483648)), + ] { + let mut iter = trie.iter(); + for (i, chr) in query.chars().enumerate() { + let res = iter.next(chr); + if i + 1 == query.len() { + assert_eq!(res, expected); + } else { + assert_eq!(res, TrieResult::NoValue); + } + } + } +} + +#[test] +fn long_sequence() { + let trie_data = + toml::from_str::(include_str!("data/char16trie/test_long_sequence.toml")) + .unwrap() + .ucharstrie + .data; + let trie = Char16Trie::new(ZeroVec::from_slice_or_alloc(trie_data.as_slice())); + + for (query, expected) in [ + ("a", TrieResult::Intermediate(-1)), + // sequence of linear-match nodes + ( + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + TrieResult::Intermediate(-2), + ), + // more than 256 units + ( + concat!( + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + ), + TrieResult::FinalValue(-3), + ), + ] { + let mut iter = trie.iter(); + for (i, chr) in query.chars().enumerate() { + let res = iter.next(chr); + if i + 1 == query.len() { + assert_eq!(res, expected); + } else if i == 0 { + assert_eq!(res, TrieResult::Intermediate(-1)); + } else if i == 51 { + assert_eq!(res, TrieResult::Intermediate(-2)); + } else { + assert_eq!(res, TrieResult::NoValue); + } + } + } +} + +#[test] +fn long_branch() { + let trie_data = + toml::from_str::(include_str!("data/char16trie/test_long_branch.toml")) + .unwrap() + .ucharstrie + .data; + let trie = Char16Trie::new(ZeroVec::from_slice_or_alloc(trie_data.as_slice())); + + for (query, expected) in [ + ("a", TrieResult::FinalValue(-2)), + ("b", TrieResult::FinalValue(-1)), + ("c", TrieResult::FinalValue(0)), + ("d2", TrieResult::FinalValue(1)), + ("f", TrieResult::FinalValue(0x3f)), + ("g", TrieResult::FinalValue(0x40)), + ("h", TrieResult::FinalValue(0x41)), + ("j23", TrieResult::FinalValue(0x1900)), + ("j24", TrieResult::FinalValue(0x19ff)), + ("j25", TrieResult::FinalValue(0x1a00)), + ("k2", TrieResult::FinalValue(0x1a80)), + ("k3", TrieResult::FinalValue(0x1aff)), + ("l234567890", TrieResult::Intermediate(0x1b00)), + ("l234567890123", TrieResult::FinalValue(0x1b01)), + ( + "nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn", + TrieResult::FinalValue(0x10ffff), + ), + ( + "oooooooooooooooooooooooooooooooooooooooooooooooooooooo", + TrieResult::FinalValue(0x110000), + ), + ( + "pppppppppppppppppppppppppppppppppppppppppppppppppppppp", + TrieResult::FinalValue(0x120000), + ), + ("r", TrieResult::FinalValue(0x333333)), + ("s2345", TrieResult::FinalValue(0x4444444)), + ("t234567890", TrieResult::FinalValue(0x77777777)), + ("z", TrieResult::FinalValue(-2147483647)), + ] { + let mut iter = trie.iter(); + for (i, chr) in query.chars().enumerate() { + let res = iter.next(chr); + if i + 1 == query.len() { + assert_eq!(res, expected); + } else if query == "l234567890123" && i == 9 { + assert_eq!(res, TrieResult::Intermediate(0x1b00)); + } else { + assert_eq!(res, TrieResult::NoValue); + } + } + } +} + +#[test] +fn compact() { + let trie_data = toml::from_str::(include_str!("data/char16trie/test_compact.toml")) + .unwrap() + .ucharstrie + .data; + let trie = Char16Trie::new(ZeroVec::from_slice_or_alloc(trie_data.as_slice())); + + for (query, expected) in [ + ("+", TrieResult::Intermediate(0)), + ("+august", TrieResult::FinalValue(8)), + ("+december", TrieResult::FinalValue(12)), + ("+july", TrieResult::FinalValue(7)), + ("+june", TrieResult::FinalValue(6)), + ("+november", TrieResult::FinalValue(11)), + ("+october", TrieResult::FinalValue(10)), + ("+september", TrieResult::FinalValue(9)), + ("-", TrieResult::Intermediate(0)), + ("-august", TrieResult::FinalValue(8)), + ("-december", TrieResult::FinalValue(12)), + ("-july", TrieResult::FinalValue(7)), + ("-june", TrieResult::FinalValue(6)), + ("-november", TrieResult::FinalValue(11)), + ("-october", TrieResult::FinalValue(10)), + ("-september", TrieResult::FinalValue(9)), + ("xjuly", TrieResult::FinalValue(7)), + ("xjune", TrieResult::FinalValue(6)), + ] { + let mut iter = trie.iter(); + for (i, chr) in query.chars().enumerate() { + let res = iter.next(chr); + if i + 1 == query.len() { + assert_eq!(res, expected); + } else if chr == '-' || chr == '+' { + assert_eq!(res, TrieResult::Intermediate(0)); + } else { + assert_eq!(res, TrieResult::NoValue); + } + } + } +} + +#[test] +fn months() { + let trie_data = toml::from_str::(include_str!("data/char16trie/months.toml")) + .unwrap() + .ucharstrie + .data; + let trie = Char16Trie::new(ZeroVec::from_slice_or_alloc(trie_data.as_slice())); + + let mut iter = trie.iter(); + for (chr, expected) in [ + ('j', TrieResult::NoValue), + ('u', TrieResult::NoValue), + ('n', TrieResult::Intermediate(6)), + ('e', TrieResult::FinalValue(6)), + ] { + let res = iter.next(chr); + assert_eq!(res, expected); + } + let res = iter.next('h'); + assert_eq!(res, TrieResult::NoMatch); + + let mut iter = trie.iter(); + for (chr, expected) in [ + ('j', TrieResult::NoValue), + ('u', TrieResult::NoValue), + ('l', TrieResult::NoValue), + ('y', TrieResult::FinalValue(7)), + ] { + let res = iter.next(chr); + assert_eq!(res, expected); + } + let res = iter.next('h'); + assert_eq!(res, TrieResult::NoMatch); +} + +#[derive(serde::Deserialize)] +pub struct TestFile { + ucharstrie: Char16TrieVec, +} + +#[derive(serde::Deserialize)] +pub struct Char16TrieVec { + data: Vec, +} diff --git a/deps/crates/vendor/icu_collections/tests/cpt.rs b/deps/crates/vendor/icu_collections/tests/cpt.rs new file mode 100644 index 00000000000000..210277cf40f72c --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/cpt.rs @@ -0,0 +1,489 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use icu_collections::codepointtrie::planes::get_planes_trie; +use icu_collections::codepointtrie::*; +use zerovec::ZeroVec; + +#[test] +fn planes_trie_deserialize_check_test() { + // Get expected planes trie from crate::planes::get_planes_trie() + + let exp_planes_trie = get_planes_trie(); + + // Compute actual planes trie from planes.toml + + let planes_enum_prop = + ::toml::from_str::(include_str!("data/cpt/planes.toml")) + .unwrap(); + + let code_point_trie_struct = planes_enum_prop.code_point_trie.trie_struct; + + let trie_header = CodePointTrieHeader { + high_start: code_point_trie_struct.high_start, + shifted12_high_start: code_point_trie_struct.shifted12_high_start, + index3_null_offset: code_point_trie_struct.index3_null_offset, + data_null_offset: code_point_trie_struct.data_null_offset, + null_value: code_point_trie_struct.null_value, + trie_type: TrieType::try_from(code_point_trie_struct.trie_type_enum_val).unwrap_or_else( + |_| { + panic!( + "Could not parse trie_type serialized enum value in test data file: {}", + code_point_trie_struct.name + ) + }, + ), + }; + + let data = ZeroVec::from_slice_or_alloc(code_point_trie_struct.data_8.as_ref().unwrap()); + let index = ZeroVec::from_slice_or_alloc(&code_point_trie_struct.index); + let trie_result = CodePointTrie::try_new(trie_header, index, data); + let act_planes_trie = trie_result.unwrap(); + + // Get check ranges (inversion map-style sequence of range+value) and + // apply the trie validation test fn on expected and actual tries + + let serialized_ranges: Vec<(u32, u32, u32)> = planes_enum_prop.code_point_map.data.ranges; + let mut check_ranges: Vec = vec![]; + for range_tuple in serialized_ranges { + let range_end = range_tuple.1 + 1; + let value = range_tuple.2; + check_ranges.push(range_end); + check_ranges.push(value); + } + + check_trie(&act_planes_trie, &check_ranges); + check_trie(&exp_planes_trie, &check_ranges); +} + +#[test] +fn free_blocks_16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/free-blocks.16.toml")); +} + +#[test] +fn free_blocks_32() { + run_deserialize_test_from_test_data(include_str!("data/cpt/free-blocks.32.toml")); +} + +#[test] +fn free_blocks_8() { + run_deserialize_test_from_test_data(include_str!("data/cpt/free-blocks.8.toml")); +} + +#[test] +fn free_blocks_small16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/free-blocks.small16.toml")); +} + +#[test] +fn grow_data_16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/grow-data.16.toml")); +} + +#[test] +fn grow_data_32() { + run_deserialize_test_from_test_data(include_str!("data/cpt/grow-data.32.toml")); +} + +#[test] +fn grow_data_8() { + run_deserialize_test_from_test_data(include_str!("data/cpt/grow-data.8.toml")); +} + +#[test] +fn grow_data_small16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/grow-data.small16.toml")); +} + +#[test] +fn set1_16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set1.16.toml")); +} + +#[test] +fn set1_32() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set1.32.toml")); +} + +#[test] +fn set1_8() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set1.8.toml")); +} + +#[test] +fn set1_small16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set1.small16.toml")); +} + +#[test] +fn set2_overlap_16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set2-overlap.16.toml")); +} + +#[test] +fn set2_overlap_32() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set2-overlap.32.toml")); +} + +#[test] +fn set2_overlap_small16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set2-overlap.small16.toml")); +} + +#[test] +fn set3_initial_9_16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set3-initial-9.16.toml")); +} + +#[test] +fn set3_initial_9_32() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set3-initial-9.32.toml")); +} + +#[test] +fn set3_initial_9_8() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set3-initial-9.8.toml")); +} + +#[test] +fn set3_initial_9_small16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set3-initial-9.small16.toml")); +} + +#[test] +fn set_empty_16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set-empty.16.toml")); +} + +#[test] +fn set_empty_32() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set-empty.32.toml")); +} + +#[test] +fn set_empty_8() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set-empty.8.toml")); +} + +#[test] +fn set_empty_small16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set-empty.small16.toml")); +} + +#[test] +fn set_single_value_16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set-single-value.16.toml")); +} + +#[test] +fn set_single_value_32() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set-single-value.32.toml")); +} + +#[test] +fn set_single_value_8() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set-single-value.8.toml")); +} + +#[test] +fn set_single_value_small16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/set-single-value.small16.toml")); +} + +#[test] +fn short_all_same_16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/short-all-same.16.toml")); +} + +#[test] +fn short_all_same_8() { + run_deserialize_test_from_test_data(include_str!("data/cpt/short-all-same.8.toml")); +} + +#[test] +fn short_all_same_small16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/short-all-same.small16.toml")); +} + +#[test] +fn small0_in_fast_16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/small0-in-fast.16.toml")); +} + +#[test] +fn small0_in_fast_32() { + run_deserialize_test_from_test_data(include_str!("data/cpt/small0-in-fast.32.toml")); +} + +#[test] +fn small0_in_fast_8() { + run_deserialize_test_from_test_data(include_str!("data/cpt/small0-in-fast.8.toml")); +} + +#[test] +fn small0_in_fast_small16() { + run_deserialize_test_from_test_data(include_str!("data/cpt/small0-in-fast.small16.toml")); +} + +/// The width of the elements in the data array of a [`CodePointTrie`]. +/// See [`UCPTrieValueWidth`](https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/ucptrie_8h.html) in ICU4C. +#[derive(Clone, Copy, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ValueWidthEnum { + Bits16 = 0, + Bits32 = 1, + Bits8 = 2, +} + +/// Test .get() on CodePointTrie by iterating through each range in +/// check_ranges and assert that the associated +/// value matches the trie value for each code point in the range. +pub fn check_trie>(trie: &CodePointTrie, check_ranges: &[u32]) { + assert_eq!( + 0, + check_ranges.len() % 2, + "check_ranges must have an even number of 32-bit values in (limit,value) pairs" + ); + + let mut i: u32 = 0; + let check_range_tuples = check_ranges.chunks(2); + // Iterate over each check range + for range_tuple in check_range_tuples { + let range_limit = range_tuple[0]; + let range_value = range_tuple[1]; + // Check all values in this range, one-by-one + while i < range_limit { + assert_eq!(range_value, trie.get32(i).into(), "trie_get({})", i,); + i += 1; + } + } +} + +/// Test `.get_range()` / `.iter_ranges()` on CodePointTrie by calling +/// `.iter_ranges()` on the trie. +/// +/// `.iter_ranges()` returns an iterator that produces values +/// by calls to .get_range, and this checks if it matches the values in check_ranges. +pub fn test_check_ranges_get_ranges>( + trie: &CodePointTrie, + check_ranges: &[u32], +) { + assert_eq!( + 0, + check_ranges.len() % 2, + "check_ranges must have an even number of 32-bit values in (limit,value) pairs" + ); + + let mut trie_ranges = trie.iter_ranges(); + + let mut range_start: u32 = 0; + let check_range_tuples = check_ranges.chunks(2); + // Iterate over each check range + for range_tuple in check_range_tuples { + let range_limit = range_tuple[0]; + let range_value = range_tuple[1]; + + // The check ranges array seems to start with a trivial range whose + // limit is zero. range_start is initialized to 0, so we can skip. + if range_limit == 0 { + continue; + } + + let cpm_range = trie_ranges.next(); + assert!(cpm_range.is_some(), "CodePointTrie iter_ranges() produces fewer ranges than the check_ranges field in testdata has"); + let cpm_range = cpm_range.unwrap(); + let cpmr_start = cpm_range.range.start(); + let cpmr_end = cpm_range.range.end(); + let cpmr_value: u32 = cpm_range.value.into(); + + assert_eq!(range_start, *cpmr_start); + assert_eq!(range_limit, *cpmr_end + 1); + assert_eq!(range_value, cpmr_value); + + range_start = range_limit; + } + + assert!(trie_ranges.next().is_none(), "CodePointTrie iter_ranges() produces more ranges than the check_ranges field in testdata has"); +} + +/// Run above tests that verify the validity of CodePointTrie methods +pub fn run_trie_tests>(trie: &CodePointTrie, check_ranges: &[u32]) { + check_trie(trie, check_ranges); + test_check_ranges_get_ranges(trie, check_ranges); +} + +// The following structs might be useful later for de-/serialization of the +// main `CodePointTrie` struct in the corresponding data provider. + +#[cfg_attr(any(feature = "serde", test), derive(serde::Deserialize))] +pub struct UnicodeEnumeratedProperty { + pub code_point_map: EnumPropCodePointMap, + pub code_point_trie: EnumPropSerializedCPT, +} + +#[cfg_attr(any(feature = "serde", test), derive(serde::Deserialize))] +pub struct EnumPropCodePointMap { + pub data: EnumPropCodePointMapData, +} + +#[cfg_attr(any(feature = "serde", test), derive(serde::Deserialize))] +pub struct EnumPropCodePointMapData { + pub long_name: String, + pub name: String, + pub ranges: Vec<(u32, u32, u32)>, +} + +#[allow(clippy::upper_case_acronyms)] +#[cfg_attr(any(feature = "serde", test), derive(serde::Deserialize))] +pub struct EnumPropSerializedCPT { + #[cfg_attr(any(feature = "serde", test), serde(rename = "struct"))] + pub trie_struct: EnumPropSerializedCPTStruct, +} + +// These structs support the test data dumped as TOML files from ICU. +// Because the properties CodePointMap data will also be dumped from ICU +// using similar functions, some of these structs may be useful to refactor +// into main code at a later point. + +#[allow(clippy::upper_case_acronyms)] +#[cfg_attr(any(feature = "serde", test), derive(serde::Deserialize))] +pub struct EnumPropSerializedCPTStruct { + #[cfg_attr(any(feature = "serde", test), serde(skip))] + pub long_name: String, + pub name: String, + pub index: Vec, + pub data_8: Option>, + pub data_16: Option>, + pub data_32: Option>, + #[cfg_attr(any(feature = "serde", test), serde(skip))] + pub index_length: u32, + #[cfg_attr(any(feature = "serde", test), serde(skip))] + pub data_length: u32, + #[cfg_attr(any(feature = "serde", test), serde(rename = "highStart"))] + pub high_start: u32, + #[cfg_attr(any(feature = "serde", test), serde(rename = "shifted12HighStart"))] + pub shifted12_high_start: u16, + #[cfg_attr(any(feature = "serde", test), serde(rename = "type"))] + pub trie_type_enum_val: u8, + #[cfg_attr(any(feature = "serde", test), serde(rename = "valueWidth"))] + pub value_width_enum_val: u8, + #[cfg_attr(any(feature = "serde", test), serde(rename = "index3NullOffset"))] + pub index3_null_offset: u16, + #[cfg_attr(any(feature = "serde", test), serde(rename = "dataNullOffset"))] + pub data_null_offset: u32, + #[cfg_attr(any(feature = "serde", test), serde(rename = "nullValue"))] + pub null_value: u32, +} + +// Given a .toml file dumped from ICU4C test data for UCPTrie, run the test +// data file deserialization into the test file struct, convert and construct +// the `CodePointTrie`, and test the constructed struct against the test file's +// "check ranges" (inversion map ranges) using `check_trie` to verify the +// validity of the `CodePointTrie`'s behavior for all code points. +#[allow(dead_code)] +pub fn run_deserialize_test_from_test_data(test_file: &str) { + // The following structs are specific to the TOML format files for dumped ICU + // test data. + + #[derive(serde::Deserialize)] + pub struct TestFile { + code_point_trie: TestCodePointTrie, + } + + #[derive(serde::Deserialize)] + pub struct TestCodePointTrie { + // The trie_struct field for test data files is dumped from the same source + // (ICU4C) using the same function (usrc_writeUCPTrie) as property data + // for the provider, so we can reuse the same struct here. + #[serde(rename(deserialize = "struct"))] + trie_struct: EnumPropSerializedCPTStruct, + #[serde(rename(deserialize = "testdata"))] + test_data: TestData, + } + + #[derive(serde::Deserialize)] + pub struct TestData { + #[serde(rename(deserialize = "checkRanges"))] + check_ranges: Vec, + } + + let test_file = ::toml::from_str::(test_file).unwrap(); + + let test_struct = test_file.code_point_trie.trie_struct; + + println!( + "Running CodePointTrie reader logic test on test data file: {}", + test_struct.name + ); + + let trie_type_enum = match TrieType::try_from(test_struct.trie_type_enum_val) { + Ok(enum_val) => enum_val, + _ => { + panic!( + "Could not parse trie_type serialized enum value in test data file: {}", + test_struct.name + ); + } + }; + + let trie_header = CodePointTrieHeader { + high_start: test_struct.high_start, + shifted12_high_start: test_struct.shifted12_high_start, + index3_null_offset: test_struct.index3_null_offset, + data_null_offset: test_struct.data_null_offset, + null_value: test_struct.null_value, + trie_type: trie_type_enum, + }; + + let index = ZeroVec::from_slice_or_alloc(&test_struct.index); + + match (test_struct.data_8, test_struct.data_16, test_struct.data_32) { + (Some(data_8), _, _) => { + let data = ZeroVec::from_slice_or_alloc(&data_8); + let trie_result = CodePointTrie::try_new(trie_header, index, data); + assert!(trie_result.is_ok(), "Could not construct trie"); + assert_eq!( + test_struct.value_width_enum_val, + ValueWidthEnum::Bits8 as u8 + ); + run_trie_tests( + &trie_result.unwrap(), + &test_file.code_point_trie.test_data.check_ranges, + ); + } + + (_, Some(data_16), _) => { + let data = ZeroVec::from_slice_or_alloc(&data_16); + let trie_result = CodePointTrie::try_new(trie_header, index, data); + assert!(trie_result.is_ok(), "Could not construct trie"); + assert_eq!( + test_struct.value_width_enum_val, + ValueWidthEnum::Bits16 as u8 + ); + run_trie_tests( + &trie_result.unwrap(), + &test_file.code_point_trie.test_data.check_ranges, + ); + } + + (_, _, Some(data_32)) => { + let data = ZeroVec::from_slice_or_alloc(&data_32); + let trie_result = CodePointTrie::try_new(trie_header, index, data); + assert!(trie_result.is_ok(), "Could not construct trie"); + assert_eq!( + test_struct.value_width_enum_val, + ValueWidthEnum::Bits32 as u8 + ); + run_trie_tests( + &trie_result.unwrap(), + &test_file.code_point_trie.test_data.check_ranges, + ); + } + + (_, _, _) => { + panic!("Could not match test trie data to a known value width or trie type"); + } + }; +} diff --git a/deps/crates/vendor/icu_collections/tests/data/char16trie/empty.toml b/deps/crates/vendor/icu_collections/tests/data/char16trie/empty.toml new file mode 100644 index 00000000000000..91f04b03ac17a6 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/char16trie/empty.toml @@ -0,0 +1,11 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: empty.toml +# +# machine-generated by: ucharstrietest.c + +[ucharstrie] +data = [ + 32768, +] diff --git a/deps/crates/vendor/icu_collections/tests/data/char16trie/months.toml b/deps/crates/vendor/icu_collections/tests/data/char16trie/months.toml new file mode 100644 index 00000000000000..79bfd4c92df3d7 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/char16trie/months.toml @@ -0,0 +1,19 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: months.toml +# +# machine-generated by: ucharstrietest.c + +[ucharstrie] +data = [ + 1,97,134,106,1,97,13,117,1,108,6,110,449,46,32774,101,32774, + 48,121,32775,48,110,147,106,72,111,22,111,32769,112,11,113,12, + 114,32769,117,49,97,114,176,121,32769,48,112,32769,49,113,113,32769, + 106,32769,107,35,108,32769,109,32769,110,58,110,110,110,110,110,110, + 110,110,110,110,110,63,110,110,110,110,110,110,110,110,110,110, + 110,110,110,110,110,110,32769,2,107,32769,108,32769,109,48,109,32769, + 101,22,101,12,102,32769,103,13,104,32769,105,50,105,105,105,32769, + 1,101,32769,102,32769,48,103,32769,46,32769,97,32769,98,7,99,32769, + 100,49,100,100,32769,48,98,32769,52,117,103,117,115,116,32776, +] diff --git a/deps/crates/vendor/icu_collections/tests/data/char16trie/test_a.toml b/deps/crates/vendor/icu_collections/tests/data/char16trie/test_a.toml new file mode 100644 index 00000000000000..48f53aaa860b90 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/char16trie/test_a.toml @@ -0,0 +1,11 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: test_a.toml +# +# machine-generated by: ucharstrietest.c + +[ucharstrie] +data = [ + 48,97,32769, +] diff --git a/deps/crates/vendor/icu_collections/tests/data/char16trie/test_a_ab.toml b/deps/crates/vendor/icu_collections/tests/data/char16trie/test_a_ab.toml new file mode 100644 index 00000000000000..c4633ba56059a4 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/char16trie/test_a_ab.toml @@ -0,0 +1,11 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: test_a_ab.toml +# +# machine-generated by: ucharstrietest.c + +[ucharstrie] +data = [ + 48,97,176,98,32868, +] diff --git a/deps/crates/vendor/icu_collections/tests/data/char16trie/test_branches.toml b/deps/crates/vendor/icu_collections/tests/data/char16trie/test_branches.toml new file mode 100644 index 00000000000000..1c7c62619186ed --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/char16trie/test_branches.toml @@ -0,0 +1,15 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: test_branches.toml +# +# machine-generated by: ucharstrietest.c + +[ucharstrie] +data = [ + 13,112,42,116,22,116,49216,0,117,8,118,10,122,48,122,65535,32768, + 0,48,117,49280,0,48,118,65535,32767,65535,112,9,114,49168,0,115, + 49,115,115,49184,0,51,112,112,112,112,49156,0,103,19,103,7, + 105,36864,107,7,110,49153,0,49,103,103,33792,50,107,107,107,49152, + 16384,97,32784,99,2,101,33024,48,99,32832, +] diff --git a/deps/crates/vendor/icu_collections/tests/data/char16trie/test_compact.toml b/deps/crates/vendor/icu_collections/tests/data/char16trie/test_compact.toml new file mode 100644 index 00000000000000..780ca9491a8fd4 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/char16trie/test_compact.toml @@ -0,0 +1,16 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: test_compact.toml +# +# machine-generated by: ucharstrietest.c + +[ucharstrie] +data = [ + 2,43,13,45,11,120,49,106,117,1,108,53,110,48,101,32774,69, + 110,32,110,13,111,20,115,55,101,112,116,101,109,98,101,114, + 32777,54,111,118,101,109,98,101,114,32779,53,99,116,111,98,101, + 114,32778,97,15,100,20,106,48,117,1,108,4,110,48,101,32774, + 48,121,32775,52,117,103,117,115,116,32776,54,101,99,101,109,98, + 101,114,32780, +] diff --git a/deps/crates/vendor/icu_collections/tests/data/char16trie/test_long_branch.toml b/deps/crates/vendor/icu_collections/tests/data/char16trie/test_long_branch.toml new file mode 100644 index 00000000000000..4c260ce61b38e8 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/char16trie/test_long_branch.toml @@ -0,0 +1,28 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: test_long_branch.toml +# +# machine-generated by: ucharstrietest.c + +[ucharstrie] +data = [ + 16,107,240,112,92,112,11,114,49203,13107,115,65,116,70,122,65535,32768, + 1,52,112,112,112,112,112,63,112,112,112,112,112,112,112,112, + 112,112,112,112,112,112,112,112,63,112,112,112,112,112,112,112, + 112,112,112,112,112,112,112,112,112,63,112,112,112,112,112,112, + 112,112,112,112,112,112,112,112,112,112,49170,0,51,50,51,52, + 53,50244,17476,56,50,51,52,53,54,55,56,57,48,65535,30583,30583, + 107,64,108,67,110,81,111,52,111,111,111,111,111,63,111,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111,111,63,111, + 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,63, + 111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111, + 49169,0,1,50,39552,51,39679,56,50,51,52,53,54,55,56,57, + 48,16498,6912,49,50,51,39681,52,110,110,110,110,110,63,110,110, + 110,110,110,110,110,110,110,110,110,110,110,110,110,110,63,110, + 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,63, + 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, + 49168,65535,102,16,102,32831,103,32832,104,32833,106,48,50,2,51,39168, + 52,39423,53,39424,97,65535,65535,65534,98,65535,65535,65535,99,32768,100,48, + 50,32769, +] diff --git a/deps/crates/vendor/icu_collections/tests/data/char16trie/test_long_sequence.toml b/deps/crates/vendor/icu_collections/tests/data/char16trie/test_long_sequence.toml new file mode 100644 index 00000000000000..72722a369cb6c8 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/char16trie/test_long_sequence.toml @@ -0,0 +1,32 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: test_long_sequence.toml +# +# machine-generated by: ucharstrietest.c + +[ucharstrie] +data = [ + 48,97,32754,65535,65535,98,99,100,63,101,102,103,104,105,106,107,108, + 109,110,111,112,113,114,115,116,63,117,118,119,120,121,122,65, + 66,67,68,69,70,71,72,73,74,63,75,76,77,78,79,80, + 81,82,83,84,85,86,87,88,89,90,32755,65535,65534,97,98,99, + 100,63,101,102,103,104,105,106,107,108,109,110,111,112,113,114, + 115,116,63,117,118,119,120,121,122,65,66,67,68,69,70,71, + 72,73,74,63,75,76,77,78,79,80,81,82,83,84,85,86, + 87,88,89,90,63,97,98,99,100,101,102,103,104,105,106,107, + 108,109,110,111,112,63,113,114,115,116,117,118,119,120,121,122, + 65,66,67,68,69,70,63,71,72,73,74,75,76,77,78,79, + 80,81,82,83,84,85,86,63,87,88,89,90,97,98,99,100, + 101,102,103,104,105,106,107,108,63,109,110,111,112,113,114,115, + 116,117,118,119,120,121,122,65,66,63,67,68,69,70,71,72, + 73,74,75,76,77,78,79,80,81,82,63,83,84,85,86,87, + 88,89,90,97,98,99,100,101,102,103,104,63,105,106,107,108, + 109,110,111,112,113,114,115,116,117,118,119,120,63,121,122,65, + 66,67,68,69,70,71,72,73,74,75,76,77,78,63,79,80, + 81,82,83,84,85,86,87,88,89,90,97,98,99,100,63,101, + 102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,63, + 117,118,119,120,121,122,65,66,67,68,69,70,71,72,73,74, + 63,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89, + 90,65535,65535,65533, +] diff --git a/deps/crates/vendor/icu_collections/tests/data/char16trie/test_shortest_branch.toml b/deps/crates/vendor/icu_collections/tests/data/char16trie/test_shortest_branch.toml new file mode 100644 index 00000000000000..639cb0314c3357 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/char16trie/test_shortest_branch.toml @@ -0,0 +1,11 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: test_shortest_branch.toml +# +# machine-generated by: ucharstrietest.c + +[ucharstrie] +data = [ + 1,97,33768,98,34768, +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.16.toml new file mode 100644 index 00000000000000..7febd4c3b47008 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.16.toml @@ -0,0 +1,113 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: free-blocks.16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "free-blocks.16" +index = [ + 0,0x40,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,0x80,0xc0,0xc0, + 0xc0,0xc0,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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 +] +data_16 = [ + 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, + 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, + 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, + 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, + 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,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,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 1,0xad +] +indexLength = 1024 +dataLength = 258 +highStart = 0xa00 +shifted12HighStart = 0x1 +type = 0 +valueWidth = 0 +index3NullOffset = 0x7fff +dataNullOffset = 0x0 +nullValue = 0x1 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,1,0x740,1,0x780,2,0x880,3,0x110000,1 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.32.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.32.toml new file mode 100644 index 00000000000000..002b6f260dfa5b --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.32.toml @@ -0,0 +1,113 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: free-blocks.32 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "free-blocks.32" +index = [ + 0,0x40,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,0x80,0xc0,0xc0, + 0xc0,0xc0,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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 +] +data_32 = [ + 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, + 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, + 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, + 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, + 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,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,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 1,0xad +] +indexLength = 1024 +dataLength = 258 +highStart = 0xa00 +shifted12HighStart = 0x1 +type = 0 +valueWidth = 1 +index3NullOffset = 0x7fff +dataNullOffset = 0x0 +nullValue = 0x1 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,1,0x740,1,0x780,2,0x880,3,0x110000,1 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.8.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.8.toml new file mode 100644 index 00000000000000..c8c469cedc4ef2 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.8.toml @@ -0,0 +1,113 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: free-blocks.8 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "free-blocks.8" +index = [ + 0,0x40,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,0x80,0xc0,0xc0, + 0xc0,0xc0,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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 +] +data_8 = [ + 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, + 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, + 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, + 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, + 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,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,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 1,1,1,0xad +] +indexLength = 1024 +dataLength = 260 +highStart = 0xa00 +shifted12HighStart = 0x1 +type = 0 +valueWidth = 2 +index3NullOffset = 0x7fff +dataNullOffset = 0x0 +nullValue = 0x1 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,1,0x740,1,0x780,2,0x880,3,0x110000,1 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.small16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.small16.toml new file mode 100644 index 00000000000000..8a88bcb0318092 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/free-blocks.small16.toml @@ -0,0 +1,53 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: free-blocks.small16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "free-blocks.small16" +index = [ + 0,0x40,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,0x80,0xc0,0xc0, + 0xc0,0xc0,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 +] +data_16 = [ + 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, + 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, + 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, + 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, + 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,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,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 1,0xad +] +indexLength = 64 +dataLength = 258 +highStart = 0xa00 +shifted12HighStart = 0x1 +type = 1 +valueWidth = 0 +index3NullOffset = 0x7fff +dataNullOffset = 0x0 +nullValue = 0x1 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,1,0x740,1,0x780,2,0x880,3,0x110000,1 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.16.toml new file mode 100644 index 00000000000000..4977ec0d856d3b --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.16.toml @@ -0,0 +1,117 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: grow-data.16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "grow-data.16" +index = [ + 0,0x40,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,0x60,0x80,0xa0,0xc0, + 0xc0,0xc0,0xe0,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100 +] +data_16 = [ + 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,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,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,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,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,0xad +] +indexLength = 1024 +dataLength = 322 +highStart = 0xa00 +shifted12HighStart = 0x1 +type = 0 +valueWidth = 0 +index3NullOffset = 0x7fff +dataNullOffset = 0x100 +nullValue = 0x5 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,1,0x720,2,0x7a0,3,0x8a0,4,0x110000,5 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.32.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.32.toml new file mode 100644 index 00000000000000..01ea3c3adffd6b --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.32.toml @@ -0,0 +1,113 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: grow-data.32 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "grow-data.32" +index = [ + 0,0x40,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,0x60,0x80,0xa0,0xc0, + 0xc0,0xc0,0xe0,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100 +] +data_32 = [ + 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,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,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,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,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 0xad +] +indexLength = 1024 +dataLength = 321 +highStart = 0xa00 +shifted12HighStart = 0x1 +type = 0 +valueWidth = 1 +index3NullOffset = 0x7fff +dataNullOffset = 0x100 +nullValue = 0x5 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,1,0x720,2,0x7a0,3,0x8a0,4,0x110000,5 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.8.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.8.toml new file mode 100644 index 00000000000000..ef2c0956a6e6ad --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.8.toml @@ -0,0 +1,113 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: grow-data.8 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "grow-data.8" +index = [ + 0,0x40,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,0x60,0x80,0xa0,0xc0, + 0xc0,0xc0,0xe0,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100 +] +data_8 = [ + 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,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,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,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,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,0xad +] +indexLength = 1024 +dataLength = 324 +highStart = 0xa00 +shifted12HighStart = 0x1 +type = 0 +valueWidth = 2 +index3NullOffset = 0x7fff +dataNullOffset = 0x100 +nullValue = 0x5 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,1,0x720,2,0x7a0,3,0x8a0,4,0x110000,5 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.small16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.small16.toml new file mode 100644 index 00000000000000..1e761f166ca388 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/grow-data.small16.toml @@ -0,0 +1,53 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: grow-data.small16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "grow-data.small16" +index = [ + 0,0x40,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,0x60,0x80,0xa0,0xc0, + 0xc0,0xc0,0xe0,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100 +] +data_16 = [ + 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,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,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,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,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,0xad +] +indexLength = 64 +dataLength = 322 +highStart = 0xa00 +shifted12HighStart = 0x1 +type = 1 +valueWidth = 0 +index3NullOffset = 0x7fff +dataNullOffset = 0x100 +nullValue = 0x5 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,1,0x720,2,0x7a0,3,0x8a0,4,0x110000,5 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/planes.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/planes.toml new file mode 100644 index 00000000000000..d5f5e7d8160311 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/planes.toml @@ -0,0 +1,140 @@ +# This file is part of ICU4X. For terms of use, please see the file +# called LICENSE at the top level of the ICU4X source tree +# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +[code_point_map.data] +long_name = "planes" +name = "planes" +ranges = [ + [0x0, 0xffff, 0], + [0x10000, 0x1ffff, 1], + [0x20000, 0x2ffff, 2], + [0x30000, 0x3ffff, 3], + [0x40000, 0x4ffff, 4], + [0x50000, 0x5ffff, 5], + [0x60000, 0x6ffff, 6], + [0x70000, 0x7ffff, 7], + [0x80000, 0x8ffff, 8], + [0x90000, 0x9ffff, 9], + [0xa0000, 0xaffff, 10], + [0xb0000, 0xbffff, 11], + [0xc0000, 0xcffff, 12], + [0xd0000, 0xdffff, 13], + [0xe0000, 0xeffff, 14], + [0xf0000, 0xfffff, 15], + [0x100000, 0x10ffff, 16], +] + +[code_point_trie.struct] +long_name = "planes" +name = "planes" +index = [ + 0,0x40,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,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, + 0x288,0x290,0x290,0x290,0x2b0,0x2b0,0x2b0,0x2b0,0x2d0,0x2d0,0x2d0,0x2d0,0x2f0,0x2f0,0x2f0,0x2f0, + 0x310,0x310,0x310,0x310,0x330,0x330,0x330,0x330,0x350,0x350,0x350,0x350,0x370,0x370,0x370,0x370, + 0x390,0x390,0x390,0x390,0x3b0,0x3b0,0x3b0,0x3b0,0x3d0,0x3d0,0x3d0,0x3d0,0x3f0,0x3f0,0x3f0,0x3f0, + 0x410,0x410,0x410,0x410,0x430,0x430,0x430,0x430,0x450,0x450,0x450,0x450,0x470,0x470,0x470,0x470, + 0,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0,0x10,0x20,0x30,0,0x10,0x20,0x30, + 0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30, + 0,0x10,0x20,0x30,0,0x10,0x20,0x30,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0, + 0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0, + 0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0, + 0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0, + 0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0, + 0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0, + 0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100, + 0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x100,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110, + 0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110, + 0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120, + 0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120, + 0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x120,0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x130, + 0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x130, + 0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x130,0x140,0x140,0x140,0x140,0x140,0x140,0x140,0x140, + 0x140,0x140,0x140,0x140,0x140,0x140,0x140,0x140,0x140,0x140,0x140,0x140,0x140,0x140,0x140,0x140, + 0x140,0x140,0x140,0x140,0x140,0x140,0x140,0x140,0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150, + 0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150, + 0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x150,0x160,0x160,0x160,0x160,0x160,0x160,0x160,0x160, + 0x160,0x160,0x160,0x160,0x160,0x160,0x160,0x160,0x160,0x160,0x160,0x160,0x160,0x160,0x160,0x160, + 0x160,0x160,0x160,0x160,0x160,0x160,0x160,0x160,0x80,0x88,0x88,0x88,0x88,0x88,0x88,0x88, + 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,2,2, + 0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8, + 0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8, + 0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8, + 0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8, + 0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8, + 0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8, + 0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108, + 0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108,0x108, + 0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128, + 0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128,0x128, + 0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148, + 0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148,0x148, + 0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168, + 0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168,0x168, + 0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188, + 0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188, + 0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8, + 0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8,0x1a8, + 0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8, + 0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8,0x1c8, + 0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8, + 0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8,0x1e8, + 0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208, + 0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208,0x208, + 0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228, + 0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228,0x228, + 0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248, + 0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248,0x248, + 0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268, + 0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268,0x268 +] +data_8 = [ + 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, + 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, + 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, + 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, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc, + 0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, + 0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe, + 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, + 0x10,0x10,0x10,0 +] +indexLength = 1168 +dataLength = 372 +highStart = 0x100000 +shifted12HighStart = 0x100 +type = 1 +valueWidth = 2 +index3NullOffset = 0x2 +dataNullOffset = 0x0 +nullValue = 0x0 diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.16.toml new file mode 100644 index 00000000000000..b9ec8ed16ec92e --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.16.toml @@ -0,0 +1,101 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set-empty.16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set-empty.16" +index = [ + 0,0x40,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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 +] +data_16 = [ + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,0xad +] +indexLength = 1024 +dataLength = 130 +highStart = 0x0 +shifted12HighStart = 0x0 +type = 0 +valueWidth = 0 +index3NullOffset = 0x7fff +dataNullOffset = 0x0 +nullValue = 0x3 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,3,0x110000,3 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.32.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.32.toml new file mode 100644 index 00000000000000..cc3e16726431ae --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.32.toml @@ -0,0 +1,101 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set-empty.32 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set-empty.32" +index = [ + 0,0x40,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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 +] +data_32 = [ + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 0xad +] +indexLength = 1024 +dataLength = 129 +highStart = 0x0 +shifted12HighStart = 0x0 +type = 0 +valueWidth = 1 +index3NullOffset = 0x7fff +dataNullOffset = 0x0 +nullValue = 0x3 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,3,0x110000,3 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.8.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.8.toml new file mode 100644 index 00000000000000..5ce7bba5b5f52b --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.8.toml @@ -0,0 +1,101 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set-empty.8 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set-empty.8" +index = [ + 0,0x40,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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 +] +data_8 = [ + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,0xad +] +indexLength = 1024 +dataLength = 132 +highStart = 0x0 +shifted12HighStart = 0x0 +type = 0 +valueWidth = 2 +index3NullOffset = 0x7fff +dataNullOffset = 0x0 +nullValue = 0x3 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,3,0x110000,3 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.small16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.small16.toml new file mode 100644 index 00000000000000..f61d9fe18ad1f1 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set-empty.small16.toml @@ -0,0 +1,41 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set-empty.small16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set-empty.small16" +index = [ + 0,0x40,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,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 +] +data_16 = [ + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,0xad +] +indexLength = 64 +dataLength = 130 +highStart = 0x0 +shifted12HighStart = 0x0 +type = 1 +valueWidth = 0 +index3NullOffset = 0x7fff +dataNullOffset = 0x0 +nullValue = 0x3 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,3,0x110000,3 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.16.toml new file mode 100644 index 00000000000000..6eac4b7bdc8a76 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.16.toml @@ -0,0 +1,101 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set-single-value.16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set-single-value.16" +index = [ + 0,0x40,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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 +] +data_16 = [ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,0xad +] +indexLength = 1024 +dataLength = 130 +highStart = 0x0 +shifted12HighStart = 0x0 +type = 0 +valueWidth = 0 +index3NullOffset = 0x7fff +dataNullOffset = 0x0 +nullValue = 0x5 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,3,0x110000,5 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.32.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.32.toml new file mode 100644 index 00000000000000..9db848236d6a2a --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.32.toml @@ -0,0 +1,101 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set-single-value.32 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set-single-value.32" +index = [ + 0,0x40,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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 +] +data_32 = [ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 0xad +] +indexLength = 1024 +dataLength = 129 +highStart = 0x0 +shifted12HighStart = 0x0 +type = 0 +valueWidth = 1 +index3NullOffset = 0x7fff +dataNullOffset = 0x0 +nullValue = 0x5 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,3,0x110000,5 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.8.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.8.toml new file mode 100644 index 00000000000000..c92b7a8e1e5dfa --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.8.toml @@ -0,0 +1,101 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set-single-value.8 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set-single-value.8" +index = [ + 0,0x40,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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 +] +data_8 = [ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,0xad +] +indexLength = 1024 +dataLength = 132 +highStart = 0x0 +shifted12HighStart = 0x0 +type = 0 +valueWidth = 2 +index3NullOffset = 0x7fff +dataNullOffset = 0x0 +nullValue = 0x5 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,3,0x110000,5 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.small16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.small16.toml new file mode 100644 index 00000000000000..568362f5565a3d --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set-single-value.small16.toml @@ -0,0 +1,41 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set-single-value.small16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set-single-value.small16" +index = [ + 0,0x40,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,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 +] +data_16 = [ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,0xad +] +indexLength = 64 +dataLength = 130 +highStart = 0x0 +shifted12HighStart = 0x0 +type = 1 +valueWidth = 0 +index3NullOffset = 0x7fff +dataNullOffset = 0x0 +nullValue = 0x5 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,3,0x110000,5 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set1.16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set1.16.toml new file mode 100644 index 00000000000000..e064217ae6f553 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set1.16.toml @@ -0,0 +1,138 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set1.16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set1.16" +index = [ + 0,0x40,0x40,0x59,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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0xb3,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xfb,0x121,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x14d,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x495,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x4bc,0x4bf,0x4bf, + 0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf, + 0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf, + 0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4df,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x1ba,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x1c6,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,0x1d3,0x1da,0x1da,0x1da,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,0x3bc,0x3bc,0x3bc,0x3bc,0x3bc,0x3bc,0x3bc,0x3bc,0x439,0xd0,0xd0, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0x455,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0x475 +] +data_16 = [ + 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, + 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, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 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,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,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,0,0,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,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,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,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0,0,0,0,0,0, + 0,0,0,0,0,0,0xf,0x10,0x10,0x11,0x12,0x12,0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0,0xad +] +indexLength = 1248 +dataLength = 492 +highStart = 0xf0200 +shifted12HighStart = 0xf1 +type = 0 +valueWidth = 0 +index3NullOffset = 0x4 +dataNullOffset = 0x0 +nullValue = 0x0 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,0,0x40,0,0xe7,0x34,0x3400,0,0x9fa6,0x61,0xda9e,0x31,0xdada,0,0xeeee,0xff, + 0x11111,1,0x44444,0x61,0xf0003,0,0xf0004,0xf,0xf0006,0x10,0xf0007,0x11,0xf0040,0x12,0x110000,0 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set1.32.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set1.32.toml new file mode 100644 index 00000000000000..9b7299b37ff82d --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set1.32.toml @@ -0,0 +1,138 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set1.32 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set1.32" +index = [ + 0,0x40,0x40,0x59,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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0xb3,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xfb,0x121,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x14d,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x495,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x4bc,0x4bf,0x4bf, + 0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf, + 0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf, + 0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4df,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x1ba,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x1c6,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,0x1d3,0x1da,0x1da,0x1da,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,0x3bc,0x3bc,0x3bc,0x3bc,0x3bc,0x3bc,0x3bc,0x3bc,0x439,0xd0,0xd0, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0x455,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0x475 +] +data_32 = [ + 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, + 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, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 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,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,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,0,0,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,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,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,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0,0,0,0,0,0, + 0,0,0,0,0,0,0xf,0x10,0x10,0x11,0x12,0x12,0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0,0xad +] +indexLength = 1248 +dataLength = 492 +highStart = 0xf0200 +shifted12HighStart = 0xf1 +type = 0 +valueWidth = 1 +index3NullOffset = 0x4 +dataNullOffset = 0x0 +nullValue = 0x0 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,0,0x40,0,0xe7,0x34,0x3400,0,0x9fa6,0x61,0xda9e,0x31,0xdada,0,0xeeee,0xff, + 0x11111,1,0x44444,0x61,0xf0003,0,0xf0004,0xf,0xf0006,0x10,0xf0007,0x11,0xf0040,0x12,0x110000,0 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set1.8.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set1.8.toml new file mode 100644 index 00000000000000..4d06bf9d3bb635 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set1.8.toml @@ -0,0 +1,138 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set1.8 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set1.8" +index = [ + 0,0x40,0x40,0x59,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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0xb3,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xfb,0x121,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b, + 0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x13b,0x14d,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x495,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x49e,0x4bc,0x4bf,0x4bf, + 0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf, + 0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf, + 0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4bf,0x4df,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b, + 0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x17b,0x1ba,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x1c6,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,0x1d3,0x1da,0x1da,0x1da,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,0x3bc,0x3bc,0x3bc,0x3bc,0x3bc,0x3bc,0x3bc,0x3bc,0x439,0xd0,0xd0, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0x455,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0x475 +] +data_8 = [ + 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, + 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, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 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,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,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,0,0,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,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,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,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0,0,0,0,0,0, + 0,0,0,0,0,0,0xf,0x10,0x10,0x11,0x12,0x12,0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0,0xad +] +indexLength = 1248 +dataLength = 492 +highStart = 0xf0200 +shifted12HighStart = 0xf1 +type = 0 +valueWidth = 2 +index3NullOffset = 0x4 +dataNullOffset = 0x0 +nullValue = 0x0 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,0,0x40,0,0xe7,0x34,0x3400,0,0x9fa6,0x61,0xda9e,0x31,0xdada,0,0xeeee,0xff, + 0x11111,1,0x44444,0x61,0xf0003,0,0xf0004,0xf,0xf0006,0x10,0xf0007,0x11,0xf0040,0x12,0x110000,0 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set1.small16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set1.small16.toml new file mode 100644 index 00000000000000..1a724177591189 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set1.small16.toml @@ -0,0 +1,81 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set1.small16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set1.small16" +index = [ + 0,0x40,0x40,0x59,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,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, + 0x17f,0x199,0x1aa,0x1bd,0x1d5,0x199,0x199,0x199,0x199,0x199,0x199,0x199,0x199,0x199,0x199,0x199, + 0x199,0x1f3,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6, + 0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6, + 0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x1f6,0x216,0,0x10,0x20, + 0x30,0x40,0x50,0x60,0x70,0x40,0x50,0x60,0x70,0x59,0x69,0x79,0x89,0,0x10,0x20, + 0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20, + 0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0xa3,0xa9,0xa9, + 0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9, + 0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xab,0, + 0,0,0xb9,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3, + 0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3, + 0xc3,0xc3,0xc3,0xc5,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3, + 0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3, + 0xd3,0xd3,0xd3,0xd3,0xe2,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x99,0x99,0x99,0xee,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,0xfb, + 0x102,0x102,0x102,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,0x7d, + 0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,0xad,0xad,0xad,0xad,0xad,0xad,0xad, + 0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad, + 0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xb3,0xce,0xce,0xce,0xce,0xce,0xce, + 0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xe5,0xf3,0xf3,0xf3,0xf3,0xf3, + 0xf3,0xf3,0xf3,0xf3,0x105,0x114,0x114,0x114,0x114,0x114,0x114,0x114,0x114,0x123,0xad,0xad, + 0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad, + 0xad,0xad,0xad,0xad,0xad,0x13f,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,0x15f +] +data_16 = [ + 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, + 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, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 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,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0,0,0,0,0,0,0, + 0,0,0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x61,0x61,0,0,0,0,0,0,0,0,0,0,0,0,0xf,0x10, + 0x10,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, + 0x12,0x12,0xad,0,0xad +] +indexLength = 535 +dataLength = 277 +highStart = 0xf0200 +shifted12HighStart = 0xf1 +type = 1 +valueWidth = 0 +index3NullOffset = 0x4 +dataNullOffset = 0x0 +nullValue = 0x0 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,0,0x40,0,0xe7,0x34,0x3400,0,0x9fa6,0x61,0xda9e,0x31,0xdada,0,0xeeee,0xff, + 0x11111,1,0x44444,0x61,0xf0003,0,0xf0004,0xf,0xf0006,0x10,0xf0007,0x11,0xf0040,0x12,0x110000,0 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set2-overlap.16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set2-overlap.16.toml new file mode 100644 index 00000000000000..79bed6eae23665 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set2-overlap.16.toml @@ -0,0 +1,128 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set2-overlap.16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set2-overlap.16" +index = [ + 0,0x40,0x72,0x95,0xb3,0xb3,0xb3,0xb3,0xf2,0xf2,0xf2,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0x45e,0x45e,0x45e,0x45e,0x45e,0x45e,0x45e,0x462,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0x132,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135, + 0x13e,0x145,0x145,0x145,0x145,0x145,0x145,0x145,0x145,0x145,0x14d,0x135,0x135,0x135,0x135,0x135, + 0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135, + 0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x155,0x161,0x161,0x161,0x161, + 0x161,0x161,0x161,0x161,0x161,0x161,0x161,0x161,0x167,0x172,0xb3,0xb3,0xb3,0xb3,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0x408,0x421, + 0x42b,0x43e +] +data_16 = [ + 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, + 0,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,4,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,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,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,0,0,0,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a, + 0x7a,0x7a,0x7a,0x7a,0x7a,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a, + 0x7a,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,0,0,0,0,0,0,0,0,0,0,0,7,7,7, + 7,7,0,0xad +] +indexLength = 1154 +dataLength = 388 +highStart = 0x30000 +shifted12HighStart = 0x30 +type = 0 +valueWidth = 0 +index3NullOffset = 0xb +dataNullOffset = 0xb3 +nullValue = 0x0 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,0,0x21,0,0x72,0x5555,0xdd,3,0xde,4,0x201,0,0x240,6,0x241,0, + 0x280,6,0x281,0,0x2c0,6,0x2f883,0,0x2f987,0x7a,0x2fa98,5,0x2fedc,0x7a,0x2ffaa,1, + 0x2ffab,2,0x2ffbb,0,0x2ffc0,7,0x110000,0 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set2-overlap.32.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set2-overlap.32.toml new file mode 100644 index 00000000000000..7582d9608ee5d4 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set2-overlap.32.toml @@ -0,0 +1,128 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set2-overlap.32 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set2-overlap.32" +index = [ + 0,0x40,0x72,0x95,0xb3,0xb3,0xb3,0xb3,0xf2,0xf2,0xf2,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0x45e,0x45e,0x45e,0x45e,0x45e,0x45e,0x45e,0x462,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0x132,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135, + 0x13e,0x145,0x145,0x145,0x145,0x145,0x145,0x145,0x145,0x145,0x14d,0x135,0x135,0x135,0x135,0x135, + 0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135, + 0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x155,0x161,0x161,0x161,0x161, + 0x161,0x161,0x161,0x161,0x161,0x161,0x161,0x161,0x167,0x172,0xb3,0xb3,0xb3,0xb3,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0x408,0x421, + 0x42b,0x43e +] +data_32 = [ + 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, + 0,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,4,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,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,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,0,0,0,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a, + 0x7a,0x7a,0x7a,0x7a,0x7a,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a, + 0x7a,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,0,0,0,0,0,0,0,0,0,0,0,7,7,7, + 7,7,0,0xad +] +indexLength = 1154 +dataLength = 388 +highStart = 0x30000 +shifted12HighStart = 0x30 +type = 0 +valueWidth = 1 +index3NullOffset = 0xb +dataNullOffset = 0xb3 +nullValue = 0x0 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,0,0x21,0,0x72,0x5555,0xdd,3,0xde,4,0x201,0,0x240,6,0x241,0, + 0x280,6,0x281,0,0x2c0,6,0x2f883,0,0x2f987,0x7a,0x2fa98,5,0x2fedc,0x7a,0x2ffaa,1, + 0x2ffab,2,0x2ffbb,0,0x2ffc0,7,0x110000,0 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set2-overlap.small16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set2-overlap.small16.toml new file mode 100644 index 00000000000000..08741aca228e02 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set2-overlap.small16.toml @@ -0,0 +1,73 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set2-overlap.small16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set2-overlap.small16" +index = [ + 0,0x40,0x72,0x95,0xb3,0xb3,0xb3,0xb3,0xf2,0xf2,0xf2,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xee,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xfa,0,0x10,0x20,0x30, + 0x40,0x50,0x60,0x70,0x72,0x82,0x92,0xa2,0x95,0xa5,0xb5,0xc5,0xb3,0xc3,0xd3,0xe3, + 0xb3,0xc3,0xd3,0xe3,0xb3,0xc3,0xd3,0xe3,0xb3,0xc3,0xd3,0xe3,0xf2,0x102,0x112,0x122, + 0xf2,0x102,0x112,0x122,0xf2,0x102,0x112,0x122,0xb3,0xc3,0xd3,0xe3,0xb3,0xc3,0xd3,0xe3, + 0xb3,0xc3,0xd3,0xe3,0xb3,0xc3,0xd3,0xe3,0xb3,0xc3,0xd3,0xe3,0xb3,0xc3,0xd3,0xe3, + 0xb3,0xc3,0xd3,0xe3,0xb3,0xc3,0xd3,0xe3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0x132,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135, + 0x13e,0x145,0x145,0x145,0x145,0x145,0x145,0x145,0x145,0x145,0x14d,0x135,0x135,0x135,0x135,0x135, + 0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135, + 0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x135,0x155,0x161,0x161,0x161,0x161, + 0x161,0x161,0x161,0x161,0x161,0x161,0x161,0x161,0x167,0x172,0xb3,0xb3,0xb3,0xb3,0x4c,0x6c, + 0x78,0x78,0x78,0x78,0x78,0x78,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xb,0xb,0xb,0xb,0xb,0xb,0x98,0xb1,0xbb,0xce +] +data_16 = [ + 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, + 0,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555,0x5555, + 0x5555,0x5555,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,4,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,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,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,0,0,0,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a, + 0x7a,0x7a,0x7a,0x7a,0x7a,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a, + 0x7a,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,0,0,0,0,0,0,0,0,0,0,0,7,7,7, + 7,7,0,0xad +] +indexLength = 282 +dataLength = 388 +highStart = 0x30000 +shifted12HighStart = 0x30 +type = 1 +valueWidth = 0 +index3NullOffset = 0xb +dataNullOffset = 0xb3 +nullValue = 0x0 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,0,0x21,0,0x72,0x5555,0xdd,3,0xde,4,0x201,0,0x240,6,0x241,0, + 0x280,6,0x281,0,0x2c0,6,0x2f883,0,0x2f987,0x7a,0x2fa98,5,0x2fedc,0x7a,0x2ffaa,1, + 0x2ffab,2,0x2ffbb,0,0x2ffc0,7,0x110000,0 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.16.toml new file mode 100644 index 00000000000000..c94365e84cc92a --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.16.toml @@ -0,0 +1,128 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set3-initial-9.16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set3-initial-9.16" +index = [ + 0,0x40,0x5c,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xf7,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137, + 0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137, + 0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137, + 0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x177, + 0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184, + 0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184, + 0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184, + 0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184, + 0x184,0x184,0x184,0x1a6,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x1da,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6 +] +data_16 = [ + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,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,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,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 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,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,2,2,2,2, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,9,9,9,9,9,9,9,9,9, + 9,9,9,9,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,0xad +] +indexLength = 1024 +dataLength = 552 +highStart = 0xce00 +shifted12HighStart = 0xd +type = 0 +valueWidth = 0 +index3NullOffset = 0x7fff +dataNullOffset = 0x80 +nullValue = 0x9 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,9,0x31,9,0xa4,1,0x3400,9,0x6789,2,0x9000,9,0xa000,4,0xabcd,9, + 0xbcde,3,0xcccc,9,0x110000,6 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.32.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.32.toml new file mode 100644 index 00000000000000..1a0c9732c8dff4 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.32.toml @@ -0,0 +1,128 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set3-initial-9.32 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set3-initial-9.32" +index = [ + 0,0x40,0x5c,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xf7,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137, + 0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137, + 0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137, + 0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x177, + 0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184, + 0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184, + 0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184, + 0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184, + 0x184,0x184,0x184,0x1a6,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x1da,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6 +] +data_32 = [ + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,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,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,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 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,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,2,2,2,2, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,9,9,9,9,9,9,9,9,9, + 9,9,9,9,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,0xad +] +indexLength = 1024 +dataLength = 551 +highStart = 0xce00 +shifted12HighStart = 0xd +type = 0 +valueWidth = 1 +index3NullOffset = 0x7fff +dataNullOffset = 0x80 +nullValue = 0x9 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,9,0x31,9,0xa4,1,0x3400,9,0x6789,2,0x9000,9,0xa000,4,0xabcd,9, + 0xbcde,3,0xcccc,9,0x110000,6 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.8.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.8.toml new file mode 100644 index 00000000000000..5008268b71ac9f --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.8.toml @@ -0,0 +1,128 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set3-initial-9.8 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set3-initial-9.8" +index = [ + 0,0x40,0x5c,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xf7,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137, + 0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137, + 0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137, + 0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137,0x137, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x177, + 0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184, + 0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184, + 0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184, + 0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184,0x184, + 0x184,0x184,0x184,0x1a6,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x1da,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6, + 0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6,0x1e6 +] +data_8 = [ + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,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,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,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 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,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,2,2,2,2, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,9,9,9,9,9,9,9,9,9, + 9,9,9,9,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,0xad +] +indexLength = 1024 +dataLength = 552 +highStart = 0xce00 +shifted12HighStart = 0xd +type = 0 +valueWidth = 2 +index3NullOffset = 0x7fff +dataNullOffset = 0x80 +nullValue = 0x9 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,9,0x31,9,0xa4,1,0x3400,9,0x6789,2,0x9000,9,0xa000,4,0xabcd,9, + 0xbcde,3,0xcccc,9,0x110000,6 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.small16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.small16.toml new file mode 100644 index 00000000000000..aee1538455db75 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/set3-initial-9.small16.toml @@ -0,0 +1,72 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: set3-initial-9.small16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "set3-initial-9.small16" +index = [ + 0,0x40,0x5c,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x11c,0x136,0x14e,0x16d,0,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x5c,0x6c,0x7c,0x8c, + 0x80,0x90,0xa0,0xb0,0x80,0x90,0xa0,0xb0,0x80,0x90,0xa0,0xb0,0x80,0x90,0xa0,0xb0, + 0x80,0x90,0xa0,0xb0,0x80,0x90,0xa0,0xb0,0x80,0x90,0xa0,0xb0,0x80,0x90,0xa0,0xb0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc7,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7, + 0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7, + 0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0xe7,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4, + 0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4, + 0xf4,0xf4,0xf4,0xf4,0xf4,0xf6,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x104,0x110,0x110,0x110,0x110,0x110,0x110,0x110, + 0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x44,0x50,0x50,0x50, + 0x50,0x50,0x50,0x50,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70, + 0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x78,3,3,3,3,3,3, + 3,3,3,3,3,3,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,3,3, + 3,3,3,0xb8,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xe8,3,3,3, + 3,3,3,0xfc +] +data_16 = [ + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,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,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,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 9,9,9,9,9,9,9,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,9,9,9,9,9,9,9,9,9, + 9,9,9,9,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,9,9,9,9,9,9,9,9,9,9,9,9, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,0xad +] +indexLength = 372 +dataLength = 290 +highStart = 0xce00 +shifted12HighStart = 0xd +type = 1 +valueWidth = 0 +index3NullOffset = 0x3 +dataNullOffset = 0x80 +nullValue = 0x9 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0,9,0x31,9,0xa4,1,0x3400,9,0x6789,2,0x9000,9,0xa000,4,0xabcd,9, + 0xbcde,3,0xcccc,9,0x110000,6 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/short-all-same.16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/short-all-same.16.toml new file mode 100644 index 00000000000000..c8156e69b0054f --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/short-all-same.16.toml @@ -0,0 +1,321 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: short-all-same.small16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "short-all-same.small16" +index = [ + 0,0x40,0x80,0xc0,0x100,0x140,0x180,0x1c0,0x200,0x240,0x280,0x2c0,0x300,0x340,0x380,0x3c0, + 0x400,0x440,0x480,0x4c0,0x500,0x540,0x580,0x5c0,0x600,0x640,0x680,0x6c0,0x700,0x740,0x780,0x7c0, + 0x800,0x840,0x880,0x8c0,0x900,0x940,0x980,0x9c0,0xa00,0xa40,0xa80,0xac0,0xb00,0xb40,0xb80,0xbc0, + 0xc00,0xc40,0xc80,0xcc0,0xd00,0xd40,0xd80,0xdc0,0xe00,0xe40,0xe80,0xec0,0xf00,0xf40,0xf80,0xfc0 +] +data_16 = [ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc, + 0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, + 0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe, + 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d, + 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21, + 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, + 0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25, + 0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26, + 0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27, + 0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28, + 0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29, + 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, + 0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b, + 0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c, + 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d, + 0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e, + 0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32, + 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35, + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + 0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37, + 0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38, + 0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, + 0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a, + 0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b, + 0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c, + 0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d, + 0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, + 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42, + 0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45, + 0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46, + 0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47, + 0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48, + 0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49, + 0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a, + 0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b, + 0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c, + 0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, + 0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e, + 0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f, + 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50, + 0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51, + 0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52, + 0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53, + 0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54, + 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, + 0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56, + 0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57, + 0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58, + 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59, + 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, + 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, + 0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c, + 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, + 0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e, + 0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f, + 0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62, + 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63, + 0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, + 0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65, + 0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66, + 0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67, + 0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68, + 0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69, + 0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a, + 0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b, + 0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c, + 0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d, + 0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, + 0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f, + 0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70, + 0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71, + 0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72, + 0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73, + 0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74, + 0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75, + 0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76, + 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, + 0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78, + 0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79, + 0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a, + 0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b, + 0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c, + 0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d, + 0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e, + 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81, + 0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82, + 0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85, + 0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86, + 0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87, + 0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88, + 0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89, + 0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a, + 0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b, + 0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c, + 0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d, + 0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e, + 0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f, + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91, + 0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92, + 0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93, + 0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94, + 0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95, + 0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96, + 0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97, + 0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a, + 0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b, + 0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c, + 0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d, + 0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e, + 0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f, + 0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0, + 0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1, + 0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2, + 0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3, + 0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4, + 0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5, + 0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6, + 0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7, + 0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8, + 0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab, + 0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac, + 0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad, + 0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae, + 0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf, + 0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0, + 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, + 0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4, + 0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5, + 0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6, + 0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7, + 0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8, + 0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9, + 0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba, + 0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb, + 0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc, + 0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd, + 0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe, + 0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1, + 0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2, + 0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3, + 0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, + 0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5, + 0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6, + 0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7, + 0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8, + 0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9, + 0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca, + 0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb, + 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc, + 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd, + 0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce, + 0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0, + 0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1, + 0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2, + 0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3, + 0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4, + 0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5, + 0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6, + 0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7, + 0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb, + 0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc, + 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, + 0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde, + 0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf, + 0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2, + 0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3, + 0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4, + 0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5, + 0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6, + 0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7, + 0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8, + 0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9, + 0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea, + 0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb, + 0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec, + 0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed, + 0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee, + 0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef, + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, + 0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1, + 0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2, + 0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3, + 0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4, + 0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5, + 0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6, + 0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7, + 0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8, + 0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9, + 0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa, + 0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb, + 0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc, + 0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd, + 0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0,0xad +] +indexLength = 64 +dataLength = 4098 +highStart = 0x1000 +shifted12HighStart = 0x1 +type = 1 +valueWidth = 0 +index3NullOffset = 0x7fff +dataNullOffset = 0xfffff +nullValue = 0x0 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0x10,0,0x20,1,0x30,2,0x40,3,0x50,4,0x60,5,0x70,6,0x80,7, + 0x90,8,0xa0,9,0xb0,0xa,0xc0,0xb,0xd0,0xc,0xe0,0xd,0xf0,0xe,0x100,0xf, + 0x110,0x10,0x120,0x11,0x130,0x12,0x140,0x13,0x150,0x14,0x160,0x15,0x170,0x16,0x180,0x17, + 0x190,0x18,0x1a0,0x19,0x1b0,0x1a,0x1c0,0x1b,0x1d0,0x1c,0x1e0,0x1d,0x1f0,0x1e,0x200,0x1f, + 0x210,0x20,0x220,0x21,0x230,0x22,0x240,0x23,0x250,0x24,0x260,0x25,0x270,0x26,0x280,0x27, + 0x290,0x28,0x2a0,0x29,0x2b0,0x2a,0x2c0,0x2b,0x2d0,0x2c,0x2e0,0x2d,0x2f0,0x2e,0x300,0x2f, + 0x310,0x30,0x320,0x31,0x330,0x32,0x340,0x33,0x350,0x34,0x360,0x35,0x370,0x36,0x380,0x37, + 0x390,0x38,0x3a0,0x39,0x3b0,0x3a,0x3c0,0x3b,0x3d0,0x3c,0x3e0,0x3d,0x3f0,0x3e,0x400,0x3f, + 0x410,0x40,0x420,0x41,0x430,0x42,0x440,0x43,0x450,0x44,0x460,0x45,0x470,0x46,0x480,0x47, + 0x490,0x48,0x4a0,0x49,0x4b0,0x4a,0x4c0,0x4b,0x4d0,0x4c,0x4e0,0x4d,0x4f0,0x4e,0x500,0x4f, + 0x510,0x50,0x520,0x51,0x530,0x52,0x540,0x53,0x550,0x54,0x560,0x55,0x570,0x56,0x580,0x57, + 0x590,0x58,0x5a0,0x59,0x5b0,0x5a,0x5c0,0x5b,0x5d0,0x5c,0x5e0,0x5d,0x5f0,0x5e,0x600,0x5f, + 0x610,0x60,0x620,0x61,0x630,0x62,0x640,0x63,0x650,0x64,0x660,0x65,0x670,0x66,0x680,0x67, + 0x690,0x68,0x6a0,0x69,0x6b0,0x6a,0x6c0,0x6b,0x6d0,0x6c,0x6e0,0x6d,0x6f0,0x6e,0x700,0x6f, + 0x710,0x70,0x720,0x71,0x730,0x72,0x740,0x73,0x750,0x74,0x760,0x75,0x770,0x76,0x780,0x77, + 0x790,0x78,0x7a0,0x79,0x7b0,0x7a,0x7c0,0x7b,0x7d0,0x7c,0x7e0,0x7d,0x7f0,0x7e,0x800,0x7f, + 0x810,0x80,0x820,0x81,0x830,0x82,0x840,0x83,0x850,0x84,0x860,0x85,0x870,0x86,0x880,0x87, + 0x890,0x88,0x8a0,0x89,0x8b0,0x8a,0x8c0,0x8b,0x8d0,0x8c,0x8e0,0x8d,0x8f0,0x8e,0x900,0x8f, + 0x910,0x90,0x920,0x91,0x930,0x92,0x940,0x93,0x950,0x94,0x960,0x95,0x970,0x96,0x980,0x97, + 0x990,0x98,0x9a0,0x99,0x9b0,0x9a,0x9c0,0x9b,0x9d0,0x9c,0x9e0,0x9d,0x9f0,0x9e,0xa00,0x9f, + 0xa10,0xa0,0xa20,0xa1,0xa30,0xa2,0xa40,0xa3,0xa50,0xa4,0xa60,0xa5,0xa70,0xa6,0xa80,0xa7, + 0xa90,0xa8,0xaa0,0xa9,0xab0,0xaa,0xac0,0xab,0xad0,0xac,0xae0,0xad,0xaf0,0xae,0xb00,0xaf, + 0xb10,0xb0,0xb20,0xb1,0xb30,0xb2,0xb40,0xb3,0xb50,0xb4,0xb60,0xb5,0xb70,0xb6,0xb80,0xb7, + 0xb90,0xb8,0xba0,0xb9,0xbb0,0xba,0xbc0,0xbb,0xbd0,0xbc,0xbe0,0xbd,0xbf0,0xbe,0xc00,0xbf, + 0xc10,0xc0,0xc20,0xc1,0xc30,0xc2,0xc40,0xc3,0xc50,0xc4,0xc60,0xc5,0xc70,0xc6,0xc80,0xc7, + 0xc90,0xc8,0xca0,0xc9,0xcb0,0xca,0xcc0,0xcb,0xcd0,0xcc,0xce0,0xcd,0xcf0,0xce,0xd00,0xcf, + 0xd10,0xd0,0xd20,0xd1,0xd30,0xd2,0xd40,0xd3,0xd50,0xd4,0xd60,0xd5,0xd70,0xd6,0xd80,0xd7, + 0xd90,0xd8,0xda0,0xd9,0xdb0,0xda,0xdc0,0xdb,0xdd0,0xdc,0xde0,0xdd,0xdf0,0xde,0xe00,0xdf, + 0xe10,0xe0,0xe20,0xe1,0xe30,0xe2,0xe40,0xe3,0xe50,0xe4,0xe60,0xe5,0xe70,0xe6,0xe80,0xe7, + 0xe90,0xe8,0xea0,0xe9,0xeb0,0xea,0xec0,0xeb,0xed0,0xec,0xee0,0xed,0xef0,0xee,0xf00,0xef, + 0xf10,0xf0,0xf20,0xf1,0xf30,0xf2,0xf40,0xf3,0xf50,0xf4,0xf60,0xf5,0xf70,0xf6,0xf80,0xf7, + 0xf90,0xf8,0xfa0,0xf9,0xfb0,0xfa,0xfc0,0xfb,0xfd0,0xfc,0xfe0,0xfd,0xff0,0xfe,0x1000,0xff, + 0x110000,0 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/short-all-same.8.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/short-all-same.8.toml new file mode 100644 index 00000000000000..e1b264884780df --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/short-all-same.8.toml @@ -0,0 +1,385 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: short-all-same.8 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "short-all-same.8" +index = [ + 0,0x40,0x80,0xc0,0x100,0x140,0x180,0x1c0,0x200,0x240,0x280,0x2c0,0x300,0x340,0x380,0x3c0, + 0x400,0x440,0x480,0x4c0,0x500,0x540,0x580,0x5c0,0x600,0x640,0x680,0x6c0,0x700,0x740,0x780,0x7c0, + 0x800,0x840,0x880,0x8c0,0x900,0x940,0x980,0x9c0,0xa00,0xa40,0xa80,0xac0,0xb00,0xb40,0xb80,0xbc0, + 0xc00,0xc40,0xc80,0xcc0,0xd00,0xd40,0xd80,0xdc0,0xe00,0xe40,0xe80,0xec0,0xf00,0xf40,0xf80,0xfc0, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, + 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000 +] +data_8 = [ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc, + 0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, + 0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe, + 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d, + 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21, + 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, + 0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25, + 0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26, + 0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27, + 0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28, + 0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29, + 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, + 0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b, + 0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c, + 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d, + 0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e, + 0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32, + 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35, + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + 0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37, + 0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38, + 0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, + 0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a, + 0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b, + 0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c, + 0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d, + 0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, + 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42, + 0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45, + 0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46, + 0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47, + 0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48, + 0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49, + 0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a, + 0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b, + 0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c, + 0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, + 0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e, + 0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f, + 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50, + 0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51, + 0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52, + 0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53, + 0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54, + 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, + 0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56, + 0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57, + 0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58, + 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59, + 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, + 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, + 0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c, + 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, + 0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e, + 0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f, + 0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62, + 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63, + 0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, + 0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65, + 0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66, + 0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67, + 0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68, + 0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69, + 0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a, + 0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b, + 0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c, + 0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d, + 0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, + 0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f, + 0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70, + 0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71, + 0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72, + 0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73, + 0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74, + 0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75, + 0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76, + 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, + 0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78, + 0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79, + 0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a, + 0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b, + 0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c, + 0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d, + 0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e, + 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81, + 0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82, + 0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85, + 0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86, + 0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87, + 0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88, + 0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89, + 0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a, + 0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b, + 0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c, + 0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d, + 0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e, + 0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f, + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91, + 0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92, + 0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93, + 0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94, + 0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95, + 0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96, + 0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97, + 0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a, + 0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b, + 0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c, + 0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d, + 0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e, + 0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f, + 0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0, + 0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1, + 0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2, + 0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3, + 0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4, + 0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5, + 0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6, + 0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7, + 0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8, + 0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab, + 0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac, + 0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad, + 0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae, + 0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf, + 0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0, + 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, + 0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4, + 0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5, + 0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6, + 0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7, + 0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8, + 0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9, + 0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba, + 0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb, + 0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc, + 0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd, + 0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe, + 0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1, + 0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2, + 0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3, + 0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, + 0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5, + 0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6, + 0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7, + 0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8, + 0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9, + 0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca, + 0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb, + 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc, + 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd, + 0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce, + 0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0, + 0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1, + 0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2, + 0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3, + 0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4, + 0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5, + 0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6, + 0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7, + 0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb, + 0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc, + 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, + 0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde, + 0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf, + 0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2, + 0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3, + 0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4, + 0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5, + 0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6, + 0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7, + 0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8, + 0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9, + 0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea, + 0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb, + 0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec, + 0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed, + 0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee, + 0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef, + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, + 0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1, + 0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2, + 0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3, + 0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4, + 0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5, + 0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6, + 0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7, + 0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8, + 0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9, + 0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa, + 0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb, + 0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc, + 0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd, + 0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 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, + 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, + 0,0,0,0xad +] +indexLength = 1024 +dataLength = 4164 +highStart = 0x1000 +shifted12HighStart = 0x1 +type = 0 +valueWidth = 2 +index3NullOffset = 0x7fff +dataNullOffset = 0x1000 +nullValue = 0x0 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0x10,0,0x20,1,0x30,2,0x40,3,0x50,4,0x60,5,0x70,6,0x80,7, + 0x90,8,0xa0,9,0xb0,0xa,0xc0,0xb,0xd0,0xc,0xe0,0xd,0xf0,0xe,0x100,0xf, + 0x110,0x10,0x120,0x11,0x130,0x12,0x140,0x13,0x150,0x14,0x160,0x15,0x170,0x16,0x180,0x17, + 0x190,0x18,0x1a0,0x19,0x1b0,0x1a,0x1c0,0x1b,0x1d0,0x1c,0x1e0,0x1d,0x1f0,0x1e,0x200,0x1f, + 0x210,0x20,0x220,0x21,0x230,0x22,0x240,0x23,0x250,0x24,0x260,0x25,0x270,0x26,0x280,0x27, + 0x290,0x28,0x2a0,0x29,0x2b0,0x2a,0x2c0,0x2b,0x2d0,0x2c,0x2e0,0x2d,0x2f0,0x2e,0x300,0x2f, + 0x310,0x30,0x320,0x31,0x330,0x32,0x340,0x33,0x350,0x34,0x360,0x35,0x370,0x36,0x380,0x37, + 0x390,0x38,0x3a0,0x39,0x3b0,0x3a,0x3c0,0x3b,0x3d0,0x3c,0x3e0,0x3d,0x3f0,0x3e,0x400,0x3f, + 0x410,0x40,0x420,0x41,0x430,0x42,0x440,0x43,0x450,0x44,0x460,0x45,0x470,0x46,0x480,0x47, + 0x490,0x48,0x4a0,0x49,0x4b0,0x4a,0x4c0,0x4b,0x4d0,0x4c,0x4e0,0x4d,0x4f0,0x4e,0x500,0x4f, + 0x510,0x50,0x520,0x51,0x530,0x52,0x540,0x53,0x550,0x54,0x560,0x55,0x570,0x56,0x580,0x57, + 0x590,0x58,0x5a0,0x59,0x5b0,0x5a,0x5c0,0x5b,0x5d0,0x5c,0x5e0,0x5d,0x5f0,0x5e,0x600,0x5f, + 0x610,0x60,0x620,0x61,0x630,0x62,0x640,0x63,0x650,0x64,0x660,0x65,0x670,0x66,0x680,0x67, + 0x690,0x68,0x6a0,0x69,0x6b0,0x6a,0x6c0,0x6b,0x6d0,0x6c,0x6e0,0x6d,0x6f0,0x6e,0x700,0x6f, + 0x710,0x70,0x720,0x71,0x730,0x72,0x740,0x73,0x750,0x74,0x760,0x75,0x770,0x76,0x780,0x77, + 0x790,0x78,0x7a0,0x79,0x7b0,0x7a,0x7c0,0x7b,0x7d0,0x7c,0x7e0,0x7d,0x7f0,0x7e,0x800,0x7f, + 0x810,0x80,0x820,0x81,0x830,0x82,0x840,0x83,0x850,0x84,0x860,0x85,0x870,0x86,0x880,0x87, + 0x890,0x88,0x8a0,0x89,0x8b0,0x8a,0x8c0,0x8b,0x8d0,0x8c,0x8e0,0x8d,0x8f0,0x8e,0x900,0x8f, + 0x910,0x90,0x920,0x91,0x930,0x92,0x940,0x93,0x950,0x94,0x960,0x95,0x970,0x96,0x980,0x97, + 0x990,0x98,0x9a0,0x99,0x9b0,0x9a,0x9c0,0x9b,0x9d0,0x9c,0x9e0,0x9d,0x9f0,0x9e,0xa00,0x9f, + 0xa10,0xa0,0xa20,0xa1,0xa30,0xa2,0xa40,0xa3,0xa50,0xa4,0xa60,0xa5,0xa70,0xa6,0xa80,0xa7, + 0xa90,0xa8,0xaa0,0xa9,0xab0,0xaa,0xac0,0xab,0xad0,0xac,0xae0,0xad,0xaf0,0xae,0xb00,0xaf, + 0xb10,0xb0,0xb20,0xb1,0xb30,0xb2,0xb40,0xb3,0xb50,0xb4,0xb60,0xb5,0xb70,0xb6,0xb80,0xb7, + 0xb90,0xb8,0xba0,0xb9,0xbb0,0xba,0xbc0,0xbb,0xbd0,0xbc,0xbe0,0xbd,0xbf0,0xbe,0xc00,0xbf, + 0xc10,0xc0,0xc20,0xc1,0xc30,0xc2,0xc40,0xc3,0xc50,0xc4,0xc60,0xc5,0xc70,0xc6,0xc80,0xc7, + 0xc90,0xc8,0xca0,0xc9,0xcb0,0xca,0xcc0,0xcb,0xcd0,0xcc,0xce0,0xcd,0xcf0,0xce,0xd00,0xcf, + 0xd10,0xd0,0xd20,0xd1,0xd30,0xd2,0xd40,0xd3,0xd50,0xd4,0xd60,0xd5,0xd70,0xd6,0xd80,0xd7, + 0xd90,0xd8,0xda0,0xd9,0xdb0,0xda,0xdc0,0xdb,0xdd0,0xdc,0xde0,0xdd,0xdf0,0xde,0xe00,0xdf, + 0xe10,0xe0,0xe20,0xe1,0xe30,0xe2,0xe40,0xe3,0xe50,0xe4,0xe60,0xe5,0xe70,0xe6,0xe80,0xe7, + 0xe90,0xe8,0xea0,0xe9,0xeb0,0xea,0xec0,0xeb,0xed0,0xec,0xee0,0xed,0xef0,0xee,0xf00,0xef, + 0xf10,0xf0,0xf20,0xf1,0xf30,0xf2,0xf40,0xf3,0xf50,0xf4,0xf60,0xf5,0xf70,0xf6,0xf80,0xf7, + 0xf90,0xf8,0xfa0,0xf9,0xfb0,0xfa,0xfc0,0xfb,0xfd0,0xfc,0xfe0,0xfd,0xff0,0xfe,0x1000,0xff, + 0x110000,0 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/short-all-same.small16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/short-all-same.small16.toml new file mode 100644 index 00000000000000..c8156e69b0054f --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/short-all-same.small16.toml @@ -0,0 +1,321 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: short-all-same.small16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "short-all-same.small16" +index = [ + 0,0x40,0x80,0xc0,0x100,0x140,0x180,0x1c0,0x200,0x240,0x280,0x2c0,0x300,0x340,0x380,0x3c0, + 0x400,0x440,0x480,0x4c0,0x500,0x540,0x580,0x5c0,0x600,0x640,0x680,0x6c0,0x700,0x740,0x780,0x7c0, + 0x800,0x840,0x880,0x8c0,0x900,0x940,0x980,0x9c0,0xa00,0xa40,0xa80,0xac0,0xb00,0xb40,0xb80,0xbc0, + 0xc00,0xc40,0xc80,0xcc0,0xd00,0xd40,0xd80,0xdc0,0xe00,0xe40,0xe80,0xec0,0xf00,0xf40,0xf80,0xfc0 +] +data_16 = [ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, + 0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb,0xb, + 0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc, + 0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, + 0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe,0xe, + 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d, + 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21, + 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, + 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, + 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, + 0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25, + 0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26, + 0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27, + 0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28, + 0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29, + 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, + 0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b, + 0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c, + 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d, + 0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e, + 0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31, + 0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32, + 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34, + 0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35, + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + 0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37, + 0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38, + 0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, + 0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a, + 0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b, + 0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c, + 0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d, + 0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e,0x3e, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, + 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42, + 0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44, + 0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45, + 0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46, + 0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47, + 0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48, + 0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49, + 0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a, + 0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b,0x4b, + 0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c, + 0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, + 0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e,0x4e, + 0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f, + 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50, + 0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51,0x51, + 0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52, + 0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53, + 0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x54, + 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, + 0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56,0x56, + 0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57,0x57, + 0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58,0x58, + 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59, + 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, + 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, + 0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c,0x5c, + 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, + 0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e,0x5e, + 0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f,0x5f, + 0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60, + 0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61,0x61, + 0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62, + 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63, + 0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, + 0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65, + 0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66, + 0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67, + 0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68, + 0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69,0x69, + 0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a, + 0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b, + 0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c, + 0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d,0x6d, + 0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, + 0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f,0x6f, + 0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70, + 0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71,0x71, + 0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72,0x72, + 0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73, + 0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74,0x74, + 0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x75, + 0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76, + 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, + 0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78, + 0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79,0x79, + 0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a,0x7a, + 0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b, + 0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c, + 0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d, + 0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e, + 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81,0x81, + 0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82, + 0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83, + 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, + 0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85,0x85, + 0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86, + 0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87, + 0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88, + 0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x89, + 0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a, + 0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b,0x8b, + 0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8c, + 0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d, + 0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e, + 0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f, + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91, + 0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92, + 0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93, + 0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94, + 0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95, + 0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96, + 0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97, + 0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98, + 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99, + 0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a, + 0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b, + 0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c, + 0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d, + 0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e, + 0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f, + 0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0, + 0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1, + 0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2, + 0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3, + 0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4,0xa4, + 0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5, + 0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6, + 0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7,0xa7, + 0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8, + 0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab,0xab, + 0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac,0xac, + 0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad,0xad, + 0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae,0xae, + 0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf, + 0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0,0xb0, + 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, + 0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2, + 0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3, + 0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4, + 0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5, + 0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6, + 0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7,0xb7, + 0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8,0xb8, + 0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9,0xb9, + 0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba, + 0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb,0xbb, + 0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc,0xbc, + 0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd, + 0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe, + 0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf, + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, + 0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1, + 0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2,0xc2, + 0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3, + 0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, + 0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5, + 0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6, + 0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7, + 0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8, + 0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9, + 0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca, + 0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb,0xcb, + 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc, + 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd, + 0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce,0xce, + 0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0, + 0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1, + 0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2, + 0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3,0xd3, + 0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4,0xd4, + 0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5, + 0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6, + 0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7, + 0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8, + 0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9,0xd9, + 0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda, + 0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb, + 0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc,0xdc, + 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, + 0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde,0xde, + 0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf,0xdf, + 0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2, + 0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3, + 0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4, + 0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5, + 0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6, + 0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7, + 0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8, + 0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9, + 0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea,0xea, + 0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb, + 0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec,0xec, + 0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed,0xed, + 0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee,0xee, + 0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef,0xef, + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, + 0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1, + 0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2, + 0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3,0xf3, + 0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4,0xf4, + 0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf5, + 0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6, + 0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7, + 0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8, + 0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9, + 0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa, + 0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb, + 0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc, + 0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd, + 0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0,0xad +] +indexLength = 64 +dataLength = 4098 +highStart = 0x1000 +shifted12HighStart = 0x1 +type = 1 +valueWidth = 0 +index3NullOffset = 0x7fff +dataNullOffset = 0xfffff +nullValue = 0x0 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0x10,0,0x20,1,0x30,2,0x40,3,0x50,4,0x60,5,0x70,6,0x80,7, + 0x90,8,0xa0,9,0xb0,0xa,0xc0,0xb,0xd0,0xc,0xe0,0xd,0xf0,0xe,0x100,0xf, + 0x110,0x10,0x120,0x11,0x130,0x12,0x140,0x13,0x150,0x14,0x160,0x15,0x170,0x16,0x180,0x17, + 0x190,0x18,0x1a0,0x19,0x1b0,0x1a,0x1c0,0x1b,0x1d0,0x1c,0x1e0,0x1d,0x1f0,0x1e,0x200,0x1f, + 0x210,0x20,0x220,0x21,0x230,0x22,0x240,0x23,0x250,0x24,0x260,0x25,0x270,0x26,0x280,0x27, + 0x290,0x28,0x2a0,0x29,0x2b0,0x2a,0x2c0,0x2b,0x2d0,0x2c,0x2e0,0x2d,0x2f0,0x2e,0x300,0x2f, + 0x310,0x30,0x320,0x31,0x330,0x32,0x340,0x33,0x350,0x34,0x360,0x35,0x370,0x36,0x380,0x37, + 0x390,0x38,0x3a0,0x39,0x3b0,0x3a,0x3c0,0x3b,0x3d0,0x3c,0x3e0,0x3d,0x3f0,0x3e,0x400,0x3f, + 0x410,0x40,0x420,0x41,0x430,0x42,0x440,0x43,0x450,0x44,0x460,0x45,0x470,0x46,0x480,0x47, + 0x490,0x48,0x4a0,0x49,0x4b0,0x4a,0x4c0,0x4b,0x4d0,0x4c,0x4e0,0x4d,0x4f0,0x4e,0x500,0x4f, + 0x510,0x50,0x520,0x51,0x530,0x52,0x540,0x53,0x550,0x54,0x560,0x55,0x570,0x56,0x580,0x57, + 0x590,0x58,0x5a0,0x59,0x5b0,0x5a,0x5c0,0x5b,0x5d0,0x5c,0x5e0,0x5d,0x5f0,0x5e,0x600,0x5f, + 0x610,0x60,0x620,0x61,0x630,0x62,0x640,0x63,0x650,0x64,0x660,0x65,0x670,0x66,0x680,0x67, + 0x690,0x68,0x6a0,0x69,0x6b0,0x6a,0x6c0,0x6b,0x6d0,0x6c,0x6e0,0x6d,0x6f0,0x6e,0x700,0x6f, + 0x710,0x70,0x720,0x71,0x730,0x72,0x740,0x73,0x750,0x74,0x760,0x75,0x770,0x76,0x780,0x77, + 0x790,0x78,0x7a0,0x79,0x7b0,0x7a,0x7c0,0x7b,0x7d0,0x7c,0x7e0,0x7d,0x7f0,0x7e,0x800,0x7f, + 0x810,0x80,0x820,0x81,0x830,0x82,0x840,0x83,0x850,0x84,0x860,0x85,0x870,0x86,0x880,0x87, + 0x890,0x88,0x8a0,0x89,0x8b0,0x8a,0x8c0,0x8b,0x8d0,0x8c,0x8e0,0x8d,0x8f0,0x8e,0x900,0x8f, + 0x910,0x90,0x920,0x91,0x930,0x92,0x940,0x93,0x950,0x94,0x960,0x95,0x970,0x96,0x980,0x97, + 0x990,0x98,0x9a0,0x99,0x9b0,0x9a,0x9c0,0x9b,0x9d0,0x9c,0x9e0,0x9d,0x9f0,0x9e,0xa00,0x9f, + 0xa10,0xa0,0xa20,0xa1,0xa30,0xa2,0xa40,0xa3,0xa50,0xa4,0xa60,0xa5,0xa70,0xa6,0xa80,0xa7, + 0xa90,0xa8,0xaa0,0xa9,0xab0,0xaa,0xac0,0xab,0xad0,0xac,0xae0,0xad,0xaf0,0xae,0xb00,0xaf, + 0xb10,0xb0,0xb20,0xb1,0xb30,0xb2,0xb40,0xb3,0xb50,0xb4,0xb60,0xb5,0xb70,0xb6,0xb80,0xb7, + 0xb90,0xb8,0xba0,0xb9,0xbb0,0xba,0xbc0,0xbb,0xbd0,0xbc,0xbe0,0xbd,0xbf0,0xbe,0xc00,0xbf, + 0xc10,0xc0,0xc20,0xc1,0xc30,0xc2,0xc40,0xc3,0xc50,0xc4,0xc60,0xc5,0xc70,0xc6,0xc80,0xc7, + 0xc90,0xc8,0xca0,0xc9,0xcb0,0xca,0xcc0,0xcb,0xcd0,0xcc,0xce0,0xcd,0xcf0,0xce,0xd00,0xcf, + 0xd10,0xd0,0xd20,0xd1,0xd30,0xd2,0xd40,0xd3,0xd50,0xd4,0xd60,0xd5,0xd70,0xd6,0xd80,0xd7, + 0xd90,0xd8,0xda0,0xd9,0xdb0,0xda,0xdc0,0xdb,0xdd0,0xdc,0xde0,0xdd,0xdf0,0xde,0xe00,0xdf, + 0xe10,0xe0,0xe20,0xe1,0xe30,0xe2,0xe40,0xe3,0xe50,0xe4,0xe60,0xe5,0xe70,0xe6,0xe80,0xe7, + 0xe90,0xe8,0xea0,0xe9,0xeb0,0xea,0xec0,0xeb,0xed0,0xec,0xee0,0xed,0xef0,0xee,0xf00,0xef, + 0xf10,0xf0,0xf20,0xf1,0xf30,0xf2,0xf40,0xf3,0xf50,0xf4,0xf60,0xf5,0xf70,0xf6,0xf80,0xf7, + 0xf90,0xf8,0xfa0,0xf9,0xfb0,0xfa,0xfc0,0xfb,0xfd0,0xfc,0xfe0,0xfd,0xff0,0xfe,0x1000,0xff, + 0x110000,0 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.16.toml new file mode 100644 index 00000000000000..56163ddaad977a --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.16.toml @@ -0,0 +1,116 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: small0-in-fast.16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "small0-in-fast.16" +index = [ + 0,0x40,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,0x80,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0x90,0xd0,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0x424,0x424,0x424,0x424,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1, + 0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1, + 0xd1,0xd1,0xd1,0xd1,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404, + 0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404, + 0x404,0x404,0x404,0x404 +] +data_16 = [ + 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, + 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, + 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, + 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, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,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,2,2,2,2, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,0xad,9,0xad +] +indexLength = 1092 +dataLength = 292 +highStart = 0x20000 +shifted12HighStart = 0x20 +type = 0 +valueWidth = 0 +index3NullOffset = 0x404 +dataNullOffset = 0xd1 +nullValue = 0x0 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0x880,1,0x890,0,0x1040,2,0x1051,0,0x10000,3,0x20000,0,0x110000,9 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.32.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.32.toml new file mode 100644 index 00000000000000..9d4685ba2f8684 --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.32.toml @@ -0,0 +1,116 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: small0-in-fast.32 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "small0-in-fast.32" +index = [ + 0,0x40,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,0x80,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0x90,0xd0,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0x424,0x424,0x424,0x424,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1, + 0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1, + 0xd1,0xd1,0xd1,0xd1,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404, + 0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404, + 0x404,0x404,0x404,0x404 +] +data_32 = [ + 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, + 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, + 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, + 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, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,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,2,2,2,2, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,9,0xad +] +indexLength = 1092 +dataLength = 291 +highStart = 0x20000 +shifted12HighStart = 0x20 +type = 0 +valueWidth = 1 +index3NullOffset = 0x404 +dataNullOffset = 0xd1 +nullValue = 0x0 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0x880,1,0x890,0,0x1040,2,0x1051,0,0x10000,3,0x20000,0,0x110000,9 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.8.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.8.toml new file mode 100644 index 00000000000000..8f42007065c93c --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.8.toml @@ -0,0 +1,116 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: small0-in-fast.8 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "small0-in-fast.8" +index = [ + 0,0x40,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,0x80,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0x90,0xd0,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1,0xe1, + 0x424,0x424,0x424,0x424,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1, + 0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1, + 0xd1,0xd1,0xd1,0xd1,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404, + 0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404,0x404, + 0x404,0x404,0x404,0x404 +] +data_8 = [ + 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, + 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, + 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, + 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, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,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,2,2,2,2, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,9,9,0xad +] +indexLength = 1092 +dataLength = 292 +highStart = 0x20000 +shifted12HighStart = 0x20 +type = 0 +valueWidth = 2 +index3NullOffset = 0x404 +dataNullOffset = 0xd1 +nullValue = 0x0 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0x880,1,0x890,0,0x1040,2,0x1051,0,0x10000,3,0x20000,0,0x110000,9 +] diff --git a/deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.small16.toml b/deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.small16.toml new file mode 100644 index 00000000000000..dd203a39de697e --- /dev/null +++ b/deps/crates/vendor/icu_collections/tests/data/cpt/small0-in-fast.small16.toml @@ -0,0 +1,63 @@ +# Copyright (C) 2021 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# file name: small0-in-fast.small16 +# +# machine-generated by: ucptrietest.c + +[code_point_trie.struct] +name = "small0-in-fast.small16" +index = [ + 0,0x40,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,0x80,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, + 0xda,0xe3,0xe3,0xe3,0x103,0x103,0x103,0x103,0,0x10,0x20,0x30,0x40,0x50,0x60,0x70, + 0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30, + 0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30, + 0x80,0x90,0xa0,0xb0,0x90,0xa0,0xb0,0xc0,0x90,0xa0,0xb0,0xc0,0x90,0xa0,0xb0,0xc0, + 0x90,0xa0,0xb0,0xc0,0x90,0xa0,0xb0,0xc0,0x90,0xa0,0xb0,0xc0,0x90,0xa0,0xb0,0xc0, + 0x90,0xa0,0xb0,0xc0,0x90,0x90,0x90,0x90,0xd0,0xdf,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0, + 0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0, + 0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0, + 0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0x48,0x50,0x50,0x50,0x68,0x74, + 0x74,0x74,0x94,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a, + 0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a, + 0x9a,0x9a,0x9a,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba, + 0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba,0xba, + 0xba,0xba,0xba +] +data_16 = [ + 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, + 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, + 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, + 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, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,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,2,2,2,2, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 0xad,9,0xad +] +indexLength = 291 +dataLength = 243 +highStart = 0x20000 +shifted12HighStart = 0x20 +type = 1 +valueWidth = 0 +index3NullOffset = 0xba +dataNullOffset = 0xd0 +nullValue = 0x0 + +[code_point_trie.testdata] +# Array of (limit, value) pairs +checkRanges = [ + 0x880,1,0x890,0,0x1040,2,0x1051,0,0x10000,3,0x20000,0,0x110000,9 +] diff --git a/deps/crates/vendor/icu_locale/.cargo-checksum.json b/deps/crates/vendor/icu_locale/.cargo-checksum.json new file mode 100644 index 00000000000000..6a5d8438d2631c --- /dev/null +++ b/deps/crates/vendor/icu_locale/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"805f67596f172ac7494771909ebf7b32211d9d6b69010798fe0741e78fc0845d","LICENSE":"f367c1b8e1aa262435251e442901da4607b4650e0e63a026f5044473ecfb90f2","README.md":"3eabddc961d47b3205baacf44113fc4aa414d8429ae0b045a6a7e264af980747","benches/fixtures/locales.json":"9846601a29874baf140cac1252d4624fadc30182fec106d17f008ece886b9185","benches/fixtures/uncanonicalized-locales.json":"a866ed318b92f79d8853567e79b373c02984967023f5f39161140544e71b0c72","benches/locale_canonicalizer.rs":"3b6599352c88d2c039d083f91b5b7e222614946c55a77e3ccb1ae0b5fa2ae346","src/canonicalizer.rs":"a1266f265ea51e724496e1d789c9fc8768dd83ea6653a056bcd71b09cee7e774","src/directionality.rs":"af2e0421cf36d08232c1cf6b6d7e08824132128559fc69b888974c2ae007e8f5","src/exemplar_chars.rs":"70f37cde5153f27a4f112b908354d584a00daa6047ef9901569ef64f1a1da5f6","src/expander.rs":"6e865c782717fc3f1a5d16054142aa3cfb443e2ee4ebc1eb432070355f7f1a0e","src/fallback/algorithms.rs":"8141ff08b43b20275b54f97e5a890e52dca3c293d9a8dad42d48ca43c2304b35","src/fallback/mod.rs":"a4d802f9a06440f97784449b28da49ba349b8402f2b96dfebb7611c982b6fcf6","src/lib.rs":"683b67c0352bab45eb38c0aa249532a16168edac33ec278c9aed60be8aa5df9f","src/provider.rs":"6ff47585fda0d8f60db3c34492890b1bf0fcf8354cfe2b80ebce884bf78f1179","tests/fixtures/canonicalize.json":"3dc2f661b04e4c9ecced70fc1b98a504eb5f5a0067b38665b10e50c25174bc4a","tests/fixtures/maximize.json":"bc38baf34858d6000e617a63bb30d07c439e838aaac493e2d6513cd36b222c3c","tests/fixtures/minimize.json":"efe180ddaf299670a900cf1d676c5f97caa97f7827d10a2e436ce959d637ba7f","tests/fixtures/mod.rs":"98ee70076a3554bb5043ecb1e3643fd47c6bac126724ee207b0633017b8763ed","tests/locale_canonicalizer.rs":"db8f560a0a8591aca4bd8713c13e5bf705b08f8ea184efdf64e240218188b767"},"package":"6ae5921528335e91da1b6c695dbf1ec37df5ac13faa3f91e5640be93aa2fbefd"} \ No newline at end of file diff --git a/deps/crates/vendor/icu_locale/Cargo.toml b/deps/crates/vendor/icu_locale/Cargo.toml new file mode 100644 index 00000000000000..7c1c38bb74c4f5 --- /dev/null +++ b/deps/crates/vendor/icu_locale/Cargo.toml @@ -0,0 +1,161 @@ +# 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.82" +name = "icu_locale" +version = "2.0.0" +authors = ["The ICU4X Project Developers"] +build = false +include = [ + "data/**/*", + "src/**/*", + "examples/**/*", + "benches/**/*", + "tests/**/*", + "Cargo.toml", + "LICENSE", + "README.md", + "build.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "API for Unicode Language and Locale Identifiers canonicalization" +homepage = "https://icu4x.unicode.org" +readme = "README.md" +categories = ["internationalization"] +license = "Unicode-3.0" +repository = "https://github.com/unicode-org/icu4x" + +[package.metadata.cargo-all-features] +skip_optional_dependencies = true + +[package.metadata.docs.rs] +all-features = true + +[features] +compiled_data = [ + "dep:icu_locale_data", + "icu_provider/baked", +] +datagen = [ + "serde", + "dep:databake", + "zerovec/databake", + "icu_locale_core/databake", + "tinystr/databake", + "icu_collections/databake", + "icu_provider/export", +] +default = ["compiled_data"] +serde = [ + "dep:serde", + "icu_locale_core/serde", + "tinystr/serde", + "zerovec/serde", + "icu_provider/serde", + "potential_utf/serde", + "icu_collections/serde", +] + +[lib] +name = "icu_locale" +path = "src/lib.rs" +bench = false + +[[test]] +name = "locale_canonicalizer" +path = "tests/locale_canonicalizer.rs" +required-features = ["serde"] + +[[bench]] +name = "locale_canonicalizer" +path = "benches/locale_canonicalizer.rs" +harness = false + +[dependencies.databake] +version = "0.2.0" +features = ["derive"] +optional = true +default-features = false + +[dependencies.displaydoc] +version = "0.2.3" +default-features = false + +[dependencies.icu_collections] +version = "~2.0.0" +default-features = false + +[dependencies.icu_locale_core] +version = "2.0.0" +features = [ + "alloc", + "zerovec", +] +default-features = false + +[dependencies.icu_locale_data] +version = "~2.0.0" +optional = true +default-features = false + +[dependencies.icu_provider] +version = "2.0.0" +default-features = false + +[dependencies.potential_utf] +version = "0.1.1" +features = [ + "alloc", + "zerovec", +] +default-features = false + +[dependencies.serde] +version = "1.0.110" +features = [ + "derive", + "alloc", +] +optional = true +default-features = false + +[dependencies.tinystr] +version = "0.8.0" +features = [ + "alloc", + "zerovec", +] +default-features = false + +[dependencies.zerovec] +version = "0.11.1" +features = [ + "alloc", + "yoke", +] +default-features = false + +[dev-dependencies.serde] +version = "1.0.110" +features = ["derive"] +default-features = false + +[dev-dependencies.serde_json] +version = "1.0.45" + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies.criterion] +version = "0.5.0" diff --git a/deps/crates/vendor/icu_locale/LICENSE b/deps/crates/vendor/icu_locale/LICENSE new file mode 100644 index 00000000000000..c9be6012c53792 --- /dev/null +++ b/deps/crates/vendor/icu_locale/LICENSE @@ -0,0 +1,46 @@ +UNICODE LICENSE V3 + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 2020-2024 Unicode, Inc. + +NOTICE TO USER: Carefully read the following legal agreement. BY +DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR +SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT +DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of data files and any associated documentation (the "Data Files") or +software and any associated documentation (the "Software") to deal in the +Data Files or Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, and/or sell +copies of the Data Files or Software, and to permit persons to whom the +Data Files or Software are furnished to do so, provided that either (a) +this copyright and permission notice appear with all copies of the Data +Files or Software, or (b) this copyright and permission notice appear in +associated Documentation. + +THE DATA FILES AND SOFTWARE ARE 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 OF +THIRD PARTY RIGHTS. + +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE +BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA +FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in these Data Files or Software without prior written +authorization of the copyright holder. + +SPDX-License-Identifier: Unicode-3.0 + +— + +Portions of ICU4X may have been adapted from ICU4C and/or ICU4J. +ICU 1.8.1 to ICU 57.1 © 1995-2016 International Business Machines Corporation and others. diff --git a/deps/crates/vendor/icu_locale/README.md b/deps/crates/vendor/icu_locale/README.md new file mode 100644 index 00000000000000..80f92c8af9847a --- /dev/null +++ b/deps/crates/vendor/icu_locale/README.md @@ -0,0 +1,75 @@ +# icu_locale [![crates.io](https://img.shields.io/crates/v/icu_locale)](https://crates.io/crates/icu_locale) + + + +Canonicalization of locale identifiers based on [`CLDR`] data. + +This module is published as its own crate ([`icu_locale`](https://docs.rs/icu_locale/latest/icu_locale/)) +and as part of the [`icu`](https://docs.rs/icu/latest/icu/) crate. See the latter for more details on the ICU4X project. + +It currently supports locale canonicalization based upon the canonicalization +algorithm from [`UTS #35: Unicode LDML 3. LocaleId Canonicalization`], +as well as the minimize and maximize likely subtags algorithms +as described in [`UTS #35: Unicode LDML 3. Likely Subtags`]. + +The maximize method potentially updates a passed in locale in place +depending up the results of running the 'Add Likely Subtags' algorithm +from [`UTS #35: Unicode LDML 3. Likely Subtags`]. + +This minimize method returns a new Locale that is the result of running the +'Remove Likely Subtags' algorithm from [`UTS #35: Unicode LDML 3. Likely Subtags`]. + +## Examples + +```rust +use icu::locale::Locale; +use icu::locale::{LocaleCanonicalizer, TransformResult}; + +let lc = LocaleCanonicalizer::new_extended(); + +let mut locale: Locale = "ja-Latn-fonipa-hepburn-heploc" + .parse() + .expect("parse failed"); +assert_eq!(lc.canonicalize(&mut locale), TransformResult::Modified); +assert_eq!(locale, "ja-Latn-alalc97-fonipa".parse::().unwrap()); +``` + +```rust +use icu::locale::{locale, LocaleExpander, TransformResult}; + +let lc = LocaleExpander::new_common(); + +let mut locale = locale!("zh-CN"); +assert_eq!(lc.maximize(&mut locale.id), TransformResult::Modified); +assert_eq!(locale, locale!("zh-Hans-CN")); + +let mut locale = locale!("zh-Hant-TW"); +assert_eq!(lc.maximize(&mut locale.id), TransformResult::Unmodified); +assert_eq!(locale, locale!("zh-Hant-TW")); +``` + +```rust +use icu::locale::{locale, LocaleExpander, TransformResult}; +use writeable::assert_writeable_eq; + +let lc = LocaleExpander::new_common(); + +let mut locale = locale!("zh-Hans-CN"); +assert_eq!(lc.minimize(&mut locale.id), TransformResult::Modified); +assert_eq!(locale, locale!("zh")); + +let mut locale = locale!("zh"); +assert_eq!(lc.minimize(&mut locale.id), TransformResult::Unmodified); +assert_eq!(locale, locale!("zh")); +``` + +[`ICU4X`]: ../icu/index.html +[`CLDR`]: http://cldr.unicode.org/ +[`UTS #35: Unicode LDML 3. Likely Subtags`]: https://www.unicode.org/reports/tr35/#Likely_Subtags. +[`UTS #35: Unicode LDML 3. LocaleId Canonicalization`]: http://unicode.org/reports/tr35/#LocaleId_Canonicalization, + + + +## More Information + +For more information on development, authorship, contributing etc. please visit [`ICU4X home page`](https://github.com/unicode-org/icu4x). diff --git a/deps/crates/vendor/icu_locale/benches/fixtures/locales.json b/deps/crates/vendor/icu_locale/benches/fixtures/locales.json new file mode 100644 index 00000000000000..0e8ba8b798eb44 --- /dev/null +++ b/deps/crates/vendor/icu_locale/benches/fixtures/locales.json @@ -0,0 +1,41 @@ +[ + "en-US", + "en-GB", + "es-AR", + "it", + "zh-Hans-CN", + "de-AT", + "pl", + "fr-FR", + "de-AT", + "sr-Cyrl-SR", + "nb-NO", + "fr-FR", + "mk", + "uk", + "und-PL", + "und-Latn-AM", + "ug-Cyrl", + "sr-ME", + "mn-Mong", + "lif-Limb", + "gan", + "zh-Hant", + "yue-Hans", + "unr", + "unr-Deva", + "und-Thai-CN", + "ug-Cyrl", + "en-Latn-DE", + "pl-FR", + "de-CH", + "tuq", + "sr-ME", + "ng", + "klx", + "kk-Arab", + "en-Cyrl", + "und-Cyrl-UK", + "und-Arab", + "und-Arab-FO" +] diff --git a/deps/crates/vendor/icu_locale/benches/fixtures/uncanonicalized-locales.json b/deps/crates/vendor/icu_locale/benches/fixtures/uncanonicalized-locales.json new file mode 100644 index 00000000000000..18eadbce68e206 --- /dev/null +++ b/deps/crates/vendor/icu_locale/benches/fixtures/uncanonicalized-locales.json @@ -0,0 +1,88 @@ +[ + "cka", + "cze", + "gfx", + "sgn-BR", + "sgn-DD", + "tam", + "und-aaland", + "nob-bokmal", + "no-nynorsk", + "und-Qaai", + "en-554", + "en-084", + "art-lojban", + "zh-guoyu", + "zh-hakka", + "zh-xiang", + "aar-x-private", + "heb-x-private", + "ces", + "hy-arevela", + "hy-arevmda", + "cel-gaulish", + "ja-latn-hepburn-heploc", + "ja-Latn-fonipa-hepburn-heploc", + "und-Armn-SU", + "sh", + "sh-Cyrl", + "cnr", + "cnr-BA", + "ru-SU", + "ru-810", + "en-SU", + "en-810", + "und-SU", + "und-810", + "und-Latn-SU", + "und-Latn-810", + "hy-SU", + "hy-810", + "und-Armn-SU", + "und-Armn-810", + "sr-CS", + "sr-Latn-CS", + "sr-Cyrl-CS", + "az-NT", + "sl-t-sl-rozaj-biske-1994", + "DE-T-M0-DIN-K0-QWERTZ", + "en-t-m0-true", + "en-t-iw", + "und-u-rg-no23", + "und-u-rg-cn11", + "und-u-rg-cz10a", + "und-u-rg-fra", + "und-u-rg-frg", + "und-u-rg-lud", + "und-NO-u-rg-no23", + "und-CN-u-rg-cn11", + "und-CZ-u-rg-cz10a", + "und-FR-u-rg-fra", + "und-FR-u-rg-frg", + "und-u-rg-lud", + "und-u-sd-no23", + "und-u-sd-cn11", + "und-u-sd-cz10a", + "und-u-sd-fra", + "hy-arevela", + "hy-Armn-arevela", + "hy-AM-arevela", + "hy-arevela-fonipa", + "hy-fonipa-arevela", + "hy-arevmda", + "hy-Armn-arevmda", + "hy-AM-arevmda", + "hy-arevmda-fonipa", + "hy-fonipa-arevmda", + "ja-Latn-hepburn-heploc", + "ja-Latn-JP-hepburn-heploc", + "sv-aaland", + "el-polytoni", + "ja-Latn-alalc97-hepburn-heploc", + "ja-Latn-hepburn-alalc97-heploc", + "ja-Latn-hepburn-heploc-alalc97", + "ja-Latn-heploc-hepburn", + "ja-Latn-heploc", + "ja-Latn-aaland-heploc", + "ja-Latn-heploc-polytoni" +] diff --git a/deps/crates/vendor/icu_locale/benches/locale_canonicalizer.rs b/deps/crates/vendor/icu_locale/benches/locale_canonicalizer.rs new file mode 100644 index 00000000000000..11d8668196ac0c --- /dev/null +++ b/deps/crates/vendor/icu_locale/benches/locale_canonicalizer.rs @@ -0,0 +1,107 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use icu_locale::LocaleCanonicalizer; +use icu_locale::LocaleExpander; +use icu_locale_core::Locale; + +fn canonicalize_bench(c: &mut Criterion) { + let lc = LocaleCanonicalizer::new_common(); + + let mut group = c.benchmark_group("uncanonicalized"); + + let data: Vec = + serde_json::from_str(include_str!("fixtures/uncanonicalized-locales.json")) + .expect("Failed to read a fixture"); + let locales: Vec = data.iter().map(|s| s.parse().unwrap()).collect(); + + group.bench_function("clone", |b| { + b.iter(|| { + for locale in &locales { + let _ = black_box(locale).clone(); + } + }) + }); + + group.bench_function("canonicalize", |b| { + b.iter(|| { + for locale in &locales { + let mut locale = black_box(locale).clone(); + lc.canonicalize(&mut locale); + } + }) + }); + + group.finish(); +} + +fn canonicalize_noop_bench(c: &mut Criterion) { + let lc = LocaleCanonicalizer::new_common(); + + let mut group = c.benchmark_group("canonicalized"); + + // None of these locales require canonicalization, so this measures the cost of calling + // the canonicalizer on locales that will not be modified. + let data: Vec = serde_json::from_str(include_str!("fixtures/locales.json")) + .expect("Failed to read a fixture"); + let locales: Vec = data.iter().map(|s| s.parse().unwrap()).collect(); + + group.bench_function("clone", |b| { + b.iter(|| { + for locale in &locales { + let _ = black_box(locale).clone(); + } + }) + }); + + group.bench_function("canonicalize", |b| { + b.iter(|| { + for locale in &locales { + let mut locale = black_box(locale).clone(); + lc.canonicalize(&mut locale); + } + }) + }); + + group.finish(); +} + +fn maximize_bench(c: &mut Criterion) { + let lc = LocaleExpander::new_common(); + + let mut group = c.benchmark_group("likelysubtags"); + + let data: Vec = serde_json::from_str(include_str!("fixtures/locales.json")) + .expect("Failed to read a fixture"); + let locales: Vec = data.iter().map(|s| s.parse().unwrap()).collect(); + + group.bench_function("maximize", |b| { + b.iter(|| { + for locale in &locales { + let mut locale = locale.clone(); + lc.maximize(black_box(&mut locale.id)); + } + }) + }); + + group.bench_function("minimize", |b| { + b.iter(|| { + for locale in &locales { + let mut locale = locale.clone(); + lc.minimize(black_box(&mut locale.id)); + } + }) + }); + + group.finish(); +} + +criterion_group!( + benches, + canonicalize_bench, + canonicalize_noop_bench, + maximize_bench +); +criterion_main!(benches); diff --git a/deps/crates/vendor/icu_locale/src/canonicalizer.rs b/deps/crates/vendor/icu_locale/src/canonicalizer.rs new file mode 100644 index 00000000000000..c8320cc1d447fe --- /dev/null +++ b/deps/crates/vendor/icu_locale/src/canonicalizer.rs @@ -0,0 +1,625 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! The collection of code for locale canonicalization. + +use crate::provider::*; +use alloc::vec::Vec; +use core::cmp::Ordering; + +use crate::LocaleExpander; +use crate::TransformResult; +use icu_locale_core::extensions::Extensions; +use icu_locale_core::subtags::{Language, Region, Script}; +use icu_locale_core::{ + extensions::unicode::key, + subtags::{language, Variant, Variants}, + LanguageIdentifier, Locale, +}; +use icu_provider::prelude::*; +use tinystr::TinyAsciiStr; + +/// Implements the algorithm defined in *[UTS #35: Annex C, LocaleId Canonicalization]*. +/// +/// # Examples +/// +/// ``` +/// use icu::locale::Locale; +/// use icu::locale::{LocaleCanonicalizer, TransformResult}; +/// +/// let lc = LocaleCanonicalizer::new_extended(); +/// +/// let mut locale: Locale = "ja-Latn-fonipa-hepburn-heploc".parse().unwrap(); +/// assert_eq!(lc.canonicalize(&mut locale), TransformResult::Modified); +/// assert_eq!(locale, "ja-Latn-alalc97-fonipa".parse().unwrap()); +/// ``` +/// +/// [UTS #35: Annex C, LocaleId Canonicalization]: http://unicode.org/reports/tr35/#LocaleId_Canonicalization +#[derive(Debug)] +pub struct LocaleCanonicalizer { + /// Data to support canonicalization. + aliases: DataPayload, + /// Likely subtags implementation for delegation. + expander: Expander, +} + +fn uts35_rule_matches<'a, I>( + source: &LanguageIdentifier, + language: Language, + script: Option, + replacement: &LanguageIdentifier, +) where + I: Iterator, +{ + if ruletype_has_language || (source.language.is_unknown() && !replacement.language.is_unknown()) + { + source.language = replacement.language; + } + if ruletype_has_script || (source.script.is_none() && replacement.script.is_some()) { + source.script = replacement.script; + } + if ruletype_has_region || (source.region.is_none() && replacement.region.is_some()) { + source.region = replacement.region; + } + if let Some(skips) = ruletype_variants { + // The rule matches if the ruletype variants are a subset of the source variants. + // This means ja-Latn-fonipa-hepburn-heploc matches against the rule for + // hepburn-heploc and is canonicalized to ja-Latn-alalc97-fonipa + + // We're merging three sorted deduped iterators into a new sequence: + // sources - skips + replacements + + let mut sources = source.variants.iter().peekable(); + let mut replacements = replacement.variants.iter().peekable(); + let mut skips = skips.peekable(); + + let mut variants: Vec = Vec::new(); + + loop { + match (sources.peek(), skips.peek(), replacements.peek()) { + (Some(&source), Some(skip), _) + if source.as_str().cmp(skip) == Ordering::Greater => + { + skips.next(); + } + (Some(&source), Some(skip), _) if source.as_str().cmp(skip) == Ordering::Equal => { + skips.next(); + sources.next(); + } + (Some(&source), _, Some(&replacement)) + if replacement.cmp(source) == Ordering::Less => + { + variants.push(*replacement); + replacements.next(); + } + (Some(&source), _, Some(&replacement)) + if replacement.cmp(source) == Ordering::Equal => + { + variants.push(*source); + sources.next(); + replacements.next(); + } + (Some(&source), _, _) => { + variants.push(*source); + sources.next(); + } + (None, _, Some(&replacement)) => { + variants.push(*replacement); + replacements.next(); + } + (None, _, None) => { + break; + } + } + } + source.variants = Variants::from_vec_unchecked(variants); + } +} + +#[inline] +fn uts35_check_language_rules( + langid: &mut LanguageIdentifier, + alias_data: &DataPayload, +) -> TransformResult { + if !langid.language.is_unknown() { + let lang: TinyAsciiStr<3> = langid.language.into(); + let replacement = if lang.len() == 2 { + alias_data + .get() + .language_len2 + .get(&lang.resize().to_unvalidated()) + } else { + alias_data.get().language_len3.get(&lang.to_unvalidated()) + }; + + if let Some(replacement) = replacement { + if let Ok(new_langid) = replacement.parse() { + uts35_replacement::>( + langid, + true, + false, + false, + None, + &new_langid, + ); + return TransformResult::Modified; + } + } + } + + TransformResult::Unmodified +} + +impl LocaleCanonicalizer { + /// A constructor which creates a [`LocaleCanonicalizer`] from compiled data, + /// using a [`LocaleExpander`] for common locales. + /// + /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + #[cfg(feature = "compiled_data")] + pub const fn new_common() -> Self { + Self::new_with_expander(LocaleExpander::new_common()) + } + + icu_provider::gen_buffer_data_constructors!(() -> error: DataError, + functions: [ + new_common: skip, + try_new_common_with_buffer_provider, + try_new_common_unstable, + Self, + ] + ); + + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new_common)] + pub fn try_new_common_unstable

(provider: &P) -> Result + where + P: DataProvider + + DataProvider + + DataProvider + + ?Sized, + { + let expander = LocaleExpander::try_new_common_unstable(provider)?; + Self::try_new_with_expander_unstable(provider, expander) + } + + /// A constructor which creates a [`LocaleCanonicalizer`] from compiled data, + /// using a [`LocaleExpander`] for all locales. + /// + /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + #[cfg(feature = "compiled_data")] + pub const fn new_extended() -> Self { + Self::new_with_expander(LocaleExpander::new_extended()) + } + + icu_provider::gen_buffer_data_constructors!(() -> error: DataError, + functions: [ + new_extended: skip, + try_new_extended_with_buffer_provider, + try_new_extended_unstable, + Self, + ] + ); + + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new_extended)] + pub fn try_new_extended_unstable

(provider: &P) -> Result + where + P: DataProvider + + DataProvider + + DataProvider + + DataProvider + + ?Sized, + { + let expander = LocaleExpander::try_new_extended_unstable(provider)?; + Self::try_new_with_expander_unstable(provider, expander) + } +} + +impl> LocaleCanonicalizer { + /// Creates a [`LocaleCanonicalizer`] with a custom [`LocaleExpander`] and compiled data. + /// + /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + #[cfg(feature = "compiled_data")] + pub const fn new_with_expander(expander: Expander) -> Self { + Self { + aliases: DataPayload::from_static_ref( + crate::provider::Baked::SINGLETON_LOCALE_ALIASES_V1, + ), + expander, + } + } + + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new_with_expander)] + pub fn try_new_with_expander_unstable

( + provider: &P, + expander: Expander, + ) -> Result + where + P: DataProvider + ?Sized, + { + let aliases: DataPayload = provider.load(Default::default())?.payload; + + Ok(Self { aliases, expander }) + } + + icu_provider::gen_buffer_data_constructors!((options: Expander) -> error: DataError, + functions: [ + new_with_expander: skip, + try_new_with_expander_with_buffer_provider, + try_new_with_expander_unstable, + Self, + ] + ); + + /// The canonicalize method potentially updates a passed in locale in place + /// depending up the results of running the canonicalization algorithm + /// from . + /// + /// Some BCP47 canonicalization data is not part of the CLDR json package. Because + /// of this, some canonicalizations are not performed, e.g. the canonicalization of + /// `und-u-ca-islamicc` to `und-u-ca-islamic-civil`. This will be fixed in a future + /// release once the missing data has been added to the CLDR json data. See: + /// + /// + /// # Examples + /// + /// ``` + /// use icu::locale::{Locale, LocaleCanonicalizer, TransformResult}; + /// + /// let lc = LocaleCanonicalizer::new_extended(); + /// + /// let mut locale: Locale = "ja-Latn-fonipa-hepburn-heploc".parse().unwrap(); + /// assert_eq!(lc.canonicalize(&mut locale), TransformResult::Modified); + /// assert_eq!(locale, "ja-Latn-alalc97-fonipa".parse().unwrap()); + /// ``` + pub fn canonicalize(&self, locale: &mut Locale) -> TransformResult { + let mut result = TransformResult::Unmodified; + + // This loops until we get a 'fixed point', where applying the rules do not + // result in any more changes. + loop { + // These are linear searches due to the ordering imposed by the canonicalization + // rules, where rules with more variants should be considered first. With the + // current data in CLDR, we will only do this for locales which have variants, + // or new rules which we haven't special-cased yet (of which there are fewer + // than 20). + let modified = if locale.id.variants.is_empty() { + self.canonicalize_absolute_language_fallbacks(&mut locale.id) + } else { + self.canonicalize_language_variant_fallbacks(&mut locale.id) + }; + if modified { + result = TransformResult::Modified; + continue; + } + + if !locale.id.language.is_unknown() { + // If the region is specified, check sgn-region rules first + if let Some(region) = locale.id.region { + if locale.id.language == language!("sgn") { + if let Some(&sgn_lang) = self + .aliases + .get() + .sgn_region + .get(®ion.to_tinystr().to_unvalidated()) + { + uts35_replacement::>( + &mut locale.id, + true, + false, + true, + None, + &sgn_lang.into(), + ); + result = TransformResult::Modified; + continue; + } + } + } + + if uts35_check_language_rules(&mut locale.id, &self.aliases) + == TransformResult::Modified + { + result = TransformResult::Modified; + continue; + } + } + + if let Some(script) = locale.id.script { + if let Some(&replacement) = self + .aliases + .get() + .script + .get(&script.to_tinystr().to_unvalidated()) + { + locale.id.script = Some(replacement); + result = TransformResult::Modified; + continue; + } + } + + if let Some(region) = locale.id.region { + let replacement = if region.is_alphabetic() { + self.aliases + .get() + .region_alpha + .get(®ion.to_tinystr().resize().to_unvalidated()) + } else { + self.aliases + .get() + .region_num + .get(®ion.to_tinystr().to_unvalidated()) + }; + if let Some(&replacement) = replacement { + locale.id.region = Some(replacement); + result = TransformResult::Modified; + continue; + } + + if let Some(regions) = self + .aliases + .get() + .complex_region + .get(®ion.to_tinystr().to_unvalidated()) + { + // Skip if regions are empty + if let Some(default_region) = regions.get(0) { + let mut maximized = LanguageIdentifier { + language: locale.id.language, + script: locale.id.script, + region: None, + variants: Variants::default(), + }; + + locale.id.region = Some( + match ( + self.expander.as_ref().maximize(&mut maximized), + maximized.region, + ) { + (TransformResult::Modified, Some(candidate)) + if regions.iter().any(|x| x == candidate) => + { + candidate + } + _ => default_region, + }, + ); + result = TransformResult::Modified; + continue; + } + } + } + + if !locale.id.variants.is_empty() { + let mut modified = Vec::with_capacity(0); + for (idx, &variant) in locale.id.variants.iter().enumerate() { + if let Some(&updated) = self + .aliases + .get() + .variant + .get(&variant.to_tinystr().to_unvalidated()) + { + if modified.is_empty() { + modified = locale.id.variants.to_vec(); + } + #[allow(clippy::indexing_slicing)] + let _ = core::mem::replace(&mut modified[idx], updated); + } + } + + if !modified.is_empty() { + modified.sort(); + modified.dedup(); + locale.id.variants = Variants::from_vec_unchecked(modified); + result = TransformResult::Modified; + continue; + } + } + + // Nothing matched in this iteration, we're done. + break; + } + + if !locale.extensions.transform.is_empty() || !locale.extensions.unicode.is_empty() { + self.canonicalize_extensions(&mut locale.extensions, &mut result); + } + result + } + + fn canonicalize_extensions(&self, extensions: &mut Extensions, result: &mut TransformResult) { + // Handle Locale extensions in their own loops, because these rules do not interact + // with each other. + if let Some(ref mut lang) = extensions.transform.lang { + while uts35_check_language_rules(lang, &self.aliases) == TransformResult::Modified { + *result = TransformResult::Modified; + } + } + + if !extensions.unicode.keywords.is_empty() { + for key in [key!("rg"), key!("sd")] { + if let Some(value) = extensions.unicode.keywords.get_mut(&key) { + if let Some(only_value) = value.as_single_subtag() { + if let Some(modified_value) = self + .aliases + .get() + .subdivision + .get(&only_value.to_tinystr().resize().to_unvalidated()) + { + if let Ok(modified_value) = modified_value.parse() { + *value = modified_value; + *result = TransformResult::Modified; + } + } + } + } + } + } + } + + fn canonicalize_language_variant_fallbacks(&self, lid: &mut LanguageIdentifier) -> bool { + // These language/variant comibnations have around 20 rules + for LanguageStrStrPair(lang, raw_variants, raw_to) in self + .aliases + .get() + .language_variants + .iter() + .map(zerofrom::ZeroFrom::zero_from) + { + let raw_variants = raw_variants.split('-'); + // if is_iter_sorted(raw_variants.clone()) { // can we sort at construction? + if uts35_rule_matches(lid, lang, None, None, raw_variants.clone()) { + if let Ok(to) = raw_to.parse() { + uts35_replacement( + lid, + !lang.is_unknown(), + false, + false, + Some(raw_variants), + &to, + ); + return true; + } + } + } + false + } + + fn canonicalize_absolute_language_fallbacks(&self, lid: &mut LanguageIdentifier) -> bool { + for StrStrPair(raw_from, raw_to) in self + .aliases + .get() + .language + .iter() + .map(zerofrom::ZeroFrom::zero_from) + { + if let Ok(from) = raw_from.parse::() { + if uts35_rule_matches( + lid, + from.language, + from.script, + from.region, + from.variants.iter().map(Variant::as_str), + ) { + if let Ok(to) = raw_to.parse() { + uts35_replacement( + lid, + !from.language.is_unknown(), + from.script.is_some(), + from.region.is_some(), + Some(from.variants.iter().map(Variant::as_str)), + &to, + ); + return true; + } + } + } + } + false + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_uts35_rule_matches() { + for (source, rule, result) in [ + ("ja", "und", true), + ("und-heploc-hepburn", "und-hepburn", true), + ("ja-heploc-hepburn", "und-hepburn", true), + ("ja-hepburn", "und-hepburn-heploc", false), + ] { + let source = source.parse().unwrap(); + let rule = rule.parse::().unwrap(); + assert_eq!( + uts35_rule_matches( + &source, + rule.language, + rule.script, + rule.region, + rule.variants.iter().map(Variant::as_str), + ), + result, + "{}", + source + ); + } + } + + #[test] + fn test_uts35_replacement() { + for (locale, rule_0, rule_1, result) in [ + ( + "ja-Latn-fonipa-hepburn-heploc", + "und-hepburn-heploc", + "und-alalc97", + "ja-Latn-alalc97-fonipa", + ), + ("sgn-DD", "und-DD", "und-DE", "sgn-DE"), + ("sgn-DE", "sgn-DE", "gsg", "gsg"), + ] { + let mut locale: Locale = locale.parse().unwrap(); + let rule_0 = rule_0.parse::().unwrap(); + let rule_1 = rule_1.parse().unwrap(); + let result = result.parse::().unwrap(); + uts35_replacement( + &mut locale.id, + !rule_0.language.is_unknown(), + rule_0.script.is_some(), + rule_0.region.is_some(), + Some(rule_0.variants.iter().map(Variant::as_str)), + &rule_1, + ); + assert_eq!(result, locale); + } + } +} diff --git a/deps/crates/vendor/icu_locale/src/directionality.rs b/deps/crates/vendor/icu_locale/src/directionality.rs new file mode 100644 index 00000000000000..a746b57142d33f --- /dev/null +++ b/deps/crates/vendor/icu_locale/src/directionality.rs @@ -0,0 +1,255 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::provider::*; +use crate::LocaleExpander; +use icu_locale_core::subtags::Script; +use icu_locale_core::LanguageIdentifier; +use icu_provider::prelude::*; + +/// Represents the direction of a script. +/// +/// [`LocaleDirectionality`] can be used to get this information. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[non_exhaustive] +pub enum Direction { + /// The script is left-to-right. + LeftToRight, + /// The script is right-to-left. + RightToLeft, +} + +/// Provides methods to determine the direction of a locale. +/// +/// The `Expander` generic parameter wraps a [`LocaleExpander`]. +/// +/// # Examples +/// +/// ``` +/// use icu::locale::{langid, Direction, LocaleDirectionality}; +/// +/// let ld = LocaleDirectionality::new_common(); +/// +/// assert_eq!(ld.get(&langid!("en")), Some(Direction::LeftToRight)); +/// ``` +#[derive(Debug)] +pub struct LocaleDirectionality { + script_direction: DataPayload, + expander: Expander, +} + +impl LocaleDirectionality { + /// Creates a [`LocaleDirectionality`] from compiled data, using [`LocaleExpander`] + /// data for common locales. + /// + /// This includes limited likely subtags data, see [`LocaleExpander::new_common()`]. + #[cfg(feature = "compiled_data")] + pub const fn new_common() -> Self { + Self::new_with_expander(LocaleExpander::new_common()) + } + + // Note: This is a custom impl because the bounds on `try_new_unstable` don't suffice + #[doc = icu_provider::gen_buffer_unstable_docs!(BUFFER, Self::new_common)] + #[cfg(feature = "serde")] + pub fn try_new_common_with_buffer_provider( + provider: &(impl BufferProvider + ?Sized), + ) -> Result { + let expander = LocaleExpander::try_new_common_with_buffer_provider(provider)?; + Self::try_new_with_expander_unstable(&provider.as_deserializing(), expander) + } + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new_common)] + pub fn try_new_common_unstable

(provider: &P) -> Result + where + P: DataProvider + + DataProvider + + DataProvider + + ?Sized, + { + let expander = LocaleExpander::try_new_common_unstable(provider)?; + Self::try_new_with_expander_unstable(provider, expander) + } + + /// Creates a [`LocaleDirectionality`] from compiled data, using [`LocaleExpander`] + /// data for all locales. + /// + /// This includes all likely subtags data, see [`LocaleExpander::new_extended()`]. + #[cfg(feature = "compiled_data")] + pub const fn new_extended() -> Self { + Self::new_with_expander(LocaleExpander::new_extended()) + } + + // Note: This is a custom impl because the bounds on `try_new_unstable` don't suffice + #[doc = icu_provider::gen_buffer_unstable_docs!(BUFFER, Self::new_extended)] + #[cfg(feature = "serde")] + pub fn try_new_extended_with_buffer_provider( + provider: &(impl BufferProvider + ?Sized), + ) -> Result { + let expander = LocaleExpander::try_new_extended_with_buffer_provider(provider)?; + Self::try_new_with_expander_unstable(&provider.as_deserializing(), expander) + } + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new_extended)] + pub fn try_new_extended_unstable

(provider: &P) -> Result + where + P: DataProvider + + DataProvider + + DataProvider + + DataProvider + + ?Sized, + { + let expander = LocaleExpander::try_new_extended_unstable(provider)?; + Self::try_new_with_expander_unstable(provider, expander) + } +} + +impl> LocaleDirectionality { + /// Creates a [`LocaleDirectionality`] with a custom [`LocaleExpander`] and compiled data. + /// + /// This allows using [`LocaleExpander::new_extended()`] with data for all locales. + /// + /// # Examples + /// + /// ``` + /// use icu::locale::{ + /// langid, Direction, LocaleDirectionality, LocaleExpander, + /// }; + /// + /// let ld_default = LocaleDirectionality::new_common(); + /// + /// assert_eq!(ld_default.get(&langid!("jbn")), None); + /// + /// let expander = LocaleExpander::new_extended(); + /// let ld_extended = LocaleDirectionality::new_with_expander(expander); + /// + /// assert_eq!( + /// ld_extended.get(&langid!("jbn")), + /// Some(Direction::RightToLeft) + /// ); + /// ``` + #[cfg(feature = "compiled_data")] + pub const fn new_with_expander(expander: Expander) -> Self { + LocaleDirectionality { + script_direction: DataPayload::from_static_ref( + crate::provider::Baked::SINGLETON_LOCALE_SCRIPT_DIRECTION_V1, + ), + expander, + } + } + + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new_with_expander)] + pub fn try_new_with_expander_unstable

( + provider: &P, + expander: Expander, + ) -> Result + where + P: DataProvider + ?Sized, + { + let script_direction = provider.load(Default::default())?.payload; + + Ok(LocaleDirectionality { + script_direction, + expander, + }) + } + + /// Returns the script direction of the given locale. + /// + /// Note that the direction is a property of the script of a locale, not of the language. As such, + /// when given a locale without an associated script tag (i.e., `locale!("en")` vs. `locale!("en-Latn")`), + /// this method first tries to infer the script using the language and region before returning its direction. + /// + /// If you already have a script struct and want to get its direction, you should use + /// `Locale::from(Some(my_script))` and call this method. + /// + /// This method will return `None` if either a locale's script cannot be determined, or there is no information + /// for the script. + /// + /// # Examples + /// + /// Using an existing locale: + /// + /// ``` + /// use icu::locale::{langid, Direction, LocaleDirectionality}; + /// + /// let ld = LocaleDirectionality::new_common(); + /// + /// assert_eq!(ld.get(&langid!("en-US")), Some(Direction::LeftToRight)); + /// + /// assert_eq!(ld.get(&langid!("ar")), Some(Direction::RightToLeft)); + /// + /// assert_eq!(ld.get(&langid!("en-Arab")), Some(Direction::RightToLeft)); + /// + /// assert_eq!(ld.get(&langid!("foo")), None); + /// ``` + /// + /// Using a script directly: + /// + /// ``` + /// use icu::locale::subtags::script; + /// use icu::locale::{Direction, LanguageIdentifier, LocaleDirectionality}; + /// + /// let ld = LocaleDirectionality::new_common(); + /// + /// assert_eq!( + /// ld.get(&LanguageIdentifier::from(Some(script!("Latn")))), + /// Some(Direction::LeftToRight) + /// ); + /// ``` + pub fn get(&self, langid: &LanguageIdentifier) -> Option { + let script = self.expander.as_ref().get_likely_script(langid)?; + + if self.script_in_ltr(script) { + Some(Direction::LeftToRight) + } else if self.script_in_rtl(script) { + Some(Direction::RightToLeft) + } else { + None + } + } + + /// Returns whether the given locale is right-to-left. + /// + /// Note that if this method returns `false`, the locale is either left-to-right or + /// the [`LocaleDirectionality`] does not include data for the locale. + /// You should use [`LocaleDirectionality::get`] if you need to differentiate between these cases. + /// + /// See [`LocaleDirectionality::get`] for more information. + pub fn is_right_to_left(&self, langid: &LanguageIdentifier) -> bool { + self.expander + .as_ref() + .get_likely_script(langid) + .map(|s| self.script_in_rtl(s)) + .unwrap_or(false) + } + + /// Returns whether the given locale is left-to-right. + /// + /// Note that if this method returns `false`, the locale is either right-to-left or + /// the [`LocaleDirectionality`] does not include data for the locale. + /// You should use [`LocaleDirectionality::get`] if you need to differentiate between these cases. + /// + /// See [`LocaleDirectionality::get`] for more information. + pub fn is_left_to_right(&self, langid: &LanguageIdentifier) -> bool { + self.expander + .as_ref() + .get_likely_script(langid) + .map(|s| self.script_in_ltr(s)) + .unwrap_or(false) + } + + fn script_in_rtl(&self, script: Script) -> bool { + self.script_direction + .get() + .rtl + .binary_search(&script.to_tinystr().to_unvalidated()) + .is_ok() + } + + fn script_in_ltr(&self, script: Script) -> bool { + self.script_direction + .get() + .ltr + .binary_search(&script.to_tinystr().to_unvalidated()) + .is_ok() + } +} diff --git a/deps/crates/vendor/icu_locale/src/exemplar_chars.rs b/deps/crates/vendor/icu_locale/src/exemplar_chars.rs new file mode 100644 index 00000000000000..98385e1a95bd1d --- /dev/null +++ b/deps/crates/vendor/icu_locale/src/exemplar_chars.rs @@ -0,0 +1,305 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! This module provides APIs for getting exemplar characters for a locale. +//! +//! Exemplars are characters used by a language, separated into different sets. +//! The sets are: main, auxiliary, punctuation, numbers, and index. +//! +//! The sets define, according to typical usage in the language, +//! which characters occur in which contexts with which frequency. +//! For more information, see the documentation in the +//! [Exemplars section in Unicode Technical Standard #35](https://unicode.org/reports/tr35/tr35-general.html#Exemplars) +//! of the LDML specification. +//! +//! # Examples +//! +//! ``` +//! use icu::locale::exemplar_chars::ExemplarCharacters; +//! use icu::locale::locale; +//! +//! let locale = locale!("en-001").into(); +//! let exemplars_main = ExemplarCharacters::try_new_main(&locale) +//! .expect("locale should be present"); +//! +//! assert!(exemplars_main.contains('a')); +//! assert!(exemplars_main.contains('z')); +//! assert!(exemplars_main.contains_str("a")); +//! assert!(!exemplars_main.contains_str("ä")); +//! assert!(!exemplars_main.contains_str("ng")); +//! ``` + +use crate::provider::*; +use core::ops::Deref; +use icu_collections::codepointinvliststringlist::CodePointInversionListAndStringList; +use icu_provider::{marker::ErasedMarker, prelude::*}; + +/// A wrapper around `UnicodeSet` data (characters and strings) +#[derive(Debug)] +pub struct ExemplarCharacters { + data: DataPayload>>, +} + +impl ExemplarCharacters { + /// Construct a borrowed version of this type that can be queried. + /// + /// This avoids a potential small underlying cost per API call (ex: `contains()`) by consolidating it + /// up front. + #[inline] + pub fn as_borrowed(&self) -> ExemplarCharactersBorrowed<'_> { + ExemplarCharactersBorrowed { + data: self.data.get(), + } + } +} + +/// A borrowed wrapper around code point set data, returned by +/// [`ExemplarCharacters::as_borrowed()`]. More efficient to query. +#[derive(Clone, Copy, Debug)] +pub struct ExemplarCharactersBorrowed<'a> { + data: &'a ExemplarCharactersData<'a>, +} + +impl<'a> Deref for ExemplarCharactersBorrowed<'a> { + type Target = CodePointInversionListAndStringList<'a>; + + fn deref(&self) -> &Self::Target { + &self.data.0 + } +} + +impl ExemplarCharactersBorrowed<'static> { + /// Cheaply converts a [`ExemplarCharactersBorrowed<'static>`] into a [`ExemplarCharacters`]. + /// + /// Note: Due to branching and indirection, using [`ExemplarCharacters`] might inhibit some + /// compile-time optimizations that are possible with [`ExemplarCharactersBorrowed`]. + pub const fn static_to_owned(self) -> ExemplarCharacters { + ExemplarCharacters { + data: DataPayload::from_static_ref(self.data), + } + } +} + +macro_rules! make_exemplar_chars_unicode_set_property { + ( + // currently unused + dyn_data_marker: $d:ident; + data_marker: $data_marker:ty; + func: + pub fn $unstable:ident(); + $(#[$attr:meta])* + pub fn $compiled:ident(); + ) => { + impl ExemplarCharactersBorrowed<'static> { + $(#[$attr])* + #[cfg(feature = "compiled_data")] + #[inline] + pub fn $compiled( + locale: &DataLocale, + ) -> Result { + Ok(ExemplarCharactersBorrowed { + data: DataProvider::<$data_marker>::load( + &crate::provider::Baked, + DataRequest { + id: DataIdentifierBorrowed::for_locale(locale), + ..Default::default() + })? + .payload + .get_static() + .ok_or_else(|| DataError::custom("Baked provider didn't return static payload"))? + }) + } + + } + impl ExemplarCharacters { + $(#[$attr])* + #[cfg(feature = "compiled_data")] + pub fn $compiled( + locale: &DataLocale, + ) -> Result, DataError> { + ExemplarCharactersBorrowed::$compiled(locale) + } + + #[doc = concat!("A version of [`Self::", stringify!($compiled), "()`] that uses custom data provided by a [`DataProvider`].")] + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + pub fn $unstable( + provider: &(impl DataProvider<$data_marker> + ?Sized), + locale: &DataLocale, + ) -> Result { + Ok(Self { + data: + provider.load( + DataRequest { + id: DataIdentifierBorrowed::for_locale(locale), + ..Default::default() + })? + .payload + .cast() + }) + } + } + } +} + +make_exemplar_chars_unicode_set_property!( + dyn_data_marker: ExemplarCharactersMain; + data_marker: LocaleExemplarCharactersMainV1; + func: + pub fn try_new_main_unstable(); + + /// Get the "main" set of exemplar characters. + /// + /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + /// + /// # Examples + /// + /// ``` + /// use icu::locale::locale; + /// use icu::locale::exemplar_chars::ExemplarCharacters; + /// + /// let exemplars_main = ExemplarCharacters::try_new_main(&locale!("en").into()) + /// .expect("locale should be present"); + /// + /// assert!(exemplars_main.contains('a')); + /// assert!(exemplars_main.contains('z')); + /// assert!(exemplars_main.contains_str("a")); + /// assert!(!exemplars_main.contains_str("ä")); + /// assert!(!exemplars_main.contains_str("ng")); + /// assert!(!exemplars_main.contains_str("A")); + /// ``` + pub fn try_new_main(); +); + +make_exemplar_chars_unicode_set_property!( + dyn_data_marker: ExemplarCharactersAuxiliary; + data_marker: LocaleExemplarCharactersAuxiliaryV1; + func: + pub fn try_new_auxiliary_unstable(); + + /// Get the "auxiliary" set of exemplar characters. + /// + /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + /// + /// # Examples + /// + /// ``` + /// use icu::locale::locale; + /// use icu::locale::exemplar_chars::ExemplarCharacters; + /// + /// let exemplars_auxiliary = + /// ExemplarCharacters::try_new_auxiliary(&locale!("en").into()) + /// .expect("locale should be present"); + /// + /// assert!(!exemplars_auxiliary.contains('a')); + /// assert!(!exemplars_auxiliary.contains('z')); + /// assert!(!exemplars_auxiliary.contains_str("a")); + /// assert!(exemplars_auxiliary.contains_str("ä")); + /// assert!(!exemplars_auxiliary.contains_str("ng")); + /// assert!(!exemplars_auxiliary.contains_str("A")); + /// ``` + pub fn try_new_auxiliary(); +); + +make_exemplar_chars_unicode_set_property!( + dyn_data_marker: ExemplarCharactersPunctuation; + data_marker: LocaleExemplarCharactersPunctuationV1; + func: + pub fn try_new_punctuation_unstable(); + + /// Get the "punctuation" set of exemplar characters. + /// + /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + /// + /// # Examples + /// + /// ``` + /// use icu::locale::locale; + /// use icu::locale::exemplar_chars::ExemplarCharacters; + /// + /// let exemplars_punctuation = + /// ExemplarCharacters::try_new_punctuation(&locale!("en").into()) + /// .expect("locale should be present"); + /// + /// assert!(!exemplars_punctuation.contains('0')); + /// assert!(!exemplars_punctuation.contains('9')); + /// assert!(!exemplars_punctuation.contains('%')); + /// assert!(exemplars_punctuation.contains(',')); + /// assert!(exemplars_punctuation.contains('.')); + /// assert!(exemplars_punctuation.contains('!')); + /// assert!(exemplars_punctuation.contains('?')); + /// ``` + pub fn try_new_punctuation(); +); + +make_exemplar_chars_unicode_set_property!( + dyn_data_marker: ExemplarCharactersNumbers; + data_marker: LocaleExemplarCharactersNumbersV1; + func: + pub fn try_new_numbers_unstable(); + + /// Get the "numbers" set of exemplar characters. + /// + /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + /// + /// # Examples + /// + /// ``` + /// use icu::locale::locale; + /// use icu::locale::exemplar_chars::ExemplarCharacters; + /// + /// let exemplars_numbers = + /// ExemplarCharacters::try_new_numbers(&locale!("en").into()) + /// .expect("locale should be present"); + /// + /// assert!(exemplars_numbers.contains('0')); + /// assert!(exemplars_numbers.contains('9')); + /// assert!(exemplars_numbers.contains('%')); + /// assert!(exemplars_numbers.contains(',')); + /// assert!(exemplars_numbers.contains('.')); + /// assert!(!exemplars_numbers.contains('!')); + /// assert!(!exemplars_numbers.contains('?')); + /// ``` + pub fn try_new_numbers(); +); + +make_exemplar_chars_unicode_set_property!( + dyn_data_marker: ExemplarCharactersIndex; + data_marker: LocaleExemplarCharactersIndexV1; + func: + pub fn try_new_index_unstable(); + + /// Get the "index" set of exemplar characters. + /// + /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// + /// [📚 Help choosing a constructor](icu_provider::constructors) + /// + /// # Examples + /// + /// ``` + /// use icu::locale::locale; + /// use icu::locale::exemplar_chars::ExemplarCharacters; + /// + /// let exemplars_index = + /// ExemplarCharacters::try_new_index(&locale!("en").into()) + /// .expect("locale should be present"); + /// + /// assert!(!exemplars_index.contains('a')); + /// assert!(!exemplars_index.contains('z')); + /// assert!(!exemplars_index.contains_str("a")); + /// assert!(!exemplars_index.contains_str("ä")); + /// assert!(!exemplars_index.contains_str("ng")); + /// assert!(exemplars_index.contains_str("A")); + /// ``` + pub fn try_new_index(); +); diff --git a/deps/crates/vendor/icu_locale/src/expander.rs b/deps/crates/vendor/icu_locale/src/expander.rs new file mode 100644 index 00000000000000..25291a6649013d --- /dev/null +++ b/deps/crates/vendor/icu_locale/src/expander.rs @@ -0,0 +1,606 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::provider::*; + +use icu_locale_core::subtags::{Language, Region, Script}; +use icu_locale_core::LanguageIdentifier; +use icu_provider::prelude::*; + +use crate::TransformResult; + +/// Implements the *Add Likely Subtags* and *Remove Likely Subtags* +/// algorithms as defined in *[UTS #35: Likely Subtags]*. +/// +/// # Examples +/// +/// Add likely subtags: +/// +/// ``` +/// use icu::locale::locale; +/// use icu::locale::{LocaleExpander, TransformResult}; +/// +/// let lc = LocaleExpander::new_common(); +/// +/// let mut locale = locale!("zh-CN"); +/// assert_eq!(lc.maximize(&mut locale.id), TransformResult::Modified); +/// assert_eq!(locale, locale!("zh-Hans-CN")); +/// +/// let mut locale = locale!("zh-Hant-TW"); +/// assert_eq!(lc.maximize(&mut locale.id), TransformResult::Unmodified); +/// assert_eq!(locale, locale!("zh-Hant-TW")); +/// ``` +/// +/// Remove likely subtags: +/// +/// ``` +/// use icu::locale::{locale, LocaleExpander, TransformResult}; +/// +/// let lc = LocaleExpander::new_common(); +/// +/// let mut locale = locale!("zh-Hans-CN"); +/// assert_eq!(lc.minimize(&mut locale.id), TransformResult::Modified); +/// assert_eq!(locale, locale!("zh")); +/// +/// let mut locale = locale!("zh"); +/// assert_eq!(lc.minimize(&mut locale.id), TransformResult::Unmodified); +/// assert_eq!(locale, locale!("zh")); +/// ``` +/// +/// Normally, only CLDR locales with Basic or higher coverage are included. To include more +/// locales for maximization, use [`try_new_extended`](Self::try_new_extended_unstable): +/// +/// ``` +/// use icu::locale::{locale, LocaleExpander, TransformResult}; +/// +/// let lc = LocaleExpander::new_extended(); +/// +/// let mut locale = locale!("atj"); +/// assert_eq!(lc.maximize(&mut locale.id), TransformResult::Modified); +/// assert_eq!(locale, locale!("atj-Latn-CA")); +/// ``` +/// +/// [UTS #35: Likely Subtags]: https://www.unicode.org/reports/tr35/#Likely_Subtags +#[derive(Debug, Clone)] +pub struct LocaleExpander { + likely_subtags_l: DataPayload, + likely_subtags_sr: DataPayload, + likely_subtags_ext: Option>, +} + +struct LocaleExpanderBorrowed<'a> { + likely_subtags_l: &'a LikelySubtagsForLanguage<'a>, + likely_subtags_sr: &'a LikelySubtagsForScriptRegion<'a>, + likely_subtags_ext: Option<&'a LikelySubtagsExtended<'a>>, +} + +impl LocaleExpanderBorrowed<'_> { + fn get_l(&self, l: Language) -> Option<(Script, Region)> { + let key = &l.to_tinystr().to_unvalidated(); + self.likely_subtags_l.language.get_copied(key).or_else(|| { + self.likely_subtags_ext + .and_then(|ext| ext.language.get_copied(key)) + }) + } + + fn get_ls(&self, l: Language, s: Script) -> Option { + let key = &( + l.to_tinystr().to_unvalidated(), + s.to_tinystr().to_unvalidated(), + ); + self.likely_subtags_l + .language_script + .get_copied(key) + .or_else(|| { + self.likely_subtags_ext + .and_then(|ext| ext.language_script.get_copied(key)) + }) + } + + fn get_lr(&self, l: Language, r: Region) -> Option