diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 936c2a06125795..3950bc702eb58b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,4 +1,8 @@ @@ -147,13 +147,21 @@ platforms. This is true regardless of entries in the table below. [^4]: Our macOS Binaries are compiled with 13.5 as a target. Xcode 16 is required to compile. -[^7]: Native riscv64 builds need GCC >= 14 or Clang >= 19 because V8 +[^5]: Native riscv64 builds need GCC >= 14 or Clang >= 19 because V8 includes `` and uses `target("arch=+v")` in `deps/v8/src/base/cpu.cc`. GCC 13's `riscv_vector.h` errors out without `-march=rv64gcv` and doesn't support the `target` attribute at all. Cross-compilation from x64 is unaffected (the code is behind `V8_HOST_ARCH_RISCV64`). +[^8]: Our macOS testing infrastructure provider has announced end of support for + Intel-based architecture for early 2028 at which time that platform will move to + experimental status as the Node.js project will no longer be able to test changes on any + Intel-based macOS version. When this change occurs the project intends to continue + creating universal binaries for versions of Node.js which are still in support which will + be compatible with both Apple Silicon-based and Intel-based macOS versions but + they will be untested. + ### Supported toolchains @@ -172,7 +180,7 @@ Binaries at are produced on: | Binary package | Platform and Toolchain | | ----------------------- | ------------------------------------------------------------- | -| aix-ppc64 | AIX 7.2 TL04 on PPC64BE with GCC 12[^5] | +| aix-ppc64 | AIX 7.2 TL04 on PPC64BE with Clang 20.1 | | darwin-x64 | macOS 15, Xcode 16 with -mmacosx-version-min=13.5 | | darwin-arm64 (and .pkg) | macOS 15 (arm64), Xcode 16 with -mmacosx-version-min=13.5 | | linux-arm64 | RHEL 8 with Clang 20.1 and gcc-toolset-14-libatomic-devel[^6] | @@ -189,9 +197,6 @@ on your Linux distribution. -[^5]: Binaries produced on these systems require libstdc++12, available - from the [AIX toolbox][]. - [^6]: Binaries produced on these systems are compatible with glibc >= 2.28 and libstdc++ >= 6.0.25 (`GLIBCXX_3.4.25`). These are available on distributions natively supporting GCC 8.1 or higher, such as Debian 10, @@ -1052,8 +1057,8 @@ Node.js supports the [Temporal](https://github.com/tc39/proposal-temporal) APIs, linking statically or dynamically with a version of [temporal\_rs](https://github.com/boa-dev/temporal). Building it requires a Rust toolchain: -* rustc >= 1.82 (with LLVM >= 19) -* cargo >= 1.82 +* rustc >= 1.83 (with LLVM >= 19) +* cargo >= 1.83 Refer to [Install Rust](https://rust-lang.org/tools/install/) for instructions. Individual packages such as `rust` and `cargo` in some operating system distributions may be considered @@ -1152,7 +1157,6 @@ version of a dependency), please reserve and use a custom `NODE_MODULE_VERSION` by opening a pull request against the registry available at . -[AIX toolbox]: https://www.ibm.com/support/pages/aix-toolbox-open-source-software-overview [Developer Mode]: https://learn.microsoft.com/en-us/windows/advanced-settings/developer-mode [Python downloads]: https://www.python.org/downloads/ [Python versions]: https://devguide.python.org/versions/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ea49b86360be7..2f14a393b9c24a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,8 @@ release. -26.4.0
+26.5.0
+26.4.0
26.3.1
26.3.0
26.2.0
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e22f23543e5ccc..b47b9868461be5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,10 @@ # Contributing to Node.js +> \[!TIP] +> Contributing for the first time? Please read our +> [Guide for First-Time Contributors](./doc/contributing/first-contributions.md) for tips +> and answers to FAQs. + Contributions to Node.js include code, documentation, answering user questions, running the project's infrastructure, and advocating for all types of Node.js users. diff --git a/Makefile b/Makefile index 961682e607272c..985ed3dd84834d 100644 --- a/Makefile +++ b/Makefile @@ -932,6 +932,22 @@ out/doc/apilinks.json: $(wildcard lib/*.js) tools/doc/node_modules | out/doc ) \ fi +doc/node.1: + $(error Please use 'make node.1' instead of 'make $@'.) + +.PHONY: node.1 +node.1: doc/api/cli.md tools/doc/node_modules + @if [ "$(shell $(node_use_openssl_and_icu))" != "true" ]; then \ + echo "Skipping $@ (no crypto and/or no ICU)"; \ + else \ + $(call available-node, \ + $(DOC_KIT) generate \ + -v $(VERSION) \ + --config-file tools/doc/man-page.doc-kit.config.mjs \ + -o doc \ + ) \ + fi + .PHONY: docopen docopen: doc-only ## Open the documentation in a web browser. @$(PYTHON) -mwebbrowser file://$(abspath $<) @@ -1480,8 +1496,26 @@ tools/.mdlintstamp: tools/lint-md/node_modules/remark-parse/package.json $(LINT_ @$(call available-node,$(run-lint-md)) @touch $@ +tools/.manpagelintstamp: doc/node.1 doc/api/cli.md tools/doc/node_modules + $(info Verifying that $< is up to date...) + @if [ "$(shell $(node_use_openssl_and_icu))" != "true" ]; then \ + echo "Skipping $< verification (no crypto and/or no ICU)"; \ + else \ + $(RM) -r tools/doc/.manpagecheck && \ + $(call available-node, \ + $(DOC_KIT) generate \ + -v $(VERSION) \ + --config-file tools/doc/man-page.doc-kit.config.mjs \ + ) \ + if ! diff -u $< tools/doc/.manpagecheck/node.1; then \ + echo '$< is out of date; run `make node.1` to regenerate it.' >&2; \ + exit 1; \ + fi; \ + fi + @touch $@ + .PHONY: lint-md -lint-md: lint-js-doc | tools/.mdlintstamp ## Lint the markdown documents maintained by us in the codebase. +lint-md: lint-js-doc | tools/.mdlintstamp tools/.manpagelintstamp ## Lint the markdown documents maintained by us in the codebase. run-format-md = tools/lint-md/lint-md.mjs --format $(LINT_MD_FILES) .PHONY: format-md diff --git a/README.md b/README.md index c2012523eb199a..dc175eadf5bb6a 100644 --- a/README.md +++ b/README.md @@ -405,8 +405,6 @@ For information about the governance of the Node.js project, see **Tim Perry** <> (he/him) * [pmarchini](https://github.com/pmarchini) - **Pietro Marchini** <> (he/him) -* [puskin](https://github.com/puskin) - - **Giovanni Bucci** <> (he/him) * [Qard](https://github.com/Qard) - **Stephen Belanger** <> (he/him) * [RafaelGSS](https://github.com/RafaelGSS) - @@ -653,6 +651,8 @@ For information about the governance of the Node.js project, see **Prince John Wesley** <> * [psmarshall](https://github.com/psmarshall) - **Peter Marshall** <> (he/him) +* [puskin](https://github.com/puskin) - + **Giovanni Bucci** <> (he/him) * [puzpuzpuz](https://github.com/puzpuzpuz) - **Andrey Pechkurov** <> (he/him) * [refack](https://github.com/refack) - @@ -785,6 +785,8 @@ Primary GPG keys for Node.js Releasers (some Releasers sign with subkeys): `C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C` * **Ruy Adorno** <> `108F52B48DB57BB0CC439B2997B01419BD92F80A` +* **Stewart X Addison** <> + `655F3B5C1FB3FA8D1A0CA6BDE4A7D232B936D2FD` * **Ulises Gascón** <> `A363A499291CBBC940DD62E41F10027AF002F8B0` @@ -802,6 +804,7 @@ gpg --keyserver hkps://keys.openpgp.org --recv-keys 8FCCA13FEF1D0C2E91008E09770F gpg --keyserver hkps://keys.openpgp.org --recv-keys 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 # Rafael Gonzaga gpg --keyserver hkps://keys.openpgp.org --recv-keys C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C # Richard Lau gpg --keyserver hkps://keys.openpgp.org --recv-keys 108F52B48DB57BB0CC439B2997B01419BD92F80A # Ruy Adorno +gpg --keyserver hkps://keys.openpgp.org --recv-keys 655F3B5C1FB3FA8D1A0CA6BDE4A7D232B936D2FD # Stewart X Addison gpg --keyserver hkps://keys.openpgp.org --recv-keys A363A499291CBBC940DD62E41F10027AF002F8B0 # Ulises Gascón ``` diff --git a/SECURITY.md b/SECURITY.md index 8444534c77bd15..4caa3cc18971af 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -124,23 +124,32 @@ This policy recognizes that experimental platforms may not compile, may not pass the test suite, and do not have the same level of testing and support infrastructure as Tier 1 and Tier 2 platforms. -### Experimental features behind compile-time flags +### Experimental features behind compile-time flags and V8 flags Node.js includes certain experimental features that are only available when Node.js is compiled with specific flags. These features are intended for development, debugging, or testing purposes and are not enabled in official releases. +Node.js may also expose V8 features that are controlled by V8 command-line flags +(e.g., `--js-staging`, `--max_old_space_size`). These flags +enable or modify V8-level JavaScript engine behavior that is not part of the +ECMAScript specification that Node.js implements and is not part of the +Node.js documented API surface. + * Security vulnerabilities that only affect features behind compile-time flags - will **not** be accepted as valid security issues. + or V8 flags will **not** be accepted as valid security issues. * Any issues with these features will be treated as normal bugs. -* No CVEs will be issued for issues that only affect compile-time flag features. -* Bug bounty rewards are not available for compile-time flag feature issues. +* No CVEs will be issued for issues that only affect compile-time flag or V8 flag features. +* Bug bounty rewards are not available for compile-time flag or V8 flag feature issues. This policy recognizes that experimental features behind compile-time flags are not ready for public consumption and may have incomplete implementations, missing security hardening, or other limitations that make them unsuitable -for production use. +for production use. Similarly, V8 flags expose internal V8 engine options that +are not part of the Node.js documented API surface, are not enabled by +default in production builds, and may have incomplete implementations or +missing security hardening. ### What constitutes a vulnerability @@ -276,6 +285,22 @@ the community they pose. ### Examples of non-vulnerabilities +#### Defense-in-depth issues + +* Bugs whose fixes would only improve resilience after another security + boundary has already failed, or reduce the impact of an issue outside the + Node.js threat model, are considered defense-in-depth issues. +* Defense-in-depth issues are never treated as Node.js security vulnerabilities, + do not receive CVEs, and are handled as regular bugs or hardening improvements. + +#### Malicious protocol peers + +* Node.js treats data from remote network peers as untrusted, and bugs in + parsers or protocol implementations may be security vulnerabilities. +* Node.js treats data from HTTP/1.1 keep-alive connections as trusted, meaning that a Node.js + client consuming unsolicited or misordered responses within the same HTTP/1.1 connection + reuse lifecycle are generally not considered Node.js vulnerabilities. + #### Malicious Third-Party Modules (CWE-1357) * Code is trusted by Node.js. Therefore any scenario that requires a malicious @@ -421,6 +446,24 @@ The following are **not** vulnerabilities in Node.js: restrictions of their parent process. Passing an empty or modified `execArgv` to a worker does not grant it additional permissions. +#### Virtual File System (`node:vfs`) + +The experimental [Virtual File System](https://nodejs.org/api/vfs.html) +(`node:vfs`) is a virtualized file-system API for tests, fixtures, embedded +assets, and application-managed storage. It is **not** a sandbox, permission +system, or security boundary for untrusted code. + +Code that can load `node:vfs`, receive a `VirtualFileSystem` instance, install a +mount, choose a provider, or pass paths to VFS APIs is trusted application code. +A VFS mount only redirects matching file-system calls; it does not hide or +restrict access to the host file system. `RealFSProvider` root checks and +read-only providers are implementation behavior, not security guarantees. + +Reports that rely on using VFS to isolate untrusted JavaScript, native code, or +user-controlled paths are not considered Node.js vulnerabilities. Use OS-level +isolation, such as separate users, containers, or platform sandboxes, when a +security boundary is required. + #### V8 Sandbox The V8 sandbox is an in-process isolation mechanism internal to V8 that is not @@ -532,6 +575,7 @@ In addition, these individuals have access: * [cjihrig](https://github.com/cjihrig) **Colin Ihrig** * [joesepi](https://github.com/joesepi) - **Joe Sepi** * [juanarbol](https://github.com/juanarbol) **Juan Jose Arboleda** +* [sxa](https://github.com/sxa) - **Stewart X Addison** * [ulisesgascon](https://github.com/ulisesgascon) **Ulises Gascón** * [vdeturckheim](https://github.com/vdeturckheim) - **Vladimir de Turckheim** @@ -546,6 +590,7 @@ the Node.js program on HackerOne. * [@anonrig](https://github.com/anonrig) - Yagiz Nizipli * [@bengl](https://github.com/bengl) - Bryan English * [@benjamingr](https://github.com/benjamingr) - Benjamin Gruenbaum +* [@BethGriggs](https://github.com/BethGriggs) - Beth Griggs * [@bmeck](https://github.com/bmeck) - Bradley Farias * [@bnoordhuis](https://github.com/bnoordhuis) - Ben Noordhuis * [@BridgeAR](https://github.com/BridgeAR) - Ruben Bridgewater @@ -568,6 +613,7 @@ the Node.js program on HackerOne. * [@ruyadorno](https://github.com/ruyadorno) - Ruy Adorno * [@santigimeno](https://github.com/santigimeno) - Santiago Gimeno * [@ShogunPanda](https://github.com/ShogunPanda) - Paolo Insogna +* [@sxa](https://github.com/sxa) - Stewart X Addison * [@targos](https://github.com/targos) - Michaël Zasso * [@tniessen](https://github.com/tniessen) - Tobias Nießen * [@UlisesGascon](https://github.com/UlisesGascon) - Ulises Gascón diff --git a/benchmark/abort_controller/abort-controller-creation.js b/benchmark/abort_controller/abort-controller-creation.js new file mode 100644 index 00000000000000..cf21e2aac86585 --- /dev/null +++ b/benchmark/abort_controller/abort-controller-creation.js @@ -0,0 +1,33 @@ +'use strict'; + +const common = require('../common.js'); +const assert = require('node:assert'); + +const bench = common.createBenchmark(main, { + n: [1e6], + kind: ['AbortController', 'AbortSignal.timeout'], +}); + +function main({ n, kind }) { + let result; + + switch (kind) { + case 'AbortController': + bench.start(); + for (let i = 0; i < n; i++) + result = new AbortController().signal; // AbortSignal is created lazily on first .signal access + bench.end(n); + break; + case 'AbortSignal.timeout': + bench.start(); + for (let i = 0; i < n; i++) + result = AbortSignal.timeout(1); + bench.end(n); + break; + default: + throw new Error('Invalid kind'); + } + + // Avoid V8 dead code elimination + assert.ok(result); +} diff --git a/benchmark/crypto/argon2.js b/benchmark/crypto/argon2.js index ce6a824233e636..c11d5837954a05 100644 --- a/benchmark/crypto/argon2.js +++ b/benchmark/crypto/argon2.js @@ -17,10 +17,12 @@ if (!hasOpenSSL(3, 2)) { const bench = common.createBenchmark(main, { mode: ['sync', 'async'], algorithm: ['argon2d', 'argon2i', 'argon2id'], - passes: [1, 3], - parallelism: [2, 4, 8], - memory: [2 ** 11, 2 ** 16, 2 ** 21], - n: [50], + passes: [3], + parallelism: [1], + // Argon2 memory cost dominates runtime. Keep the default suite small enough + // to finish while still covering a low-cost and a memory-heavy derivation. + memory: [2 ** 11, 2 ** 16], + n: [5], }); function measureSync(n, algorithm, message, nonce, options) { diff --git a/benchmark/dgram/send-to-ip.js b/benchmark/dgram/send-to-ip.js new file mode 100644 index 00000000000000..8704462cf8d8bd --- /dev/null +++ b/benchmark/dgram/send-to-ip.js @@ -0,0 +1,43 @@ +// Measure the send rate to a literal IP destination. The destination needs no +// name resolution, so this isolates the per-send overhead the default lookup +// pays before the packet reaches the socket. +'use strict'; + +const common = require('../common.js'); +const dgram = require('dgram'); +const PORT = common.PORT; + +// `n` is the number of send requests queued each round. Keep it high (>10) so +// the measurement reflects send overhead rather than event loop cycles. +const bench = common.createBenchmark(main, { + n: [100], + dur: [5], +}); + +function main({ dur, n }) { + const chunk = Buffer.allocUnsafe(1); + let sent = 0; + const socket = dgram.createSocket('udp4'); + + function onsend() { + if (sent++ % n === 0) { + setImmediate(() => { + for (let i = 0; i < n; i++) { + socket.send(chunk, PORT, '127.0.0.1', onsend); + } + }); + } + } + + socket.on('listening', () => { + bench.start(); + onsend(); + + setTimeout(() => { + bench.end(sent); + process.exit(0); + }, dur * 1000); + }); + + socket.bind(PORT); +} diff --git a/common.gypi b/common.gypi index 36b4b1138dbfd2..bae09d8a5d6300 100644 --- a/common.gypi +++ b/common.gypi @@ -14,6 +14,7 @@ 'enable_pgo_use%': '0', 'clang_profile_lib%': '', 'python%': 'python', + 'emulator%': [], 'node_shared%': 'false', 'node_enable_experimentals%': 'false', @@ -40,7 +41,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.21', + 'v8_embedder_string': '-node.24', ##### V8 defaults for Node.js ##### diff --git a/configure.py b/configure.py index cb237922a90697..73a755f67e7068 100755 --- a/configure.py +++ b/configure.py @@ -55,7 +55,7 @@ valid_mips_float_abi = ('soft', 'hard') valid_intl_modes = ('none', 'small-icu', 'full-icu', 'system-icu') icu_versions = json.loads((tools_path / 'icu' / 'icu_versions.json').read_text(encoding='utf-8')) -maglev_enabled_architectures = ('x64', 'arm', 'arm64', 'ppc64', 's390x') +maglev_enabled_architectures = ('x64', 'arm', 'arm64', 'ppc64', 's390x', 'riscv64') # builtins may be removed later if they have been disabled by options shareable_builtins = {'undici/undici': 'deps/undici/undici.js', @@ -117,6 +117,12 @@ choices=valid_arch, help=f"CPU architecture to build for ({', '.join(valid_arch)})") +parser.add_argument('--emulator', + action='store', + dest='emulator', + default=None, + help='emulator command that can run executables built for the target system') + parser.add_argument('--cross-compiling', action='store_true', dest='cross_compiling', @@ -2936,6 +2942,14 @@ def make_bin_override(): # will fail to run python scripts. gyp_args += ['-Dpython=' + python] +if options.emulator is not None: + if not options.cross_compiling: + # Note that emulator is a list so we have to quote the variable. + gyp_args += ['-Demulator=' + shlex.quote(options.emulator)] + else: + # TODO: perhaps use emulator for tests? + warn('The `--emulator` option has no effect when cross-compiling.') + if not options.v8_disable_temporal_support or not options.shared_temporal_capi: cargo = os.environ.get('CARGO') if cargo: diff --git a/deps/cares/src/lib/ares_sysconfig_win.c b/deps/cares/src/lib/ares_sysconfig_win.c index 35f4bd8e72ac9c..94a3817de348bb 100644 --- a/deps/cares/src/lib/ares_sysconfig_win.c +++ b/deps/cares/src/lib/ares_sysconfig_win.c @@ -106,7 +106,7 @@ static ares_bool_t get_REG_SZ(HKEY hKey, const WCHAR *leafKeyName, char **outptr /* Get the value for real */ res = RegQueryValueExW(hKey, leafKeyName, 0, NULL, (BYTE *)val, &size); - if (res != ERROR_SUCCESS || size == 1) { + if (res != ERROR_SUCCESS || size == sizeof(WCHAR)) { ares_free(val); return ARES_FALSE; } diff --git a/deps/crates/Cargo.lock b/deps/crates/Cargo.lock index b8586e1b704145..0bce93ad8dfe21 100644 --- a/deps/crates/Cargo.lock +++ b/deps/crates/Cargo.lock @@ -10,9 +10,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "calendrical_calculations" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a0b39595c6ee54a8d0900204ba4c401d0ab4eb45adaf07178e8d017541529e7" +checksum = "5abbd6eeda6885048d357edc66748eea6e0268e3dd11f326fff5bd248d779c26" dependencies = [ "core_maths", "displaydoc", @@ -29,9 +29,9 @@ dependencies = [ [[package]] name = "diplomat" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece782ffeb426ef0d3074c5623e8f6552cc912e4bbeecfda9583cb01b02b8ba1" +checksum = "9adb46b05e2f53dcf6a7dfc242e4ce9eb60c369b6b6eb10826a01e93167f59c6" dependencies = [ "diplomat_core", "proc-macro2", @@ -41,15 +41,15 @@ dependencies = [ [[package]] name = "diplomat-runtime" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c270cf75c6ba9d974a7a670d96c7bf8007cd0d03e1fbe128d62bd47d9fe25aef" +checksum = "0569bd3caaf13829da7ee4e83dbf9197a0e1ecd72772da6d08f0b4c9285c8d29" [[package]] name = "diplomat_core" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb0f9322e2c506400ac3f374abfcaf9fd841fcdb729bbf008a135b600f99ede7" +checksum = "51731530ed7f2d4495019abc7df3744f53338e69e2863a6a64ae91821c763df1" dependencies = [ "proc-macro2", "quote", @@ -72,9 +72,9 @@ dependencies = [ [[package]] name = "icu_calendar" -version = "2.0.6" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "362941891d17750e05cd8fdfca4a89a86552825d625a937020ee1a65580da1f9" +checksum = "d6f0e52e009b6b16ba9c0693578796f2dd4aaa59a7f8f920423706714a89ac4e" dependencies = [ "calendrical_calculations", "displaydoc", @@ -82,23 +82,22 @@ dependencies = [ "icu_locale", "icu_locale_core", "icu_provider", - "ixdtf 0.5.0", + "ixdtf", "tinystr", - "writeable", "zerovec", ] [[package]] name = "icu_calendar_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219c8639ab936713a87b571eed2bc2615aa9137e8af6eb221446ee5644acc18" +checksum = "527f04223b17edfe0bd43baf14a0cb1b017830db65f3950dc00224860a9a446d" [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -109,11 +108,10 @@ dependencies = [ [[package]] name = "icu_locale" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ae5921528335e91da1b6c695dbf1ec37df5ac13faa3f91e5640be93aa2fbefd" +checksum = "532b11722e350ab6bf916ba6eb0efe3ee54b932666afec989465f9243fe6dd60" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_locale_data", @@ -125,12 +123,13 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93cca704c2d63cf8a91f5c2c5f88e027940dede132319b85a52939db9758f7e5" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", + "serde", "tinystr", "writeable", "zerovec", @@ -138,20 +137,20 @@ dependencies = [ [[package]] name = "icu_locale_data" -version = "2.0.0" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fdef0c124749d06a743c69e938350816554eb63ac979166590e2b4ee4252765" +checksum = "1c5f1d16b4c3a2642d3a719f18f6b06070ab0aef246a6418130c955ae08aa831" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", + "serde", "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -161,34 +160,25 @@ dependencies = [ [[package]] name = "ixdtf" -version = "0.5.0" +version = "0.6.5" 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" +checksum = "2ceaf4c6c48465bead8cb6a0b7c4ee0c86ecbb31239032b9c66ab9a08d2f3ee1" [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "litemap" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "node_crates" -version = "0.1.0" +version = "0.1.2" dependencies = [ "icu_calendar", "icu_collections", @@ -211,9 +201,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "serde_core", "writeable", @@ -222,18 +212,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.42" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -299,9 +289,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.111" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -321,9 +311,9 @@ dependencies = [ [[package]] name = "temporal_capi" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf286aa4f5e07b9e46eeab2e1a55f8a752635f2fa92c88bf8287404e190c6cb" +checksum = "a151e402c2bdb6a3a2a2f3f225eddaead2e7ce7dd5d3fa2090deb11b17aa4ed8" dependencies = [ "diplomat", "diplomat-runtime", @@ -338,14 +328,14 @@ dependencies = [ [[package]] name = "temporal_rs" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7305090e19b67670330fde1365b7c2c8a3b5a5ef6c92efc238b3b964a8c395fd" +checksum = "88afde3bd75d2fc68d77a914bece426aa08aa7649ffd0cdd4a11c3d4d33474d1" dependencies = [ "core_maths", "icu_calendar", "icu_locale", - "ixdtf 0.6.4", + "ixdtf", "num-traits", "timezone_provider", "tinystr", @@ -354,9 +344,9 @@ dependencies = [ [[package]] name = "timezone_provider" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071d5533454ed925a1f4841f7128d1d248f3465d6a18e9afe298212916cc3269" +checksum = "df9ba0000e9e73862f3e7ca1ff159e2ddf915c9d8bb11e38a7874760f445d993" dependencies = [ "tinystr", "zerotrie", @@ -366,9 +356,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "serde_core", @@ -377,21 +367,21 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "yoke" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -400,9 +390,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", @@ -412,18 +402,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", @@ -433,18 +423,19 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", + "zerovec", ] [[package]] name = "zerovec" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "serde", "yoke", @@ -454,9 +445,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", @@ -465,9 +456,9 @@ dependencies = [ [[package]] name = "zoneinfo64" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6916519e4a1cff59d49e0b902caed549d85dbbbf623a95af5c8320d5c08c6e13" +checksum = "bb2e5597efbe7c421da8a7fd396b20b571704e787c21a272eecf35dfe9d386f0" dependencies = [ "calendrical_calculations", "icu_locale_core", diff --git a/deps/crates/Cargo.toml b/deps/crates/Cargo.toml index 7c67cc30e31944..c891b7a423bcab 100644 --- a/deps/crates/Cargo.toml +++ b/deps/crates/Cargo.toml @@ -4,42 +4,42 @@ [package] edition = "2021" name = "node_crates" -version = "0.1.0" -rust-version = "1.82" +version = "0.1.2" +rust-version = "1.83" [lib] crate-type = ["staticlib"] [dependencies] -# Pin all temporal dependencies to the last version support rustc 1.82 -icu_collections = "~2.0.0" -icu_locale_core = "~2.0.0" -icu_provider = "~2.0.0" -timezone_provider = "=0.1.0" +# Pin all temporal dependencies to be in sync with the version defined in deps/v8/DEPS:deps[third_party/rust] +icu_collections = "=2.1.1" +icu_locale_core = "=2.1.1" +icu_provider = "=2.1.1" +timezone_provider = "=0.1.2" [dependencies.temporal_capi] -version = "=0.1.0" +version = "=0.1.2" # Should be in sync with the version defined in deps/v8/DEPS:deps[third_party/rust] features = ["zoneinfo64"] default-features = false [dependencies.temporal_rs] -version = "=0.1.0" +version = "=0.1.2" # Should be in sync with the version defined in deps/v8/DEPS:deps[third_party/rust] default-features = false -# This is necessary to enable a spec-compliance quirk when upgrading to v0.1.2 -# features = ["float64_representable_durations"] +# This is necessary to enable a spec-compliance quirk +features = ["float64_representable_durations"] # Disable `icu_calendar_data` and `icu_locale_data` crates with disabling # `compiled_data` features. However these datasets are still enabled until -# https://github.com/boa-dev/temporal/pull/694 lands. +# https://github.com/boa-dev/temporal/pull/694 ships. [dependencies.icu_calendar] -version = "~2.0.0" +version = "~2.1.1" features = [ "ixdtf", # Parser for Internet eXtended DateTime Format ] default-features = false [dependencies.icu_locale] -version = "~2.0.0" +version = "~2.1.1" default-features = false [patch.crates-io] diff --git a/deps/crates/vendor/autocfg/.cargo-checksum.json b/deps/crates/vendor/autocfg/.cargo-checksum.json index 64152cc71efb71..944074e2e137ad 100644 --- a/deps/crates/vendor/autocfg/.cargo-checksum.json +++ b/deps/crates/vendor/autocfg/.cargo-checksum.json @@ -1 +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 +{"files":{".cargo_vcs_info.json":"bbdbd90be8e01b10f5516e44a9d4a09efc7e0c489eed3bb4e64adcde3b9d91a3","Cargo.lock":"152ebf71feed214951186ccc738958236b493bacf634d48ce422371c92ef0b07","Cargo.toml":"919934158a57ad16895ec2e937c5c14e3cef405b168c191d64dc81b69b9abe4a","Cargo.toml.orig":"958306c591cb50cd4b090194971e2eb213c641b304af82b2b36c31b60ffdc126","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_vcs_info.json b/deps/crates/vendor/autocfg/.cargo_vcs_info.json new file mode 100644 index 00000000000000..80087c70715896 --- /dev/null +++ b/deps/crates/vendor/autocfg/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "d912169ed67977efe5a465269b0e73cb66060c49" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/deps/crates/vendor/autocfg/Cargo.toml.orig b/deps/crates/vendor/autocfg/Cargo.toml.orig new file mode 100644 index 00000000000000..75b34ea605716d --- /dev/null +++ b/deps/crates/vendor/autocfg/Cargo.toml.orig @@ -0,0 +1,15 @@ +[package] +name = "autocfg" +version = "1.5.0" +authors = ["Josh Stone "] +license = "Apache-2.0 OR MIT" +repository = "https://github.com/cuviper/autocfg" +documentation = "https://docs.rs/autocfg/" +description = "Automatic cfg for Rust compiler features" +readme = "README.md" +keywords = ["rustc", "build", "autoconf"] +categories = ["development-tools::build-utils"] +exclude = ["/.github/**"] +rust-version = "1.0" + +[dependencies] diff --git a/deps/crates/vendor/calendrical_calculations/.cargo-checksum.json b/deps/crates/vendor/calendrical_calculations/.cargo-checksum.json index 852d8188cadf3f..10737af91c2ed7 100644 --- a/deps/crates/vendor/calendrical_calculations/.cargo-checksum.json +++ b/deps/crates/vendor/calendrical_calculations/.cargo-checksum.json @@ -1 +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 +{"files":{".cargo_vcs_info.json":"b9f2654b355735506074ccaa992507509587685da6d104a385440d532496fee1","Cargo.lock":"163885f5e1714f91f6e462583c5c35fe36e500d8ad82e4a59bd65549312900c4","Cargo.toml":"f9f054053fe9cad9f30e0ebe2ab78219d1db32a3600c55aee25a6edbee82a071","Cargo.toml.orig":"59918453e9b61b26bce7008ba322e0600176eab7e6ccc5558ecc90d266b0bfbe","LICENSE":"192ea857d1bff2b87c174de36cbae5c173234726c6b8eceab9790a535d7dbc95","README.md":"cdffd3b4ab1a4efad95de0dcdf0b097fce24fedf04d076e8ab3909ac2e2accb5","src/astronomy.rs":"4917e6234028628562acb225758e335ac80b0688e95381a8a288bfa5a2bad29a","src/chinese_based.rs":"aa200c6292a22e52f184d711cbbb7729eada103ef746cca3dd976669cc87bbc1","src/coptic.rs":"db3acc2988d5050aa050d8fd82af104049be49bdc56a6be7eb7d5f351d758de9","src/error.rs":"40dcbc44560061cfadd6f1c42ecb0c6eeb6cf8cc8f5f7bfb8a24496b0d46476d","src/ethiopian.rs":"ee85be0a7713e551d94bcf51c2029cb73c509488d3b158c798842654af960f04","src/gregorian.rs":"3b5edce2a8bb30c99d22124d3aee163c7bbb774f05b8fd0807233f9a23760efa","src/hebrew.rs":"bd84464d45b2b28395e2b8d474049ec196268299087d036dc0462b0e1efc1178","src/hebrew_keviyah.rs":"26d5902829e7b76063c77ca6fb7111a8b16bce3a3d3d93c43cfa367424c9246e","src/helpers.rs":"5251910b007f8ffc27acac7e60a7c66e524ecef9811c9c0e3d711bf453153b25","src/islamic.rs":"a0f7b3d4ce430f97aefff1894957393a7c44227974c0b530111358e83c2bb73e","src/julian.rs":"adfea63519a03e83e496863c4964222ee284053d1d690ee6e2db4186c50024ff","src/lib.rs":"b131a99b20a8a7f15ebcee4ea66cc057c7259dc81ad3f50e3e04318f8b53721e","src/persian.rs":"177efc990dea2c9243e0e7dc39b5fb33f4276b360bae7128352a0a6f8931eb2f","src/rata_die.rs":"ef5a2bbab9b3e0f5d008d304acbfec7d80f190105fffa0eda62169ba9252ee65"},"package":"5abbd6eeda6885048d357edc66748eea6e0268e3dd11f326fff5bd248d779c26"} \ No newline at end of file diff --git a/deps/crates/vendor/calendrical_calculations/.cargo_vcs_info.json b/deps/crates/vendor/calendrical_calculations/.cargo_vcs_info.json new file mode 100644 index 00000000000000..b03e8475f59d63 --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "c9fac4e625ccb2c6a7aa35079fff9709db4385ac" + }, + "path_in_vcs": "utils/calendrical_calculations" +} \ No newline at end of file diff --git a/deps/crates/vendor/calendrical_calculations/Cargo.lock b/deps/crates/vendor/calendrical_calculations/Cargo.lock new file mode 100644 index 00000000000000..b922d06163121f --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/Cargo.lock @@ -0,0 +1,79 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "calendrical_calculations" +version = "0.2.4" +dependencies = [ + "core_maths", + "displaydoc", + "log", +] + +[[package]] +name = "core_maths" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30" +dependencies = [ + "libm", +] + +[[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 = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" diff --git a/deps/crates/vendor/calendrical_calculations/Cargo.toml b/deps/crates/vendor/calendrical_calculations/Cargo.toml index 8420b6241bc920..e4a1b3486cb57e 100644 --- a/deps/crates/vendor/calendrical_calculations/Cargo.toml +++ b/deps/crates/vendor/calendrical_calculations/Cargo.toml @@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.82" name = "calendrical_calculations" -version = "0.2.3" +version = "0.2.4" authors = ["The ICU4X Project Developers"] build = false include = [ @@ -35,10 +35,8 @@ autobenches = false description = "Calendrical calculations in Rust" readme = "README.md" keywords = [ - "zerocopy", - "serialization", - "zero-copy", - "serde", + "calendars", + "mathematics", ] categories = [ "rust-patterns", @@ -75,3 +73,52 @@ default-features = false version = "0.4.17" optional = true default-features = false + +[lints.clippy] +alloc-instead-of-core = "warn" +branches-sharing-code = "warn" +collection_is_never_read = "warn" +crosspointer_transmute = "warn" +dbg_macro = "warn" +debug_assert_with_mut_call = "warn" +doc_markdown = "warn" +exhaustive_enums = "deny" +exhaustive_structs = "deny" +fn_to_numeric_cast_any = "warn" +infinite_loop = "warn" +large_stack_arrays = "warn" +mismatching_type_param_order = "warn" +missing_fields_in_debug = "warn" +missing_transmute_annotations = "warn" +negative_feature_names = "warn" +or-fun-call = "warn" +same_functions_in_if_condition = "warn" +todo = "warn" +transmute_bytes_to_str = "warn" +transmute_int_to_bool = "warn" +transmute_int_to_non_zero = "warn" +transmute_ptr_to_ptr = "warn" +transmute_ptr_to_ref = "warn" +transmute_undefined_repr = "warn" +transmutes_expressible_as_ptr_casts = "warn" +trivially_copy_pass_by_ref = "deny" +unnecessary-wraps = "warn" +useless_transmute = "warn" +wildcard_dependencies = "warn" + +[lints.rust] +missing_debug_implementations = "deny" +trivial_numeric_casts = "deny" +unused_lifetimes = "warn" +unused_macro_rules = "warn" +unused_qualifications = "warn" + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = [ + "cfg(icu4c_enable_renaming)", + "cfg(needs_alloc_error_handler)", + "cfg(icu4x_run_size_tests)", + "cfg(icu4x_unstable_fast_trie_only)", +] diff --git a/deps/crates/vendor/calendrical_calculations/Cargo.toml.orig b/deps/crates/vendor/calendrical_calculations/Cargo.toml.orig new file mode 100644 index 00000000000000..0485db22775809 --- /dev/null +++ b/deps/crates/vendor/calendrical_calculations/Cargo.toml.orig @@ -0,0 +1,42 @@ +# 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. + +[package] +name = "calendrical_calculations" +description = "Calendrical calculations in Rust" +version = "0.2.4" +categories = ["rust-patterns", "memory-management", "caching", "no-std", "data-structures"] +keywords = ["calendars", "mathematics"] + +authors.workspace = true +edition.workspace = true +include.workspace = true +repository.workspace = true +rust-version = "1.82" + +# This is a special exception: The algorithms in this crate are based on "Calendrical Calculations" by Reingold and Dershowitz +# which has its lisp code published at https://github.com/EdReingold/calendar-code2/ +license = "Apache-2.0" + +[package.metadata.workspaces] +independent = true + +[package.metadata.docs.rs] +all-features = true + +[dependencies] +core_maths = { workspace = true } +displaydoc = { workspace = true } +log = { workspace = true, optional = true } + +[features] +logging = ["dep:log"] + +[lints] +workspace = true diff --git a/deps/crates/vendor/calendrical_calculations/src/astronomy.rs b/deps/crates/vendor/calendrical_calculations/src/astronomy.rs index ad07dfc4afb25b..6b28ea47aaed30 100644 --- a/deps/crates/vendor/calendrical_calculations/src/astronomy.rs +++ b/deps/crates/vendor/calendrical_calculations/src/astronomy.rs @@ -44,7 +44,8 @@ pub struct Location { pub(crate) longitude: f64, /// elevation in meters pub(crate) elevation: f64, - /// UTC timezone offset in fractional days (1 hr = 1.0 / 24.0 day) + /// UTC timezone offset in fractional days (1 hr = 1.0 / 24.0 day), + /// within the range (-12.0 / 24.0) to (14.0 / 24.0) pub(crate) utc_offset: f64, } @@ -77,10 +78,10 @@ pub const WINTER: f64 = 270.0; 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( + /// Create a location; latitude is from -90 to 90, longitude is from -180 to 180, + /// and `utc_offset` is from (-12.0 / 24.0) to (14.0 / 24.0); + /// attempting to create a location outside of these bounds will result in a [`LocationOutOfBoundsError`]. + pub fn try_new( latitude: f64, longitude: f64, elevation: f64, @@ -170,7 +171,7 @@ impl Location { /// 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 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. @@ -181,7 +182,7 @@ impl Location { } /// 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 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. @@ -1178,7 +1179,7 @@ impl Astronomical { } /// 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. + /// 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: @@ -1412,7 +1413,7 @@ impl Astronomical { } /// Average anomaly of the sun (in degrees) at a given Moment in Julian centuries. - /// See: https://en.wikipedia.org/wiki/Mean_anomaly + /// See: /// /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, /// originally from _Astronomical Algorithms_ by Jean Meeus, 2nd edn., 1998, p. 338. @@ -1424,7 +1425,7 @@ impl Astronomical { } /// Average anomaly of the moon (in degrees) at a given Moment in Julian centuries - /// See: https://en.wikipedia.org/wiki/Mean_anomaly + /// See: /// /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz, /// originally from _Astronomical Algorithms_ by Jean Meeus, 2nd edn., 1998, p. 338. @@ -1846,7 +1847,7 @@ impl Astronomical { } /// Aberration at the time given in Julian centuries. - /// See: https://sceweb.sce.uhcl.edu/helm/WEB-Positional%20Astronomy/Tutorial/Aberration/Aberration.html + /// See: /// /// Based on functions from _Calendrical Calculations_ by Reingold & Dershowitz. /// Lisp code reference: diff --git a/deps/crates/vendor/calendrical_calculations/src/chinese_based.rs b/deps/crates/vendor/calendrical_calculations/src/chinese_based.rs index f84d8b7a38e77f..9f692e3db4c943 100644 --- a/deps/crates/vendor/calendrical_calculations/src/chinese_based.rs +++ b/deps/crates/vendor/calendrical_calculations/src/chinese_based.rs @@ -30,12 +30,12 @@ const MAX_ITERS_FOR_MONTHS_OF_YEAR: u8 = 14; 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. +/// 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, +/// - 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 @@ -43,7 +43,7 @@ pub trait ChineseBased { /// 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 + /// 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; @@ -87,11 +87,10 @@ 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) } { + if fixed < const { fixed_from_gregorian(1929, 1, 1) } { 1397.0 / 180.0 / 24.0 } else { 8.0 / 24.0 @@ -99,23 +98,22 @@ impl ChineseBased for Chinese { } /// 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 EPOCH: RataDie = 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) } { + if fixed < const { fixed_from_gregorian(1908, 4, 1) } { 3809.0 / 450.0 / 24.0 - } else if fixed < const { gregorian(1912, 1, 1) } { + } else if fixed < const { fixed_from_gregorian(1912, 1, 1) } { 8.5 / 24.0 - } else if fixed < const { gregorian(1954, 3, 21) } { + } else if fixed < const { fixed_from_gregorian(1954, 3, 21) } { 9.0 / 24.0 - } else if fixed < const { gregorian(1961, 8, 10) } { + } else if fixed < const { fixed_from_gregorian(1961, 8, 10) } { 8.5 / 24.0 } else { 9.0 / 24.0 @@ -123,7 +121,7 @@ impl ChineseBased for Dangi { } /// 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 EPOCH: RataDie = fixed_from_gregorian(-2332, 2, 15); const DEBUG_NAME: &'static str = "dangi"; } @@ -138,7 +136,7 @@ pub struct YearBounds { } impl YearBounds { - /// Compute the YearBounds for the lunar year (年) containing `date`, + /// 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`. @@ -175,7 +173,7 @@ impl YearBounds { /// 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 +/// Lisp reference code: pub(crate) fn major_solar_term_from_fixed(date: RataDie) -> u32 { let moment: Moment = date.as_moment(); let universal = moment - C::utc_offset(date); @@ -194,7 +192,7 @@ pub(crate) fn major_solar_term_from_fixed(date: RataDie) -> 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 +/// Lisp reference code: 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()); @@ -204,7 +202,7 @@ pub(crate) fn new_moon_on_or_after(moment: Moment) -> RataDie { /// 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 +/// Lisp reference code: 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()); @@ -214,7 +212,7 @@ pub(crate) fn new_moon_before(moment: Moment) -> RataDie { /// 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 +/// Lisp reference code: pub(crate) fn midnight(moment: Moment) -> Moment { moment - C::utc_offset(moment.as_rata_die()) } @@ -225,7 +223,7 @@ pub(crate) fn midnight(moment: Moment) -> Moment { /// 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 +/// Lisp reference code: 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 @@ -259,7 +257,7 @@ pub(crate) fn new_year_in_sui(prior_solstice: RataDie) -> (Rata } } -/// This function forces the RataDie to be on December 20, 21, 22, or 23. It was +/// 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: @@ -300,7 +298,7 @@ fn bind_winter_solstice(solstice: RataDie) -> RataDie { /// 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 +/// Lisp reference code: pub(crate) fn winter_solstice_on_or_before(date: RataDie) -> RataDie { let approx = Astronomical::estimate_prior_solar_longitude( astronomy::WINTER, @@ -328,10 +326,10 @@ pub(crate) fn winter_solstice_on_or_before(date: RataDie) -> Ra /// 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 +/// 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 +/// Lisp reference code: pub(crate) fn new_year_on_or_before_fixed_date( date: RataDie, prior_solstice: RataDie, @@ -350,10 +348,10 @@ pub(crate) fn new_year_on_or_before_fixed_date( } } -/// Get a RataDie in the middle of a year. +/// 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 +/// 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 @@ -388,7 +386,7 @@ pub fn days_in_provided_year(year: i32) -> u16 { bounds.count_days() } -/// chinese_based_date_from_fixed returns extra things for use in caching +/// [`chinese_based_date_from_fixed`] returns extra things for use in caching #[derive(Debug)] #[non_exhaustive] pub struct ChineseFromFixedResult { @@ -494,7 +492,7 @@ pub fn month_days(year: i32, month: u8) -> u8 { } /// 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. +/// Also returns the [`RataDie`] of the new moon beginning the next month. pub fn days_in_month( month: u8, new_year: RataDie, @@ -628,10 +626,10 @@ mod test { #[test] fn test_chinese_new_year_on_or_before() { - let fixed = crate::gregorian::fixed_from_gregorian(2023, 6, 22); + let fixed = 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(); + let (y, m, d) = gregorian_from_fixed(result_fixed).unwrap(); assert_eq!(y, 2023); assert_eq!(m, 1); assert_eq!(d, 22); @@ -646,7 +644,7 @@ mod 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 fixed = 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, @@ -794,13 +792,13 @@ mod test { ]; for case in cases { - let fixed = crate::gregorian::fixed_from_gregorian( + let fixed = 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(); + let (y, m, d) = gregorian_from_fixed(seollal).unwrap(); assert_eq!( y, case.expected_year, "Year check failed for case: {case:?}" @@ -813,3 +811,26 @@ mod test { } } } + +#[test] +fn test_chinese_leap_months() { + let expected = [ + (1933, 6), + (1938, 8), + (1984, 11), + (2009, 6), + (2017, 7), + (2028, 6), + ]; + + for (year, expected_month) in expected { + let bounds = YearBounds::compute::(fixed_from_gregorian(year, 6, 1)); + + assert!(bounds.is_leap(), "{year} should be a leap year"); + assert_eq!( + expected_month, + get_leap_month_from_new_year::(bounds.new_year), + "{year} have leap month {expected_month}" + ); + } +} diff --git a/deps/crates/vendor/calendrical_calculations/src/coptic.rs b/deps/crates/vendor/calendrical_calculations/src/coptic.rs index 85b917ee7dfebe..cb886d5be941ec 100644 --- a/deps/crates/vendor/calendrical_calculations/src/coptic.rs +++ b/deps/crates/vendor/calendrical_calculations/src/coptic.rs @@ -12,6 +12,13 @@ use crate::rata_die::RataDie; pub(crate) const COPTIC_EPOCH: RataDie = crate::julian::fixed_from_julian(284, 8, 29); +/// Lisp code reference: +#[inline(always)] +pub const fn is_leap_year(year: i32) -> bool { + // The book uses year % 4 == 3, which does not behave correctly for negative numbers + (year + 1) % 4 == 0 +} + /// Lisp code reference: pub fn fixed_from_coptic(year: i32, month: u8, day: u8) -> RataDie { COPTIC_EPOCH - 1 diff --git a/deps/crates/vendor/calendrical_calculations/src/gregorian.rs b/deps/crates/vendor/calendrical_calculations/src/gregorian.rs index 6da3d1bce842d1..3359846b627d77 100644 --- a/deps/crates/vendor/calendrical_calculations/src/gregorian.rs +++ b/deps/crates/vendor/calendrical_calculations/src/gregorian.rs @@ -96,11 +96,11 @@ pub const fn day_before_year(year: i32) -> RataDie { 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) + EPOCH.add(fixed - 1) } /// Calculates the month/day from the 1-based day of the year -pub fn year_day(year: i32, day_of_year: u16) -> (u8, u8) { +pub const 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 @@ -113,21 +113,26 @@ pub fn year_day(year: i32, day_of_year: u16) -> (u8, u8) { } /// 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); +pub const fn gregorian_from_fixed(date: RataDie) -> Result<(i32, u8, u8), I32CastError> { + let year = match year_from_fixed(date) { + Ok(y) => y, + Err(e) => return Err(e), + }; + + let day_of_year = date.to_i64_date() - day_before_year(year).to_i64_date(); 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 { +pub const 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; + let paschal_moon = + RataDie::new(fixed_from_gregorian(year, 4, 19).to_i64_date() - adjusted_epact as i64); k_day_after(0, paschal_moon) } diff --git a/deps/crates/vendor/calendrical_calculations/src/hebrew.rs b/deps/crates/vendor/calendrical_calculations/src/hebrew.rs index 7eb1560a169f6b..1ea30bd01b25f0 100644 --- a/deps/crates/vendor/calendrical_calculations/src/hebrew.rs +++ b/deps/crates/vendor/calendrical_calculations/src/hebrew.rs @@ -13,8 +13,7 @@ use crate::rata_die::{Moment, RataDie}; use core_maths::*; /// Lisp code reference: -pub(crate) const FIXED_HEBREW_EPOCH: RataDie = - crate::julian::fixed_from_julian_book_version(-3761, 10, 7); +pub const 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 @@ -116,7 +115,7 @@ impl BookHebrew { + ((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) + HEBREW_EPOCH.to_f64_date() - (876.0 / 25920.0) + months_elapsed * (29.0 + (1.0 / 2.0) + (793.0 / 25920.0)), ) } @@ -166,7 +165,7 @@ impl BookHebrew { /// Lisp code reference: pub fn book_hebrew_new_year(book_year: i32) -> RataDie { RataDie::new( - FIXED_HEBREW_EPOCH.to_i64_date() + 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, ) @@ -256,7 +255,7 @@ impl BookHebrew { /// 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 + 1 + ((date - 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()); @@ -573,7 +572,7 @@ mod tests { #[test] fn test_hebrew_epoch() { // page 119 of the Calendrical Calculations book - assert_eq!(FIXED_HEBREW_EPOCH, RataDie::new(-1373427)); + assert_eq!(HEBREW_EPOCH, RataDie::new(-1373427)); } #[test] diff --git a/deps/crates/vendor/calendrical_calculations/src/hebrew_keviyah.rs b/deps/crates/vendor/calendrical_calculations/src/hebrew_keviyah.rs index b36a39c157b382..c2d434965f8e4e 100644 --- a/deps/crates/vendor/calendrical_calculations/src/hebrew_keviyah.rs +++ b/deps/crates/vendor/calendrical_calculations/src/hebrew_keviyah.rs @@ -81,9 +81,9 @@ //! 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::hebrew::HEBREW_EPOCH; +use crate::helpers::i64_to_saturated_i32; use crate::rata_die::RataDie; -use core::cmp::Ordering; // A note on time notation // @@ -162,20 +162,11 @@ const MOLAD_BEHERAD_OFFSET: i32 = ḥal!(2 - 5 - 204); /// 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) @@ -221,7 +212,7 @@ pub struct YearInfo { } impl YearInfo { - /// Compute the YearInfo for a given year + /// 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); @@ -243,63 +234,32 @@ impl YearInfo { } } - /// Returns the YearInfo and h_year for the year containing `date` + /// 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) - } - }; + // 35975351/98496 is the mean year length for a Hebrew year + // (from Reingold, ch 8.2, in implementation for fixed-from-hebrew) + // + // +1 because the epoch is new year of year 1 + // Before the epoch the division will round up (towards 0), so we need to + // subtract 1, which is the same as not adding the 1. + let mut h_year = i64_to_saturated_i32( + (date - HEBREW_EPOCH) * 98496 / 35975351 + (date >= HEBREW_EPOCH) as i64, + ); - 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)); + let mut year = Self::compute_for(h_year); - (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 + if date < year.new_year() && h_year > i32::MIN { + h_year -= 1; + year = Self::compute_for(h_year) + } else if date >= year.new_year() + year.keviyah.year_length() as i64 && h_year < i32::MAX { + h_year += 1; + year = Self::compute_for(h_year) } + + (year, h_year) } /// Compute the date of New Year's Day @@ -310,7 +270,7 @@ impl YearInfo { 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 + HEBREW_EPOCH + days_since_beharad } } @@ -318,7 +278,7 @@ impl YearInfo { /// /// 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 +/// Complete), and the weekday 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). /// @@ -327,7 +287,7 @@ impl YearInfo { /// 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. +/// 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 (ג). @@ -388,24 +348,6 @@ impl YearType { 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)] @@ -422,39 +364,6 @@ pub enum StartOfYear { 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 @@ -531,133 +440,71 @@ impl Keviyah { } } - /// 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 + // this function is branch-free #[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 - } - } + let year_type = self.year_type(); + let is_leap = self.is_leap(); + + // In a leap year, ordinals after Adar correspond to the previous month number. + let month_number = ordinal_month - (is_leap && ordinal_month >= 6) as u8; + + 29 + ( + // Months with odd month numbers are long. + month_number % 2 + // Ḥeshvan is long in complete years + + (ordinal_month == 2 && year_type == YearType::Complete) as u8 + // Kislev is short in deficient years + - (ordinal_month == 3 && year_type == YearType::Deficient) as u8 + ) } /// Get the number of days preceding this month + // this function is branch-free #[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 + let is_leap = self.is_leap(); + + // In a leap year, ordinals after Adar correspond to the previous month number. + let month_number = ordinal_month - (is_leap && ordinal_month > 6) as u8; + + 29 * (ordinal_month as u16 - 1) + + ( + // Months with odd month numbers are long. + month_number / 2 + // Adar I is long + + (is_leap && ordinal_month > 6) as u8 + // Ḥeshvan is long in complete years + + (ordinal_month > 2 && year_type == YearType::Complete) as u8 + // Kislev is short in deficient years + - (ordinal_month > 3 && year_type == YearType::Deficient) as u8 + ) as u16 } - /// 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); + /// Given a 1-indexed day of the year, return the ordinal month and day as (month, day). + pub fn month_day_for(self, day_of_year: u16) -> (u8, u8) { + // 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 - 1) / 30) as u8 + 1; + let mut days_before_month = self.days_preceding(month); + let mut last_day_of_month = self.days_preceding(month + 1); + + while day_of_year > last_day_of_month { + month += 1; + days_before_month = last_day_of_month; + last_day_of_month = self.days_preceding(month + 1); } - 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() + + (month, (day_of_year - days_before_month) as u8) } /// 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) - } + (12 + self.is_leap() as u8, 29) } /// Whether this year is a leap year @@ -669,7 +516,7 @@ impl Keviyah { self >= Self::בחה } - /// Given the hebrew year for this Keviyah, calculate the YearInfo + /// 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); @@ -880,7 +727,7 @@ fn keviyah_for(year_type: MetonicCycleType, ḥalakim: i32) -> Keviyah { #[cfg(test)] mod test { use super::*; - use crate::hebrew::{self, BookHebrew}; + use crate::hebrew::BookHebrew; #[test] fn test_consts() { @@ -892,9 +739,6 @@ mod test { // // 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] diff --git a/deps/crates/vendor/calendrical_calculations/src/helpers.rs b/deps/crates/vendor/calendrical_calculations/src/helpers.rs index b19160b6f96e95..f51418a407f073 100644 --- a/deps/crates/vendor/calendrical_calculations/src/helpers.rs +++ b/deps/crates/vendor/calendrical_calculations/src/helpers.rs @@ -285,9 +285,9 @@ fn test_invert_angular() { #[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 + /// Less than [`i32::MIN`] BelowMin, - /// Greater than i32::MAX + /// Greater than [`i32::MAX`] AboveMax, } @@ -339,9 +339,9 @@ fn test_i64_to_saturated_i32() { } /// 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 }) +pub(crate) const fn k_day_after(desired_weekday: i64, fixed: RataDie) -> RataDie { + let weekday = fixed.to_i64_date().rem_euclid(7); + let beginning_of_week = fixed.to_i64_date() - weekday; + let day = beginning_of_week + desired_weekday; + RataDie::new(day + if desired_weekday <= weekday { 7 } else { 0 }) } diff --git a/deps/crates/vendor/calendrical_calculations/src/islamic.rs b/deps/crates/vendor/calendrical_calculations/src/islamic.rs index a1d9b1324fba04..53f93f1ebaaf67 100644 --- a/deps/crates/vendor/calendrical_calculations/src/islamic.rs +++ b/deps/crates/vendor/calendrical_calculations/src/islamic.rs @@ -55,7 +55,13 @@ pub fn fixed_from_observational_islamic( - 1 } +/// Calculates an Islamic date from a [`RataDie`] and [`Location`]. +/// +/// This uses the phasis criterion proposed by S. K. Shaukat[^1], explained in Reingold section 14.9. +/// /// Lisp code reference: +/// +/// [^1]: K. Abdali, O. Afzal, I. A. Ahmad, M. Durrani, A. Salama, and S. K. Shaukat, “Crescent Moon Visibility: Consensus on Moon-Sighting and Determination of an Islamic Calendar,” manuscript, 1996. 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)); @@ -144,19 +150,29 @@ pub fn fixed_from_tabular_islamic(year: i32, month: u8, day: u8, epoch: RataDie) } /// 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 + let year = tabular_year_from_fixed(date, epoch); + let prior_days = date - fixed_from_tabular_islamic(year, 1, 1, epoch); + debug_assert!(prior_days >= 0); + debug_assert!(prior_days <= 354); + let month = (((prior_days * 11) + 330) / 325) 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. + let day = (date - fixed_from_tabular_islamic(year, month, 1, epoch) + 1) 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) } +/// Lisp code reference: +pub fn tabular_year_from_fixed(date: RataDie, epoch: RataDie) -> i32 { + // (354 * 30 + 11) / 30 is the mean year length for a tabular year + // This is slightly different from the `calendrical_calculations::islamic::MEAN_YEAR_LENGTH`, which is based on + // the (current) synodic month length. + // + // +1 because the epoch is new year of year 1 + // Before the epoch the division will round up (towards 0), so we need to + // subtract 1, which is the same as not adding the 1. + i64_to_saturated_i32((date - epoch) * 30 / (354 * 30 + 11) + (date >= epoch) as i64) +} + /// 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() diff --git a/deps/crates/vendor/calendrical_calculations/src/julian.rs b/deps/crates/vendor/calendrical_calculations/src/julian.rs index fc1be1279a361f..ecbed8eff602d1 100644 --- a/deps/crates/vendor/calendrical_calculations/src/julian.rs +++ b/deps/crates/vendor/calendrical_calculations/src/julian.rs @@ -13,6 +13,11 @@ 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); +const DAYS_IN_YEAR: i64 = 365; + +// One leap year every 4 years +const DAYS_IN_4_YEAR_CYCLE: i64 = DAYS_IN_YEAR * 4 + 1; + /// Lisp code reference: #[inline(always)] pub const fn is_leap_year(year: i32) -> bool { @@ -21,78 +26,76 @@ pub const fn is_leap_year(year: i32) -> bool { /// 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)) + day_before_year(year) + .add(days_before_month(year, month) as i64) + .add(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 { +/// 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 - }; - let adjusted_year = if prior_days >= 365 { - year.saturating_add(1) + } else { + 31 + } } 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 + 31 + 28 + is_leap_year(year) as u16 + ((979 * (month as u32) - 2919) >> 5) as u16 + } +} + +/// Lisp code reference: +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(JULIAN_EPOCH); + + let (n_4, date) = ( + date.div_euclid(DAYS_IN_4_YEAR_CYCLE), + date.rem_euclid(DAYS_IN_4_YEAR_CYCLE), + ); + + let n_1 = date / DAYS_IN_YEAR; + + let year = 4 * n_4 + n_1 + (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 4, + // distributes correctly over the calculation on the next line. + const YEAR_SHIFT: i64 = (-(i32::MIN as i64 - 1) / 4 + 1) * 4; + fixed += (prev_year + YEAR_SHIFT) / 4 - const { YEAR_SHIFT / 4 }; + JULIAN_EPOCH.add(fixed - 1) +} + +/// 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 { - 12 + (!is_leap_year(year)) as i32 }; - 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}"); + 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) +} - Ok((adjusted_year, month, day)) +/// Lisp code reference: +pub fn julian_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)) } /// Get a fixed date from the ymd of a Julian date. diff --git a/deps/crates/vendor/calendrical_calculations/src/lib.rs b/deps/crates/vendor/calendrical_calculations/src/lib.rs index f1d2f9adb376d9..22cc32867eac01 100644 --- a/deps/crates/vendor/calendrical_calculations/src/lib.rs +++ b/deps/crates/vendor/calendrical_calculations/src/lib.rs @@ -7,17 +7,6 @@ // 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( @@ -27,21 +16,28 @@ 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)] +//! 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. mod astronomy; /// Chinese-like lunar calendars (Chinese, Dangi) pub mod chinese_based; /// The Coptic calendar pub mod coptic; /// Error handling -mod error; +pub mod error; /// The Ethiopian calendar pub mod ethiopian; /// The Gregorian calendar diff --git a/deps/crates/vendor/calendrical_calculations/src/persian.rs b/deps/crates/vendor/calendrical_calculations/src/persian.rs index 32fe743fb3cbba..e8e5609698e058 100644 --- a/deps/crates/vendor/calendrical_calculations/src/persian.rs +++ b/deps/crates/vendor/calendrical_calculations/src/persian.rs @@ -57,7 +57,7 @@ pub fn fixed_from_arithmetic_persian(year: i32, month: u8, day: u8) -> RataDie { ) } -/// fixed_from_arithmetic_persian, modified to use the more correct 33-year rule +/// [`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); @@ -95,7 +95,7 @@ pub fn arithmetic_persian_from_fixed(date: RataDie) -> Result<(i32, u8, u8), I32 Ok((year, month, day)) } -/// arithmetic_persian_from_fixed, modified to use the 33-year rule method +/// [`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)?; @@ -136,13 +136,13 @@ fn arithmetic_persian_year_from_fixed(date: RataDie) -> i64 { } } -/// arithmetic_persian_year_from_fixed modified for the 33-year rule +/// [`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 +/// Lisp code reference: /// Not used, but kept for comparative purposes #[allow(dead_code)] fn is_arithmetic_leap_year(p_year: i32) -> bool { diff --git a/deps/crates/vendor/calendrical_calculations/src/rata_die.rs b/deps/crates/vendor/calendrical_calculations/src/rata_die.rs index f4de6f4ce11bc0..bfacd3e00f01fe 100644 --- a/deps/crates/vendor/calendrical_calculations/src/rata_die.rs +++ b/deps/crates/vendor/calendrical_calculations/src/rata_die.rs @@ -18,7 +18,7 @@ use core_maths::*; /// /// See: /// -/// Typically, one should obtain RataDies from other calendrical code, rather than constructing them from integers. +/// 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. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct RataDie(i64); @@ -122,7 +122,7 @@ impl fmt::Debug for RataDie { } } -/// Shift a RataDie N days into the future +/// Shift a [`RataDie`] N days into the future impl Add for RataDie { type Output = Self; fn add(self, rhs: i64) -> Self::Output { @@ -136,7 +136,7 @@ impl AddAssign for RataDie { } } -/// Shift a RataDie N days into the past +/// Shift a [`RataDie`] N days into the past impl Sub for RataDie { type Output = Self; fn sub(self, rhs: i64) -> Self::Output { @@ -153,7 +153,7 @@ impl SubAssign for RataDie { } } -/// Calculate the number of days between two RataDie +/// Calculate the number of days between two [`RataDie`] impl Sub for RataDie { type Output = i64; fn sub(self, rhs: Self) -> Self::Output { @@ -161,7 +161,7 @@ impl Sub for RataDie { } } -/// A moment is a RataDie with a fractional part giving the time of day. +/// 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. @@ -215,7 +215,7 @@ impl Moment { self.0 } - /// Get the RataDie of a Moment + /// Get the [`RataDie`] of a Moment pub fn as_rata_die(self) -> RataDie { RataDie::new(self.0.floor() as i64) } diff --git a/deps/crates/vendor/core_maths/.cargo-checksum.json b/deps/crates/vendor/core_maths/.cargo-checksum.json index 8bfd3119e348f4..2b739c4fad641b 100644 --- a/deps/crates/vendor/core_maths/.cargo-checksum.json +++ b/deps/crates/vendor/core_maths/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"1564fee10504e497a68aad04f7a6ebacb467956f4a50a85415227eaafa55b96e","LICENSE":"9ebf8c4cc0b735ca13a766451f7b8097db3185975ceb2ba94b5abf439156a91f","README.md":"cf4421c888471876bf715ce49aabe59ace32d165b1cd9878fa8d8f5ecd005fc1","src/lib.rs":"3ccbc7d11f612c33b8e5beb966ebda4aee777132ac1568c6a9f77a3d5fe08fda"},"package":"77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"81eedf3b38b6c2eaa3f54f1590b5598a6f7e36a99deade63984967b794efc1ab","Cargo.toml":"1564fee10504e497a68aad04f7a6ebacb467956f4a50a85415227eaafa55b96e","Cargo.toml.orig":"05230cd6c2de2c64a8ec068220a6aa2559a73149154d6ee007fdced88e6ae1af","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_vcs_info.json b/deps/crates/vendor/core_maths/.cargo_vcs_info.json new file mode 100644 index 00000000000000..1ac326037b43e7 --- /dev/null +++ b/deps/crates/vendor/core_maths/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "d8ea96acac3893ad9a7e16cd7526936fbfc51021" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/deps/crates/vendor/core_maths/Cargo.toml.orig b/deps/crates/vendor/core_maths/Cargo.toml.orig new file mode 100644 index 00000000000000..2b52a491758c10 --- /dev/null +++ b/deps/crates/vendor/core_maths/Cargo.toml.orig @@ -0,0 +1,11 @@ +[package] +name = "core_maths" +version = "0.1.1" +description = "Extension trait for full float functionality in `#[no_std]` backed by `libm`." +authors = ["Robert Bastian ", "Manish Goregaokar ", diff --git a/deps/crates/vendor/diplomat-runtime/Cargo.toml.orig b/deps/crates/vendor/diplomat-runtime/Cargo.toml.orig new file mode 100644 index 00000000000000..47197a7f2c7f03 --- /dev/null +++ b/deps/crates/vendor/diplomat-runtime/Cargo.toml.orig @@ -0,0 +1,23 @@ +[package] +name = "diplomat-runtime" +description = "Common runtime utilities used by diplomat codegen" +version.workspace = true +rust-version.workspace = true +authors.workspace = true +categories.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +keywords.workspace = true +readme = "../README.md" + +[lib] +path = "src/lib.rs" + +[features] +jvm-callback-support = ["dep:jni"] +log = ["dep:log"] + +[dependencies] +jni = { version = "0.21", optional = true } +log = { version = "0.4", optional = true } diff --git a/deps/crates/vendor/diplomat/.cargo-checksum.json b/deps/crates/vendor/diplomat/.cargo-checksum.json index 07aba30c344a18..c84899ebc24e13 100644 --- a/deps/crates/vendor/diplomat/.cargo-checksum.json +++ b/deps/crates/vendor/diplomat/.cargo-checksum.json @@ -1 +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 +{"files":{".cargo_vcs_info.json":"9ba2efe81e59f48fa6b99a7a3b92ca0d583dadc7536b4717422fa0de70f53bf7","Cargo.lock":"010a53cb587762a23a1736689ce527a39a94cbe7c611f27c2ef267abe5ddc01b","Cargo.toml":"2332654bd67ecbf64ba739e7c5949c493afd622cb5238454e12c7d6ea020dd7d","Cargo.toml.orig":"465f6722b4bed464e0abb11d51c9c013c405476203011deac8d9a9c44ada6122","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":"9adb46b05e2f53dcf6a7dfc242e4ce9eb60c369b6b6eb10826a01e93167f59c6"} \ No newline at end of file diff --git a/deps/crates/vendor/diplomat/.cargo_vcs_info.json b/deps/crates/vendor/diplomat/.cargo_vcs_info.json new file mode 100644 index 00000000000000..627f26a5b7a803 --- /dev/null +++ b/deps/crates/vendor/diplomat/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "532eea36ae48d7f2fe4ed6d076bce20e750ef1bb" + }, + "path_in_vcs": "macro" +} \ No newline at end of file diff --git a/deps/crates/vendor/diplomat/Cargo.lock b/deps/crates/vendor/diplomat/Cargo.lock new file mode 100644 index 00000000000000..7ce46f6e67f393 --- /dev/null +++ b/deps/crates/vendor/diplomat/Cargo.lock @@ -0,0 +1,299 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "windows-sys", +] + +[[package]] +name = "diplomat" +version = "0.14.0" +dependencies = [ + "diplomat_core", + "insta", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "tempfile", +] + +[[package]] +name = "diplomat_core" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51731530ed7f2d4495019abc7df3744f53338e69e2863a6a64ae91821c763df1" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "smallvec", + "strck", + "syn", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" + +[[package]] +name = "insta" +version = "1.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a7c22c4d34ef4788c351e971c52bfdfe7ea2766f8c5466bc175dd46e52ac22e" +dependencies = [ + "console", + "lazy_static", + "linked-hash-map", + "similar", + "yaml-rust", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "prettyplease" +version = "0.2.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1ccf34da56fc294e7d4ccf69a85992b7dfb826b7cf57bac6a70bba3494cc08a" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustix" +version = "0.38.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "similar" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[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.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] diff --git a/deps/crates/vendor/diplomat/Cargo.toml b/deps/crates/vendor/diplomat/Cargo.toml index c0ea234e8ec99a..85689ba54b500f 100644 --- a/deps/crates/vendor/diplomat/Cargo.toml +++ b/deps/crates/vendor/diplomat/Cargo.toml @@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.81" name = "diplomat" -version = "0.13.0" +version = "0.14.0" authors = [ "Shadaj Laddad ", "Manish Goregaokar ", @@ -44,7 +44,7 @@ path = "src/lib.rs" proc-macro = true [dependencies.diplomat_core] -version = "0.13.0" +version = "0.14.0" default-features = false [dependencies.proc-macro2] diff --git a/deps/crates/vendor/diplomat/Cargo.toml.orig b/deps/crates/vendor/diplomat/Cargo.toml.orig new file mode 100644 index 00000000000000..97024a2b0fc7d3 --- /dev/null +++ b/deps/crates/vendor/diplomat/Cargo.toml.orig @@ -0,0 +1,27 @@ +[package] +name = "diplomat" +description = "The diplomat FFI generation macro" +version.workspace = true +rust-version.workspace = true +authors.workspace = true +categories.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +keywords.workspace = true +readme = "../README.md" + +[lib] +proc-macro = true +path = "src/lib.rs" + +[dependencies] +diplomat_core.workspace = true +syn = { version = "2.0", features = ["full", "extra-traits"] } +quote = "1.0" +proc-macro2 = "1.0.27" + +[dev-dependencies] +insta = "1.7.1" +tempfile = "3.2.0" +prettyplease = "0.2.30" diff --git a/deps/crates/vendor/diplomat_core/.cargo-checksum.json b/deps/crates/vendor/diplomat_core/.cargo-checksum.json index 2f3b0004aa0213..541c80158530f4 100644 --- a/deps/crates/vendor/diplomat_core/.cargo-checksum.json +++ b/deps/crates/vendor/diplomat_core/.cargo-checksum.json @@ -1 +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 +{"files":{".cargo_vcs_info.json":"eb79ee3491b18c54af7644439ea83b46b0132da552218ef00dd3f16168606e49","Cargo.lock":"f198174250d0f4984d1f0a603651f282767d1387d44b3b3e4590d9b51953bf2b","Cargo.toml":"861b52b0fec93928143e674b1949c6a2ea36dc8f6c9ec4f19a7b618a608a75dc","Cargo.toml.orig":"b97a48ae1210c42032f03e7352672bec7bae811cb35812a255d282cb7280b301","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":"189eda274d24715a9de6e4dcdf2681b9afa3c67043ded2e4e451da04a4a850a2","src/ast/mod.rs":"03ef2c1e5664fed612a1f5ee6a871f7ec960e3af605478719cbd9b11e6a42dcf","src/ast/modules.rs":"d9e96421ae4d0c368e4779500cdacf43529b6eff997076a9d1dc3482c6522789","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":"48cdc9d6dff7761d69f556bcfc0430c9e2c518512080d61fc3ee89558cf5096c","src/ast/snapshots/diplomat_core__ast__methods__tests__nonstatic_methods-2.snap":"31299380639b3ad93d125f8240457620f6dff500e8f06b4ec7f488f296e5dc6d","src/ast/snapshots/diplomat_core__ast__methods__tests__nonstatic_methods.snap":"d7ff75c7ca587c9381a1f8acc366ffc8e1d9aca36201de814317c3ff2e1bffad","src/ast/snapshots/diplomat_core__ast__methods__tests__static_methods-2.snap":"0bb782e375c142eb2522fe39d5b80c3928ba955b57479ee7b48d3651c4285966","src/ast/snapshots/diplomat_core__ast__methods__tests__static_methods.snap":"b341453686e11a01f0c388ab45f261b3bc5809f7c8429b9f321885f60a3f3e5e","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":"aa087910ffffb35e8c79f8bea5a78789af680eeb7df6079871d3f988f52caf81","src/ast/snapshots/diplomat_core__ast__modules__tests__simple_mod.snap":"3428f222ca2a430165c52e6cb9ecb4b725c8bc50163809ff9a5467f39588f6dd","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":"2a72a38cb6969014cbbfa9f06c53b66d263c39e0f42535c93c4ca3f053b4be30","src/hir/defs.rs":"e69c37ecba56d8aa3dd73659132fd568cd37786f671bd3519aa4395cb490772c","src/hir/elision.rs":"529036dc30102e8b049178753b4cc293111d210c0c861238d281d369804bd1bb","src/hir/lifetimes.rs":"44d21b066b1ca7471a6a4c0e6cd5f674d985083962431de6fa7f543368e612f4","src/hir/lowering.rs":"875c8840c8d1665f1ca5b70b6181f6feef19ab7675f057fa2ff4044df9517bb2","src/hir/methods.rs":"f5c836286d3edf0c3b0e787767dd049f9d8ada29ef92e856ec30cf3382e29b30","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":"8988c0440e25963342764a6357820730f6999ca8fd86a5aa7db7c5de2c53f5a1","src/hir/type_context.rs":"8370d7133d359a685810dc7694f43f4e8cb08444dcf592485b240365c06e6cf9","src/hir/types.rs":"0e3c0edf7745cf9215c1d0d79cf54d350a73e2249e2222254e22383c1d399806","src/lib.rs":"6bca84ef449b737270c0da7e8ae9dc82cfbd57e83c078b20c9894050274ed7e7"},"package":"51731530ed7f2d4495019abc7df3744f53338e69e2863a6a64ae91821c763df1"} \ No newline at end of file diff --git a/deps/crates/vendor/diplomat_core/.cargo_vcs_info.json b/deps/crates/vendor/diplomat_core/.cargo_vcs_info.json new file mode 100644 index 00000000000000..417f9687f86c68 --- /dev/null +++ b/deps/crates/vendor/diplomat_core/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "532eea36ae48d7f2fe4ed6d076bce20e750ef1bb" + }, + "path_in_vcs": "core" +} \ No newline at end of file diff --git a/deps/crates/vendor/diplomat_core/Cargo.lock b/deps/crates/vendor/diplomat_core/Cargo.lock new file mode 100644 index 00000000000000..9645778279bfbf --- /dev/null +++ b/deps/crates/vendor/diplomat_core/Cargo.lock @@ -0,0 +1,236 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "windows-sys", +] + +[[package]] +name = "diplomat_core" +version = "0.14.0" +dependencies = [ + "displaydoc", + "either", + "insta", + "proc-macro2", + "quote", + "serde", + "smallvec", + "strck", + "syn", +] + +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "insta" +version = "1.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a7c22c4d34ef4788c351e971c52bfdfe7ea2766f8c5466bc175dd46e52ac22e" +dependencies = [ + "console", + "lazy_static", + "linked-hash-map", + "serde", + "similar", + "yaml-rust", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "similar" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[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.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] diff --git a/deps/crates/vendor/diplomat_core/Cargo.toml b/deps/crates/vendor/diplomat_core/Cargo.toml index ae8dab9318d3e3..d0807ac1e99143 100644 --- a/deps/crates/vendor/diplomat_core/Cargo.toml +++ b/deps/crates/vendor/diplomat_core/Cargo.toml @@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.81" name = "diplomat_core" -version = "0.13.0" +version = "0.14.0" authors = [ "Shadaj Laddad ", "Manish Goregaokar ", diff --git a/deps/crates/vendor/diplomat_core/Cargo.toml.orig b/deps/crates/vendor/diplomat_core/Cargo.toml.orig new file mode 100644 index 00000000000000..51c1f2f35eb2cb --- /dev/null +++ b/deps/crates/vendor/diplomat_core/Cargo.toml.orig @@ -0,0 +1,35 @@ +[package] +name = "diplomat_core" +description = "Shared utilities between Diplomat macros and code generation" +version.workspace = true +rust-version.workspace = true +authors.workspace = true +categories.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +keywords.workspace = true +readme = "../README.md" + +[lib] +path = "src/lib.rs" + +[features] +# Enable the higher level IR +hir = ["either"] + +[package.metadata.docs.rs] +all-features = true + +[dependencies] +syn = { version = "2", features = [ "full", "extra-traits" ] } +quote = "1.0" +proc-macro2 = "1.0.27" +serde = { version = "1.0", features = ["derive", "alloc"], default-features = false } +displaydoc = { version = "0.2", optional = true } +smallvec = "1.9.0" +strck = { version = "1.0", features = ["ident"] } +either = {version = "1.9.0", optional = true, default-features = false} + +[dev-dependencies] +insta = { version = "1.7.1", features = ["yaml"] } diff --git a/deps/crates/vendor/diplomat_core/src/ast/methods.rs b/deps/crates/vendor/diplomat_core/src/ast/methods.rs index 1b67a5fd4c3707..976c1c67c421b9 100644 --- a/deps/crates/vendor/diplomat_core/src/ast/methods.rs +++ b/deps/crates/vendor/diplomat_core/src/ast/methods.rs @@ -22,6 +22,9 @@ pub struct Method { /// The `self` param of the method, if any. pub self_param: Option, + // the 'Self' type of the method, if any. + pub self_type: Option, + /// All non-`self` params taken by the method. pub params: Vec, @@ -78,7 +81,7 @@ impl Method { // support it so we can insert the expanded explicit lifetimes. Some(TypeName::from_syn( return_typ.as_ref(), - Some(self_path_type), + Some(self_path_type.clone()), )) } syn::ReturnType::Default => None, @@ -97,6 +100,7 @@ impl Method { docs: Docs::from_attrs(&m.attrs), abi_name: Ident::from(&extern_ident), self_param, + self_type: Some(self_path_type), params: all_params, return_type: return_ty, lifetime_env, @@ -351,7 +355,7 @@ impl BorrowedParams<'_> { self.0.iter().map(move |_| self_name).chain( self.1 .iter() - .filter(|(_, ltk)| (*ltk == LifetimeKind::ReturnValue)) + .filter(|(_, ltk)| *ltk == LifetimeKind::ReturnValue) .map(|(param, _)| ¶m.name), ) } @@ -361,7 +365,7 @@ impl BorrowedParams<'_> { pub fn static_names(&self) -> impl Iterator { self.1 .iter() - .filter(|(_, ltk)| (*ltk == LifetimeKind::Static)) + .filter(|(_, ltk)| *ltk == LifetimeKind::Static) .map(|(param, _)| ¶m.name) } diff --git a/deps/crates/vendor/diplomat_core/src/ast/modules.rs b/deps/crates/vendor/diplomat_core/src/ast/modules.rs index 2d93dba464a2d5..e158d3a466ad79 100644 --- a/deps/crates/vendor/diplomat_core/src/ast/modules.rs +++ b/deps/crates/vendor/diplomat_core/src/ast/modules.rs @@ -116,6 +116,10 @@ struct ModuleBuilder { functions_by_name: BTreeMap, sub_modules: Vec, imports: Vec<(Path, Ident)>, + /// As we traverse through the module, are we inside of #[diplomat::bridge]? + /// If so, then `analyze_types` is set to true, and types, functions, and traits are all updated according to information parsed. + /// + /// Otherwise, we traverse through modules until we find a module marked by #[diplomat::bridge] analyze_types: bool, type_parent_attrs: Attrs, impl_parent_attrs: Attrs, @@ -267,22 +271,25 @@ impl ModuleBuilder { } } 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); + if self.analyze_types { + 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 { - 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); + let items = self.mod_macros.evaluate_item_macro(mac); + for i in items { + self.add(&i); + } } } } @@ -366,6 +373,10 @@ impl Module { out.insert(path_to_self, mod_symbols); } + /// Convert an [`ItemMod`] to a [`Module`]. + /// + /// `force_analyze` is for forcibly parsing the module in the case where we know the `#[diplomat::bridge]` attribute should be present, + /// but proc_macro (or some other analyzer) has removed the attribute in advance. pub fn from_syn(input: &ItemMod, force_analyze: bool) -> Module { let mod_attrs: Attrs = (&*input.attrs).into(); 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 index 245fe61d04448d..8fc7d297587fbc 100644 --- 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 @@ -1,6 +1,6 @@ --- 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())" +expression: "Method::from_syn(&syn::parse_quote!\n{\n #[doc = r\" Some docs.\"] #[diplomat::rust_link(foo::Bar::batz, FnInStruct)]\n #[cfg(any(feature = \"foo\", not(feature = \"bar\")))] fn\n foo(x: u64, y: MyCustomStruct) {}\n},\nPathType::new(Path::empty().sub_path(Ident::from(\"MyStructContainingMethod\"))),\nNone, &Attrs::default())" --- name: foo docs: @@ -14,6 +14,11 @@ docs: display: Normal abi_name: MyStructContainingMethod_foo self_param: ~ +self_type: + path: + elements: + - MyStructContainingMethod + lifetimes: [] params: - name: x ty: 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 index 5dfc34cc3debab..653efca04ecf28 100644 --- 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 @@ -1,6 +1,6 @@ --- 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())" +expression: "Method::from_syn(&syn::parse_quote!\n{\n #[diplomat::rust_link(foo::Bar::batz, FnInStruct)] fn\n foo(&mut self, x: u64, y: MyCustomStruct) -> u64 { x }\n},\nPathType::new(Path::empty().sub_path(Ident::from(\"MyStructContainingMethod\"))),\nNone, &Attrs::default())" --- name: foo docs: @@ -23,6 +23,11 @@ self_param: - MyStructContainingMethod lifetimes: [] attrs: {} +self_type: + path: + elements: + - MyStructContainingMethod + lifetimes: [] params: - name: x ty: 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 index 4147b134113fb5..97041456fb8cf4 100644 --- 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 @@ -1,6 +1,6 @@ --- 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())" +expression: "Method::from_syn(&syn::parse_quote!\n{ fn foo(&self, x: u64, y: MyCustomStruct) {} },\nPathType::new(Path::empty().sub_path(Ident::from(\"MyStructContainingMethod\"))),\nNone, &Attrs::default())" --- name: foo docs: @@ -17,6 +17,11 @@ self_param: - MyStructContainingMethod lifetimes: [] attrs: {} +self_type: + path: + elements: + - MyStructContainingMethod + lifetimes: [] params: - name: x ty: 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 index 516f511bd0026f..998fd181e2dfa1 100644 --- 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 @@ -1,6 +1,6 @@ --- 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())" +expression: "Method::from_syn(&syn::parse_quote!\n{\n #[doc = r\" Some docs.\"] #[doc = r\" Some more docs.\"] #[doc = r\"\"]\n #[doc = r\" Even more docs.\"]\n #[diplomat::rust_link(foo::Bar::batz, FnInEnum)] fn\n foo(x: u64, y: MyCustomStruct) -> u64 { x }\n},\nPathType::new(Path::empty().sub_path(Ident::from(\"MyStructContainingMethod\"))),\nNone, &Attrs::default())" --- name: foo docs: @@ -14,6 +14,11 @@ docs: display: Normal abi_name: MyStructContainingMethod_foo self_param: ~ +self_type: + path: + elements: + - MyStructContainingMethod + lifetimes: [] params: - name: x ty: 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 index 58bc55c51af865..9ac5c2a64f9a15 100644 --- 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 @@ -1,6 +1,6 @@ --- 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())" +expression: "Method::from_syn(&syn::parse_quote!\n{\n #[doc = r\" Some docs.\"] #[diplomat::rust_link(foo::Bar::batz, FnInStruct)]\n fn foo(x: u64, y: MyCustomStruct) {}\n},\nPathType::new(Path::empty().sub_path(Ident::from(\"MyStructContainingMethod\"))),\nNone, &Attrs::default())" --- name: foo docs: @@ -14,6 +14,11 @@ docs: display: Normal abi_name: MyStructContainingMethod_foo self_param: ~ +self_type: + path: + elements: + - MyStructContainingMethod + lifetimes: [] params: - name: x ty: 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 index 19b682aa7fba1a..e780f41b92dcad 100644 --- 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 @@ -20,6 +20,11 @@ declared_types: - [] abi_name: Foo_pub_fn self_param: ~ + self_type: + path: + elements: + - Foo + lifetimes: [] params: [] return_type: ~ lifetime_env: {} 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 index 095a9a46098944..a9853bb171b748 100644 --- 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 @@ -35,6 +35,11 @@ declared_types: - [] abi_name: NonOpaqueStruct_new self_param: ~ + self_type: + path: + elements: + - NonOpaqueStruct + lifetimes: [] params: - name: x ty: @@ -63,6 +68,11 @@ declared_types: - NonOpaqueStruct lifetimes: [] attrs: {} + self_type: + path: + elements: + - NonOpaqueStruct + lifetimes: [] params: - name: new_a ty: @@ -87,6 +97,11 @@ declared_types: - [] abi_name: OpaqueStruct_new self_param: ~ + self_type: + path: + elements: + - OpaqueStruct + lifetimes: [] params: [] return_type: Box: @@ -112,6 +127,11 @@ declared_types: - OpaqueStruct lifetimes: [] attrs: {} + self_type: + path: + elements: + - OpaqueStruct + lifetimes: [] params: [] return_type: Named: diff --git a/deps/crates/vendor/diplomat_core/src/hir/attrs.rs b/deps/crates/vendor/diplomat_core/src/hir/attrs.rs index 31421da626887e..d2760dcdaeb7b7 100644 --- a/deps/crates/vendor/diplomat_core/src/hir/attrs.rs +++ b/deps/crates/vendor/diplomat_core/src/hir/attrs.rs @@ -228,7 +228,7 @@ pub enum AttributeContext<'a, 'b> { Type(TypeDef<'a>), Trait(&'a TraitDef), EnumVariant(&'a EnumVariant), - Method(&'a Method, TypeId, &'b mut SpecialMethodPresence), + Method(&'a Method, Option, &'b mut SpecialMethodPresence), Function(&'a Method), Module, Param, @@ -547,7 +547,7 @@ impl Attrs { } if let SuccessType::OutType(t) = &output { - if t.id() != Some(self_id) { + if t.id() != self_id || self_id.is_none() { errors.push(LoweringError::Other( "Constructors must return Self!".to_string(), )); diff --git a/deps/crates/vendor/diplomat_core/src/hir/elision.rs b/deps/crates/vendor/diplomat_core/src/hir/elision.rs index 71c26f8fda4790..381fff805fa72e 100644 --- a/deps/crates/vendor/diplomat_core/src/hir/elision.rs +++ b/deps/crates/vendor/diplomat_core/src/hir/elision.rs @@ -99,6 +99,7 @@ use super::lifetimes::{BoundedLifetime, Lifetime, LifetimeEnv, Lifetimes, MaybeStatic}; use super::LoweringContext; use crate::ast; +use crate::hir::ty_position::Sealed; use smallvec::SmallVec; /// Lower [`ast::Lifetime`]s to [`Lifetime`]s. @@ -107,7 +108,7 @@ use smallvec::SmallVec; /// 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 { +pub trait LifetimeLowerer: Sealed { /// Lowers an [`ast::Lifetime`]. fn lower_lifetime(&mut self, lifetime: &ast::Lifetime) -> MaybeStatic; @@ -228,6 +229,12 @@ pub(super) struct ReturnLifetimeLowerer<'ast> { base: BaseLifetimeLowerer<'ast>, } +impl<'ast> Sealed for BaseLifetimeLowerer<'ast> {} +impl<'ast> Sealed for SelfParamLifetimeLowerer<'ast> {} +impl<'ast> Sealed for ParamLifetimeLowerer<'ast> {} +impl<'ast> Sealed for ReturnLifetimeLowerer<'ast> {} +impl<'ast> Sealed for &'ast ast::LifetimeEnv {} + impl<'ast> BaseLifetimeLowerer<'ast> { /// Returns a [`Lifetime`] representing a new anonymous lifetime, and /// pushes it to the nodes vector. diff --git a/deps/crates/vendor/diplomat_core/src/hir/lowering.rs b/deps/crates/vendor/diplomat_core/src/hir/lowering.rs index c92dc42d3d1973..bb4b074bcc8227 100644 --- a/deps/crates/vendor/diplomat_core/src/hir/lowering.rs +++ b/deps/crates/vendor/diplomat_core/src/hir/lowering.rs @@ -5,8 +5,8 @@ use super::{ 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, + StructField, StructPath, SuccessType, TraitDef, TraitParamSelf, TraitPath, TyPosition, Type, + TypeDef, TypeId, }; use crate::ast::attrs::AttrInheritContext; use crate::{ast, Env}; @@ -125,7 +125,6 @@ pub(crate) struct ItemAndInfo<'ast, Ast> { /// 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> { @@ -250,7 +249,6 @@ impl<'ast> LoweringContext<'ast> { &ast_enum.methods[..], item.in_path, &item.method_parent_attrs, - item.id.try_into()?, &mut special_method_presence, )? }; @@ -292,7 +290,6 @@ impl<'ast> LoweringContext<'ast> { &ast_opaque.methods[..], item.in_path, &item.method_parent_attrs, - item.id.try_into()?, &mut special_method_presence, )? }; @@ -385,7 +382,6 @@ impl<'ast> LoweringContext<'ast> { &ast_struct.methods[..], item.in_path, &item.method_parent_attrs, - item.id.try_into()?, &mut special_method_presence, )? }; @@ -617,7 +613,6 @@ impl<'ast> LoweringContext<'ast> { &ast_out_struct.methods[..], item.in_path, &item.method_parent_attrs, - item.id.try_into()?, &mut special_method_presence, )? }; @@ -649,7 +644,6 @@ impl<'ast> LoweringContext<'ast> { 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"); @@ -679,6 +673,7 @@ impl<'ast> LoweringContext<'ast> { )?; let abi_name = self.lower_ident(&method.abi_name, "method abi name")?; + let hir_method = Method { docs: method.docs.clone(), name: name?, @@ -690,9 +685,11 @@ impl<'ast> LoweringContext<'ast> { attrs, }; + let self_type_id = self.lower_self_type(method, in_path); + self.attr_validator.validate( &hir_method.attrs, - AttributeContext::Method(&hir_method, self_id, special_method_presence), + AttributeContext::Method(&hir_method, self_type_id, special_method_presence), &mut self.errors, ); @@ -710,6 +707,39 @@ impl<'ast> LoweringContext<'ast> { Ok(hir_method) } + fn lower_self_type( + &mut self, + method: &'ast ast::Method, + in_path: &ast::Path, + ) -> Option { + method + .self_type + .as_ref() + .map(|self_type| match self_type.resolve(in_path, self.env) { + ast::CustomType::Enum(e) => self + .lookup_id + .resolve_enum(e) + .expect("enum is in env") + .into(), + ast::CustomType::Opaque(o) => self + .lookup_id + .resolve_opaque(o) + .expect("opaque is in env") + .into(), + ast::CustomType::Struct(s) => { + if let Some(s_id) = self.lookup_id.resolve_struct(s) { + s_id.into() + } else if let Some(os_id) = self.lookup_id.resolve_out_struct(s) { + os_id.into() + } else { + unreachable!( + "struct `{}` not found in the set of structs or out_structs.", + s.name + ) + } + } + }) + } /// 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. @@ -718,7 +748,6 @@ impl<'ast> LoweringContext<'ast> { 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())); @@ -734,8 +763,7 @@ impl<'ast> LoweringContext<'ast> { if attrs.disable { continue; } - let method = - self.lower_method(method, in_path, attrs, self_id, special_method_presence); + let method = self.lower_method(method, in_path, attrs, special_method_presence); match (method, &mut methods) { (Ok(method), Ok(methods)) => { if matches!( diff --git a/deps/crates/vendor/diplomat_core/src/hir/methods.rs b/deps/crates/vendor/diplomat_core/src/hir/methods.rs index 16190e8b3fc506..1d8bcd8712b740 100644 --- a/deps/crates/vendor/diplomat_core/src/hir/methods.rs +++ b/deps/crates/vendor/diplomat_core/src/hir/methods.rs @@ -9,6 +9,7 @@ use super::{ }; use super::lifetimes::{Lifetime, LifetimeEnv, Lifetimes, MaybeStatic}; +use super::ty_position::Sealed; use borrowing_field::BorrowingFieldVisitor; use borrowing_param::BorrowingParamVisitor; @@ -41,7 +42,7 @@ pub struct Method { pub attrs: Attrs, } -pub trait CallbackInstantiationFunctionality { +pub trait CallbackInstantiationFunctionality: Sealed { #[allow(clippy::result_unit_err)] fn get_inputs(&self) -> Result<&[CallbackParam], ()>; // the types of the parameters #[allow(clippy::result_unit_err)] @@ -65,6 +66,9 @@ pub struct Callback { #[non_exhaustive] pub enum NoCallback {} +impl Sealed for Callback {} +impl Sealed for NoCallback {} + impl CallbackInstantiationFunctionality for Callback { fn get_inputs(&self) -> Result<&[CallbackParam], ()> { Ok(&self.params) diff --git a/deps/crates/vendor/diplomat_core/src/hir/ty_position.rs b/deps/crates/vendor/diplomat_core/src/hir/ty_position.rs index 9d6ffc57f07e64..b19d335227c5b1 100644 --- a/deps/crates/vendor/diplomat_core/src/hir/ty_position.rs +++ b/deps/crates/vendor/diplomat_core/src/hir/ty_position.rs @@ -6,6 +6,10 @@ use super::{ }; use core::fmt::Debug; +/// Most of the HIR traits are for its own internal ontology, +/// not for public implementation +pub trait Sealed {} + /// Abstraction over where a type can appear in a function signature. /// /// # "Output only" and "everywhere" types @@ -88,7 +92,7 @@ use core::fmt::Debug; /// Therefore, this trait allows be extremely precise about making invalid states /// unrepresentable, while also reducing duplicated code. /// -pub trait TyPosition: Debug + Copy +pub trait TyPosition: Debug + Copy + Sealed where for<'tcx> TypeDef<'tcx>: From<&'tcx StructDef>, { @@ -104,7 +108,7 @@ where /// borrowes, so the associated type for that impl is [`Borrow`]. type OpaqueOwnership: Debug + OpaqueOwner + Clone; - type StructId: Debug + Clone; + type StructId: Debug + Copy + Into; type StructPath: Debug + StructPathLike + Clone; @@ -113,6 +117,14 @@ where 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; + + fn resolve_struct(tcx: &TypeContext, id: Self::StructId) -> &StructDef; + + fn get_fields<'tcx>( + def: &'tcx StructDef, + ) -> impl Iterator> { + def.fields.iter() + } } /// Directionality of the type @@ -123,7 +135,7 @@ pub enum InputOrOutput { InputOutput, } -pub trait TraitIdGetter { +pub trait TraitIdGetter: Sealed { fn id(&self) -> TraitId; } @@ -151,6 +163,10 @@ pub struct OutputOnly; #[non_exhaustive] pub struct InputOnly; +impl Sealed for Everywhere {} +impl Sealed for OutputOnly {} +impl Sealed for InputOnly {} + impl TyPosition for Everywhere { const IN_OUT_STATUS: InputOrOutput = InputOrOutput::InputOutput; type OpaqueOwnership = Borrow; @@ -168,6 +184,10 @@ impl TyPosition for Everywhere { fn build_trait_path(_trait_path: TraitPath) -> Self::TraitPath { panic!("Traits must be input-only"); } + + fn resolve_struct(tcx: &TypeContext, id: StructId) -> &StructDef { + tcx.resolve_struct(id) + } } impl TyPosition for OutputOnly { @@ -187,6 +207,9 @@ impl TyPosition for OutputOnly { fn build_trait_path(_trait_path: TraitPath) -> Self::TraitPath { panic!("Traits must be input-only"); } + fn resolve_struct(tcx: &TypeContext, id: OutStructId) -> &StructDef { + tcx.resolve_out_struct(id) + } } impl TyPosition for InputOnly { @@ -206,9 +229,12 @@ impl TyPosition for InputOnly { fn build_trait_path(trait_path: TraitPath) -> Self::TraitPath { trait_path } + fn resolve_struct(_: &TypeContext, _: StructId) -> &StructDef { + panic!("Type Context does not store InputOnly structdefs"); + } } -pub trait StructPathLike { +pub trait StructPathLike: Sealed { fn lifetimes(&self) -> &Lifetimes; fn id(&self) -> TypeId; fn owner(&self) -> MaybeOwn; @@ -221,6 +247,9 @@ pub trait StructPathLike { ) -> LinkedLifetimes<'def, 'tcx>; } +impl Sealed for StructPath {} +impl Sealed for ReturnableStructPath {} + impl StructPathLike for StructPath { fn lifetimes(&self) -> &Lifetimes { &self.lifetimes @@ -269,6 +298,9 @@ impl StructPathLike for ReturnableStructPath { } } +impl Sealed for TraitPath {} +impl Sealed for NoTraitPath {} + impl TraitIdGetter for TraitPath { fn id(&self) -> TraitId { self.tcx_id @@ -287,7 +319,7 @@ impl TraitIdGetter for NoTraitPath { /// 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 { +pub trait OpaqueOwner: Sealed { /// Return the mutability of this owner fn mutability(&self) -> Option; @@ -297,6 +329,9 @@ pub trait OpaqueOwner { fn lifetime(&self) -> Option>; } +impl Sealed for MaybeOwn {} +impl Sealed for Borrow {} + impl OpaqueOwner for MaybeOwn { fn mutability(&self) -> Option { match self { diff --git a/deps/crates/vendor/diplomat_core/src/hir/type_context.rs b/deps/crates/vendor/diplomat_core/src/hir/type_context.rs index 68979367d7b81d..7bedcfa04d928b 100644 --- a/deps/crates/vendor/diplomat_core/src/hir/type_context.rs +++ b/deps/crates/vendor/diplomat_core/src/hir/type_context.rs @@ -9,7 +9,6 @@ use super::{ 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; @@ -25,7 +24,7 @@ pub struct TypeContext { opaques: Vec, enums: Vec, traits: Vec, - functions: Vec, + functions: Vec, } /// Additional features/config to support while lowering @@ -57,7 +56,7 @@ pub struct EnumId(usize); pub struct TraitId(usize); /// Key used to index into a [`TypeContext`] representing a function. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct FunctionId(usize); #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -127,7 +126,7 @@ impl TypeContext { pub fn all_free_functions<'tcx>( &'tcx self, - ) -> impl Iterator { + ) -> impl Iterator { self.functions .iter() .enumerate() @@ -195,7 +194,7 @@ impl TypeContext { self.traits.index(id.0) } - pub fn resolve_function(&self, id: FunctionId) -> &Method { + pub fn resolve_function(&self, id: FunctionId) -> &hir::Method { self.functions.index(id.0) } @@ -265,17 +264,11 @@ impl TypeContext { 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); @@ -289,7 +282,6 @@ impl TypeContext { 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) } @@ -299,7 +291,6 @@ impl TypeContext { 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) } @@ -310,7 +301,6 @@ impl TypeContext { 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) } @@ -320,7 +310,6 @@ impl TypeContext { 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) } diff --git a/deps/crates/vendor/displaydoc/.cargo-checksum.json b/deps/crates/vendor/displaydoc/.cargo-checksum.json index ddbf7a3890d17a..0a7c9fa5ad566c 100644 --- a/deps/crates/vendor/displaydoc/.cargo-checksum.json +++ b/deps/crates/vendor/displaydoc/.cargo-checksum.json @@ -1 +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 +{"files":{".cargo_vcs_info.json":"15b6f86bb464b0b3a0ea41accdf7153d721f83835881292f76fca73a6e37b29a",".github/workflows/ci.yml":"d9f8c68f56908f4db84a982f94a5075158be332ecabc9330edae2483c4cda847","CHANGELOG.md":"9aadbd7c8b22fa4574b2080d0baaa908f43b5ed2c320c64ec88476cbf739871b","Cargo.lock":"53ebb1c438812bf2e049126afd9bb833d02278416d49ed436d67b4c5c03f21b1","Cargo.toml":"c6f12ae2dd031cf599ec131d3b6b89fb5de66edc4416b4a8f2f06b3fda889620","Cargo.toml.orig":"8758bd1de805bb131da8871a94d92b266df10766d304a6ddecae0be8b07dde1a","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/.cargo_vcs_info.json b/deps/crates/vendor/displaydoc/.cargo_vcs_info.json new file mode 100644 index 00000000000000..b961cfb7bb025b --- /dev/null +++ b/deps/crates/vendor/displaydoc/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "e4028851bfb82998300237f7568a45f589a19e40" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/deps/crates/vendor/displaydoc/.github/workflows/ci.yml b/deps/crates/vendor/displaydoc/.github/workflows/ci.yml new file mode 100644 index 00000000000000..1713afdf26cf84 --- /dev/null +++ b/deps/crates/vendor/displaydoc/.github/workflows/ci.yml @@ -0,0 +1,120 @@ +on: + push: + pull_request: + schedule: + - cron: '0 0 * * *' + +name: Continuous integration + +jobs: + check: + name: Check + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - stable + - 1.56.0 + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + override: true + - uses: actions-rs/cargo@v1 + with: + command: check + + test: + name: Test Suite + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - stable + - nightly + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + override: true + - uses: Swatinem/rust-cache@v1 + - name: Install cargo-nextest + uses: baptiste0928/cargo-install@v1 + with: + crate: cargo-nextest + version: 0.9 + - uses: actions-rs/cargo@v1 + with: + command: nextest + args: run + - uses: actions-rs/cargo@v1 + with: + command: nextest + args: run --no-default-features + - uses: actions-rs/cargo@v1 + with: + command: test + args: --doc + + test-msrv: + name: msrv Test Suite + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - 1.56.0 + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + override: true + - uses: Swatinem/rust-cache@v1 + - uses: actions-rs/cargo@v1 + with: + command: test + - uses: actions-rs/cargo@v1 + with: + command: test + args: --no-default-features + + fmt: + name: Rustfmt + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - stable + - 1.56.0 + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + override: true + - run: rustup component add rustfmt + - uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check + + clippy: + name: Clippy + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - stable + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + override: true + - run: rustup component add clippy + - uses: actions-rs/cargo@v1 + with: + command: clippy + args: -- -D warnings diff --git a/deps/crates/vendor/displaydoc/Cargo.toml.orig b/deps/crates/vendor/displaydoc/Cargo.toml.orig new file mode 100644 index 00000000000000..c80116c26c5fc4 --- /dev/null +++ b/deps/crates/vendor/displaydoc/Cargo.toml.orig @@ -0,0 +1,81 @@ +[package] +name = "displaydoc" +version = "0.2.5" +rust-version = "1.56.0" +authors = ["Jane Lusby "] +edition = "2021" +license = "MIT OR Apache-2.0" +readme = "README.md" +repository = "https://github.com/yaahc/displaydoc" +homepage = "https://github.com/yaahc/displaydoc" +documentation = "https://docs.rs/displaydoc" +keywords = ["display", "derive"] +description = """ +A derive macro for implementing the display Trait via a doc comment and string interpolation +""" + +[lib] +proc-macro = true +path = "src/lib.rs" + +[features] +default = ["std"] +std = [] + +[dependencies] +syn = "2.0" +quote = "1.0" +proc-macro2 = "1.0" + +[dev-dependencies] +trybuild = "1.0" +static_assertions = "1.1" +libc = { version = "0.2", default-features = false } +rustversion = "1.0.0" +pretty_assertions = "0.6.1" +thiserror = "1.0.24" + +[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" +search = "Unreleased" +replace="{{version}}" + +[[package.metadata.release.pre-release-replacements]] +file = "src/lib.rs" +search = "#!\\[doc\\(html_root_url.*" +replace = "#![doc(html_root_url = \"https://docs.rs/{{crate_name}}/{{version}}\")]" +exactly = 1 + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +search = "ReleaseDate" +replace="{{date}}" + +[[package.metadata.release.pre-release-replacements]] +file="CHANGELOG.md" +search="" +replace="\n\n# [Unreleased] - ReleaseDate" +exactly=1 + +# Disable this replacement on the very first release +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +search = "\\.\\.\\.HEAD" +replace="...{{tag_name}}" +exactly = 1 +# END SECTION, do not comment out the replacement below this, and do not reorder them + +[[package.metadata.release.pre-release-replacements]] +file="CHANGELOG.md" +search="" +replace="\n[Unreleased]: https://github.com/yaahc/{{crate_name}}/compare/{{tag_name}}...HEAD" +exactly=1 + diff --git a/deps/crates/vendor/icu_calendar/.cargo-checksum.json b/deps/crates/vendor/icu_calendar/.cargo-checksum.json index 24c90d80a0e937..d80a2b2841be47 100644 --- a/deps/crates/vendor/icu_calendar/.cargo-checksum.json +++ b/deps/crates/vendor/icu_calendar/.cargo-checksum.json @@ -1 +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 +{"files":{".cargo_vcs_info.json":"5bf4d11031ba6544415af89fa62cacac923c8dddf49d4e292d24daff57d87571","Cargo.lock":"7c97bb97524646eb50dcb495e070eb99d6df27527119437923ff9f366023b76e","Cargo.toml":"5f2b9d93ec859d508a5c12f4f131cd7bc6cde61b65d63e824c0730d43e71d01b","Cargo.toml.orig":"93770e7fde059818db19ffdc3668cead2f95b4d4645a118b92e2386a586cf734","LICENSE":"f367c1b8e1aa262435251e442901da4607b4650e0e63a026f5044473ecfb90f2","README.md":"c51a6704a477876d2ebe131267a2a8023d3deaa3a2f208b9895dda192a2ff880","benches/convert.rs":"14b05e5328a2ffa347f4adba079de9bce8c0dad67bd0e2c7825e50c46affe342","benches/date.rs":"e1272dc8a6f4fac843ca1231983adaf7264a364932a9a3e06cadb32fd6e62013","benches/fixtures/datetimes.json":"ad8db74905ad8837b5e75ddc0bb51c1f277a8aa20e486d6927438a8fc7f094a6","src/any_calendar.rs":"fe0ddeccfeeb47dad36f88297e85d4823556b999079136b385dbdadb373c804f","src/cal/abstract_gregorian.rs":"ff0f57b889450cc0b376b02f46464e2bf86059e1faef649906eab86c07b46532","src/cal/buddhist.rs":"bc03a42366af670672db24a88ffadb4487bf6f31efcd47eaa68c76bac2d0dafe","src/cal/coptic.rs":"a06067a8585f74b96fe1a3995fc44e3547f0d843672d88af143ed5b3671b9cb6","src/cal/east_asian_traditional.rs":"6a54a8f8167703393c937db04e79f56851b8b5d77521f8d1afca998adc4336fa","src/cal/east_asian_traditional/china_data.rs":"f57440be085f5076125b2efcd92c66196a652655cb287ce124319dfd45052df5","src/cal/east_asian_traditional/korea_data.rs":"715ec9fe69500adfeba704143ebaabdeecc078ae7974b3db362e58b36e5d2189","src/cal/east_asian_traditional/qing_data.rs":"e8097d4ba4651863644ef2ed7247d57640e949eb2c2ef207a2d8ebf9b5c4f69e","src/cal/east_asian_traditional/simple.rs":"b362f75297198eaf71b6f84b39991e39705637198ae941ded8bf9a7563ddb867","src/cal/ethiopian.rs":"e315c63c36fea55b8626497489a1382cbc4cbcac521079d3ea6a77923128a72a","src/cal/gregorian.rs":"42f30696460caee5af1981b76100a8cf3e8460876d8f733b4828db99d5a9beea","src/cal/hebrew.rs":"6f995191f5205d6858a0afe28f9aed3ecb4f48e0e17075c5ebba7a294cf282a3","src/cal/hijri.rs":"17cca441ad57a596dcc44481f631d97fa3de413581c3aa9b437c0ea0921edfbb","src/cal/hijri/simulated_mecca_data.rs":"f1defaee03b91a503dd2d8039257ba297cda238cc23f6ba75ef35d622b70f483","src/cal/hijri/ummalqura_data.rs":"15118990b415f15ebf5d63502bebc0d6a99a5e021e14d87da4beb6fb136fdfa0","src/cal/indian.rs":"2b71744ee7a7beba6054424fcaa34acc96e7a2d293ac340600ecd448c0026425","src/cal/iso.rs":"b3e415ecc0aa5a44318fd7e24c879e5e2f2f03fc9a8c102a4613edb9c450744f","src/cal/japanese.rs":"baa085cf698af3ba88c31b0f9d876b082193b5004dde52d77f6594ebfcae8653","src/cal/julian.rs":"ffeac88c5bbe9c5288cbc9e89ac5c3366a7039e828ba48729e9266e447a5fcf7","src/cal/mod.rs":"2e65ce43eb8a19b0141407e3806d74d57724655605cd9cf1698ba836d69c2a12","src/cal/persian.rs":"10cd0d17116dd0887d20fa2fbf9c34eda7f3833817226f48e9fce2ef603e0e41","src/cal/roc.rs":"6c716c6fa00982ffbeaa905333c795022b7559e627a80920d72d5c9eefcaf7a0","src/calendar.rs":"961a67f72a1c5733b97c16c3b3e3bc1bda55f61e1f6819f7f40be0af4923c84c","src/calendar_arithmetic.rs":"8850422da53f06d19691b374b3476680cd0854f6c69e0816eaac3a750b477934","src/date.rs":"479681ce9eddd15b3dc10b6d96a597169932e5e6828722baccc3a414de823f3e","src/duration.rs":"7dd00f9f702c0f57796e0f9ec5d3f4a002a5739fda78879e482982b0a5c61385","src/error.rs":"a1e8bdf73bcbf533aac005050c2ebcc5e1decdec45091f2b0a3765b92544fec5","src/ixdtf.rs":"a9f3cddafd209e6f828825a2c42bf4280eb1a0456e9bae7e293d72072cc9c007","src/lib.rs":"03bab72eafec685d861d3ba075114483e751447a53c44455de81011e49ad2672","src/options.rs":"a6051b983427f035e9aea38be3607e4363998d6ad1adb341b63af4cce130fb9a","src/provider.rs":"37a27cd8f3ca98b58e0ca82ec570314ecb951371fcab772fd48af5eabc4daa98","src/tests/continuity_test.rs":"16ce3029e79a6b7148e898eac299c5a2d4efb9af51fa1d1d7157529be37cba7d","src/tests/extrema.rs":"4f752bfeb0fde51470c22bdb8cd2fbd74eb436af027a2ef2e3ba7ab7887d2d9a","src/tests/mod.rs":"aed1fc2784f1d66671477645ef6e6007a456977cc1502205ad5057ef62fc86a1","src/tests/not_enough_fields.rs":"570dc9696e1afa068aa6ca30625a01901003fc8689e316cda13adfac017a419b","src/types.rs":"a7bdc94f5a6bb44b08d188cf5e3a6e877fbf27b0a731285883b98afdc1e684b3","src/week.rs":"a69c1ad8b9399dcc4446f7bc259c6c0da281ac0b4fb3f6093ff897287674177c","tests/arithmetic.rs":"21ae8051246d706b3e5eb4d41010b1011e9ac82a19fdc687e38b0222ca84c4ca","tests/exhaustive.rs":"9bda342cfa8db3d73ebfd5cd03ab0c6692f5e8c0bd28ffd8d119242b705614e3","tests/extended_year.rs":"e63f358426bd6c5d290565822420fc313c4f31ac99e5cd35122024e6273e1a8e","tests/reference_year.rs":"fd2bbc54b5a932490669de2ba8cf62f36539e56737f6f296a076856712e0b6bb"},"package":"d6f0e52e009b6b16ba9c0693578796f2dd4aaa59a7f8f920423706714a89ac4e"} \ No newline at end of file diff --git a/deps/crates/vendor/icu_calendar/.cargo_vcs_info.json b/deps/crates/vendor/icu_calendar/.cargo_vcs_info.json new file mode 100644 index 00000000000000..d75612e253d45c --- /dev/null +++ b/deps/crates/vendor/icu_calendar/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "38a49da495248dd1ded84cf306e4ca42e64d5bb3" + }, + "path_in_vcs": "components/calendar" +} \ No newline at end of file diff --git a/deps/crates/vendor/icu_calendar/Cargo.lock b/deps/crates/vendor/icu_calendar/Cargo.lock new file mode 100644 index 00000000000000..80249d10b9ad78 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/Cargo.lock @@ -0,0 +1,1317 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[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.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "calendrical_calculations" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a0b39595c6ee54a8d0900204ba4c401d0ab4eb45adaf07178e8d017541529e7" +dependencies = [ + "core_maths", + "displaydoc", + "log", +] + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.2.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "739eb0f94557554b3ca9a86d2d37bebd49c5e6d0c1d2bda35ba5bdac830befc2" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[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.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror", +] + +[[package]] +name = "colored" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "core_maths" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30" +dependencies = [ + "libm", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[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 0.10.5", + "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 0.10.5", +] + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[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 = "deranged" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +dependencies = [ + "powerfmt", +] + +[[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 = "erased-serde" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + +[[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[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 = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "icu_calendar" +version = "2.1.1" +dependencies = [ + "calendrical_calculations", + "criterion", + "databake", + "displaydoc", + "icu_calendar_data", + "icu_locale", + "icu_locale_core", + "icu_provider", + "itertools 0.14.0", + "ixdtf", + "serde", + "serde_json", + "simple_logger", + "tinystr", + "ureq", + "zerovec", +] + +[[package]] +name = "icu_calendar_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527f04223b17edfe0bd43baf14a0cb1b017830db65f3950dc00224860a9a446d" + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "532b11722e350ab6bf916ba6eb0efe3ee54b932666afec989465f9243fe6dd60" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_locale_data", + "icu_provider", + "potential_utf", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "serde", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locale_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f03e2fcaefecdf05619f3d6f91740e79ab969b4dd54f77cbf546b1d0d28e3147" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "databake", + "displaydoc", + "erased-serde", + "icu_locale_core", + "postcard", + "serde", + "stable_deref_trait", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "is-terminal" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "ixdtf" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84de9d95a6d2547d9b77ee3f25fa0ee32e3c3a6484d47a55adebc0439c077992" + +[[package]] +name = "js-sys" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[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 = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[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 = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "serde", +] + +[[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 = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[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.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +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.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[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.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 = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simple_logger" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291bee647ce7310b0ea721bfd7e0525517b4468eb7c7e15eb8bd774343179702" +dependencies = [ + "colored", + "log", + "time", + "windows-sys 0.61.2", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +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 = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +dependencies = [ + "deranged", + "itoa", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" + +[[package]] +name = "time-macros" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "databake", + "displaydoc", + "serde_core", + "zerovec", +] + +[[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 = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + +[[package]] +name = "unicode-ident" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99ba1025f18a4a3fc3e9b48c868e9beb4f24f4b4b1a325bada26bd4119f46537" +dependencies = [ + "base64", + "flate2", + "log", + "percent-encoding", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "ureq-proto", + "utf-8", + "webpki-roots", +] + +[[package]] +name = "ureq-proto" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b4531c118335662134346048ddb0e54cc86bd7e81866757873055f0e38f5d2" +dependencies = [ + "base64", + "http", + "httparse", + "log", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b130c0d2d49f8b6889abc456e795e82525204f27c42cf767cf0d7734e089b8" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[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-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[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 = "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 = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[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 = [ + "databake", + "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", +] diff --git a/deps/crates/vendor/icu_calendar/Cargo.toml b/deps/crates/vendor/icu_calendar/Cargo.toml index 79be24ad34b964..2987c1c4be7f9e 100644 --- a/deps/crates/vendor/icu_calendar/Cargo.toml +++ b/deps/crates/vendor/icu_calendar/Cargo.toml @@ -11,9 +11,9 @@ [package] edition = "2021" -rust-version = "1.82" +rust-version = "1.83" name = "icu_calendar" -version = "2.0.6" +version = "2.1.1" authors = ["The ICU4X Project Developers"] build = false include = [ @@ -42,8 +42,15 @@ repository = "https://github.com/unicode-org/icu4x" [package.metadata.docs.rs] all-features = true +[package.metadata.cargo-semver-checks.lints] +workspace = true + [features] -alloc = [] +alloc = [ + "icu_locale_core/alloc", + "tinystr/alloc", + "serde?/alloc", +] compiled_data = [ "dep:icu_calendar_data", "dep:icu_locale", @@ -70,11 +77,29 @@ serde = [ "tinystr/serde", "icu_provider/serde", ] +unstable = [] [lib] name = "icu_calendar" path = "src/lib.rs" +[[test]] +name = "arithmetic" +path = "tests/arithmetic.rs" +required-features = ["ixdtf"] + +[[test]] +name = "exhaustive" +path = "tests/exhaustive.rs" + +[[test]] +name = "extended_year" +path = "tests/extended_year.rs" + +[[test]] +name = "reference_year" +path = "tests/reference_year.rs" + [[bench]] name = "convert" path = "benches/convert.rs" @@ -86,7 +111,7 @@ path = "benches/date.rs" harness = false [dependencies.calendrical_calculations] -version = "0.2.2" +version = "0.2.3" default-features = false [dependencies.databake] @@ -100,58 +125,49 @@ version = "0.2.3" default-features = false [dependencies.icu_calendar_data] -version = "~2.0.0" +version = "~2.1.1" optional = true default-features = false [dependencies.icu_locale] -version = "~2.0.0" +version = "~2.1.1" optional = true default-features = false [dependencies.icu_locale_core] -version = "2.0.0" -features = ["alloc"] +version = "2.1.1" default-features = false [dependencies.icu_provider] -version = "2.0.0" -features = ["alloc"] +version = "2.1.1" default-features = false [dependencies.ixdtf] -version = "0.5.0" +version = "0.6.0" optional = true default-features = false [dependencies.serde] -version = "1.0.110" -features = [ - "derive", - "alloc", -] +version = "1.0.220" +features = ["derive"] optional = true default-features = false [dependencies.tinystr] version = "0.8.0" -features = [ - "alloc", - "zerovec", -] -default-features = false - -[dependencies.writeable] -version = "0.6.0" +features = ["zerovec"] default-features = false [dependencies.zerovec] -version = "0.11.1" +version = "0.11.3" features = ["derive"] default-features = false +[dev-dependencies.itertools] +version = "0.14.0" + [dev-dependencies.serde] -version = "1.0.110" +version = "1.0.220" features = [ "derive", "alloc", @@ -164,5 +180,8 @@ version = "1.0.45" [dev-dependencies.simple_logger] version = "5.0.0" +[dev-dependencies.ureq] +version = "3.0.0" + [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies.criterion] version = "0.5.0" diff --git a/deps/crates/vendor/icu_calendar/Cargo.toml.orig b/deps/crates/vendor/icu_calendar/Cargo.toml.orig new file mode 100644 index 00000000000000..1567ce4a40b65b --- /dev/null +++ b/deps/crates/vendor/icu_calendar/Cargo.toml.orig @@ -0,0 +1,75 @@ +# 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 ). + +[package] +name = "icu_calendar" +description = "Date APIs for Gregorian and non-Gregorian calendars" +version.workspace = true + +authors.workspace = true +categories.workspace = true +edition.workspace = true +homepage.workspace = true +include.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true + +[package.metadata.docs.rs] +all-features = true + +[dependencies] +calendrical_calculations = { workspace = true } +displaydoc = { workspace = true } +icu_provider = { workspace = true } +icu_locale_core = { workspace = true } +ixdtf = { workspace = true, optional = true } +tinystr = { workspace = true, features = ["zerovec"] } +zerovec = { workspace = true, features = ["derive"] } + +databake = { workspace = true, features = ["derive"], optional = true } +serde = { workspace = true, features = ["derive"], optional = true } + +icu_calendar_data = { workspace = true, optional = true } +icu_locale = { workspace = true, optional = true } + +[dev-dependencies] +icu_provider = { path = "../../provider/core", features = ["logging"] } +icu = { path = "../../components/icu", default-features = false } +itertools = { workspace = true } +serde = { workspace = true, features = ["derive", "alloc"] } +serde_json = { workspace = true } +simple_logger = { workspace = true } +ureq = { workspace = true } + + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +criterion = { workspace = true } + + +[features] +default = ["compiled_data", "ixdtf"] +ixdtf = ["dep:ixdtf"] +logging = ["calendrical_calculations/logging"] +serde = ["dep:serde", "zerovec/serde", "tinystr/serde", "icu_provider/serde"] +datagen = ["serde", "dep:databake", "zerovec/databake", "tinystr/databake", "alloc", "icu_provider/export"] +compiled_data = ["dep:icu_calendar_data", "dep:icu_locale", "icu_locale?/compiled_data", "icu_provider/baked"] +unstable = [] + +alloc = ["icu_locale_core/alloc", "tinystr/alloc", "serde?/alloc"] + +[[bench]] +name = "date" +harness = false + +[[bench]] +name = "convert" +harness = false + +[[test]] +name = "arithmetic" +required-features = ["ixdtf"] + +[package.metadata.cargo-semver-checks.lints] +workspace = true diff --git a/deps/crates/vendor/icu_calendar/benches/convert.rs b/deps/crates/vendor/icu_calendar/benches/convert.rs index 90b18f256cc8d6..7e84fb364f31f2 100644 --- a/deps/crates/vendor/icu_calendar/benches/convert.rs +++ b/deps/crates/vendor/icu_calendar/benches/convert.rs @@ -2,8 +2,6 @@ // 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, }; @@ -49,16 +47,10 @@ fn convert_benches(c: &mut Criterion) { 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(), + icu::calendar::cal::ChineseTraditional::new(), ); bench_calendar( @@ -72,30 +64,30 @@ fn convert_benches(c: &mut Criterion) { bench_calendar( &mut group, "calendar/islamic/observational", - icu::calendar::cal::HijriSimulated::new_mecca_always_calculating(), + icu::calendar::cal::Hijri::new_simulated_mecca(), ); bench_calendar( &mut group, "calendar/islamic/civil", - icu::calendar::cal::HijriTabular::new( - icu::calendar::cal::HijriTabularLeapYears::TypeII, - icu::calendar::cal::HijriTabularEpoch::Friday, + icu::calendar::cal::Hijri::new_tabular( + icu::calendar::cal::hijri::TabularAlgorithmLeapYears::TypeII, + icu::calendar::cal::hijri::TabularAlgorithmEpoch::Friday, ), ); bench_calendar( &mut group, "calendar/islamic/ummalqura", - icu::calendar::cal::HijriUmmAlQura::new(), + icu::calendar::cal::Hijri::new_umm_al_qura(), ); bench_calendar( &mut group, "calendar/islamic/tabular", - icu::calendar::cal::HijriTabular::new( - icu::calendar::cal::HijriTabularLeapYears::TypeII, - icu::calendar::cal::HijriTabularEpoch::Thursday, + icu::calendar::cal::Hijri::new_tabular( + icu::calendar::cal::hijri::TabularAlgorithmLeapYears::TypeII, + icu::calendar::cal::hijri::TabularAlgorithmEpoch::Thursday, ), ); diff --git a/deps/crates/vendor/icu_calendar/benches/date.rs b/deps/crates/vendor/icu_calendar/benches/date.rs index 4cd5e5fecd22b9..25786ac3f458ae 100644 --- a/deps/crates/vendor/icu_calendar/benches/date.rs +++ b/deps/crates/vendor/icu_calendar/benches/date.rs @@ -2,23 +2,45 @@ // 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 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, +} use criterion::{ black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, }; -use fixtures::DateFixture; -use icu_calendar::{AsCalendar, Calendar, Date, DateDuration}; +use icu_calendar::{ + options::{DateAddOptions, Overflow}, + types, AsCalendar, Calendar, Date, +}; 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), - )); + let mut options = DateAddOptions::default(); + options.overflow = Some(Overflow::Constrain); + date.try_add_with_options( + types::DateDuration { + is_negative: false, + years: black_box(1), + months: black_box(2), + weeks: black_box(3), + days: black_box(4), + }, + options, + ) + .unwrap(); // Retrieving vals let _ = black_box(date.year()); @@ -34,13 +56,14 @@ fn bench_calendar( name: &str, fxs: &DateFixture, calendar: C, - calendar_date_init: impl Fn(i32, u8, u8) -> Date, + calendar_date_init: impl Fn(i32, u8, u8, C) -> 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); + let mut instantiated_date_calendar = + calendar_date_init(fx.year, fx.month, fx.day, calendar.clone()); // Conversion from ISO let date_iso = Date::try_new_iso(fx.year, fx.month, fx.day).unwrap(); @@ -62,7 +85,7 @@ fn date_benches(c: &mut Criterion) { "calendar/overview", &fxs, icu::calendar::cal::Iso, - |y, m, d| Date::try_new_iso(y, m, d).unwrap(), + |y, m, d, _| Date::try_new_iso(y, m, d).unwrap(), ); bench_calendar( @@ -70,7 +93,7 @@ fn date_benches(c: &mut Criterion) { "calendar/buddhist", &fxs, icu::calendar::cal::Buddhist, - |y, m, d| Date::try_new_buddhist(y, m, d).unwrap(), + |y, m, d, _| Date::try_new_buddhist(y, m, d).unwrap(), ); bench_calendar( @@ -78,7 +101,7 @@ fn date_benches(c: &mut Criterion) { "calendar/coptic", &fxs, icu::calendar::cal::Coptic, - |y, m, d| Date::try_new_coptic(y, m, d).unwrap(), + |y, m, d, _| Date::try_new_coptic(y, m, d).unwrap(), ); bench_calendar( @@ -86,7 +109,7 @@ fn date_benches(c: &mut Criterion) { "calendar/ethiopic", &fxs, icu::calendar::cal::Ethiopian::new(), - |y, m, d| { + |y, m, d, _| { Date::try_new_ethiopian(icu::calendar::cal::EthiopianEraStyle::AmeteMihret, y, m, d) .unwrap() }, @@ -97,7 +120,7 @@ fn date_benches(c: &mut Criterion) { "calendar/indian", &fxs, icu::calendar::cal::Indian, - |y, m, d| Date::try_new_indian(y, m, d).unwrap(), + |y, m, d, _| Date::try_new_indian(y, m, d).unwrap(), ); bench_calendar( @@ -105,7 +128,7 @@ fn date_benches(c: &mut Criterion) { "calendar/persian", &fxs, icu::calendar::cal::Persian, - |y, m, d| Date::try_new_persian(y, m, d).unwrap(), + |y, m, d, _| Date::try_new_persian(y, m, d).unwrap(), ); bench_calendar( @@ -113,7 +136,7 @@ fn date_benches(c: &mut Criterion) { "calendar/roc", &fxs, icu::calendar::cal::Roc, - |y, m, d| Date::try_new_roc(y, m, d).unwrap(), + |y, m, d, _| Date::try_new_roc(y, m, d).unwrap(), ); bench_calendar( @@ -121,59 +144,28 @@ fn date_benches(c: &mut Criterion) { "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() - }, + |y, m, d, _| Date::try_new_julian(y, m, d).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()) + icu::calendar::cal::ChineseTraditional::new(), + |y, m, d, c| { + Date::try_new_from_codes(None, y, types::MonthCode::new_normal(m).unwrap(), d, c) .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() + icu::calendar::cal::KoreanTraditional::new(), + |y, m, d, c| { + Date::try_new_from_codes(None, y, types::MonthCode::new_normal(m).unwrap(), d, c) + .unwrap() }, ); @@ -182,7 +174,10 @@ fn date_benches(c: &mut Criterion) { "calendar/hebrew", &fxs, icu::calendar::cal::Hebrew, - |y, m, d| Date::try_new_hebrew(y, m, d).unwrap(), + |y, m, d, c| { + Date::try_new_from_codes(None, y, types::MonthCode::new_normal(m).unwrap(), d, c) + .unwrap() + }, ); bench_calendar( @@ -190,75 +185,45 @@ fn date_benches(c: &mut Criterion) { "calendar/gregorian", &fxs, icu::calendar::cal::Gregorian, - |y, m, d| Date::try_new_gregorian(y, m, d).unwrap(), + |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, + icu::calendar::cal::Hijri::new_tabular( + icu::calendar::cal::hijri::TabularAlgorithmLeapYears::TypeII, + icu::calendar::cal::hijri::TabularAlgorithmEpoch::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() - }, + |y, m, d, c| Date::try_new_hijri_with_calendar(y, m, d, c).unwrap(), ); bench_calendar( &mut group, "calendar/islamic/tabular", &fxs, - icu::calendar::cal::HijriTabular::new( - icu::calendar::cal::HijriTabularLeapYears::TypeII, - icu::calendar::cal::HijriTabularEpoch::Thursday, + icu::calendar::cal::Hijri::new_tabular( + icu::calendar::cal::hijri::TabularAlgorithmLeapYears::TypeII, + icu::calendar::cal::hijri::TabularAlgorithmEpoch::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() - }, + |y, m, d, c| Date::try_new_hijri_with_calendar(y, m, d, c).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(), + icu::calendar::cal::Hijri::new_umm_al_qura(), + |y, m, d, c| Date::try_new_hijri_with_calendar(y, m, d, c).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() - }, + icu::calendar::cal::Hijri::new_simulated_mecca(), + |y, m, d, c| Date::try_new_hijri_with_calendar(y, m, d, c).unwrap(), ); group.finish(); diff --git a/deps/crates/vendor/icu_calendar/benches/fixtures/mod.rs b/deps/crates/vendor/icu_calendar/benches/fixtures/mod.rs deleted file mode 100644 index c4bc9336ea0aee..00000000000000 --- a/deps/crates/vendor/icu_calendar/benches/fixtures/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -// 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 index 6ce6ed1164e6bd..3032034600d8c2 100644 --- a/deps/crates/vendor/icu_calendar/src/any_calendar.rs +++ b/deps/crates/vendor/icu_calendar/src/any_calendar.rs @@ -4,20 +4,16 @@ //! 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::cal::*; +use crate::error::{DateError, DateFromFieldsError}; +use crate::options::DateFromFieldsOptions; +use crate::options::{DateAddOptions, DateDifferenceOptions}; +use crate::types::{DateFields, YearInfo}; +use crate::{types, AsCalendar, Calendar, Date, 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; @@ -44,7 +40,7 @@ define_preferences!( /// /// There are many ways of constructing an AnyCalendar'd date: /// ``` -/// use icu::calendar::{AnyCalendar, AnyCalendarKind, Date, cal::Japanese, types::MonthCode}; +/// use icu::calendar::{AnyCalendar, AnyCalendarKind, Date, cal::{Japanese, Gregorian}, types::MonthCode}; /// use icu::locale::locale; /// use tinystr::tinystr; /// # use std::rc::Rc; @@ -52,26 +48,26 @@ define_preferences!( /// 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); +/// // This is a Date +/// let any_japanese_date = Date::try_new_gregorian(2020, 9, 1) +/// .expect("Failed to construct Gregorian Date.") +/// .to_calendar(calendar) +/// .to_any(); /// /// // 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, +/// let japanese_date = Date::try_new_japanese_with_calendar("reiwa", 2, 9, 1, /// japanese_calendar).unwrap(); -/// // This is a Date -/// let any_japanese_date = japanese_date.to_any(); +/// assert_eq!(japanese_date.to_any(), any_japanese_date); +/// +/// // this is also Date, but it uses a different calendar +/// let any_gregorian_date = any_japanese_date.to_calendar(Gregorian).to_any(); +/// +/// // Date does not have a total order +/// assert!(any_gregorian_date <= any_gregorian_date); +/// assert!(any_japanese_date <= any_japanese_date); +/// assert!(!(any_gregorian_date <= any_japanese_date) && !(any_japanese_date <= any_gregorian_date)); /// ``` #[derive(Debug, Clone)] #[non_exhaustive] @@ -79,11 +75,11 @@ pub enum AnyCalendar { /// A [`Buddhist`] calendar Buddhist(Buddhist), /// A [`Chinese`] calendar - Chinese(Chinese), + Chinese(ChineseTraditional), /// A [`Coptic`] calendar Coptic(Coptic), /// A [`Dangi`] calendar - Dangi(Dangi), + Dangi(KoreanTraditional), /// An [`Ethiopian`] calendar Ethiopian(Ethiopian), /// A [`Gregorian`] calendar @@ -93,11 +89,11 @@ pub enum AnyCalendar { /// An [`Indian`] calendar Indian(Indian), /// A [`HijriTabular`] calendar - HijriTabular(HijriTabular), + HijriTabular(Hijri), /// A [`HijriSimulated`] calendar - HijriSimulated(HijriSimulated), + HijriSimulated(Hijri), /// A [`HijriUmmAlQura`] calendar - HijriUmmAlQura(HijriUmmAlQura), + HijriUmmAlQura(Hijri), /// An [`Iso`] calendar Iso(Iso), /// A [`Japanese`] calendar @@ -118,11 +114,11 @@ pub enum AnyDateInner { /// A date for a [`Buddhist`] calendar Buddhist(::DateInner), /// A date for a [`Chinese`] calendar - Chinese(::DateInner), + Chinese(::DateInner), /// A date for a [`Coptic`] calendar Coptic(::DateInner), /// A date for a [`Dangi`] calendar - Dangi(::DateInner), + Dangi(::DateInner), /// A date for an [`Ethiopian`] calendar Ethiopian(::DateInner), /// A date for a [`Gregorian`] calendar @@ -133,14 +129,13 @@ pub enum AnyDateInner { Indian(::DateInner), /// A date for a [`HijriTabular`] calendar HijriTabular( - ::DateInner, - HijriTabularLeapYears, - HijriTabularEpoch, + as Calendar>::DateInner, + hijri::TabularAlgorithm, ), /// A date for a [`HijriSimulated`] calendar - HijriSimulated(::DateInner), + HijriSimulated( as Calendar>::DateInner), /// A date for a [`HijriUmmAlQura`] calendar - HijriUmmAlQura(::DateInner), + HijriUmmAlQura( as Calendar>::DateInner), /// A date for an [`Iso`] calendar Iso(::DateInner), /// A date for a [`Japanese`] calendar @@ -153,6 +148,32 @@ pub enum AnyDateInner { Roc(::DateInner), } +impl PartialOrd for AnyDateInner { + #[rustfmt::skip] + fn partial_cmp(&self, other: &Self) -> Option { + use AnyDateInner::*; + match (self, other) { + (Buddhist(d1), Buddhist(d2)) => d1.partial_cmp(d2), + (Chinese(d1), Chinese(d2)) => d1.partial_cmp(d2), + (Coptic(d1), Coptic(d2)) => d1.partial_cmp(d2), + (Dangi(d1), Dangi(d2)) => d1.partial_cmp(d2), + (Ethiopian(d1), Ethiopian(d2)) => d1.partial_cmp(d2), + (Gregorian(d1), Gregorian(d2)) => d1.partial_cmp(d2), + (Hebrew(d1), Hebrew(d2)) => d1.partial_cmp(d2), + (Indian(d1), Indian(d2)) => d1.partial_cmp(d2), + (&HijriTabular(ref d1, s1), &HijriTabular(ref d2, s2)) if s1 == s2 => d1.partial_cmp(d2), + (HijriSimulated(d1), HijriSimulated(d2)) => d1.partial_cmp(d2), + (HijriUmmAlQura(d1), HijriUmmAlQura(d2)) => d1.partial_cmp(d2), + (Iso(d1), Iso(d2)) => d1.partial_cmp(d2), + (Japanese(d1), Japanese(d2)) => d1.partial_cmp(d2), + (JapaneseExtended(d1), JapaneseExtended(d2)) => d1.partial_cmp(d2), + (Persian(d1), Persian(d2)) => d1.partial_cmp(d2), + (Roc(d1), Roc(d2)) => d1.partial_cmp(d2), + _ => None, + } + } +} + macro_rules! match_cal_and_date { (match ($cal:ident, $date:ident): ($cal_matched:ident, $date_matched:ident) => $e:expr) => { match ($cal, $date) { @@ -166,8 +187,8 @@ macro_rules! match_cal_and_date { (&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, + &AnyDateInner::HijriTabular(ref $date_matched, sighting), + ) if $cal_matched.0 == sighting => $e, ( &Self::HijriSimulated(ref $cal_matched), &AnyDateInner::HijriSimulated(ref $date_matched), @@ -184,11 +205,8 @@ macro_rules! match_cal_and_date { ) => $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() - ), + // This is only reached from misuse of from_raw, a semi-internal api + _ => panic!("AnyCalendar with mismatched date type"), } }; } @@ -205,9 +223,7 @@ macro_rules! match_cal { &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::HijriTabular(ref $cal_matched) => AnyDateInner::HijriTabular($e, $cal_matched.0), &Self::HijriUmmAlQura(ref $cal_matched) => AnyDateInner::HijriUmmAlQura($e), &Self::Iso(ref $cal_matched) => AnyDateInner::Iso($e), &Self::Japanese(ref $cal_matched) => AnyDateInner::Japanese($e), @@ -218,10 +234,45 @@ macro_rules! match_cal { }; } +/// Error returned when comparing two [`Date`]s with [`AnyCalendar`]. +#[derive(Clone, Copy, PartialEq, Debug)] +#[non_exhaustive] +#[doc(hidden)] // unstable, not yet graduated +pub enum AnyCalendarDifferenceError { + /// The calendars of the two dates being compared are not equal. + /// + /// To compare dates in different calendars, convert them to the same calendar first. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::cal::AnyCalendarDifferenceError; + /// use icu::calendar::Date; + /// + /// let d1 = Date::try_new_gregorian(2000, 1, 1).unwrap().to_any(); + /// let d2 = Date::try_new_persian(1562, 1, 1).unwrap().to_any(); + /// + /// assert_eq!( + /// d1.try_until_with_options(&d2, Default::default()) + /// .unwrap_err(), + /// AnyCalendarDifferenceError::MismatchedCalendars, + /// ); + /// + /// // To compare the dates, convert them to the same calendar, + /// // such as ISO. + /// + /// d1.to_iso() + /// .try_until_with_options(&d2.to_iso(), Default::default()) + /// .unwrap(); + /// ``` + MismatchedCalendars, +} + impl crate::cal::scaffold::UnstableSealed for AnyCalendar {} impl Calendar for AnyCalendar { type DateInner = AnyDateInner; type Year = YearInfo; + type DifferenceError = AnyCalendarDifferenceError; fn from_codes( &self, @@ -233,10 +284,44 @@ impl Calendar for AnyCalendar { Ok(match_cal!(match self: (c) => c.from_codes(era, year, month_code, day)?)) } + #[cfg(feature = "unstable")] + fn from_fields( + &self, + fields: DateFields, + options: DateFromFieldsOptions, + ) -> Result { + Ok(match_cal!(match self: (c) => c.from_fields(fields, options)?)) + } + + fn has_cheap_iso_conversion(&self) -> bool { + match self { + Self::Buddhist(ref c) => c.has_cheap_iso_conversion(), + Self::Chinese(ref c) => c.has_cheap_iso_conversion(), + Self::Coptic(ref c) => c.has_cheap_iso_conversion(), + Self::Dangi(ref c) => c.has_cheap_iso_conversion(), + Self::Ethiopian(ref c) => c.has_cheap_iso_conversion(), + Self::Gregorian(ref c) => c.has_cheap_iso_conversion(), + Self::Hebrew(ref c) => c.has_cheap_iso_conversion(), + Self::Indian(ref c) => c.has_cheap_iso_conversion(), + Self::HijriSimulated(ref c) => c.has_cheap_iso_conversion(), + Self::HijriTabular(ref c) => c.has_cheap_iso_conversion(), + Self::HijriUmmAlQura(ref c) => c.has_cheap_iso_conversion(), + Self::Iso(ref c) => c.has_cheap_iso_conversion(), + Self::Japanese(ref c) => c.has_cheap_iso_conversion(), + Self::JapaneseExtended(ref c) => c.has_cheap_iso_conversion(), + Self::Persian(ref c) => c.has_cheap_iso_conversion(), + Self::Roc(ref c) => c.has_cheap_iso_conversion(), + } + } + fn from_iso(&self, iso: IsoDateInner) -> AnyDateInner { match_cal!(match self: (c) => c.from_iso(iso)) } + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + match_cal_and_date!(match (self, date): (c, d) => c.to_iso(d)) + } + fn from_rata_die(&self, rd: calendrical_calculations::rata_die::RataDie) -> Self::DateInner { match_cal!(match self: (c) => c.from_rata_die(rd)) } @@ -245,10 +330,6 @@ impl Calendar for AnyCalendar { 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)) } @@ -261,222 +342,141 @@ impl Calendar for AnyCalendar { 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) { + #[cfg(feature = "unstable")] + fn add( + &self, + date: &Self::DateInner, + duration: types::DateDuration, + options: DateAddOptions, + ) -> Result { + let mut date = *date; + match (self, &mut date) { (Self::Buddhist(c), AnyDateInner::Buddhist(ref mut d)) => { - c.offset_date(d, offset.cast_unit()) + *d = c.add(d, duration, options)? } (Self::Chinese(c), AnyDateInner::Chinese(ref mut d)) => { - c.offset_date(d, offset.cast_unit()) + *d = c.add(d, duration, options)? } (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()) + *d = c.add(d, duration, options)? } + (Self::Dangi(c), AnyDateInner::Dangi(ref mut d)) => *d = c.add(d, duration, options)?, (Self::Ethiopian(c), AnyDateInner::Ethiopian(ref mut d)) => { - c.offset_date(d, offset.cast_unit()) + *d = c.add(d, duration, options)? } (Self::Gregorian(c), AnyDateInner::Gregorian(ref mut d)) => { - c.offset_date(d, offset.cast_unit()) + *d = c.add(d, duration, options)? } (Self::Hebrew(c), AnyDateInner::Hebrew(ref mut d)) => { - c.offset_date(d, offset.cast_unit()) + *d = c.add(d, duration, options)? } (Self::Indian(c), AnyDateInner::Indian(ref mut d)) => { - c.offset_date(d, offset.cast_unit()) + *d = c.add(d, duration, options)? } - ( - 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::HijriTabular(c), AnyDateInner::HijriTabular(ref mut d, sighting)) + if c.0 == *sighting => + { + *d = c.add(d, duration, options)? } (Self::HijriSimulated(c), AnyDateInner::HijriSimulated(ref mut d)) => { - c.offset_date(d, offset.cast_unit()) + *d = c.add(d, duration, options)? } (Self::HijriUmmAlQura(c), AnyDateInner::HijriUmmAlQura(ref mut d)) => { - c.offset_date(d, offset.cast_unit()) + *d = c.add(d, duration, options)? } - (Self::Iso(c), AnyDateInner::Iso(ref mut d)) => c.offset_date(d, offset.cast_unit()), + (Self::Iso(c), AnyDateInner::Iso(ref mut d)) => *d = c.add(d, duration, options)?, (Self::Japanese(c), AnyDateInner::Japanese(ref mut d)) => { - c.offset_date(d, offset.cast_unit()) + *d = c.add(d, duration, options)? } (Self::JapaneseExtended(c), AnyDateInner::JapaneseExtended(ref mut d)) => { - c.offset_date(d, offset.cast_unit()) + *d = c.add(d, duration, options)? } (Self::Persian(c), AnyDateInner::Persian(ref mut d)) => { - c.offset_date(d, offset.cast_unit()) + *d = c.add(d, duration, options)? } - (Self::Roc(c), AnyDateInner::Roc(ref mut d)) => c.offset_date(d, offset.cast_unit()), + (Self::Roc(c), AnyDateInner::Roc(ref mut d)) => *d = c.add(d, duration, options)?, // 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() - ), + #[expect(clippy::panic)] + _ => panic!("AnyCalendar with mismatched date type"), } + Ok(date) } + #[cfg(feature = "unstable")] 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(), + options: DateDifferenceOptions, + ) -> Result { + let Ok(r) = match (self, date1, date2) { + (Self::Buddhist(c1), AnyDateInner::Buddhist(d1), AnyDateInner::Buddhist(d2)) => { + c1.until(d1, d2, options) + } + (Self::Chinese(c1), AnyDateInner::Chinese(d1), AnyDateInner::Chinese(d2)) => { + c1.until(d1, d2, options) + } + (Self::Coptic(c1), AnyDateInner::Coptic(d1), AnyDateInner::Coptic(d2)) => { + c1.until(d1, d2, options) + } + (Self::Dangi(c1), AnyDateInner::Dangi(d1), AnyDateInner::Dangi(d2)) => { + c1.until(d1, d2, options) + } + (Self::Ethiopian(c1), AnyDateInner::Ethiopian(d1), AnyDateInner::Ethiopian(d2)) => { + c1.until(d1, d2, options) + } + (Self::Gregorian(c1), AnyDateInner::Gregorian(d1), AnyDateInner::Gregorian(d2)) => { + c1.until(d1, d2, options) + } + (Self::Hebrew(c1), AnyDateInner::Hebrew(d1), AnyDateInner::Hebrew(d2)) => { + c1.until(d1, d2, options) + } + (Self::Indian(c1), AnyDateInner::Indian(d1), AnyDateInner::Indian(d2)) => { + c1.until(d1, d2, options) + } ( 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() - } + &AnyDateInner::HijriTabular(ref d1, s1), + &AnyDateInner::HijriTabular(ref d2, s2), + ) if c1.0 == s1 && s1 == s2 => c1.until(d1, d2, options), ( Self::HijriSimulated(c1), - Self::HijriSimulated(c2), AnyDateInner::HijriSimulated(d1), AnyDateInner::HijriSimulated(d2), - ) => c1 - .until(d1, d2, c2, largest_unit, smallest_unit) - .cast_unit(), + ) => c1.until(d1, d2, options), ( 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(), + ) => c1.until(d1, d2, options), + (Self::Iso(c1), AnyDateInner::Iso(d1), AnyDateInner::Iso(d2)) => { + c1.until(d1, d2, options) + } + (Self::Japanese(c1), AnyDateInner::Japanese(d1), AnyDateInner::Japanese(d2)) => { + c1.until(d1, d2, options) + } ( 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(), + ) => c1.until(d1, d2, options), + (Self::Persian(c1), AnyDateInner::Persian(d1), AnyDateInner::Persian(d2)) => { + c1.until(d1, d2, options) + } + (Self::Roc(c1), AnyDateInner::Roc(d1), AnyDateInner::Roc(d2)) => { + c1.until(d1, d2, options) + } _ => { - // 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::() - } - ) + return Err(AnyCalendarDifferenceError::MismatchedCalendars); } - } + }; + Ok(r) } 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)) @@ -556,9 +556,9 @@ impl AnyCalendar { pub const fn new(kind: AnyCalendarKind) -> Self { match kind { AnyCalendarKind::Buddhist => AnyCalendar::Buddhist(Buddhist), - AnyCalendarKind::Chinese => AnyCalendar::Chinese(Chinese::new()), + AnyCalendarKind::Chinese => AnyCalendar::Chinese(ChineseTraditional::new()), AnyCalendarKind::Coptic => AnyCalendar::Coptic(Coptic), - AnyCalendarKind::Dangi => AnyCalendar::Dangi(Dangi::new()), + AnyCalendarKind::Dangi => AnyCalendar::Dangi(KoreanTraditional::new()), AnyCalendarKind::Ethiopian => AnyCalendar::Ethiopian(Ethiopian::new_with_era_style( EthiopianEraStyle::AmeteMihret, )), @@ -569,21 +569,23 @@ impl AnyCalendar { AnyCalendarKind::Hebrew => AnyCalendar::Hebrew(Hebrew), AnyCalendarKind::Indian => AnyCalendar::Indian(Indian), AnyCalendarKind::HijriTabularTypeIIFriday => { - AnyCalendar::HijriTabular(HijriTabular::new( - crate::cal::hijri::HijriTabularLeapYears::TypeII, - HijriTabularEpoch::Friday, + AnyCalendar::HijriTabular(Hijri::new_tabular( + hijri::TabularAlgorithmLeapYears::TypeII, + hijri::TabularAlgorithmEpoch::Friday, )) } AnyCalendarKind::HijriSimulatedMecca => { - AnyCalendar::HijriSimulated(HijriSimulated::new_mecca()) + AnyCalendar::HijriSimulated(Hijri::new_simulated_mecca()) } AnyCalendarKind::HijriTabularTypeIIThursday => { - AnyCalendar::HijriTabular(HijriTabular::new( - crate::cal::hijri::HijriTabularLeapYears::TypeII, - HijriTabularEpoch::Thursday, + AnyCalendar::HijriTabular(Hijri::new_tabular( + hijri::TabularAlgorithmLeapYears::TypeII, + hijri::TabularAlgorithmEpoch::Thursday, )) } - AnyCalendarKind::HijriUmmAlQura => AnyCalendar::HijriUmmAlQura(HijriUmmAlQura::new()), + AnyCalendarKind::HijriUmmAlQura => { + AnyCalendar::HijriUmmAlQura(Hijri::new_umm_al_qura()) + } AnyCalendarKind::Iso => AnyCalendar::Iso(Iso), AnyCalendarKind::Japanese => AnyCalendar::Japanese(Japanese::new()), AnyCalendarKind::JapaneseExtended => { @@ -605,13 +607,9 @@ impl AnyCalendar { { Ok(match kind { AnyCalendarKind::Buddhist => AnyCalendar::Buddhist(Buddhist), - AnyCalendarKind::Chinese => { - AnyCalendar::Chinese(Chinese::try_new_with_buffer_provider(provider)?) - } + AnyCalendarKind::Chinese => AnyCalendar::Chinese(ChineseTraditional::new()), AnyCalendarKind::Coptic => AnyCalendar::Coptic(Coptic), - AnyCalendarKind::Dangi => { - AnyCalendar::Dangi(Dangi::try_new_with_buffer_provider(provider)?) - } + AnyCalendarKind::Dangi => AnyCalendar::Dangi(KoreanTraditional::new()), AnyCalendarKind::Ethiopian => AnyCalendar::Ethiopian(Ethiopian::new_with_era_style( EthiopianEraStyle::AmeteMihret, )), @@ -622,21 +620,23 @@ impl AnyCalendar { AnyCalendarKind::Hebrew => AnyCalendar::Hebrew(Hebrew), AnyCalendarKind::Indian => AnyCalendar::Indian(Indian), AnyCalendarKind::HijriTabularTypeIIFriday => { - AnyCalendar::HijriTabular(HijriTabular::new( - crate::cal::hijri::HijriTabularLeapYears::TypeII, - HijriTabularEpoch::Friday, + AnyCalendar::HijriTabular(Hijri::new_tabular( + hijri::TabularAlgorithmLeapYears::TypeII, + hijri::TabularAlgorithmEpoch::Friday, )) } - AnyCalendarKind::HijriSimulatedMecca => AnyCalendar::HijriSimulated( - HijriSimulated::try_new_mecca_with_buffer_provider(provider)?, - ), + AnyCalendarKind::HijriSimulatedMecca => { + AnyCalendar::HijriSimulated(Hijri::new_simulated_mecca()) + } AnyCalendarKind::HijriTabularTypeIIThursday => { - AnyCalendar::HijriTabular(HijriTabular::new( - crate::cal::hijri::HijriTabularLeapYears::TypeII, - HijriTabularEpoch::Thursday, + AnyCalendar::HijriTabular(Hijri::new_tabular( + hijri::TabularAlgorithmLeapYears::TypeII, + hijri::TabularAlgorithmEpoch::Thursday, )) } - AnyCalendarKind::HijriUmmAlQura => AnyCalendar::HijriUmmAlQura(HijriUmmAlQura::new()), + AnyCalendarKind::HijriUmmAlQura => { + AnyCalendar::HijriUmmAlQura(Hijri::new_umm_al_qura()) + } AnyCalendarKind::Iso => AnyCalendar::Iso(Iso), AnyCalendarKind::Japanese => { AnyCalendar::Japanese(Japanese::try_new_with_buffer_provider(provider)?) @@ -654,16 +654,13 @@ impl AnyCalendar { 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::Chinese => AnyCalendar::Chinese(ChineseTraditional::new()), AnyCalendarKind::Coptic => AnyCalendar::Coptic(Coptic), - AnyCalendarKind::Dangi => AnyCalendar::Dangi(Dangi::try_new_unstable(provider)?), + AnyCalendarKind::Dangi => AnyCalendar::Dangi(KoreanTraditional::new()), AnyCalendarKind::Ethiopian => AnyCalendar::Ethiopian(Ethiopian::new_with_era_style( EthiopianEraStyle::AmeteMihret, )), @@ -674,21 +671,23 @@ impl AnyCalendar { AnyCalendarKind::Hebrew => AnyCalendar::Hebrew(Hebrew), AnyCalendarKind::Indian => AnyCalendar::Indian(Indian), AnyCalendarKind::HijriTabularTypeIIFriday => { - AnyCalendar::HijriTabular(HijriTabular::new( - crate::cal::hijri::HijriTabularLeapYears::TypeII, - HijriTabularEpoch::Friday, + AnyCalendar::HijriTabular(Hijri::new_tabular( + hijri::TabularAlgorithmLeapYears::TypeII, + hijri::TabularAlgorithmEpoch::Friday, )) } AnyCalendarKind::HijriSimulatedMecca => { - AnyCalendar::HijriSimulated(HijriSimulated::try_new_mecca_unstable(provider)?) + AnyCalendar::HijriSimulated(Hijri::new_simulated_mecca()) } AnyCalendarKind::HijriTabularTypeIIThursday => { - AnyCalendar::HijriTabular(HijriTabular::new( - crate::cal::hijri::HijriTabularLeapYears::TypeII, - HijriTabularEpoch::Thursday, + AnyCalendar::HijriTabular(Hijri::new_tabular( + hijri::TabularAlgorithmLeapYears::TypeII, + hijri::TabularAlgorithmEpoch::Thursday, )) } - AnyCalendarKind::HijriUmmAlQura => AnyCalendar::HijriUmmAlQura(HijriUmmAlQura::new()), + AnyCalendarKind::HijriUmmAlQura => { + AnyCalendar::HijriUmmAlQura(Hijri::new_umm_al_qura()) + } AnyCalendarKind::Iso => AnyCalendar::Iso(Iso), AnyCalendarKind::Japanese => { AnyCalendar::Japanese(Japanese::try_new_unstable(provider)?) @@ -738,127 +737,107 @@ impl> Date { } } -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 + /// + /// This corresponds to the `"buddhist"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). Buddhist, /// The kind of a [`Chinese`] calendar + /// + /// This corresponds to the `"chinese"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). Chinese, /// The kind of a [`Coptic`] calendar + /// + /// This corresponds to the `"coptic"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). Coptic, /// The kind of a [`Dangi`] calendar + /// + /// This corresponds to the `"dangi"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). Dangi, /// The kind of an [`Ethiopian`] calendar, with Amete Mihret era + /// + /// This corresponds to the `"ethiopic"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). Ethiopian, /// The kind of an [`Ethiopian`] calendar, with Amete Alem era + /// + /// This corresponds to the `"ethioaa"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). EthiopianAmeteAlem, /// The kind of a [`Gregorian`] calendar + /// + /// This corresponds to the `"gregory"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). Gregorian, /// The kind of a [`Hebrew`] calendar + /// + /// This corresponds to the `"hebrew"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). Hebrew, /// The kind of a [`Indian`] calendar + /// + /// This corresponds to the `"indian"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). Indian, /// The kind of an [`HijriTabular`] calendar using [`HijriTabularLeapYears::TypeII`] and [`HijriTabularEpoch::Friday`] + /// + /// This corresponds to the `"islamic-civil"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). HijriTabularTypeIIFriday, /// The kind of an [`HijriSimulated`], Mecca calendar + /// + /// This corresponds to the `"islamic-rgsa"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). HijriSimulatedMecca, /// The kind of an [`HijriTabular`] calendar using [`HijriTabularLeapYears::TypeII`] and [`HijriTabularEpoch::Thursday`] + /// + /// This corresponds to the `"islamic-tbla"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). HijriTabularTypeIIThursday, /// The kind of an [`HijriUmmAlQura`] calendar + /// + /// This corresponds to the `"islamic-umalqura"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). HijriUmmAlQura, /// The kind of an [`Iso`] calendar + /// + /// This corresponds to the `"iso8601"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). Iso, /// The kind of a [`Japanese`] calendar + /// + /// This corresponds to the `"japanese"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). Japanese, /// The kind of a [`JapaneseExtended`] calendar + /// + /// This corresponds to the `"japanext"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). JapaneseExtended, /// The kind of a [`Persian`] calendar + /// + /// This corresponds to the `"persian"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). Persian, /// The kind of a [`Roc`] calendar + /// + /// This corresponds to the `"roc"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). 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()) { + if let Some(kind) = prefs.calendar_algorithm.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(), + // This is tested to be consistent with CLDR in icu_provider_source::calendar::test_calendar_resolution + match ( + prefs.calendar_algorithm, + prefs + .locale_preferences + .region() + .as_ref() + .map(|r| r.as_str()), + ) { + (Some(CalendarAlgorithm::Hijri(None)), Some("AE" | "BH" | "KW" | "QA" | "SA")) => { + AnyCalendarKind::HijriUmmAlQura + } + (Some(CalendarAlgorithm::Hijri(None)), _) => AnyCalendarKind::HijriTabularTypeIIFriday, + (_, Some("TH")) => AnyCalendarKind::Buddhist, + (_, Some("AF" | "IR")) => AnyCalendarKind::Persian, + _ => AnyCalendarKind::Gregorian, } } } @@ -991,7 +970,7 @@ impl From for AnyCalendar { } } -impl IntoAnyCalendar for Chinese { +impl IntoAnyCalendar for ChineseTraditional { #[inline] fn to_any(self) -> AnyCalendar { AnyCalendar::Chinese(self) @@ -1022,8 +1001,8 @@ impl IntoAnyCalendar for Chinese { } } -impl From for AnyCalendar { - fn from(value: Chinese) -> AnyCalendar { +impl From for AnyCalendar { + fn from(value: ChineseTraditional) -> AnyCalendar { value.to_any() } } @@ -1065,7 +1044,7 @@ impl From for AnyCalendar { } } -impl IntoAnyCalendar for Dangi { +impl IntoAnyCalendar for KoreanTraditional { #[inline] fn to_any(self) -> AnyCalendar { AnyCalendar::Dangi(self) @@ -1096,8 +1075,8 @@ impl IntoAnyCalendar for Dangi { } } -impl From for AnyCalendar { - fn from(value: Dangi) -> AnyCalendar { +impl From for AnyCalendar { + fn from(value: KoreanTraditional) -> AnyCalendar { value.to_any() } } @@ -1110,10 +1089,9 @@ impl IntoAnyCalendar for Ethiopian { } #[inline] fn kind(&self) -> AnyCalendarKind { - if self.0 { - AnyCalendarKind::EthiopianAmeteAlem - } else { - AnyCalendarKind::Ethiopian + match self.era_style() { + EthiopianEraStyle::AmeteAlem => AnyCalendarKind::EthiopianAmeteAlem, + EthiopianEraStyle::AmeteMihret => AnyCalendarKind::Ethiopian, } } #[inline] @@ -1255,20 +1233,22 @@ impl From for AnyCalendar { } } -impl IntoAnyCalendar for HijriTabular { +impl IntoAnyCalendar for Hijri { #[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 - } + match self.0 { + hijri::TabularAlgorithm { + leap_years: hijri::TabularAlgorithmLeapYears::TypeII, + epoch: hijri::TabularAlgorithmEpoch::Friday, + } => AnyCalendarKind::HijriTabularTypeIIFriday, + hijri::TabularAlgorithm { + leap_years: hijri::TabularAlgorithmLeapYears::TypeII, + epoch: hijri::TabularAlgorithmEpoch::Thursday, + } => AnyCalendarKind::HijriTabularTypeIIThursday, } } #[inline] @@ -1289,25 +1269,27 @@ impl IntoAnyCalendar for HijriTabular { } #[inline] fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner { - AnyDateInner::HijriTabular(*d, self.leap_years, self.epoch) + AnyDateInner::HijriTabular(*d, self.0) } } -impl From for AnyCalendar { - fn from(value: HijriTabular) -> AnyCalendar { +impl From> for AnyCalendar { + fn from(value: Hijri) -> AnyCalendar { value.to_any() } } -impl IntoAnyCalendar for HijriSimulated { +impl IntoAnyCalendar for Hijri { #[inline] fn to_any(self) -> AnyCalendar { AnyCalendar::HijriSimulated(self) } #[inline] fn kind(&self) -> AnyCalendarKind { - match self.location { - HijriSimulatedLocation::Mecca => AnyCalendarKind::HijriSimulatedMecca, + match self.0.location { + crate::cal::hijri_internal::SimulatedLocation::Mecca => { + AnyCalendarKind::HijriSimulatedMecca + } } } #[inline] @@ -1332,13 +1314,13 @@ impl IntoAnyCalendar for HijriSimulated { } } -impl From for AnyCalendar { - fn from(value: HijriSimulated) -> AnyCalendar { +impl From> for AnyCalendar { + fn from(value: Hijri) -> AnyCalendar { value.to_any() } } -impl IntoAnyCalendar for HijriUmmAlQura { +impl IntoAnyCalendar for Hijri { #[inline] fn to_any(self) -> AnyCalendar { AnyCalendar::HijriUmmAlQura(self) @@ -1369,8 +1351,8 @@ impl IntoAnyCalendar for HijriUmmAlQura { } } -impl From for AnyCalendar { - fn from(value: HijriUmmAlQura) -> AnyCalendar { +impl From> for AnyCalendar { + fn from(value: Hijri) -> AnyCalendar { value.to_any() } } @@ -1587,29 +1569,37 @@ mod tests { }); 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), + (month, day), + (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"); + + let roundtrip_year = roundtrip_year.era_year_or_related_iso(); assert_eq!( - (era_code, era_index), + (era_code, era_index, year), ( roundtrip_era_year.era.as_str(), - roundtrip_era_year.era_index + roundtrip_era_year.era_index, + roundtrip_year ), "Failed to roundtrip era for calendar {}", calendar.debug_name() ) + } else { + assert_eq!( + year, + date.extended_year(), + "Failed to roundtrip year for calendar {}", + calendar.debug_name() + ); } let iso = date.to_iso(); @@ -1678,7 +1668,8 @@ mod tests { 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, None, 100, "M03", 1); + single_test_roundtrip(buddhist, None, -100, "M03", 1); single_test_roundtrip(buddhist, Some(("be", Some(0))), -100, "M03", 1); single_test_error( buddhist, @@ -1691,6 +1682,7 @@ mod tests { single_test_roundtrip(coptic, Some(("am", Some(0))), 100, "M03", 1); single_test_roundtrip(coptic, None, 2000, "M03", 1); + single_test_roundtrip(coptic, None, -100, "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( @@ -1704,8 +1696,11 @@ mod tests { single_test_roundtrip(ethiopian, Some(("am", Some(1))), 100, "M03", 1); single_test_roundtrip(ethiopian, None, 2000, "M03", 1); + single_test_roundtrip(ethiopian, None, -100, "M03", 1); single_test_roundtrip(ethiopian, Some(("am", Some(1))), 2000, "M13", 1); single_test_roundtrip(ethiopian, Some(("aa", Some(0))), 5400, "M03", 1); + // Since #6910, the era range is not enforced in try_from_codes + /* single_test_error( ethiopian, Some(("am", Some(0))), @@ -1732,6 +1727,7 @@ mod tests { max: 5500, }, ); + */ single_test_error( ethiopian, Some(("am", Some(0))), @@ -1743,6 +1739,7 @@ mod tests { single_test_roundtrip(ethioaa, Some(("aa", Some(0))), 7000, "M13", 1); single_test_roundtrip(ethioaa, None, 7000, "M13", 1); + single_test_roundtrip(ethioaa, None, -100, "M13", 1); single_test_roundtrip(ethioaa, Some(("aa", Some(0))), 100, "M03", 1); single_test_error( ethiopian, @@ -1755,7 +1752,10 @@ mod tests { single_test_roundtrip(gregorian, Some(("ce", Some(1))), 100, "M03", 1); single_test_roundtrip(gregorian, None, 2000, "M03", 1); + single_test_roundtrip(gregorian, None, -100, "M03", 1); single_test_roundtrip(gregorian, Some(("bce", Some(0))), 100, "M03", 1); + // Since #6910, the era range is not enforced in try_from_codes + /* single_test_error( gregorian, Some(("ce", Some(1))), @@ -1782,7 +1782,7 @@ mod tests { max: i32::MAX, }, ); - + */ single_test_error( gregorian, Some(("bce", Some(0))), @@ -1834,7 +1834,11 @@ mod tests { 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, None, -100, "M03", 1); + single_test_roundtrip(japanese, None, 2024, "M03", 1); single_test_roundtrip(japanese, Some(("bce", None)), 10, "M03", 1); + // Since #6910, the era range is not enforced in try_from_codes + /* single_test_error( japanese, Some(("ce", None)), @@ -1861,7 +1865,7 @@ mod tests { max: i32::MAX, }, ); - + */ single_test_error( japanese, Some(("reiwa", None)), @@ -1877,6 +1881,8 @@ mod tests { 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); + // Since #6910, the era range is not enforced in try_from_codes + /* single_test_error( japanext, Some(("ce", None)), @@ -1903,7 +1909,7 @@ mod tests { max: i32::MAX, }, ); - + */ single_test_error( japanext, Some(("reiwa", None)), @@ -1915,6 +1921,7 @@ mod tests { single_test_roundtrip(persian, Some(("ap", Some(0))), 477, "M03", 1); single_test_roundtrip(persian, None, 2083, "M07", 21); + single_test_roundtrip(persian, None, -100, "M07", 21); single_test_roundtrip(persian, Some(("ap", Some(0))), 1600, "M12", 20); single_test_error( persian, @@ -1927,6 +1934,7 @@ mod tests { single_test_roundtrip(hebrew, Some(("am", Some(0))), 5773, "M03", 1); single_test_roundtrip(hebrew, None, 4993, "M07", 21); + single_test_roundtrip(hebrew, None, -100, "M07", 21); single_test_roundtrip(hebrew, Some(("am", Some(0))), 5012, "M12", 20); single_test_error( hebrew, @@ -1940,9 +1948,11 @@ mod tests { 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(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, None, -100, "M07", 21); single_test_roundtrip(hijri_simulated, Some(("ah", Some(0))), 1600, "M12", 20); single_test_error( hijri_simulated, @@ -1955,6 +1965,7 @@ mod tests { 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, None, -100, "M07", 21); single_test_roundtrip(hijri_civil, Some(("ah", Some(0))), 1600, "M12", 20); single_test_error( hijri_civil, @@ -1967,6 +1978,7 @@ mod tests { 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, None, -100, "M07", 21); single_test_roundtrip(hijri_umm_al_qura, Some(("ah", Some(0))), 1600, "M12", 20); single_test_error( hijri_umm_al_qura, @@ -1979,6 +1991,7 @@ mod tests { 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, None, -100, "M07", 21); single_test_roundtrip(hijri_astronomical, Some(("ah", Some(0))), 1600, "M12", 20); single_test_error( hijri_astronomical, diff --git a/deps/crates/vendor/icu_calendar/src/cal/abstract_gregorian.rs b/deps/crates/vendor/icu_calendar/src/cal/abstract_gregorian.rs new file mode 100644 index 00000000000000..17cd85e3f581e6 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/abstract_gregorian.rs @@ -0,0 +1,367 @@ +// 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::cal::iso::{IsoDateInner, IsoEra}; +use crate::calendar_arithmetic::{ArithmeticDate, DateFieldsResolver}; +use crate::error::{DateError, DateFromFieldsError, EcmaReferenceYearError, UnknownEraError}; +use crate::options::DateFromFieldsOptions; +use crate::options::{DateAddOptions, DateDifferenceOptions}; +use crate::preferences::CalendarAlgorithm; +use crate::types::EraYear; +use crate::{types, Calendar, RangeError}; +use calendrical_calculations::helpers::I32CastError; +use calendrical_calculations::rata_die::RataDie; + +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) struct AbstractGregorian(pub Y); + +pub(crate) trait GregorianYears: Clone + core::fmt::Debug { + // Positive if after 0 CE + const EXTENDED_YEAR_OFFSET: i32 = 0; + + fn extended_from_era_year(&self, era: Option<&[u8]>, year: i32) + -> Result; + + fn era_year_from_extended(&self, extended_year: i32, month: u8, day: u8) -> EraYear; + + fn calendar_algorithm(&self) -> Option { + None + } + + fn debug_name(&self) -> &'static str; +} + +impl ArithmeticDate> { + pub(crate) fn new_gregorian( + year: i32, + month: u8, + day: u8, + ) -> Result { + ArithmeticDate::try_from_ymd(year + Y::EXTENDED_YEAR_OFFSET, month, day) + } +} + +pub(crate) const REFERENCE_YEAR: i32 = 1972; +#[cfg(test)] +pub(crate) const LAST_DAY_OF_REFERENCE_YEAR: RataDie = + calendrical_calculations::gregorian::day_before_year(REFERENCE_YEAR + 1); + +impl DateFieldsResolver for AbstractGregorian { + // Gregorian year + type YearInfo = i32; + + fn days_in_provided_month(year: i32, month: u8) -> u8 { + // https://www.youtube.com/watch?v=J9KijLyP-yg&t=1394s + if month == 2 { + 28 + calendrical_calculations::gregorian::is_leap_year(year) as u8 + } else { + 30 | month ^ (month >> 3) + } + } + + fn months_in_provided_year(_: i32) -> u8 { + 12 + } + + #[inline] + fn year_info_from_era( + &self, + era: &[u8], + era_year: i32, + ) -> Result { + Ok(self.0.extended_from_era_year(Some(era), era_year)? + Y::EXTENDED_YEAR_OFFSET) + } + + #[inline] + fn year_info_from_extended(&self, extended_year: i32) -> Self::YearInfo { + extended_year + Y::EXTENDED_YEAR_OFFSET + } + + #[inline] + fn reference_year_from_month_day( + &self, + _month_code: types::ValidMonthCode, + _day: u8, + ) -> Result { + Ok(REFERENCE_YEAR) + } +} + +impl crate::cal::scaffold::UnstableSealed for AbstractGregorian {} + +impl Calendar for AbstractGregorian { + type DateInner = ArithmeticDate>; + type Year = types::EraYear; + type DifferenceError = core::convert::Infallible; + + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + ArithmeticDate::from_codes(era, year, month_code, day, self).map(ArithmeticDate::cast) + } + + #[cfg(feature = "unstable")] + fn from_fields( + &self, + fields: types::DateFields, + options: DateFromFieldsOptions, + ) -> Result { + ArithmeticDate::from_fields(fields, options, self).map(ArithmeticDate::cast) + } + + fn from_rata_die(&self, date: RataDie) -> Self::DateInner { + let iso = match calendrical_calculations::gregorian::gregorian_from_fixed(date) { + Err(I32CastError::BelowMin) => { + ArithmeticDate::>::new_unchecked(i32::MIN, 1, 1) + } + Err(I32CastError::AboveMax) => ArithmeticDate::new_unchecked(i32::MAX, 12, 31), + Ok((year, month, day)) => ArithmeticDate::new_unchecked(year, month, day), + }; + + if iso.year.checked_sub(Y::EXTENDED_YEAR_OFFSET).is_none() { + if Y::EXTENDED_YEAR_OFFSET < 0 { + ArithmeticDate::new_unchecked(i32::MIN - Y::EXTENDED_YEAR_OFFSET, 1, 1) + } else { + ArithmeticDate::new_unchecked(i32::MAX - Y::EXTENDED_YEAR_OFFSET, 12, 31) + } + } else { + iso + } + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + calendrical_calculations::gregorian::fixed_from_gregorian(date.year, date.month, date.day) + } + + fn has_cheap_iso_conversion(&self) -> bool { + true + } + + fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner { + iso.0 + } + + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + IsoDateInner(*date) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + AbstractGregorian::::months_in_provided_year(date.year) + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + 365 + calendrical_calculations::gregorian::is_leap_year(date.year) as u16 + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + AbstractGregorian::::days_in_provided_month(date.year, date.month) + } + + #[cfg(feature = "unstable")] + fn add( + &self, + date: &Self::DateInner, + duration: types::DateDuration, + options: DateAddOptions, + ) -> Result { + date.added(duration, &AbstractGregorian(IsoEra), options) + } + + #[cfg(feature = "unstable")] + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + options: DateDifferenceOptions, + ) -> Result { + Ok(date1.until(date2, &AbstractGregorian(IsoEra), options)) + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + self.0 + .era_year_from_extended(date.year - Y::EXTENDED_YEAR_OFFSET, date.month, date.day) + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + calendrical_calculations::gregorian::is_leap_year(date.year) + } + + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + types::MonthInfo::non_lunisolar(date.month) + } + + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + types::DayOfMonth(date.day) + } + + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + types::DayOfYear( + calendrical_calculations::gregorian::days_before_month(date.year, date.month) + + date.day as u16, + ) + } + + fn debug_name(&self) -> &'static str { + self.0.debug_name() + } + + fn calendar_algorithm(&self) -> Option { + self.0.calendar_algorithm() + } +} + +macro_rules! impl_with_abstract_gregorian { + ($cal_ty:ty, $inner_date_ty:ident, $eras_ty:ty, $self_ident:ident, $eras_expr:expr) => { + #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] + pub struct $inner_date_ty( + pub(crate) ArithmeticDate< + crate::cal::abstract_gregorian::AbstractGregorian, + >, + ); + + impl crate::cal::scaffold::UnstableSealed for $cal_ty {} + impl crate::Calendar for $cal_ty { + type DateInner = $inner_date_ty; + type Year = types::EraYear; + type DifferenceError = core::convert::Infallible; + + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr) + .from_codes(era, year, month_code, day) + .map($inner_date_ty) + } + + #[cfg(feature = "unstable")] + fn from_fields( + &self, + fields: crate::types::DateFields, + options: crate::options::DateFromFieldsOptions, + ) -> Result { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr) + .from_fields(fields, options) + .map($inner_date_ty) + } + + fn from_rata_die(&self, rd: crate::types::RataDie) -> Self::DateInner { + let $self_ident = self; + $inner_date_ty( + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr).from_rata_die(rd), + ) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> crate::types::RataDie { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr).to_rata_die(&date.0) + } + + fn has_cheap_iso_conversion(&self) -> bool { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr) + .has_cheap_iso_conversion() + } + + fn from_iso(&self, iso: crate::cal::iso::IsoDateInner) -> Self::DateInner { + let $self_ident = self; + $inner_date_ty( + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr).from_iso(iso), + ) + } + + fn to_iso(&self, date: &Self::DateInner) -> crate::cal::iso::IsoDateInner { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr).to_iso(&date.0) + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr) + .months_in_year(&date.0) + } + + fn days_in_year(&self, date: &Self::DateInner) -> u16 { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr).days_in_year(&date.0) + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr).days_in_month(&date.0) + } + + #[cfg(feature = "unstable")] + fn add( + &self, + date: &Self::DateInner, + duration: crate::types::DateDuration, + options: crate::options::DateAddOptions, + ) -> Result { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr) + .add(&date.0, duration, options) + .map($inner_date_ty) + } + + #[cfg(feature = "unstable")] + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + options: crate::options::DateDifferenceOptions, + ) -> Result { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr) + .until(&date1.0, &date2.0, options) + } + + fn year_info(&self, date: &Self::DateInner) -> Self::Year { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr).year_info(&date.0) + } + + fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr) + .is_in_leap_year(&date.0) + } + + fn month(&self, date: &Self::DateInner) -> types::MonthInfo { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr).month(&date.0) + } + + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr).day_of_month(&date.0) + } + + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr).day_of_year(&date.0) + } + + fn debug_name(&self) -> &'static str { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr).debug_name() + } + + fn calendar_algorithm(&self) -> Option { + let $self_ident = self; + crate::cal::abstract_gregorian::AbstractGregorian($eras_expr).calendar_algorithm() + } + } + }; +} +pub(crate) use impl_with_abstract_gregorian; diff --git a/deps/crates/vendor/icu_calendar/src/cal/buddhist.rs b/deps/crates/vendor/icu_calendar/src/cal/buddhist.rs index 0e56b890d1eee9..f60f03e42f50b6 100644 --- a/deps/crates/vendor/icu_calendar/src/cal/buddhist.rs +++ b/deps/crates/vendor/icu_calendar/src/cal/buddhist.rs @@ -2,158 +2,74 @@ // 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 crate::error::UnknownEraError; +use crate::preferences::CalendarAlgorithm; +use crate::{ + cal::abstract_gregorian::{impl_with_abstract_gregorian, GregorianYears}, + calendar_arithmetic::ArithmeticDate, + types, Date, DateError, RangeError, +}; 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](https://en.wikipedia.org/wiki/Thai_solar_calendar) /// -/// 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. +/// The Thai Solar Buddhist Calendar is a variant of the [`Gregorian`](crate::cal::Gregorian) calendar +/// created by the Thai government. It is identical to the Gregorian calendar except that is uses +/// the Buddhist Era (-543 CE) instead of the Common Era. /// -/// This type can be used with [`Date`] to represent dates in this calendar. +/// This implementation extends proleptically for dates before the calendar's creation +/// in 2484 BE (1941 CE). /// -/// [cal]: https://en.wikipedia.org/wiki/Thai_solar_calendar +/// This corresponds to the `"buddhist"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). /// /// # 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; +impl_with_abstract_gregorian!( + crate::cal::Buddhist, + BuddhistDateInner, + BuddhistEra, + _x, + BuddhistEra +); - fn from_codes( +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) struct BuddhistEra; + +impl GregorianYears for BuddhistEra { + const EXTENDED_YEAR_OFFSET: i32 = -543; + + fn extended_from_era_year( &self, - era: Option<&str>, + era: Option<&[u8]>, year: i32, - month_code: types::MonthCode, - day: u8, - ) -> Result { + ) -> Result { match era { - Some("be") | None => {} - _ => return Err(DateError::UnknownEra), + Some(b"be") | None => Ok(year), + _ => Err(UnknownEraError), } - 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 { + fn era_year_from_extended(&self, extended_year: i32, _month: u8, _day: u8) -> types::EraYear { types::EraYear { era: tinystr!(16, "be"), era_index: Some(0), - year: self.extended_year(date), + year: extended_year, + extended_year, 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) + fn calendar_algorithm(&self) -> Option { + Some(CalendarAlgorithm::Buddhist) } } @@ -173,13 +89,15 @@ impl Date { /// 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)) + ArithmeticDate::new_gregorian::(year, month, day) + .map(BuddhistDateInner) + .map(|i| Date::from_raw(i, Buddhist)) } } #[cfg(test)] mod test { + use crate::cal::Iso; use calendrical_calculations::rata_die::RataDie; use super::*; diff --git a/deps/crates/vendor/icu_calendar/src/cal/chinese.rs b/deps/crates/vendor/icu_calendar/src/cal/chinese.rs deleted file mode 100644 index 43ec385369438a..00000000000000 --- a/deps/crates/vendor/icu_calendar/src/cal/chinese.rs +++ /dev/null @@ -1,1039 +0,0 @@ -// 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 deleted file mode 100644 index 08ca5c81620104..00000000000000 --- a/deps/crates/vendor/icu_calendar/src/cal/chinese_based.rs +++ /dev/null @@ -1,446 +0,0 @@ -// 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 index 4eb8bd7f148909..3878168f9c9b4b 100644 --- a/deps/crates/vendor/icu_calendar/src/cal/coptic.rs +++ b/deps/crates/vendor/icu_calendar/src/cal/coptic.rs @@ -2,46 +2,49 @@ // 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 crate::calendar_arithmetic::ArithmeticDate; +use crate::calendar_arithmetic::DateFieldsResolver; +use crate::error::{ + DateError, DateFromFieldsError, EcmaReferenceYearError, MonthCodeError, UnknownEraError, +}; +use crate::options::DateFromFieldsOptions; +use crate::options::{DateAddOptions, DateDifferenceOptions}; +use crate::{types, Calendar, Date, RangeError}; use calendrical_calculations::helpers::I32CastError; use calendrical_calculations::rata_die::RataDie; use tinystr::tinystr; -/// The [Coptic Calendar] +/// The [Coptic Calendar](https://en.wikipedia.org/wiki/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. +/// The Coptic calendar, also called the Alexandrian Calendar, is a solar calendar that +/// is influenced by both the ancient Egpytian calendar and the [`Julian`](crate::cal::Julian) +/// calendar. It was introduced in Egypt under Roman rule in the first century BCE, and +/// replaced for civil use in 1875, however continues to be used liturgically. /// -/// This type can be used with [`Date`] to represent dates in this calendar. +/// This implementation extends proleptically for dates before the calendar's creation. /// -/// [Coptic calendar]: https://en.wikipedia.org/wiki/Coptic_calendar +/// This corresponds to the `"coptic"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). /// /// # 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 +/// # Months and days /// -/// 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 13 months are called Thout (`M01`, 30 days), Paopi (`M02`, 30 days), Hathor (`M03`, 30 days), +/// Koiak (`M04`, 30 days), Tobi (`M05`, 30 days), Meshir (`M06`, 30 days), Paremhat (`M07`, 30 days), +/// Parmouti (`M08`, 30 days), Pashons (`M09`, 30 days), Paoni (`M10`, 30 days), Epip (`M11`, 30 days), +/// Mesori (`M12`, 30 days), Pi Kogi Enavot (`M13`, 5 days). +/// +/// In leap years (years divisible by 4), Pi Kogi Enavot gains a 6th day. +/// +/// Standard years thus have 365 days, and leap years 366. +/// +/// # Calendar drift +/// +/// The Coptic calendar has the same year lengths and leap year rules as the Julian calendar, +/// so it experiences the same drift of 1 day in ~128 years with respect to the seasons. #[derive(Copy, Clone, Debug, Hash, Default, Eq, PartialEq, PartialOrd, Ord)] #[allow(clippy::exhaustive_structs)] // this type is stable pub struct Coptic; @@ -50,14 +53,14 @@ pub struct Coptic; #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] pub struct CopticDateInner(pub(crate) ArithmeticDate); -impl CalendarArithmetic for Coptic { +impl DateFieldsResolver 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) { + if year.rem_euclid(4) == 3 { 6 } else { 5 @@ -70,25 +73,66 @@ impl CalendarArithmetic for Coptic { fn months_in_provided_year(_: i32) -> u8 { 13 } + #[inline] + fn year_info_from_era( + &self, + era: &[u8], + era_year: i32, + ) -> Result { + match era { + b"am" => Ok(era_year), + _ => Err(UnknownEraError), + } + } - fn provided_year_is_leap(year: i32) -> bool { - year.rem_euclid(4) == 3 + #[inline] + fn year_info_from_extended(&self, extended_year: i32) -> Self::YearInfo { + extended_year } - fn last_month_day_in_provided_year(year: i32) -> (u8, u8) { - if Self::provided_year_is_leap(year) { - (13, 6) - } else { - (13, 5) + #[inline] + fn reference_year_from_month_day( + &self, + month_code: types::ValidMonthCode, + day: u8, + ) -> Result { + Coptic::reference_year_from_month_day(month_code, day) + } + + #[inline] + fn ordinal_month_from_code( + &self, + _year: &Self::YearInfo, + month_code: types::ValidMonthCode, + _options: DateFromFieldsOptions, + ) -> Result { + match month_code.to_tuple() { + (month_number @ 1..=13, false) => Ok(month_number), + _ => Err(MonthCodeError::NotInCalendar), } } +} - fn days_in_provided_year(year: i32) -> u16 { - if Self::provided_year_is_leap(year) { - 366 +impl Coptic { + pub(crate) fn reference_year_from_month_day( + month_code: types::ValidMonthCode, + day: u8, + ) -> Result { + let (ordinal_month, false) = month_code.to_tuple() else { + return Err(EcmaReferenceYearError::MonthCodeNotInCalendar); + }; + // December 31, 1972 occurs on 4th month, 22nd day, 1689 AM + let anno_martyrum_year = if ordinal_month < 4 || (ordinal_month == 4 && day <= 22) { + 1689 + // Note: this must be >=6, not just == 6, since we have not yet + // applied a potential Overflow::Constrain. + } else if ordinal_month == 13 && day >= 6 { + // 1687 AM is a leap year + 1687 } else { - 365 - } + 1688 + }; + Ok(anno_martyrum_year) } } @@ -96,6 +140,8 @@ impl crate::cal::scaffold::UnstableSealed for Coptic {} impl Calendar for Coptic { type DateInner = CopticDateInner; type Year = types::EraYear; + type DifferenceError = core::convert::Infallible; + fn from_codes( &self, era: Option<&str>, @@ -103,19 +149,23 @@ impl Calendar for Coptic { month_code: types::MonthCode, day: u8, ) -> Result { - let year = match era { - Some("am") | None => year, - Some(_) => return Err(DateError::UnknownEra), - }; + ArithmeticDate::from_codes(era, year, month_code, day, self).map(CopticDateInner) + } - ArithmeticDate::new_from_codes(self, year, month_code, day).map(CopticDateInner) + #[cfg(feature = "unstable")] + fn from_fields( + &self, + fields: types::DateFields, + options: DateFromFieldsOptions, + ) -> Result { + ArithmeticDate::from_fields(fields, options, self).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(), + Err(I32CastError::BelowMin) => ArithmeticDate::new_unchecked(i32::MIN, 1, 1), + Err(I32CastError::AboveMax) => ArithmeticDate::new_unchecked(i32::MAX, 13, 6), Ok((year, month, day)) => ArithmeticDate::new_unchecked(year, month, day), }, ) @@ -125,70 +175,71 @@ impl Calendar for Coptic { 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 has_cheap_iso_conversion(&self) -> bool { + false } fn months_in_year(&self, date: &Self::DateInner) -> u8 { - date.0.months_in_year() + Self::months_in_provided_year(date.0.year) } fn days_in_year(&self, date: &Self::DateInner) -> u16 { - date.0.days_in_year() + if self.is_in_leap_year(date) { + 366 + } else { + 365 + } } fn days_in_month(&self, date: &Self::DateInner) -> u8 { - date.0.days_in_month() + Self::days_in_provided_month(date.0.year, date.0.month) } - fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { - date.0.offset_date(offset, &()); + #[cfg(feature = "unstable")] + fn add( + &self, + date: &Self::DateInner, + duration: types::DateDuration, + options: DateAddOptions, + ) -> Result { + date.0.added(duration, self, options).map(CopticDateInner) } - #[allow(clippy::field_reassign_with_default)] + #[cfg(feature = "unstable")] 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) + options: DateDifferenceOptions, + ) -> Result { + Ok(date1.0.until(&date2.0, self, options)) } fn year_info(&self, date: &Self::DateInner) -> Self::Year { - let year = self.extended_year(date); + let year = date.0.year; types::EraYear { era: tinystr!(16, "am"), era_index: Some(0), year, + extended_year: 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) + date.0.year.rem_euclid(4) == 3 } fn month(&self, date: &Self::DateInner) -> types::MonthInfo { - date.0.month() + types::MonthInfo::non_lunisolar(date.0.month) } fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { - date.0.day_of_month() + types::DayOfMonth(date.0.day) } fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { - date.0.day_of_year() + types::DayOfYear(30 * (date.0.month as u16 - 1) + date.0.day as u16) } fn debug_name(&self) -> &'static str { @@ -214,7 +265,7 @@ impl Date { /// 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) + ArithmeticDate::try_from_ymd(year, month, day) .map(CopticDateInner) .map(|inner| Date::from_raw(inner, Coptic)) } @@ -223,6 +274,9 @@ impl Date { #[cfg(test)] mod tests { use super::*; + use crate::options::{DateFromFieldsOptions, MissingFieldsStrategy, Overflow}; + use crate::types::DateFields; + #[test] fn test_coptic_regression() { // https://github.com/unicode-org/icu4x/issues/2254 @@ -231,4 +285,23 @@ mod tests { let recovered_iso = coptic.to_iso(); assert_eq!(iso_date, recovered_iso); } + + #[test] + fn test_from_fields_monthday_constrain() { + // M13-7 is not a real day, however this should resolve to M12-6 + // with Overflow::Constrain + let fields = DateFields { + month_code: Some(b"M13"), + day: Some(7), + ..Default::default() + }; + let options = DateFromFieldsOptions { + overflow: Some(Overflow::Constrain), + missing_fields_strategy: Some(MissingFieldsStrategy::Ecma), + ..Default::default() + }; + + let date = Date::try_from_fields(fields, options, Coptic).unwrap(); + assert_eq!(date.day_of_month().0, 6, "Day was successfully constrained"); + } } diff --git a/deps/crates/vendor/icu_calendar/src/cal/dangi.rs b/deps/crates/vendor/icu_calendar/src/cal/dangi.rs deleted file mode 100644 index e0eef839a53d85..00000000000000 --- a/deps/crates/vendor/icu_calendar/src/cal/dangi.rs +++ /dev/null @@ -1,932 +0,0 @@ -// 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/east_asian_traditional.rs b/deps/crates/vendor/icu_calendar/src/cal/east_asian_traditional.rs new file mode 100644 index 00000000000000..879c4a6f2c8fd9 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/east_asian_traditional.rs @@ -0,0 +1,1940 @@ +// 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::cal::iso::Iso; +use crate::calendar_arithmetic::DateFieldsResolver; +use crate::calendar_arithmetic::{ArithmeticDate, ToExtendedYear}; +use crate::error::{ + DateError, DateFromFieldsError, EcmaReferenceYearError, MonthCodeError, UnknownEraError, +}; +use crate::options::{DateAddOptions, DateDifferenceOptions}; +use crate::options::{DateFromFieldsOptions, Overflow}; +use crate::types::ValidMonthCode; +use crate::AsCalendar; +use crate::{types, Calendar, Date}; +use calendrical_calculations::chinese_based::{ + self, ChineseBased, YearBounds, WELL_BEHAVED_ASTRONOMICAL_RANGE, +}; +use calendrical_calculations::rata_die::RataDie; +use icu_locale_core::preferences::extensions::unicode::keywords::CalendarAlgorithm; +use icu_provider::prelude::*; + +#[path = "east_asian_traditional/china_data.rs"] +mod china_data; +#[path = "east_asian_traditional/korea_data.rs"] +mod korea_data; +#[path = "east_asian_traditional/qing_data.rs"] +mod qing_data; +#[path = "east_asian_traditional/simple.rs"] +mod simple; + +/// The traditional East-Asian lunisolar calendar. +/// +/// This calendar used traditionally in China as well as in other countries in East Asia is +/// often used today to track important cultural events and holidays like the Lunar New Year. +/// +/// The type parameter specifies a particular set of calculation rules and local +/// time information, which differs by country and over time. +/// It must implement the currently-unstable `Rules` trait, at the moment this crate exports two stable +/// implementors of `Rules`: [`China`] and [`Korea`]. Please comment on [this issue](https://github.com/unicode-org/icu4x/issues/6962) +/// if you would like to see this trait stabilized. +/// +/// This corresponds to the `"chinese"` and `"dangi"` [CLDR calendars](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier) +/// respectively, when used with the [`China`] and [`Korea`] [`Rules`] types. +/// +/// # Year and Era codes +/// +/// Unlike most calendars, the traditional East-Asian 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 [`Gregorian`](crate::cal::Gregorian) (ISO) calendar. +/// This "related ISO year" marks the Gregorian year in which a traditional East-Asian year begins. +/// +/// Because the traditional East-Asian 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: +/// +/// # Months and days +/// +/// The 12 months (`M01`-`M12`) don't use names in modern usage, instead they are referred to as +/// e.g. 三月 (third month) using Chinese characters. +/// +/// As a lunar calendar, the lengths of the months depend on the lunar cycle (a month starts on the day of +/// local new moon), and will be either 29 or 30 days. As 12 such months fall short of a solar year, a leap +/// month is inserted roughly every 3 years; this can be after any month (e.g. `M02L`). +/// +/// Both the lengths of the months and the occurence of leap months are determined by the +/// concrete [`Rules`] implementation. +/// +/// The length of the year is 353-355 days, and the length of the leap year 383-385 days. +/// +/// # Calendar drift +/// +/// As leap months are determined with respect to the solar year, this calendar stays anchored +/// to the seasons. +#[derive(Clone, Debug, Default, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[allow(clippy::exhaustive_structs)] // newtype +pub struct EastAsianTraditional(pub R); + +/// The rules for the [`EastAsianTraditional`] calendar. +/// +/// The calendar depends on both astronomical calculations and local time. +/// The rules for how to perform these calculations, as well as how local +/// time is determined differ between countries and have changed over time. +/// +/// This crate currently provides [`Rules`] for [`China`] and [`Korea`]. +/// +///
+/// 🚫 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 Rules: Clone + core::fmt::Debug + crate::cal::scaffold::UnstableSealed { + /// Returns data about the given year. + fn year_data(&self, related_iso: i32) -> EastAsianTraditionalYearData; + + /// Returns an ECMA reference year that contains the given month-day combination. + /// + /// If the day is out of range, it will return a year that contains the given month + /// and the maximum day possible for that month. See [the spec][spec] for the + /// precise algorithm used. + /// + /// This API only matters when using [`MissingFieldsStrategy::Ecma`] to compute + /// a date without providing a year in [`Date::try_from_fields()`]. The default impl + /// will just error, and custom calendars who do not care about ECMA/Temporal + /// reference years do not need to override this. + /// + /// [spec]: https://tc39.es/proposal-temporal/#sec-temporal-nonisomonthdaytoisoreferencedate + /// [`MissingFieldsStrategy::Ecma`]: crate::options::MissingFieldsStrategy::Ecma + fn ecma_reference_year( + &self, + // TODO: Consider accepting ValidMonthCode + _month_code: (u8, bool), + _day: u8, + ) -> Result { + Err(EcmaReferenceYearError::Unimplemented) + } + + /// The debug name for the calendar defined by these [`Rules`]. + fn debug_name(&self) -> &'static str { + "Chinese (custom)" + } + + /// The BCP-47 [`CalendarAlgorithm`] for the calendar defined by these [`Rules`], if defined. + fn calendar_algorithm(&self) -> Option { + None + } +} + +/// The [Chinese](https://en.wikipedia.org/wiki/Chinese_calendar) variant of the [`EastAsianTraditional`] calendar. +/// +/// This type agrees with the official data published by the +/// [Purple Mountain Observatory for the years 1900-2025], as well as with +/// the data published by the [Hong Kong Observatory for the years 1901-2100]. +/// +/// For years since 1912, this uses the [GB/T 33661-2017] rules. +/// As accurate computation is computationally expensive, years until +/// 2100 are precomputed, and after that this type regresses to a simplified +/// calculation. If accuracy beyond 2100 is required, clients +/// can implement their own [`Rules`] type containing more precomputed data. +/// We note that the calendar is inherently uncertain for some future dates. +/// +/// Before 1912 [different rules](https://ytliu.epizy.com/Shixian/Shixian_summary.html) +/// were used. This type produces correct data for the years 1900-1912, and +/// falls back to a simplified calculation before 1900. If accuracy is +/// required before 1900, clients can implement their own [`Rules`] type +/// using data such as from the excellent compilation by [Yuk Tung Liu]. +/// +/// The precise behavior of this calendar may change in the future if: +/// - New ground truth is established by published government sources +/// - We decide to tweak the simplified calculation +/// - We decide to expand or reduce the range where we are correctly handling past dates. +/// +/// [Purple Mountain Observatory for the years 1900-2025]: http://www.pmo.cas.cn/xwdt2019/kpdt2019/202203/P020250414456381274062.pdf +/// [Hong Kong Observatory for the years 1901-2100]: https://www.hko.gov.hk/en/gts/time/conversion.htm +/// [GB/T 33661-2017]: China::gb_t_33661_2017 +/// [Yuk Tung Liu]: https://ytliu0.github.io/ChineseCalendar/table.html +pub type ChineseTraditional = EastAsianTraditional; + +/// The [`Rules`] used in China. +/// +/// See [`ChineseTraditional`] for more information. +#[derive(Copy, Clone, Debug, Default)] +#[non_exhaustive] +pub struct China; + +impl China { + /// Computes [`EastAsianTraditionalYearData`] according to [GB/T 33661-2017], + /// as implemented by [`calendrical_calculations::chinese_based::Chinese`]. + /// + /// The rules specified in [GB/T 33661-2017] have only been used + /// since 1912, applying them proleptically to years before 1912 will not + /// necessarily match historical calendars. + /// + /// Note that for future years there is a small degree of uncertainty, as + /// [GB/T 33661-2017] depends on the uncertain future [difference between UT1 + /// and UTC](https://en.wikipedia.org/wiki/Leap_second#Future). + /// As noted by + /// [Yuk Tung Liu](https://ytliu0.github.io/ChineseCalendar/computation.html#modern), + /// years as early as 2057, 2089, and 2097 have lunar events very close to + /// local midnight, which might affect the start of a (single) month if additional + /// leap seconds are introduced. + /// + /// [GB/T 33661-2017]: https://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=E107EA4DE9725EDF819F33C60A44B296 + pub fn gb_t_33661_2017(related_iso: i32) -> EastAsianTraditionalYearData { + EastAsianTraditionalYearData::calendrical_calculations::( + related_iso, + ) + } +} + +impl crate::cal::scaffold::UnstableSealed for China {} +impl Rules for China { + fn year_data(&self, related_iso: i32) -> EastAsianTraditionalYearData { + if let Some(year) = EastAsianTraditionalYearData::lookup( + related_iso, + china_data::STARTING_YEAR, + china_data::DATA, + ) { + year + } else if related_iso > china_data::STARTING_YEAR { + EastAsianTraditionalYearData::simple(simple::UTC_PLUS_8, related_iso) + } else if let Some(year) = EastAsianTraditionalYearData::lookup( + related_iso, + qing_data::STARTING_YEAR, + qing_data::DATA, + ) { + year + } else { + EastAsianTraditionalYearData::simple(simple::BEIJING_UTC_OFFSET, related_iso) + } + } + + fn ecma_reference_year( + &self, + month_code: (u8, bool), + day: u8, + ) -> Result { + let (number, is_leap) = month_code; + // Computed by `generate_reference_years` + let extended_year = match (number, is_leap, day > 29) { + (1, false, false) => 1972, + (1, false, true) => 1970, + (1, true, false) => 1898, + (1, true, true) => 1898, + (2, false, false) => 1972, + (2, false, true) => 1972, + (2, true, false) => 1947, + (2, true, true) => 1830, + (3, false, false) => 1972, + (3, false, true) => 1966, + (3, true, false) => 1966, + (3, true, true) => 1955, + (4, false, false) => 1972, + (4, false, true) => 1970, + (4, true, false) => 1963, + (4, true, true) => 1944, + (5, false, false) => 1972, + (5, false, true) => 1972, + (5, true, false) => 1971, + (5, true, true) => 1952, + (6, false, false) => 1972, + (6, false, true) => 1971, + (6, true, false) => 1960, + (6, true, true) => 1941, + (7, false, false) => 1972, + (7, false, true) => 1972, + (7, true, false) => 1968, + (7, true, true) => 1938, + (8, false, false) => 1972, + (8, false, true) => 1971, + (8, true, false) => 1957, + (8, true, true) => 1691, + (9, false, false) => 1972, + (9, false, true) => 1972, + (9, true, false) => 2014, + (9, true, true) => 1843, + (10, false, false) => 1972, + (10, false, true) => 1972, + (10, true, false) => 1984, + (10, true, true) => 1737, + // Dec 31, 1972 is 1972-M11-26, dates after that + // are in the next year + (11, false, false) if day > 26 => 1971, + (11, false, false) => 1972, + (11, false, true) => 1969, + (11, true, false) => 2033, + (11, true, true) => 1889, + (12, false, false) => 1971, + (12, false, true) => 1971, + (12, true, false) => 1878, + (12, true, true) => 1783, + _ => return Err(EcmaReferenceYearError::MonthCodeNotInCalendar), + }; + Ok(extended_year) + } + + fn calendar_algorithm(&self) -> Option { + Some(CalendarAlgorithm::Chinese) + } + + fn debug_name(&self) -> &'static str { + "Chinese" + } +} + +/// The [Korean](https://en.wikipedia.org/wiki/Korean_calendar) variant of the [`EastAsianTraditional`] calendar. +/// +/// This type agrees with the official data published by the +/// [Korea Astronomy and Space Science Institute for the years 1900-2050]. +/// +/// For years since 1912, this uses [adapted GB/T 33661-2017] rules, +/// using Korea time instead of Beijing Time. +/// As accurate computation is computationally expensive, years until +/// 2100 are precomputed, and after that this type regresses to a simplified +/// calculation. If accuracy beyond 2100 is required, clients +/// can implement their own [`Rules`] type containing more precomputed data. +/// We note that the calendar is inherently uncertain for some future dates. +/// +/// Before 1912 [different rules](https://ytliu.epizy.com/Shixian/Shixian_summary.html) +/// were used (those of Qing-dynasty China). This type produces correct data +/// for the years 1900-1912, and falls back to a simplified calculation +/// before 1900. If accuracy is required before 1900, clients can implement +/// their own [`Rules`] type using data such as from the excellent compilation +/// by [Yuk Tung Liu]. +/// +/// The precise behavior of this calendar may change in the future if: +/// - New ground truth is established by published government sources +/// - We decide to tweak the simplified calculation +/// - We decide to expand or reduce the range where we are correctly handling past dates. +/// +/// [Korea Astronomy and Space Science Institute for the years 1900-2050]: https://astro.kasi.re.kr/life/pageView/5 +/// [adapted GB/T 33661-2017]: Korea::adapted_gb_t_33661_2017 +/// [GB/T 33661-2017]: China::gb_t_33661_2017 +/// [Yuk Tung Liu]: https://ytliu0.github.io/ChineseCalendar/table.html +/// +/// ```rust +/// use icu::calendar::cal::{ChineseTraditional, KoreanTraditional}; +/// use icu::calendar::Date; +/// +/// let iso_a = Date::try_new_iso(2012, 4, 23).unwrap(); +/// let korean_a = iso_a.to_calendar(KoreanTraditional::new()); +/// let chinese_a = iso_a.to_calendar(ChineseTraditional::new()); +/// +/// assert_eq!(korean_a.month().standard_code.0, "M03L"); +/// assert_eq!(chinese_a.month().standard_code.0, "M04"); +/// +/// let iso_b = Date::try_new_iso(2012, 5, 23).unwrap(); +/// let korean_b = iso_b.to_calendar(KoreanTraditional::new()); +/// let chinese_b = iso_b.to_calendar(ChineseTraditional::new()); +/// +/// assert_eq!(korean_b.month().standard_code.0, "M04"); +/// assert_eq!(chinese_b.month().standard_code.0, "M04L"); +/// ``` +pub type KoreanTraditional = EastAsianTraditional; + +/// The [`Rules`] used in Korea. +/// +/// See [`KoreanTraditional`] for more information. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] +#[non_exhaustive] +pub struct Korea; + +impl Korea { + /// A version of [`China::gb_t_33661_2017`] adapted for Korean time. + /// + /// See [`China::gb_t_33661_2017`] for caveats. + pub fn adapted_gb_t_33661_2017(related_iso: i32) -> EastAsianTraditionalYearData { + EastAsianTraditionalYearData::calendrical_calculations::(related_iso) + } +} + +impl KoreanTraditional { + /// Creates a new [`KoreanTraditional`] calendar. + pub const fn new() -> Self { + Self(Korea) + } + + /// Use [`Self::new`]. + #[cfg(feature = "serde")] + #[doc = icu_provider::gen_buffer_unstable_docs!(BUFFER,Self::new)] + #[deprecated(since = "2.1.0", note = "use `Self::new()")] + pub fn try_new_with_buffer_provider( + _provider: &(impl icu_provider::buf::BufferProvider + ?Sized), + ) -> Result { + Ok(Self::new()) + } + + /// Use [`Self::new`]. + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new)] + #[deprecated(since = "2.1.0", note = "use `Self::new()")] + pub fn try_new_unstable(_provider: &D) -> Result { + Ok(Self::new()) + } + + /// Use [`Self::new`]. + #[deprecated(since = "2.1.0", note = "use `Self::new()")] + pub fn new_always_calculating() -> Self { + Self::new() + } +} + +impl crate::cal::scaffold::UnstableSealed for Korea {} +impl Rules for Korea { + fn year_data(&self, related_iso: i32) -> EastAsianTraditionalYearData { + if let Some(year) = EastAsianTraditionalYearData::lookup( + related_iso, + korea_data::STARTING_YEAR, + korea_data::DATA, + ) { + year + } else if related_iso > korea_data::STARTING_YEAR { + EastAsianTraditionalYearData::simple(simple::UTC_PLUS_9, related_iso) + } else if let Some(year) = EastAsianTraditionalYearData::lookup( + related_iso, + qing_data::STARTING_YEAR, + qing_data::DATA, + ) { + // Korea used Qing-dynasty rules before 1912 + // https://github.com/unicode-org/icu4x/issues/6455#issuecomment-3282175550 + year + } else { + EastAsianTraditionalYearData::simple(simple::BEIJING_UTC_OFFSET, related_iso) + } + } + + fn ecma_reference_year( + &self, + month_code: (u8, bool), + day: u8, + ) -> Result { + let (number, is_leap) = month_code; + // Computed by `generate_reference_years` + let extended_year = match (number, is_leap, day > 29) { + (1, false, false) => 1972, + (1, false, true) => 1970, + (1, true, false) => 1898, + (1, true, true) => 1898, + (2, false, false) => 1972, + (2, false, true) => 1972, + (2, true, false) => 1947, + (2, true, true) => 1830, + (3, false, false) => 1972, + (3, false, true) => 1968, + (3, true, false) => 1966, + (3, true, true) => 1955, + (4, false, false) => 1972, + (4, false, true) => 1970, + (4, true, false) => 1963, + (4, true, true) => 1944, + (5, false, false) => 1972, + (5, false, true) => 1972, + (5, true, false) => 1971, + (5, true, true) => 1952, + (6, false, false) => 1972, + (6, false, true) => 1971, + (6, true, false) => 1960, + (6, true, true) => 1941, + (7, false, false) => 1972, + (7, false, true) => 1972, + (7, true, false) => 1968, + (7, true, true) => 1938, + (8, false, false) => 1972, + (8, false, true) => 1971, + (8, true, false) => 1957, + (8, true, true) => 1691, + (9, false, false) => 1972, + (9, false, true) => 1972, + (9, true, false) => 2014, + (9, true, true) => 1843, + (10, false, false) => 1972, + (10, false, true) => 1972, + (10, true, false) => 1984, + (10, true, true) => 1737, + // Dec 31, 1972 is 1972-M11-26, dates after that + // are in the next year + (11, false, false) if day > 26 => 1971, + (11, false, false) => 1972, + (11, false, true) => 1969, + (11, true, false) => 2033, + (11, true, true) => 1889, + (12, false, false) => 1971, + (12, false, true) => 1971, + (12, true, false) => 1878, + (12, true, true) => 1783, + _ => return Err(EcmaReferenceYearError::MonthCodeNotInCalendar), + }; + Ok(extended_year) + } + + fn calendar_algorithm(&self) -> Option { + Some(CalendarAlgorithm::Dangi) + } + fn debug_name(&self) -> &'static str { + "Korean" + } +} + +impl> Date
{ + /// This method uses an ordinal month, which is probably not what you want. + /// + /// Use [`Date::try_new_from_codes`] + #[deprecated(since = "2.1.0", note = "use `Date::try_new_from_codes`")] + pub fn try_new_dangi_with_calendar( + related_iso_year: i32, + ordinal_month: u8, + day: u8, + calendar: A, + ) -> Result, DateError> { + ArithmeticDate::try_from_ymd( + calendar.as_calendar().0.year_data(related_iso_year), + ordinal_month, + day, + ) + .map(ChineseDateInner) + .map(|inner| Date::from_raw(inner, calendar)) + .map_err(Into::into) + } +} + +/// The inner date type used for representing [`Date`]s of [`EastAsianTraditional`]. +#[derive(Debug, Clone)] +pub struct ChineseDateInner(ArithmeticDate>); + +impl Copy for ChineseDateInner {} +impl PartialEq for ChineseDateInner { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} +impl Eq for ChineseDateInner {} +impl PartialOrd for ChineseDateInner { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} +impl Ord for ChineseDateInner { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.0.cmp(&other.0) + } +} + +impl ChineseTraditional { + /// Creates a new [`ChineseTraditional`] calendar. + pub const fn new() -> Self { + EastAsianTraditional(China) + } + + #[cfg(feature = "serde")] + #[doc = icu_provider::gen_buffer_unstable_docs!(BUFFER,Self::new)] + #[deprecated(since = "2.1.0", note = "use `Self::new()")] + pub fn try_new_with_buffer_provider( + _provider: &(impl icu_provider::buf::BufferProvider + ?Sized), + ) -> Result { + Ok(Self::new()) + } + + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new)] + #[deprecated(since = "2.1.0", note = "use `Self::new()")] + pub fn try_new_unstable(_provider: &D) -> Result { + Ok(Self::new()) + } + + /// Use [`Self::new()`]. + #[deprecated(since = "2.1.0", note = "use `Self::new()")] + pub fn new_always_calculating() -> Self { + Self::new() + } +} + +impl DateFieldsResolver for EastAsianTraditional { + type YearInfo = EastAsianTraditionalYearData; + + fn days_in_provided_month(year: EastAsianTraditionalYearData, month: u8) -> u8 { + 29 + year.packed.month_has_30_days(month) as u8 + } + + /// 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: EastAsianTraditionalYearData) -> u8 { + 12 + year.packed.leap_month().is_some() as u8 + } + + #[inline] + fn year_info_from_era( + &self, + _era: &[u8], + _era_year: i32, + ) -> Result { + // This calendar has no era codes + Err(UnknownEraError) + } + + #[inline] + fn year_info_from_extended(&self, extended_year: i32) -> Self::YearInfo { + self.0.year_data(extended_year) + } + + #[inline] + fn reference_year_from_month_day( + &self, + month_code: types::ValidMonthCode, + day: u8, + ) -> Result { + self.0 + .ecma_reference_year(month_code.to_tuple(), day) + .map(|y| self.0.year_data(y)) + } + + fn ordinal_month_from_code( + &self, + year: &Self::YearInfo, + month_code: types::ValidMonthCode, + options: DateFromFieldsOptions, + ) -> Result { + // 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 = year.packed.leap_month().unwrap_or(14); + + // leap_month identifies the ordinal month number of the leap month, + // so its month number will be leap_month - 1 + if month_code == ValidMonthCode::new_unchecked(leap_month - 1, true) { + return Ok(leap_month); + } + + let (number @ 1..13, leap) = month_code.to_tuple() else { + return Err(MonthCodeError::NotInCalendar); + }; + + if leap && options.overflow != Some(Overflow::Constrain) { + // wrong leap month and not constraining + return Err(MonthCodeError::NotInYear); + } + + // add one if there was a leap month before + Ok(number + (number >= leap_month) as u8) + } + + fn month_code_from_ordinal(&self, year: &Self::YearInfo, ordinal_month: u8) -> ValidMonthCode { + // 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 = year.packed.leap_month().unwrap_or(14); + ValidMonthCode::new_unchecked( + // subtract one if there was a leap month before + ordinal_month - (ordinal_month >= leap_month) as u8, + ordinal_month == leap_month, + ) + } +} + +impl crate::cal::scaffold::UnstableSealed for EastAsianTraditional {} +impl Calendar for EastAsianTraditional { + type DateInner = ChineseDateInner; + type Year = types::CyclicYear; + type DifferenceError = core::convert::Infallible; + + fn from_codes( + &self, + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + ) -> Result { + ArithmeticDate::from_codes(era, year, month_code, day, self).map(ChineseDateInner) + } + + #[cfg(feature = "unstable")] + fn from_fields( + &self, + fields: types::DateFields, + options: DateFromFieldsOptions, + ) -> Result { + ArithmeticDate::from_fields(fields, options, self).map(ChineseDateInner) + } + + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + let iso = Iso.from_rata_die(rd); + let year = { + let candidate = self.0.year_data(iso.0.year); + + if rd >= candidate.new_year() { + candidate + } else { + self.0.year_data(iso.0.year - 1) + } + }; + + // Clamp the RD to our year + let rd = rd.clamp( + year.new_year(), + year.new_year() + year.packed.days_in_year() as i64, + ); + + let day_of_year = (rd - year.new_year()) as u16; + + // 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 mut last_day_of_month = year.packed.last_day_of_month(month); + let mut last_day_of_prev_month = year.packed.last_day_of_month(month - 1); + + while day_of_year >= last_day_of_month { + month += 1; + last_day_of_prev_month = last_day_of_month; + last_day_of_month = year.packed.last_day_of_month(month); + } + + let day = (day_of_year + 1 - last_day_of_prev_month) as u8; + + ChineseDateInner(ArithmeticDate::new_unchecked(year, month, day)) + } + + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + date.0.year.new_year() + + date.0.year.packed.last_day_of_month(date.0.month - 1) as i64 + + (date.0.day - 1) as i64 + } + + fn has_cheap_iso_conversion(&self) -> bool { + false + } + + // 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.year.packed.days_in_year() + } + + fn days_in_month(&self, date: &Self::DateInner) -> u8 { + Self::days_in_provided_month(date.0.year, date.0.month) + } + + #[cfg(feature = "unstable")] + fn add( + &self, + date: &Self::DateInner, + duration: types::DateDuration, + options: DateAddOptions, + ) -> Result { + date.0.added(duration, self, options).map(ChineseDateInner) + } + + #[cfg(feature = "unstable")] + fn until( + &self, + date1: &Self::DateInner, + date2: &Self::DateInner, + options: DateDifferenceOptions, + ) -> Result { + Ok(date1.0.until(&date2.0, self, options)) + } + + /// Obtain a name for the calendar for debug printing + fn debug_name(&self) -> &'static str { + self.0.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 is_in_leap_year(&self, date: &Self::DateInner) -> bool { + date.0.year.packed.leap_month().is_some() + } + + /// 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 { + types::MonthInfo::for_code_and_ordinal( + self.month_code_from_ordinal(&date.0.year, date.0.month), + date.0.month, + ) + } + + /// The calendar-specific day-of-month represented by `date` + fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { + types::DayOfMonth(date.0.day) + } + + /// Information of the day of the year + fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { + types::DayOfYear(date.0.year.packed.last_day_of_month(date.0.month - 1) + date.0.day as u16) + } + + fn calendar_algorithm(&self) -> Option { + self.0.calendar_algorithm() + } + + fn months_in_year(&self, date: &Self::DateInner) -> u8 { + Self::months_in_provided_year(date.0.year) + } +} + +impl> Date { + /// This method uses an ordinal month, which is probably not what you want. + /// + /// Use [`Date::try_new_from_codes`] + #[deprecated(since = "2.1.0", note = "use `Date::try_new_from_codes`")] + pub fn try_new_chinese_with_calendar( + related_iso_year: i32, + ordinal_month: u8, + day: u8, + calendar: A, + ) -> Result, DateError> { + ArithmeticDate::try_from_ymd( + calendar.as_calendar().0.year_data(related_iso_year), + ordinal_month, + day, + ) + .map(ChineseDateInner) + .map(|inner| Date::from_raw(inner, calendar)) + .map_err(Into::into) + } +} + +/// Information about a [`EastAsianTraditional`] year. +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +// TODO(#3933): potentially make this smaller +pub struct EastAsianTraditionalYearData { + /// 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: PackedEastAsianTraditionalYearData, + related_iso: i32, +} + +impl ToExtendedYear for EastAsianTraditionalYearData { + fn to_extended_year(&self) -> i32 { + self.related_iso + } +} + +impl EastAsianTraditionalYearData { + /// Creates [`EastAsianTraditionalYearData`] from the given parts. + /// + /// `start_day` is the date for the first day of the year, see [`Date::to_rata_die`] + /// to obtain a [`RataDie`] from a [`Date`] in an arbitrary calendar. + /// + /// `leap_month` is the ordinal number of the leap month, for example if a year + /// has months 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, the `leap_month` + /// would be `Some(4)`. + /// + /// `month_lengths[n - 1]` is true if the nth month has 30 days, and false otherwise. + /// The leap month does not necessarily have the same number of days as the previous + /// month, which is why this has length 13. In non-leap years, the last value is ignored. + pub fn new( + related_iso: i32, + start_day: RataDie, + month_lengths: [bool; 13], + leap_month: Option, + ) -> Self { + Self { + packed: PackedEastAsianTraditionalYearData::new( + related_iso, + month_lengths, + leap_month, + start_day, + ), + related_iso, + } + } + + fn lookup( + related_iso: i32, + starting_year: i32, + data: &[PackedEastAsianTraditionalYearData], + ) -> Option { + Some(related_iso) + .and_then(|e| usize::try_from(e.checked_sub(starting_year)?).ok()) + .and_then(|i| data.get(i)) + .map(|&packed| Self { + related_iso, + packed, + }) + } + + fn calendrical_calculations( + related_iso: i32, + ) -> EastAsianTraditionalYearData { + let mid_year = calendrical_calculations::gregorian::fixed_from_gregorian(related_iso, 7, 1); + let year_bounds = YearBounds::compute::(mid_year); + + 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); + + EastAsianTraditionalYearData { + packed: PackedEastAsianTraditionalYearData::new( + related_iso, + month_lengths, + leap_month, + new_year, + ), + related_iso, + } + } + + /// Get the new year R.D. + fn new_year(self) -> RataDie { + self.packed.new_year(self.related_iso) + } +} + +/// 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 19 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)] +struct PackedEastAsianTraditionalYearData(u8, u8, u8); + +impl PackedEastAsianTraditionalYearData { + /// The first day on which Chinese New Year may occur + /// + /// According to Reingold & Dershowitz, ch 19.6, Chinese New Year occurs on Jan 21 - Feb 21 inclusive. + /// + /// Our simple approximation sometimes returns Feb 22. + /// + /// 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 fn earliest_ny(related_iso: i32) -> RataDie { + calendrical_calculations::gregorian::fixed_from_gregorian(related_iso, 1, 19) + } + + /// It clamps some values to avoid debug assertions on calendrical invariants. + const fn new( + related_iso: i32, + month_lengths: [bool; 13], + leap_month: Option, + new_year: RataDie, + ) -> Self { + // These assertions are API correctness assertions and even bad calendar arithmetic + // should not produce this + if let Some(l) = leap_month { + debug_assert!(2 <= l && l <= 13, "Leap month indices must be 2 <= i <= 13"); + } else { + debug_assert!( + !month_lengths[12], + "Last month length should not be set for non-leap years" + ) + } + + let ny_offset = new_year.since(Self::earliest_ny(related_iso)); + + #[cfg(debug_assertions)] + let out_of_valid_astronomical_range = WELL_BEHAVED_ASTRONOMICAL_RANGE.start.to_i64_date() + > new_year.to_i64_date() + || new_year.to_i64_date() > WELL_BEHAVED_ASTRONOMICAL_RANGE.end.to_i64_date(); + + // Assert the offset is in range, but allow it to be out of + // range when out_of_valid_astronomical_range=true + #[cfg(debug_assertions)] + debug_assert!( + ny_offset >= 0 || out_of_valid_astronomical_range, + "Year offset too small to store" + ); + // The maximum new-year's offset we have found is 34 + #[cfg(debug_assertions)] + debug_assert!( + ny_offset < 35 || out_of_valid_astronomical_range, + "Year offset too big to store" + ); + + // Just clamp to something we can represent when things get of range. + // + // This will typically happen when out_of_valid_astronomical_range + // is true. + // + // We can store up to 6 bytes for ny_offset, even if our + // maximum asserted value is otherwise 33. + let ny_offset = ny_offset & (0x40 - 1); + + let mut all = 0u32; // last byte unused + + let mut month = 0; + while month < month_lengths.len() { + #[allow(clippy::indexing_slicing)] // const iteration + if month_lengths[month] { + all |= 1 << month as u32; + } + month += 1; + } + let leap_month_idx = if let Some(leap_month_idx) = leap_month { + leap_month_idx + } else { + 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]) + } + + fn new_year(self, related_iso: i32) -> RataDie { + Self::earliest_ny(related_iso) + (self.2 as i64 >> 1) + } + + 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) + 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 + } + + // month is 1-indexed, but 0 is a valid input, producing 0 + 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 + } + + fn days_in_year(self) -> u16 { + self.last_day_of_month(12 + self.leap_month().is_some() as u8) + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::options::{DateFromFieldsOptions, Overflow}; + use crate::types::DateFields; + use calendrical_calculations::{gregorian::fixed_from_gregorian, rata_die::RataDie}; + use std::collections::BTreeMap; + + #[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: -2639, + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: -963838, + expected_year: -2638, + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: -963129, + expected_year: -2637, + expected_month: 13, + expected_day: 1, + }, + TestCase { + rd: -963100, + expected_year: -2637, + expected_month: 13, + expected_day: 30, + }, + TestCase { + rd: -963099, + expected_year: -2636, + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: 738700, + expected_year: 2023, + expected_month: 6, + expected_day: 12, + }, + TestCase { + rd: fixed_from_gregorian(2319, 2, 20).to_i64_date(), + expected_year: 2318, + expected_month: 13, + expected_day: 30, + }, + TestCase { + rd: fixed_from_gregorian(2319, 2, 21).to_i64_date(), + expected_year: 2319, + expected_month: 1, + expected_day: 1, + }, + TestCase { + rd: 738718, + expected_year: 2023, + expected_month: 6, + expected_day: 30, + }, + TestCase { + rd: 738747, + expected_year: 2023, + expected_month: 7, + expected_day: 29, + }, + TestCase { + rd: 738748, + expected_year: 2023, + expected_month: 8, + expected_day: 1, + }, + TestCase { + rd: 738865, + expected_year: 2023, + expected_month: 11, + expected_day: 29, + }, + TestCase { + rd: 738895, + expected_year: 2023, + expected_month: 12, + expected_day: 29, + }, + TestCase { + rd: 738925, + expected_year: 2023, + expected_month: 13, + expected_day: 30, + }, + TestCase { + rd: 0, + expected_year: 0, + expected_month: 11, + expected_day: 19, + }, + TestCase { + rd: -1, + expected_year: 0, + expected_month: 11, + expected_day: 18, + }, + TestCase { + rd: -365, + expected_year: -1, + expected_month: 12, + expected_day: 9, + }, + TestCase { + rd: 100, + expected_year: 1, + expected_month: 3, + expected_day: 1, + }, + ]; + + for case in cases { + let rata_die = RataDie::new(case.rd); + + let chinese = Date::from_rata_die(rata_die, ChineseTraditional::new()); + assert_eq!( + case.expected_year, + chinese.extended_year(), + "Chinese from RD failed, case: {case:?}" + ); + assert_eq!( + case.expected_month, + chinese.month().ordinal, + "Chinese from RD failed, case: {case:?}" + ); + assert_eq!( + case.expected_day, + chinese.day_of_month().0, + "Chinese from RD failed, case: {case:?}" + ); + } + } + + #[test] + fn test_rd_from_chinese() { + #[derive(Debug)] + struct TestCase { + year: i32, + ordinal_month: u8, + month_code: types::MonthCode, + day: u8, + expected: i64, + } + + let cases = [ + TestCase { + year: 2023, + ordinal_month: 6, + month_code: types::MonthCode::new_normal(5).unwrap(), + day: 6, + // June 23 2023 + expected: 738694, + }, + TestCase { + year: -2636, + ordinal_month: 1, + month_code: types::MonthCode::new_normal(1).unwrap(), + day: 1, + expected: -963099, + }, + ]; + + for case in cases { + let date = Date::try_new_from_codes( + None, + case.year, + case.month_code, + case.day, + ChineseTraditional::new(), + ) + .unwrap(); + #[allow(deprecated)] // should still test + { + assert_eq!( + Date::try_new_chinese_with_calendar( + case.year, + case.ordinal_month, + case.day, + ChineseTraditional::new() + ), + Ok(date) + ); + } + let rd = date.to_rata_die().to_i64_date(); + let expected = case.expected; + assert_eq!(rd, expected, "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; + while rd < max_rd && iters < max_iters { + let rata_die = RataDie::new(rd); + + let chinese = Date::from_rata_die(rata_die, ChineseTraditional::new()); + let result = chinese.to_rata_die(); + assert_eq!(result, rata_die, "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(); + + let chinese = iso.to_calendar(ChineseTraditional::new()); + + 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: 29, + }, + ]; + + for case in cases { + let iso = Date::try_new_iso(case.iso_year, case.iso_month, case.iso_day).unwrap(); + + let chinese = iso.to_calendar(ChineseTraditional::new()); + assert_eq!( + case.expected_year, + chinese.cyclic_year().related_iso, + "ISO to Chinese failed for case: {case:?}" + ); + assert_eq!( + case.expected_month, + chinese.month().ordinal, + "ISO to Chinese failed for case: {case:?}" + ); + assert_eq!( + case.expected_day, + chinese.day_of_month().0, + "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), + ]; + + for case in expected { + let year = case.0; + let expected_month = case.1; + let iso = Date::try_new_iso(year, 6, 1).unwrap(); + + let chinese_date = iso.to_calendar(ChineseTraditional::new()); + assert!( + chinese_date.is_in_leap_year(), + "{year} should be a leap year" + ); + let new_year = chinese_date.inner.0.year.new_year(); + assert_eq!( + expected_month, + chinese_based::get_leap_month_from_new_year::(new_year), + "{year} have leap month {expected_month}" + ); + } + } + + #[test] + fn test_month_days() { + let year = ChineseTraditional::new().0.year_data(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 = EastAsianTraditional::::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", + }, + ]; + + for case in cases { + let iso = Date::try_new_iso(case.year, case.month, case.day).unwrap(); + let chinese = iso.to_calendar(ChineseTraditional::new()); + let result_code = chinese.month().standard_code.0; + let expected_code = case.expected_code.to_string(); + assert_eq!( + expected_code, result_code, + "Month codes did not match for test case: {case:?}" + ); + } + } + + #[test] + fn test_month_code_to_ordinal() { + let cal = ChineseTraditional::new(); + let reject = DateFromFieldsOptions { + overflow: Some(Overflow::Reject), + ..Default::default() + }; + let year = cal.year_info_from_extended(2023); + let leap_month = year.packed.leap_month().unwrap(); + for ordinal in 1..=13 { + let code = ValidMonthCode::new_unchecked( + ordinal - (ordinal >= leap_month) as u8, + ordinal == leap_month, + ); + assert_eq!( + cal.ordinal_month_from_code(&year, code, reject), + Ok(ordinal), + "Code to ordinal failed for year: {}, code: {ordinal}", + year.related_iso + ); + } + } + + #[test] + fn check_invalid_month_code_to_ordinal() { + let cal = ChineseTraditional::new(); + let reject = DateFromFieldsOptions { + overflow: Some(Overflow::Reject), + ..Default::default() + }; + for year in [4659, 4660] { + let year = cal.year_info_from_extended(year); + for (code, error) in [ + ( + ValidMonthCode::new_unchecked(4, true), + MonthCodeError::NotInYear, + ), + ( + ValidMonthCode::new_unchecked(13, false), + MonthCodeError::NotInCalendar, + ), + ] { + assert_eq!( + cal.ordinal_month_from_code(&year, code, reject), + Err(error), + "Invalid month code failed for year: {}, code: {code:?}", + year.related_iso, + ); + } + } + } + + #[test] + fn test_iso_chinese_roundtrip() { + 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(); + let chinese = iso.to_calendar(ChineseTraditional::new()); + let result = chinese.to_calendar(Iso); + assert_eq!(iso, result, "ISO to Chinese roundtrip failed!\nIso: {iso:?}\nChinese: {chinese:?}\nResult: {result:?}"); + } + } + + fn check_cyclic_and_rel_iso(year: i32) { + let iso = Date::try_new_iso(year, 6, 6).unwrap(); + let chinese = iso.to_calendar(ChineseTraditional::new()); + let korean = iso.to_calendar(KoreanTraditional::new()); + let chinese_year = chinese.cyclic_year(); + let korean_year = korean.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, "Korean 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_korean_roundtrip() { + let mut rd = -1963020; + let max_rd = 1963020; + let mut iters = 0; + let max_iters = 560; + while rd < max_rd && iters < max_iters { + let rata_die = RataDie::new(rd); + let iso = Date::from_rata_die(rata_die, Iso); + let korean = iso.to_calendar(KoreanTraditional::new()); + let result = korean.to_calendar(Iso); + assert_eq!( + iso, result, + "Failed roundtrip ISO -> Korean -> ISO for RD: {rd}" + ); + + rd += 7043; + iters += 1; + } + } + + #[test] + fn test_from_fields_constrain() { + let fields = DateFields { + day: Some(31), + month_code: Some(b"M01"), + extended_year: Some(1972), + ..Default::default() + }; + let options = DateFromFieldsOptions { + overflow: Some(Overflow::Constrain), + ..Default::default() + }; + + let cal = ChineseTraditional::new(); + let date = Date::try_from_fields(fields, options, cal).unwrap(); + assert_eq!( + date.day_of_month().0, + 29, + "Day was successfully constrained" + ); + + // 2022 did not have M01L, the month should be constrained back down + let fields = DateFields { + day: Some(1), + month_code: Some(b"M01L"), + extended_year: Some(2022), + ..Default::default() + }; + let date = Date::try_from_fields(fields, options, cal).unwrap(); + assert_eq!( + date.month().standard_code.0, + "M01", + "Month was successfully constrained" + ); + } + + #[test] + fn test_from_fields_regress_7049() { + // We want to make sure that overly large years do not panic + // (we just reject them in Date::try_from_fields) + let fields = DateFields { + extended_year: Some(889192448), + ordinal_month: Some(1), + day: Some(1), + ..Default::default() + }; + let options = DateFromFieldsOptions { + overflow: Some(Overflow::Reject), + ..Default::default() + }; + + let cal = ChineseTraditional::new(); + assert!(matches!( + Date::try_from_fields(fields, options, cal).unwrap_err(), + DateFromFieldsError::Range { .. } + )); + } + + #[test] + #[ignore] // slow, network + fn test_against_hong_kong_observatory_data() { + use crate::{cal::Gregorian, Date}; + + let mut related_iso = 1900; + let mut lunar_month = ValidMonthCode::new_unchecked(11, false); + + for year in 1901..=2100 { + println!("Validating year {year}..."); + + for line in ureq::get(&format!( + "https://www.hko.gov.hk/en/gts/time/calendar/text/files/T{year}e.txt" + )) + .call() + .unwrap() + .body_mut() + .read_to_string() + .unwrap() + .split('\n') + { + if !line.starts_with(['1', '2']) { + // comments or blank lines + continue; + } + + let mut fields = line.split_ascii_whitespace(); + + let mut gregorian = fields.next().unwrap().split('/'); + let gregorian = Date::try_new_gregorian( + gregorian.next().unwrap().parse().unwrap(), + gregorian.next().unwrap().parse().unwrap(), + gregorian.next().unwrap().parse().unwrap(), + ) + .unwrap(); + + let day_or_lunar_month = fields.next().unwrap(); + + let lunar_day = if fields.next().is_some_and(|s| s.contains("Lunar")) { + let new_lunar_month = day_or_lunar_month + // 1st, 2nd, 3rd, nth + .split_once(['s', 'n', 'r', 't']) + .unwrap() + .0 + .parse() + .unwrap(); + lunar_month = ValidMonthCode::new_unchecked( + new_lunar_month, + new_lunar_month == lunar_month.number(), + ); + if new_lunar_month == 1 { + related_iso += 1; + } + 1 + } else { + day_or_lunar_month.parse().unwrap() + }; + + let chinese = Date::try_new_from_codes( + None, + related_iso, + lunar_month.to_month_code(), + lunar_day, + ChineseTraditional::new(), + ) + .unwrap(); + + assert_eq!( + gregorian, + chinese.to_calendar(Gregorian), + "{line}, {chinese:?}" + ); + } + } + } + + #[test] + #[ignore] // network + fn test_against_kasi_data() { + use crate::{cal::Gregorian, types::MonthCode, Date}; + + // TODO: query KASI directly + let uri = "https://gist.githubusercontent.com/Manishearth/d8c94a7df22a9eacefc4472a5805322e/raw/e1ea3b0aa52428686bb3a9cd0f262878515e16c1/resolved.json"; + + #[derive(serde::Deserialize)] + struct Golden(BTreeMap>); + + #[derive(serde::Deserialize)] + struct MonthData { + start_date: String, + } + + let json = ureq::get(uri) + .call() + .unwrap() + .body_mut() + .read_to_string() + .unwrap(); + + let golden = serde_json::from_str::(&json).unwrap(); + + for (&year, months) in &golden.0 { + if year == 1899 || year == 2050 { + continue; + } + for (&month, month_data) in months { + let mut gregorian = month_data.start_date.split('-'); + let gregorian = Date::try_new_gregorian( + gregorian.next().unwrap().parse().unwrap(), + gregorian.next().unwrap().parse().unwrap(), + gregorian.next().unwrap().parse().unwrap(), + ) + .unwrap(); + + assert_eq!( + Date::try_new_from_codes(None, year, month, 1, KoreanTraditional::new()) + .unwrap() + .to_calendar(Gregorian), + gregorian + ); + } + } + } + + #[test] + #[ignore] + fn generate_reference_years() { + generate_reference_years_for(ChineseTraditional::new()); + generate_reference_years_for(KoreanTraditional::new()); + fn generate_reference_years_for(calendar: EastAsianTraditional) { + use crate::Date; + + println!("Reference years for {calendar:?}:"); + let reference_year_end = Date::from_rata_die( + crate::cal::abstract_gregorian::LAST_DAY_OF_REFERENCE_YEAR, + calendar, + ); + let year_1900_start = Date::try_new_gregorian(1900, 1, 1) + .unwrap() + .to_calendar(calendar); + let year_2035_end = Date::try_new_gregorian(2035, 12, 31) + .unwrap() + .to_calendar(calendar); + for month in 1..=12 { + for leap in [false, true] { + 'outer: for long in [false, true] { + for (start_year, start_month, end_year, end_month, by) in [ + ( + reference_year_end.extended_year(), + reference_year_end.month().month_number(), + year_1900_start.extended_year(), + year_1900_start.month().month_number(), + -1, + ), + ( + reference_year_end.extended_year(), + reference_year_end.month().month_number(), + year_2035_end.extended_year(), + year_2035_end.month().month_number(), + 1, + ), + ( + year_1900_start.extended_year(), + year_1900_start.month().month_number(), + -10000, + 1, + -1, + ), + ] { + let mut year = start_year; + while year * by < end_year * by { + if year == start_year + && month as i32 * by <= start_month as i32 * by + || year == end_year + && month as i32 * by >= end_month as i32 * by + { + year += by; + continue; + } + let data = calendar.0.year_data(year); + let leap_month = data.packed.leap_month().unwrap_or(15); + let ordinal_month = if leap && month + 1 == leap_month { + month + 1 + } else { + month + (month + 1 > leap_month) as u8 + }; + if (!long || data.packed.month_has_30_days(ordinal_month)) + && (!leap || month + 1 == leap_month) + { + println!("({month}, {leap:?}, {long:?}) => {year},"); + continue 'outer; + } + year += by; + } + } + println!("({month}, {leap:?}, {long:?}) => todo!(),") + } + } + } + } + } + + #[test] + fn test_roundtrip_packed() { + fn packed_roundtrip_single( + month_lengths: [bool; 13], + leap_month_idx: Option, + ny_offset: i64, + ) { + let ny = + calendrical_calculations::gregorian::fixed_from_gregorian(1000, 1, 1) + ny_offset; + let packed = + PackedEastAsianTraditionalYearData::new(1000, month_lengths, leap_month_idx, ny); + + assert_eq!( + ny, + packed.new_year(1000), + "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}" + ); + assert_eq!( + month_lengths, + core::array::from_fn(|i| packed.month_has_30_days(i as u8 + 1)), + "Roundtrip with {month_lengths:?}, {leap_month_idx:?}, {ny_offset}" + ); + } + + 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, false, + ]; + const RANDOM1: [bool; 13] = [ + true, true, false, false, true, true, false, true, true, true, true, false, false, + ]; + 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/cal/east_asian_traditional/china_data.rs b/deps/crates/vendor/icu_calendar/src/cal/east_asian_traditional/china_data.rs new file mode 100644 index 00000000000000..034ca1cedeb535 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/east_asian_traditional/china_data.rs @@ -0,0 +1,225 @@ +// 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 obtained from [`calendrical_calculations`]. + +use super::PackedEastAsianTraditionalYearData; + +pub const STARTING_YEAR: i32 = 1912; + +#[rustfmt::skip] +#[allow(clippy::unwrap_used)] // const +pub const DATA: &[PackedEastAsianTraditionalYearData] = { + use calendrical_calculations::gregorian::fixed_from_gregorian as gregorian; + let l = true; // long + let s = false; // short + &[ + PackedEastAsianTraditionalYearData::new(1912, [l, s, l, s, s, l, s, s, l, l, s, l, s], None, gregorian(1912, 2, 18)), + PackedEastAsianTraditionalYearData::new(1913, [l, l, s, l, s, s, l, s, s, l, s, l, s], None, gregorian(1913, 2, 6)), + PackedEastAsianTraditionalYearData::new(1914, [l, l, s, l, s, l, s, l, s, s, l, s, l], Some(6), gregorian(1914, 1, 26)), + PackedEastAsianTraditionalYearData::new(1915, [l, s, l, l, s, l, s, l, s, l, s, s, s], None, gregorian(1915, 2, 14)), + PackedEastAsianTraditionalYearData::new(1916, [l, l, s, l, s, l, l, s, l, s, l, s, s], None, gregorian(1916, 2, 3)), + PackedEastAsianTraditionalYearData::new(1917, [l, s, s, l, s, l, l, s, l, l, s, l, s], Some(3), gregorian(1917, 1, 23)), + PackedEastAsianTraditionalYearData::new(1918, [l, s, s, l, s, l, s, l, l, s, l, l, s], None, gregorian(1918, 2, 11)), + PackedEastAsianTraditionalYearData::new(1919, [s, l, s, s, l, s, s, l, l, s, l, l, l], Some(8), gregorian(1919, 2, 1)), + PackedEastAsianTraditionalYearData::new(1920, [s, l, s, s, l, s, s, l, s, l, l, l, s], None, gregorian(1920, 2, 20)), + PackedEastAsianTraditionalYearData::new(1921, [l, s, l, s, s, l, s, s, l, s, l, l, s], None, gregorian(1921, 2, 8)), + PackedEastAsianTraditionalYearData::new(1922, [l, s, l, l, s, s, l, s, s, l, s, l, l], Some(6), gregorian(1922, 1, 28)), + PackedEastAsianTraditionalYearData::new(1923, [s, l, l, s, l, s, l, s, s, l, s, l, s], None, gregorian(1923, 2, 16)), + PackedEastAsianTraditionalYearData::new(1924, [s, l, l, s, l, l, s, l, s, l, s, s, s], None, gregorian(1924, 2, 5)), + PackedEastAsianTraditionalYearData::new(1925, [l, s, l, s, l, l, s, l, l, s, l, s, l], Some(5), gregorian(1925, 1, 24)), + PackedEastAsianTraditionalYearData::new(1926, [s, s, l, s, l, s, l, l, s, l, l, s, s], None, gregorian(1926, 2, 13)), + PackedEastAsianTraditionalYearData::new(1927, [l, s, s, l, s, l, s, l, s, l, l, l, s], None, gregorian(1927, 2, 2)), + PackedEastAsianTraditionalYearData::new(1928, [s, l, s, s, l, s, s, l, s, l, l, l, l], Some(3), gregorian(1928, 1, 23)), + PackedEastAsianTraditionalYearData::new(1929, [s, l, s, s, l, s, s, l, s, l, l, l, s], None, gregorian(1929, 2, 10)), + PackedEastAsianTraditionalYearData::new(1930, [s, l, l, s, s, l, s, s, l, s, l, l, s], Some(7), gregorian(1930, 1, 30)), + PackedEastAsianTraditionalYearData::new(1931, [l, l, s, l, s, l, s, s, l, s, l, s, s], None, gregorian(1931, 2, 17)), + PackedEastAsianTraditionalYearData::new(1932, [l, l, l, s, l, s, l, s, s, l, s, l, s], None, gregorian(1932, 2, 6)), + PackedEastAsianTraditionalYearData::new(1933, [s, l, l, s, l, l, s, l, s, l, s, s, l], Some(6), gregorian(1933, 1, 26)), + PackedEastAsianTraditionalYearData::new(1934, [s, l, s, l, l, s, l, s, l, l, s, l, s], None, gregorian(1934, 2, 14)), + PackedEastAsianTraditionalYearData::new(1935, [s, s, l, s, l, s, l, l, s, l, l, s, s], None, gregorian(1935, 2, 4)), + PackedEastAsianTraditionalYearData::new(1936, [l, s, s, l, s, s, l, l, s, l, l, l, s], Some(4), gregorian(1936, 1, 24)), + PackedEastAsianTraditionalYearData::new(1937, [l, s, s, l, s, s, l, s, l, l, l, s, s], None, gregorian(1937, 2, 11)), + PackedEastAsianTraditionalYearData::new(1938, [l, l, s, s, l, s, s, l, s, l, l, s, l], Some(8), gregorian(1938, 1, 31)), + PackedEastAsianTraditionalYearData::new(1939, [l, l, s, s, l, s, s, l, s, l, s, l, s], None, gregorian(1939, 2, 19)), + PackedEastAsianTraditionalYearData::new(1940, [l, l, s, l, s, l, s, s, l, s, l, s, s], None, gregorian(1940, 2, 8)), + PackedEastAsianTraditionalYearData::new(1941, [l, l, s, l, l, s, l, s, s, l, s, l, s], Some(7), gregorian(1941, 1, 27)), + PackedEastAsianTraditionalYearData::new(1942, [l, s, l, l, s, l, s, l, s, l, s, l, s], None, gregorian(1942, 2, 15)), + PackedEastAsianTraditionalYearData::new(1943, [s, l, s, l, s, l, l, s, l, s, l, s, s], None, gregorian(1943, 2, 5)), + PackedEastAsianTraditionalYearData::new(1944, [l, s, l, s, l, s, l, s, l, l, s, l, l], Some(5), gregorian(1944, 1, 25)), + PackedEastAsianTraditionalYearData::new(1945, [s, s, l, s, s, l, s, l, l, l, s, l, s], None, gregorian(1945, 2, 13)), + PackedEastAsianTraditionalYearData::new(1946, [l, s, s, l, s, s, l, s, l, l, s, l, s], None, gregorian(1946, 2, 2)), + PackedEastAsianTraditionalYearData::new(1947, [l, l, s, s, l, s, s, l, s, l, s, l, l], Some(3), gregorian(1947, 1, 22)), + PackedEastAsianTraditionalYearData::new(1948, [l, s, l, s, l, s, s, l, s, l, s, l, s], None, gregorian(1948, 2, 10)), + PackedEastAsianTraditionalYearData::new(1949, [l, s, l, l, s, l, s, s, l, s, l, s, l], Some(8), gregorian(1949, 1, 29)), + PackedEastAsianTraditionalYearData::new(1950, [s, l, l, s, l, l, s, s, l, s, l, s, s], None, gregorian(1950, 2, 17)), + PackedEastAsianTraditionalYearData::new(1951, [l, s, l, l, s, l, s, l, s, l, s, l, s], None, gregorian(1951, 2, 6)), + PackedEastAsianTraditionalYearData::new(1952, [s, l, s, l, s, l, s, l, l, s, l, s, l], Some(6), gregorian(1952, 1, 27)), + PackedEastAsianTraditionalYearData::new(1953, [s, l, s, s, l, l, s, l, l, s, l, s, s], None, gregorian(1953, 2, 14)), + PackedEastAsianTraditionalYearData::new(1954, [l, s, l, s, s, l, s, l, l, s, l, l, s], None, gregorian(1954, 2, 3)), + PackedEastAsianTraditionalYearData::new(1955, [s, l, s, l, s, s, l, s, l, s, l, l, l], Some(4), gregorian(1955, 1, 24)), + PackedEastAsianTraditionalYearData::new(1956, [s, l, s, l, s, s, l, s, l, s, l, l, s], None, gregorian(1956, 2, 12)), + PackedEastAsianTraditionalYearData::new(1957, [l, s, l, s, l, s, s, l, s, l, s, l, s], Some(9), gregorian(1957, 1, 31)), + PackedEastAsianTraditionalYearData::new(1958, [l, l, l, s, l, s, s, l, s, l, s, l, s], None, gregorian(1958, 2, 18)), + PackedEastAsianTraditionalYearData::new(1959, [s, l, l, s, l, s, l, s, l, s, l, s, s], None, gregorian(1959, 2, 8)), + PackedEastAsianTraditionalYearData::new(1960, [l, s, l, s, l, l, s, l, s, l, s, l, s], Some(7), gregorian(1960, 1, 28)), + PackedEastAsianTraditionalYearData::new(1961, [l, s, l, s, l, s, l, l, s, l, s, l, s], None, gregorian(1961, 2, 15)), + PackedEastAsianTraditionalYearData::new(1962, [s, l, s, s, l, s, l, l, s, l, l, s, s], None, gregorian(1962, 2, 5)), + PackedEastAsianTraditionalYearData::new(1963, [l, s, l, s, s, l, s, l, s, l, l, l, s], Some(5), gregorian(1963, 1, 25)), + PackedEastAsianTraditionalYearData::new(1964, [l, s, l, s, s, l, s, l, s, l, l, l, s], None, gregorian(1964, 2, 13)), + PackedEastAsianTraditionalYearData::new(1965, [s, l, s, l, s, s, l, s, s, l, l, s, s], None, gregorian(1965, 2, 2)), + PackedEastAsianTraditionalYearData::new(1966, [l, l, l, s, l, s, s, l, s, s, l, l, s], Some(4), gregorian(1966, 1, 21)), + PackedEastAsianTraditionalYearData::new(1967, [l, l, s, l, l, s, s, l, s, l, s, l, s], None, gregorian(1967, 2, 9)), + PackedEastAsianTraditionalYearData::new(1968, [s, l, s, l, l, s, l, s, l, s, l, s, l], Some(8), gregorian(1968, 1, 30)), + PackedEastAsianTraditionalYearData::new(1969, [s, l, s, l, s, l, l, s, l, s, l, s, s], None, gregorian(1969, 2, 17)), + PackedEastAsianTraditionalYearData::new(1970, [l, s, s, l, s, l, l, s, l, l, s, l, s], None, gregorian(1970, 2, 6)), + PackedEastAsianTraditionalYearData::new(1971, [s, l, s, s, l, s, l, s, l, l, l, s, l], Some(6), gregorian(1971, 1, 27)), + PackedEastAsianTraditionalYearData::new(1972, [s, l, s, s, l, s, l, s, l, l, s, l, s], None, gregorian(1972, 2, 15)), + PackedEastAsianTraditionalYearData::new(1973, [l, s, l, s, s, l, s, s, l, l, s, l, s], None, gregorian(1973, 2, 3)), + PackedEastAsianTraditionalYearData::new(1974, [l, l, s, l, s, s, l, s, s, l, l, s, l], Some(5), gregorian(1974, 1, 23)), + PackedEastAsianTraditionalYearData::new(1975, [l, l, s, l, s, s, l, s, s, l, s, l, s], None, gregorian(1975, 2, 11)), + PackedEastAsianTraditionalYearData::new(1976, [l, l, s, l, s, l, s, l, s, s, l, s, l], Some(9), gregorian(1976, 1, 31)), + PackedEastAsianTraditionalYearData::new(1977, [l, s, l, l, s, l, s, l, s, l, s, s, s], None, gregorian(1977, 2, 18)), + PackedEastAsianTraditionalYearData::new(1978, [l, s, l, l, s, l, l, s, l, s, l, s, s], None, gregorian(1978, 2, 7)), + PackedEastAsianTraditionalYearData::new(1979, [l, s, s, l, s, l, l, s, l, l, s, l, s], Some(7), gregorian(1979, 1, 28)), + PackedEastAsianTraditionalYearData::new(1980, [l, s, s, l, s, l, s, l, l, s, l, l, s], None, gregorian(1980, 2, 16)), + PackedEastAsianTraditionalYearData::new(1981, [s, l, s, s, l, s, s, l, l, s, l, l, s], None, gregorian(1981, 2, 5)), + PackedEastAsianTraditionalYearData::new(1982, [l, s, l, s, s, l, s, s, l, s, l, l, l], Some(5), gregorian(1982, 1, 25)), + PackedEastAsianTraditionalYearData::new(1983, [l, s, l, s, s, l, s, s, l, s, l, l, s], None, gregorian(1983, 2, 13)), + PackedEastAsianTraditionalYearData::new(1984, [l, s, l, l, s, s, l, s, s, l, s, l, l], Some(11), gregorian(1984, 2, 2)), + PackedEastAsianTraditionalYearData::new(1985, [s, l, l, s, l, s, l, s, s, l, s, l, s], None, gregorian(1985, 2, 20)), + PackedEastAsianTraditionalYearData::new(1986, [s, l, l, s, l, l, s, l, s, l, s, s, s], None, gregorian(1986, 2, 9)), + PackedEastAsianTraditionalYearData::new(1987, [l, s, l, s, l, l, s, l, l, s, l, s, s], Some(7), gregorian(1987, 1, 29)), + PackedEastAsianTraditionalYearData::new(1988, [l, s, l, s, l, s, l, l, s, l, l, s, s], None, gregorian(1988, 2, 17)), + PackedEastAsianTraditionalYearData::new(1989, [l, s, s, l, s, l, s, l, s, l, l, l, s], None, gregorian(1989, 2, 6)), + PackedEastAsianTraditionalYearData::new(1990, [s, l, s, s, l, s, s, l, s, l, l, l, l], Some(6), gregorian(1990, 1, 27)), + PackedEastAsianTraditionalYearData::new(1991, [s, l, s, s, l, s, s, l, s, l, l, l, s], None, gregorian(1991, 2, 15)), + PackedEastAsianTraditionalYearData::new(1992, [s, l, l, s, s, l, s, s, l, s, l, l, s], None, gregorian(1992, 2, 4)), + PackedEastAsianTraditionalYearData::new(1993, [s, l, l, s, l, s, l, s, s, l, s, l, s], Some(4), gregorian(1993, 1, 23)), + PackedEastAsianTraditionalYearData::new(1994, [l, l, l, s, l, s, l, s, s, l, s, l, s], None, gregorian(1994, 2, 10)), + PackedEastAsianTraditionalYearData::new(1995, [s, l, l, s, l, s, l, l, s, s, l, s, l], Some(9), gregorian(1995, 1, 31)), + PackedEastAsianTraditionalYearData::new(1996, [s, l, s, l, l, s, l, s, l, l, s, s, s], None, gregorian(1996, 2, 19)), + PackedEastAsianTraditionalYearData::new(1997, [l, s, l, s, l, s, l, l, s, l, l, s, s], None, gregorian(1997, 2, 7)), + PackedEastAsianTraditionalYearData::new(1998, [l, s, s, l, s, s, l, l, s, l, l, s, l], Some(6), gregorian(1998, 1, 28)), + PackedEastAsianTraditionalYearData::new(1999, [l, s, s, l, s, s, l, s, l, l, l, s, s], None, gregorian(1999, 2, 16)), + PackedEastAsianTraditionalYearData::new(2000, [l, l, s, s, l, s, s, l, s, l, l, s, s], None, gregorian(2000, 2, 5)), + PackedEastAsianTraditionalYearData::new(2001, [l, l, s, l, s, l, s, s, l, s, l, s, l], Some(5), gregorian(2001, 1, 24)), + PackedEastAsianTraditionalYearData::new(2002, [l, l, s, l, s, l, s, s, l, s, l, s, s], None, gregorian(2002, 2, 12)), + PackedEastAsianTraditionalYearData::new(2003, [l, l, s, l, l, s, l, s, s, l, s, l, s], None, gregorian(2003, 2, 1)), + PackedEastAsianTraditionalYearData::new(2004, [s, l, s, l, l, s, l, s, l, s, l, s, l], Some(3), gregorian(2004, 1, 22)), + PackedEastAsianTraditionalYearData::new(2005, [s, l, s, l, s, l, l, s, l, s, l, s, s], None, gregorian(2005, 2, 9)), + PackedEastAsianTraditionalYearData::new(2006, [l, s, l, s, l, s, l, s, l, l, s, l, l], Some(8), gregorian(2006, 1, 29)), + PackedEastAsianTraditionalYearData::new(2007, [s, s, l, s, s, l, s, l, l, l, s, l, s], None, gregorian(2007, 2, 18)), + PackedEastAsianTraditionalYearData::new(2008, [l, s, s, l, s, s, l, s, l, l, s, l, s], None, gregorian(2008, 2, 7)), + PackedEastAsianTraditionalYearData::new(2009, [l, l, s, s, l, s, s, l, s, l, s, l, l], Some(6), gregorian(2009, 1, 26)), + PackedEastAsianTraditionalYearData::new(2010, [l, s, l, s, l, s, s, l, s, l, s, l, s], None, gregorian(2010, 2, 14)), + PackedEastAsianTraditionalYearData::new(2011, [l, s, l, l, s, l, s, s, l, s, l, s, s], None, gregorian(2011, 2, 3)), + PackedEastAsianTraditionalYearData::new(2012, [l, s, l, l, s, l, s, l, s, l, s, l, s], Some(5), gregorian(2012, 1, 23)), + PackedEastAsianTraditionalYearData::new(2013, [l, s, l, s, l, l, s, l, s, l, s, l, s], None, gregorian(2013, 2, 10)), + PackedEastAsianTraditionalYearData::new(2014, [s, l, s, l, s, l, s, l, l, s, l, s, l], Some(10), gregorian(2014, 1, 31)), + PackedEastAsianTraditionalYearData::new(2015, [s, l, s, s, l, s, l, l, l, s, l, s, s], None, gregorian(2015, 2, 19)), + PackedEastAsianTraditionalYearData::new(2016, [l, s, l, s, s, l, s, l, l, s, l, l, s], None, gregorian(2016, 2, 8)), + PackedEastAsianTraditionalYearData::new(2017, [s, l, s, l, s, s, l, s, l, s, l, l, l], Some(7), gregorian(2017, 1, 28)), + PackedEastAsianTraditionalYearData::new(2018, [s, l, s, l, s, s, l, s, l, s, l, l, s], None, gregorian(2018, 2, 16)), + PackedEastAsianTraditionalYearData::new(2019, [l, s, l, s, l, s, s, l, s, s, l, l, s], None, gregorian(2019, 2, 5)), + PackedEastAsianTraditionalYearData::new(2020, [s, l, l, l, s, l, s, s, l, s, l, s, l], Some(5), gregorian(2020, 1, 25)), + PackedEastAsianTraditionalYearData::new(2021, [s, l, l, s, l, s, l, s, l, s, l, s, s], None, gregorian(2021, 2, 12)), + PackedEastAsianTraditionalYearData::new(2022, [l, s, l, s, l, l, s, l, s, l, s, l, s], None, gregorian(2022, 2, 1)), + PackedEastAsianTraditionalYearData::new(2023, [s, l, s, s, l, l, s, l, l, s, l, s, l], Some(3), gregorian(2023, 1, 22)), + PackedEastAsianTraditionalYearData::new(2024, [s, l, s, s, l, s, l, l, s, l, l, s, s], None, gregorian(2024, 2, 10)), + PackedEastAsianTraditionalYearData::new(2025, [l, s, l, s, s, l, s, l, s, l, l, l, s], Some(7), gregorian(2025, 1, 29)), + PackedEastAsianTraditionalYearData::new(2026, [l, s, l, s, s, l, s, s, l, l, l, s, s], None, gregorian(2026, 2, 17)), + PackedEastAsianTraditionalYearData::new(2027, [l, l, s, l, s, s, l, s, s, l, l, s, s], None, gregorian(2027, 2, 6)), + PackedEastAsianTraditionalYearData::new(2028, [l, l, l, s, l, s, s, l, s, s, l, l, s], Some(6), gregorian(2028, 1, 26)), + PackedEastAsianTraditionalYearData::new(2029, [l, l, s, l, s, l, s, l, s, s, l, l, s], None, gregorian(2029, 2, 13)), + PackedEastAsianTraditionalYearData::new(2030, [s, l, s, l, l, s, l, s, l, s, l, s, s], None, gregorian(2030, 2, 3)), + PackedEastAsianTraditionalYearData::new(2031, [s, l, l, s, l, s, l, l, s, l, s, l, s], Some(4), gregorian(2031, 1, 23)), + PackedEastAsianTraditionalYearData::new(2032, [l, s, s, l, s, l, l, s, l, l, s, l, s], None, gregorian(2032, 2, 11)), + PackedEastAsianTraditionalYearData::new(2033, [s, l, s, s, l, s, l, s, l, l, l, s, l], Some(12), gregorian(2033, 1, 31)), + PackedEastAsianTraditionalYearData::new(2034, [s, l, s, s, l, s, l, s, l, l, s, l, s], None, gregorian(2034, 2, 19)), + PackedEastAsianTraditionalYearData::new(2035, [l, s, l, s, s, l, s, s, l, l, s, l, s], None, gregorian(2035, 2, 8)), + PackedEastAsianTraditionalYearData::new(2036, [l, l, s, l, s, s, l, s, s, l, s, l, l], Some(7), gregorian(2036, 1, 28)), + PackedEastAsianTraditionalYearData::new(2037, [l, l, s, l, s, s, l, s, s, l, s, l, s], None, gregorian(2037, 2, 15)), + PackedEastAsianTraditionalYearData::new(2038, [l, l, s, l, s, l, s, l, s, s, l, s, s], None, gregorian(2038, 2, 4)), + PackedEastAsianTraditionalYearData::new(2039, [l, l, s, l, l, s, l, s, l, s, l, s, s], Some(6), gregorian(2039, 1, 24)), + PackedEastAsianTraditionalYearData::new(2040, [l, s, l, l, s, l, s, l, l, s, l, s, s], None, gregorian(2040, 2, 12)), + PackedEastAsianTraditionalYearData::new(2041, [s, l, s, l, s, l, l, s, l, l, s, l, s], None, gregorian(2041, 2, 1)), + PackedEastAsianTraditionalYearData::new(2042, [s, l, s, s, l, s, l, s, l, l, s, l, l], Some(3), gregorian(2042, 1, 22)), + PackedEastAsianTraditionalYearData::new(2043, [s, l, s, s, l, s, s, l, l, s, l, l, s], None, gregorian(2043, 2, 10)), + PackedEastAsianTraditionalYearData::new(2044, [l, s, l, s, s, l, s, s, l, s, l, l, l], Some(8), gregorian(2044, 1, 30)), + PackedEastAsianTraditionalYearData::new(2045, [l, s, l, s, s, l, s, s, l, s, l, l, s], None, gregorian(2045, 2, 17)), + PackedEastAsianTraditionalYearData::new(2046, [l, s, l, s, l, s, l, s, s, l, s, l, s], None, gregorian(2046, 2, 6)), + PackedEastAsianTraditionalYearData::new(2047, [l, s, l, l, s, l, s, l, s, s, l, s, l], Some(6), gregorian(2047, 1, 26)), + PackedEastAsianTraditionalYearData::new(2048, [s, l, l, s, l, l, s, l, s, s, l, s, s], None, gregorian(2048, 2, 14)), + PackedEastAsianTraditionalYearData::new(2049, [l, s, l, s, l, l, s, l, l, s, l, s, s], None, gregorian(2049, 2, 2)), + PackedEastAsianTraditionalYearData::new(2050, [s, l, s, l, s, l, s, l, l, s, l, l, s], Some(4), gregorian(2050, 1, 23)), + PackedEastAsianTraditionalYearData::new(2051, [l, s, s, l, s, s, l, l, s, l, l, l, s], None, gregorian(2051, 2, 11)), + PackedEastAsianTraditionalYearData::new(2052, [s, l, s, s, l, s, s, l, s, l, l, l, l], Some(9), gregorian(2052, 2, 1)), + PackedEastAsianTraditionalYearData::new(2053, [s, l, s, s, l, s, s, l, s, l, l, l, s], None, gregorian(2053, 2, 19)), + PackedEastAsianTraditionalYearData::new(2054, [s, l, l, s, s, l, s, s, l, s, l, l, s], None, gregorian(2054, 2, 8)), + PackedEastAsianTraditionalYearData::new(2055, [s, l, l, s, l, s, l, s, s, l, s, l, s], Some(7), gregorian(2055, 1, 28)), + PackedEastAsianTraditionalYearData::new(2056, [l, l, l, s, l, s, l, s, s, l, s, l, s], None, gregorian(2056, 2, 15)), + PackedEastAsianTraditionalYearData::new(2057, [s, l, l, s, l, s, l, s, l, s, l, s, s], None, gregorian(2057, 2, 4)), + PackedEastAsianTraditionalYearData::new(2058, [l, s, l, s, l, s, l, l, s, l, l, s, s], Some(5), gregorian(2058, 1, 24)), + PackedEastAsianTraditionalYearData::new(2059, [l, s, l, s, l, s, l, s, l, l, l, s, s], None, gregorian(2059, 2, 12)), + PackedEastAsianTraditionalYearData::new(2060, [l, s, s, l, s, s, l, s, l, l, l, s, s], None, gregorian(2060, 2, 2)), + PackedEastAsianTraditionalYearData::new(2061, [l, l, s, s, l, s, s, l, s, l, l, l, s], Some(4), gregorian(2061, 1, 21)), + PackedEastAsianTraditionalYearData::new(2062, [l, l, s, s, l, s, s, l, s, l, l, s, s], None, gregorian(2062, 2, 9)), + PackedEastAsianTraditionalYearData::new(2063, [l, l, s, l, s, l, s, s, l, s, l, s, l], Some(8), gregorian(2063, 1, 29)), + PackedEastAsianTraditionalYearData::new(2064, [l, l, s, l, s, l, s, s, l, s, l, s, s], None, gregorian(2064, 2, 17)), + PackedEastAsianTraditionalYearData::new(2065, [l, l, s, l, l, s, l, s, s, l, s, l, s], None, gregorian(2065, 2, 5)), + PackedEastAsianTraditionalYearData::new(2066, [s, l, s, l, l, s, l, s, l, s, l, s, l], Some(6), gregorian(2066, 1, 26)), + PackedEastAsianTraditionalYearData::new(2067, [s, l, s, l, s, l, l, s, l, s, l, s, s], None, gregorian(2067, 2, 14)), + PackedEastAsianTraditionalYearData::new(2068, [l, s, l, s, s, l, l, s, l, l, s, l, s], None, gregorian(2068, 2, 3)), + PackedEastAsianTraditionalYearData::new(2069, [s, l, s, l, s, s, l, s, l, l, l, s, l], Some(5), gregorian(2069, 1, 23)), + PackedEastAsianTraditionalYearData::new(2070, [s, l, s, l, s, s, l, s, l, l, s, l, s], None, gregorian(2070, 2, 11)), + PackedEastAsianTraditionalYearData::new(2071, [l, s, l, s, l, s, s, l, s, l, s, l, l], Some(9), gregorian(2071, 1, 31)), + PackedEastAsianTraditionalYearData::new(2072, [l, s, l, s, l, s, s, l, s, l, s, l, s], None, gregorian(2072, 2, 19)), + PackedEastAsianTraditionalYearData::new(2073, [l, s, l, l, s, l, s, s, l, s, l, s, s], None, gregorian(2073, 2, 7)), + PackedEastAsianTraditionalYearData::new(2074, [l, s, l, l, s, l, s, l, s, l, s, l, s], Some(7), gregorian(2074, 1, 27)), + PackedEastAsianTraditionalYearData::new(2075, [l, s, l, s, l, l, s, l, s, l, s, l, s], None, gregorian(2075, 2, 15)), + PackedEastAsianTraditionalYearData::new(2076, [s, l, s, l, s, l, s, l, l, s, l, s, s], None, gregorian(2076, 2, 5)), + PackedEastAsianTraditionalYearData::new(2077, [l, s, l, s, s, l, s, l, l, l, s, l, s], Some(5), gregorian(2077, 1, 24)), + PackedEastAsianTraditionalYearData::new(2078, [l, s, l, s, s, l, s, l, l, s, l, l, s], None, gregorian(2078, 2, 12)), + PackedEastAsianTraditionalYearData::new(2079, [s, l, s, l, s, s, l, s, l, s, l, l, s], None, gregorian(2079, 2, 2)), + PackedEastAsianTraditionalYearData::new(2080, [l, s, l, s, l, s, s, l, s, s, l, l, l], Some(4), gregorian(2080, 1, 22)), + PackedEastAsianTraditionalYearData::new(2081, [s, l, l, s, l, s, s, l, s, s, l, l, s], None, gregorian(2081, 2, 9)), + PackedEastAsianTraditionalYearData::new(2082, [s, l, l, l, s, s, l, s, l, s, s, l, l], Some(8), gregorian(2082, 1, 29)), + PackedEastAsianTraditionalYearData::new(2083, [s, l, l, s, l, s, l, s, l, s, l, s, s], None, gregorian(2083, 2, 17)), + PackedEastAsianTraditionalYearData::new(2084, [l, s, l, s, l, l, s, l, s, l, s, l, s], None, gregorian(2084, 2, 6)), + PackedEastAsianTraditionalYearData::new(2085, [s, l, s, s, l, l, s, l, l, s, l, s, l], Some(6), gregorian(2085, 1, 26)), + PackedEastAsianTraditionalYearData::new(2086, [s, l, s, s, l, s, l, l, s, l, l, s, s], None, gregorian(2086, 2, 14)), + PackedEastAsianTraditionalYearData::new(2087, [l, s, l, s, s, l, s, l, s, l, l, l, s], None, gregorian(2087, 2, 3)), + PackedEastAsianTraditionalYearData::new(2088, [s, l, s, l, s, s, l, s, s, l, l, l, s], Some(5), gregorian(2088, 1, 24)), + PackedEastAsianTraditionalYearData::new(2089, [l, l, s, l, s, s, s, l, s, l, l, s, s], None, gregorian(2089, 2, 10)), + PackedEastAsianTraditionalYearData::new(2090, [l, l, l, s, l, s, s, l, s, s, l, l, s], Some(9), gregorian(2090, 1, 30)), + PackedEastAsianTraditionalYearData::new(2091, [l, l, s, l, s, l, s, l, s, s, l, s, s], None, gregorian(2091, 2, 18)), + PackedEastAsianTraditionalYearData::new(2092, [l, l, s, l, l, s, l, s, l, s, l, s, s], None, gregorian(2092, 2, 7)), + PackedEastAsianTraditionalYearData::new(2093, [s, l, l, s, l, s, l, l, s, l, s, l, s], Some(7), gregorian(2093, 1, 27)), + PackedEastAsianTraditionalYearData::new(2094, [s, l, s, l, s, l, l, s, l, l, s, l, s], None, gregorian(2094, 2, 15)), + PackedEastAsianTraditionalYearData::new(2095, [s, l, s, s, l, s, l, s, l, l, l, s, s], None, gregorian(2095, 2, 5)), + PackedEastAsianTraditionalYearData::new(2096, [l, s, l, s, s, l, s, s, l, l, l, s, l], Some(5), gregorian(2096, 1, 25)), + PackedEastAsianTraditionalYearData::new(2097, [l, s, l, s, s, s, l, s, l, l, s, l, s], None, gregorian(2097, 2, 12)), + PackedEastAsianTraditionalYearData::new(2098, [l, l, s, l, s, s, s, l, s, l, s, l, s], None, gregorian(2098, 2, 1)), + PackedEastAsianTraditionalYearData::new(2099, [l, l, s, l, l, s, s, l, s, s, l, s, l], Some(3), gregorian(2099, 1, 21)), + PackedEastAsianTraditionalYearData::new(2100, [l, l, s, l, s, l, s, l, s, s, l, s, s], None, gregorian(2100, 2, 9)), + // Extra two years of correct data because the simple calculation lines up at the beginning of 2103 + PackedEastAsianTraditionalYearData::new(2101, [l, l, s, l, l, s, l, s, l, s, s, l, s], Some(8), gregorian(2101, 1, 29)), + PackedEastAsianTraditionalYearData::new(2102, [l, s, l, l, s, l, s, l, l, s, l, s, s], None, gregorian(2102, 2, 17)), + ] +}; + +#[test] +fn test_against_calendrical_calculations() { + use calendrical_calculations::chinese_based::Chinese; + for (i, &data) in DATA.iter().enumerate() { + assert_eq!( + data, + super::EastAsianTraditionalYearData::calendrical_calculations::( + STARTING_YEAR + i as i32 + ) + .packed + ); + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/east_asian_traditional/korea_data.rs b/deps/crates/vendor/icu_calendar/src/cal/east_asian_traditional/korea_data.rs new file mode 100644 index 00000000000000..bf4cffc45cb724 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/east_asian_traditional/korea_data.rs @@ -0,0 +1,225 @@ +// 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 obtained from [`calendrical_calculations`]. + +use super::PackedEastAsianTraditionalYearData; + +pub const STARTING_YEAR: i32 = 1912; + +#[rustfmt::skip] +#[allow(clippy::unwrap_used)] // const +pub const DATA: &[PackedEastAsianTraditionalYearData] = { + use calendrical_calculations::gregorian::fixed_from_gregorian as gregorian; + let l = true; // long + let s = false; // short + &[ + PackedEastAsianTraditionalYearData::new(1912, [l, s, l, s, s, l, s, s, l, l, s, l, s], None, gregorian(1912, 2, 18)), + PackedEastAsianTraditionalYearData::new(1913, [l, l, s, l, s, s, l, s, s, l, s, l, s], None, gregorian(1913, 2, 6)), + PackedEastAsianTraditionalYearData::new(1914, [l, l, s, l, l, s, s, l, s, l, s, s, l], Some(6), gregorian(1914, 1, 26)), + PackedEastAsianTraditionalYearData::new(1915, [l, s, l, l, s, l, s, l, s, l, s, l, s], None, gregorian(1915, 2, 14)), + PackedEastAsianTraditionalYearData::new(1916, [s, l, s, l, s, l, l, s, l, s, l, s, s], None, gregorian(1916, 2, 4)), + PackedEastAsianTraditionalYearData::new(1917, [l, s, s, l, s, l, l, s, l, l, s, l, s], Some(3), gregorian(1917, 1, 23)), + PackedEastAsianTraditionalYearData::new(1918, [l, s, s, l, s, l, s, l, l, l, s, l, s], None, gregorian(1918, 2, 11)), + PackedEastAsianTraditionalYearData::new(1919, [s, l, s, s, l, s, l, s, l, l, s, l, l], Some(8), gregorian(1919, 2, 1)), + PackedEastAsianTraditionalYearData::new(1920, [s, l, s, s, l, s, s, l, l, s, l, l, s], None, gregorian(1920, 2, 20)), + PackedEastAsianTraditionalYearData::new(1921, [l, s, l, s, s, l, s, s, l, s, l, l, s], None, gregorian(1921, 2, 8)), + PackedEastAsianTraditionalYearData::new(1922, [l, s, l, l, s, s, l, s, s, l, s, l, l], Some(6), gregorian(1922, 1, 28)), + PackedEastAsianTraditionalYearData::new(1923, [s, l, l, s, l, s, l, s, l, s, s, l, s], None, gregorian(1923, 2, 16)), + PackedEastAsianTraditionalYearData::new(1924, [l, s, l, s, l, l, s, l, s, l, s, s, s], None, gregorian(1924, 2, 5)), + PackedEastAsianTraditionalYearData::new(1925, [l, s, l, l, s, l, s, l, l, s, l, s, l], Some(5), gregorian(1925, 1, 24)), + PackedEastAsianTraditionalYearData::new(1926, [s, s, l, s, l, s, l, l, s, l, l, s, s], None, gregorian(1926, 2, 13)), + PackedEastAsianTraditionalYearData::new(1927, [l, s, s, l, s, l, s, l, l, s, l, l, s], None, gregorian(1927, 2, 2)), + PackedEastAsianTraditionalYearData::new(1928, [s, l, s, s, l, s, s, l, l, s, l, l, l], Some(3), gregorian(1928, 1, 23)), + PackedEastAsianTraditionalYearData::new(1929, [s, l, s, s, l, s, s, l, s, l, l, l, s], None, gregorian(1929, 2, 10)), + PackedEastAsianTraditionalYearData::new(1930, [s, l, l, s, s, l, s, s, l, s, l, l, s], Some(7), gregorian(1930, 1, 30)), + PackedEastAsianTraditionalYearData::new(1931, [l, l, l, s, s, l, s, s, l, s, l, s, s], None, gregorian(1931, 2, 17)), + PackedEastAsianTraditionalYearData::new(1932, [l, l, l, s, l, s, l, s, s, l, s, l, s], None, gregorian(1932, 2, 6)), + PackedEastAsianTraditionalYearData::new(1933, [s, l, l, s, l, l, s, l, s, l, s, s, l], Some(6), gregorian(1933, 1, 26)), + PackedEastAsianTraditionalYearData::new(1934, [s, l, s, l, l, s, l, l, s, l, s, l, s], None, gregorian(1934, 2, 14)), + PackedEastAsianTraditionalYearData::new(1935, [s, s, l, s, l, s, l, l, s, l, l, s, s], None, gregorian(1935, 2, 4)), + PackedEastAsianTraditionalYearData::new(1936, [l, s, s, l, s, l, s, l, s, l, l, l, s], Some(4), gregorian(1936, 1, 24)), + PackedEastAsianTraditionalYearData::new(1937, [l, s, s, l, s, s, l, s, l, l, l, s, s], None, gregorian(1937, 2, 11)), + PackedEastAsianTraditionalYearData::new(1938, [l, l, s, s, l, s, s, l, s, l, l, s, l], Some(8), gregorian(1938, 1, 31)), + PackedEastAsianTraditionalYearData::new(1939, [l, l, s, s, l, s, s, l, s, l, s, l, s], None, gregorian(1939, 2, 19)), + PackedEastAsianTraditionalYearData::new(1940, [l, l, s, l, s, l, s, s, l, s, l, s, s], None, gregorian(1940, 2, 8)), + PackedEastAsianTraditionalYearData::new(1941, [l, l, s, l, l, s, l, s, s, l, s, l, s], Some(7), gregorian(1941, 1, 27)), + PackedEastAsianTraditionalYearData::new(1942, [l, s, l, l, s, l, l, s, l, s, s, l, s], None, gregorian(1942, 2, 15)), + PackedEastAsianTraditionalYearData::new(1943, [s, l, s, l, s, l, l, s, l, l, s, l, s], None, gregorian(1943, 2, 5)), + PackedEastAsianTraditionalYearData::new(1944, [s, s, l, s, l, s, l, s, l, l, s, l, l], Some(5), gregorian(1944, 1, 26)), + PackedEastAsianTraditionalYearData::new(1945, [s, s, l, s, s, l, s, l, l, l, s, l, s], None, gregorian(1945, 2, 13)), + PackedEastAsianTraditionalYearData::new(1946, [l, s, s, l, s, s, l, s, l, l, s, l, s], None, gregorian(1946, 2, 2)), + PackedEastAsianTraditionalYearData::new(1947, [l, l, s, s, l, s, s, l, s, l, s, l, l], Some(3), gregorian(1947, 1, 22)), + PackedEastAsianTraditionalYearData::new(1948, [l, s, l, s, l, s, s, l, s, l, s, l, s], None, gregorian(1948, 2, 10)), + PackedEastAsianTraditionalYearData::new(1949, [l, l, s, l, s, l, s, s, l, s, l, s, l], Some(8), gregorian(1949, 1, 29)), + PackedEastAsianTraditionalYearData::new(1950, [l, s, l, l, s, l, s, s, l, s, l, s, s], None, gregorian(1950, 2, 17)), + PackedEastAsianTraditionalYearData::new(1951, [l, s, l, l, s, l, s, l, s, l, s, l, s], None, gregorian(1951, 2, 6)), + PackedEastAsianTraditionalYearData::new(1952, [s, l, s, l, s, l, l, s, l, s, l, s, l], Some(6), gregorian(1952, 1, 27)), + PackedEastAsianTraditionalYearData::new(1953, [s, l, s, s, l, l, s, l, l, s, l, l, s], None, gregorian(1953, 2, 14)), + PackedEastAsianTraditionalYearData::new(1954, [s, s, l, s, s, l, s, l, l, s, l, l, s], None, gregorian(1954, 2, 4)), + PackedEastAsianTraditionalYearData::new(1955, [l, s, s, l, s, s, l, s, l, s, l, l, l], Some(4), gregorian(1955, 1, 24)), + PackedEastAsianTraditionalYearData::new(1956, [s, l, s, l, s, s, l, s, l, s, l, l, s], None, gregorian(1956, 2, 12)), + PackedEastAsianTraditionalYearData::new(1957, [l, s, l, s, l, s, s, l, s, l, s, l, l], Some(9), gregorian(1957, 1, 31)), + PackedEastAsianTraditionalYearData::new(1958, [s, l, l, s, l, s, s, l, s, l, s, l, s], None, gregorian(1958, 2, 19)), + PackedEastAsianTraditionalYearData::new(1959, [s, l, l, s, l, s, l, s, l, s, l, s, s], None, gregorian(1959, 2, 8)), + PackedEastAsianTraditionalYearData::new(1960, [l, s, l, s, l, l, s, l, s, l, s, l, s], Some(7), gregorian(1960, 1, 28)), + PackedEastAsianTraditionalYearData::new(1961, [l, s, l, s, l, s, l, l, s, l, s, l, s], None, gregorian(1961, 2, 15)), + PackedEastAsianTraditionalYearData::new(1962, [s, l, s, s, l, s, l, l, s, l, l, s, s], None, gregorian(1962, 2, 5)), + PackedEastAsianTraditionalYearData::new(1963, [l, s, l, s, s, l, s, l, s, l, l, l, s], Some(5), gregorian(1963, 1, 25)), + PackedEastAsianTraditionalYearData::new(1964, [l, s, l, s, s, l, s, l, s, l, l, l, s], None, gregorian(1964, 2, 13)), + PackedEastAsianTraditionalYearData::new(1965, [s, l, s, l, s, s, l, s, s, l, l, l, s], None, gregorian(1965, 2, 2)), + PackedEastAsianTraditionalYearData::new(1966, [s, l, l, s, l, s, s, l, s, s, l, l, s], Some(4), gregorian(1966, 1, 22)), + PackedEastAsianTraditionalYearData::new(1967, [l, l, s, l, l, s, s, l, s, l, s, l, s], None, gregorian(1967, 2, 9)), + PackedEastAsianTraditionalYearData::new(1968, [s, l, l, s, l, s, l, s, l, s, l, s, l], Some(8), gregorian(1968, 1, 30)), + PackedEastAsianTraditionalYearData::new(1969, [s, l, s, l, s, l, l, s, l, s, l, s, s], None, gregorian(1969, 2, 17)), + PackedEastAsianTraditionalYearData::new(1970, [l, s, s, l, l, s, l, s, l, l, s, l, s], None, gregorian(1970, 2, 6)), + PackedEastAsianTraditionalYearData::new(1971, [s, l, s, s, l, s, l, s, l, l, l, s, l], Some(6), gregorian(1971, 1, 27)), + PackedEastAsianTraditionalYearData::new(1972, [s, l, s, s, l, s, l, s, l, l, l, s, s], None, gregorian(1972, 2, 15)), + PackedEastAsianTraditionalYearData::new(1973, [l, s, l, s, s, l, s, s, l, l, l, s, s], None, gregorian(1973, 2, 3)), + PackedEastAsianTraditionalYearData::new(1974, [l, l, s, l, s, s, l, s, s, l, l, s, l], Some(5), gregorian(1974, 1, 23)), + PackedEastAsianTraditionalYearData::new(1975, [l, l, s, l, s, s, l, s, s, l, s, l, s], None, gregorian(1975, 2, 11)), + PackedEastAsianTraditionalYearData::new(1976, [l, l, s, l, s, l, s, l, s, l, s, s, l], Some(9), gregorian(1976, 1, 31)), + PackedEastAsianTraditionalYearData::new(1977, [l, s, l, l, s, l, s, l, s, l, s, s, s], None, gregorian(1977, 2, 18)), + PackedEastAsianTraditionalYearData::new(1978, [l, l, s, l, s, l, l, s, l, s, l, s, s], None, gregorian(1978, 2, 7)), + PackedEastAsianTraditionalYearData::new(1979, [l, s, s, l, s, l, l, s, l, l, s, l, s], Some(7), gregorian(1979, 1, 28)), + PackedEastAsianTraditionalYearData::new(1980, [l, s, s, l, s, l, s, l, l, s, l, l, s], None, gregorian(1980, 2, 16)), + PackedEastAsianTraditionalYearData::new(1981, [s, l, s, s, l, s, s, l, l, s, l, l, s], None, gregorian(1981, 2, 5)), + PackedEastAsianTraditionalYearData::new(1982, [l, s, l, s, s, l, s, s, l, l, s, l, l], Some(5), gregorian(1982, 1, 25)), + PackedEastAsianTraditionalYearData::new(1983, [l, s, l, s, s, l, s, s, l, s, l, l, s], None, gregorian(1983, 2, 13)), + PackedEastAsianTraditionalYearData::new(1984, [l, s, l, l, s, s, l, s, s, l, s, l, l], Some(11), gregorian(1984, 2, 2)), + PackedEastAsianTraditionalYearData::new(1985, [s, l, l, s, l, s, l, s, s, l, s, l, s], None, gregorian(1985, 2, 20)), + PackedEastAsianTraditionalYearData::new(1986, [s, l, l, s, l, l, s, l, s, l, s, s, s], None, gregorian(1986, 2, 9)), + PackedEastAsianTraditionalYearData::new(1987, [l, s, l, l, s, l, s, l, l, s, l, s, l], Some(7), gregorian(1987, 1, 29)), + PackedEastAsianTraditionalYearData::new(1988, [s, s, l, s, l, s, l, l, s, l, l, s, s], None, gregorian(1988, 2, 18)), + PackedEastAsianTraditionalYearData::new(1989, [l, s, s, l, s, l, s, l, l, s, l, l, s], None, gregorian(1989, 2, 6)), + PackedEastAsianTraditionalYearData::new(1990, [s, l, s, s, l, s, s, l, l, s, l, l, l], Some(6), gregorian(1990, 1, 27)), + PackedEastAsianTraditionalYearData::new(1991, [s, l, s, s, l, s, s, l, s, l, l, l, s], None, gregorian(1991, 2, 15)), + PackedEastAsianTraditionalYearData::new(1992, [s, l, l, s, s, l, s, s, l, s, l, l, s], None, gregorian(1992, 2, 4)), + PackedEastAsianTraditionalYearData::new(1993, [s, l, l, s, l, s, l, s, s, l, s, l, s], Some(4), gregorian(1993, 1, 23)), + PackedEastAsianTraditionalYearData::new(1994, [l, l, l, s, l, s, l, s, s, l, s, l, s], None, gregorian(1994, 2, 10)), + PackedEastAsianTraditionalYearData::new(1995, [s, l, l, s, l, l, s, l, s, l, s, s, l], Some(9), gregorian(1995, 1, 31)), + PackedEastAsianTraditionalYearData::new(1996, [s, l, s, l, l, s, l, s, l, l, s, l, s], None, gregorian(1996, 2, 19)), + PackedEastAsianTraditionalYearData::new(1997, [s, s, l, s, l, s, l, l, s, l, l, s, s], None, gregorian(1997, 2, 8)), + PackedEastAsianTraditionalYearData::new(1998, [l, s, s, l, s, s, l, l, s, l, l, l, s], Some(6), gregorian(1998, 1, 28)), + PackedEastAsianTraditionalYearData::new(1999, [l, s, s, l, s, s, l, s, l, l, l, s, s], None, gregorian(1999, 2, 16)), + PackedEastAsianTraditionalYearData::new(2000, [l, l, s, s, l, s, s, l, s, l, l, s, s], None, gregorian(2000, 2, 5)), + PackedEastAsianTraditionalYearData::new(2001, [l, l, l, s, s, l, s, s, l, s, l, s, l], Some(5), gregorian(2001, 1, 24)), + PackedEastAsianTraditionalYearData::new(2002, [l, l, s, l, s, l, s, s, l, s, l, s, s], None, gregorian(2002, 2, 12)), + PackedEastAsianTraditionalYearData::new(2003, [l, l, s, l, l, s, l, s, s, l, s, l, s], None, gregorian(2003, 2, 1)), + PackedEastAsianTraditionalYearData::new(2004, [s, l, s, l, l, s, l, s, l, s, l, s, l], Some(3), gregorian(2004, 1, 22)), + PackedEastAsianTraditionalYearData::new(2005, [s, l, s, l, s, l, l, s, l, l, s, s, s], None, gregorian(2005, 2, 9)), + PackedEastAsianTraditionalYearData::new(2006, [l, s, l, s, l, s, l, s, l, l, s, l, l], Some(8), gregorian(2006, 1, 29)), + PackedEastAsianTraditionalYearData::new(2007, [s, s, l, s, s, l, s, l, l, l, s, l, s], None, gregorian(2007, 2, 18)), + PackedEastAsianTraditionalYearData::new(2008, [l, s, s, l, s, s, l, s, l, l, s, l, s], None, gregorian(2008, 2, 7)), + PackedEastAsianTraditionalYearData::new(2009, [l, l, s, s, l, s, s, l, s, l, s, l, l], Some(6), gregorian(2009, 1, 26)), + PackedEastAsianTraditionalYearData::new(2010, [l, s, l, s, l, s, s, l, s, l, s, l, s], None, gregorian(2010, 2, 14)), + PackedEastAsianTraditionalYearData::new(2011, [l, s, l, l, s, l, s, s, l, s, l, s, s], None, gregorian(2011, 2, 3)), + PackedEastAsianTraditionalYearData::new(2012, [l, s, l, l, l, s, l, s, s, l, s, l, s], Some(4), gregorian(2012, 1, 23)), + PackedEastAsianTraditionalYearData::new(2013, [l, s, l, l, s, l, s, l, s, l, s, l, s], None, gregorian(2013, 2, 10)), + PackedEastAsianTraditionalYearData::new(2014, [s, l, s, l, s, l, s, l, l, s, l, s, l], Some(10), gregorian(2014, 1, 31)), + PackedEastAsianTraditionalYearData::new(2015, [s, l, s, s, l, s, l, l, l, s, l, s, s], None, gregorian(2015, 2, 19)), + PackedEastAsianTraditionalYearData::new(2016, [l, s, l, s, s, l, s, l, l, s, l, l, s], None, gregorian(2016, 2, 8)), + PackedEastAsianTraditionalYearData::new(2017, [s, l, s, l, s, s, l, s, l, s, l, l, l], Some(6), gregorian(2017, 1, 28)), + PackedEastAsianTraditionalYearData::new(2018, [s, l, s, l, s, s, l, s, l, s, l, l, s], None, gregorian(2018, 2, 16)), + PackedEastAsianTraditionalYearData::new(2019, [l, s, l, s, l, s, s, l, s, l, s, l, s], None, gregorian(2019, 2, 5)), + PackedEastAsianTraditionalYearData::new(2020, [l, s, l, l, s, l, s, s, l, s, l, s, l], Some(5), gregorian(2020, 1, 25)), + PackedEastAsianTraditionalYearData::new(2021, [s, l, l, s, l, s, l, s, l, s, l, s, s], None, gregorian(2021, 2, 12)), + PackedEastAsianTraditionalYearData::new(2022, [l, s, l, s, l, l, s, l, s, l, s, l, s], None, gregorian(2022, 2, 1)), + PackedEastAsianTraditionalYearData::new(2023, [s, l, s, l, s, l, s, l, l, s, l, s, l], Some(3), gregorian(2023, 1, 22)), + PackedEastAsianTraditionalYearData::new(2024, [s, l, s, s, l, s, l, l, s, l, l, s, s], None, gregorian(2024, 2, 10)), + PackedEastAsianTraditionalYearData::new(2025, [l, s, l, s, s, l, s, l, s, l, l, l, s], Some(7), gregorian(2025, 1, 29)), + PackedEastAsianTraditionalYearData::new(2026, [l, s, l, s, s, l, s, l, s, l, l, l, s], None, gregorian(2026, 2, 17)), + PackedEastAsianTraditionalYearData::new(2027, [s, l, s, l, s, s, l, s, s, l, l, l, s], None, gregorian(2027, 2, 7)), + PackedEastAsianTraditionalYearData::new(2028, [s, l, l, s, l, s, s, l, s, s, l, l, s], Some(6), gregorian(2028, 1, 27)), + PackedEastAsianTraditionalYearData::new(2029, [l, l, s, l, l, s, s, l, s, s, l, l, s], None, gregorian(2029, 2, 13)), + PackedEastAsianTraditionalYearData::new(2030, [s, l, s, l, l, s, l, s, l, s, l, s, s], None, gregorian(2030, 2, 3)), + PackedEastAsianTraditionalYearData::new(2031, [l, s, l, s, l, s, l, l, s, l, s, l, s], Some(4), gregorian(2031, 1, 23)), + PackedEastAsianTraditionalYearData::new(2032, [l, s, s, l, s, l, l, s, l, l, s, l, s], None, gregorian(2032, 2, 11)), + PackedEastAsianTraditionalYearData::new(2033, [s, l, s, s, l, s, l, s, l, l, l, s, l], Some(12), gregorian(2033, 1, 31)), + PackedEastAsianTraditionalYearData::new(2034, [s, l, s, s, l, s, l, s, l, l, l, s, s], None, gregorian(2034, 2, 19)), + PackedEastAsianTraditionalYearData::new(2035, [l, s, l, s, s, l, s, s, l, l, s, l, s], None, gregorian(2035, 2, 8)), + PackedEastAsianTraditionalYearData::new(2036, [l, l, s, l, s, s, l, s, s, l, l, s, l], Some(7), gregorian(2036, 1, 28)), + PackedEastAsianTraditionalYearData::new(2037, [l, l, s, l, s, s, l, s, s, l, s, l, s], None, gregorian(2037, 2, 15)), + PackedEastAsianTraditionalYearData::new(2038, [l, l, s, l, s, l, s, l, s, s, l, s, s], None, gregorian(2038, 2, 4)), + PackedEastAsianTraditionalYearData::new(2039, [l, l, s, l, l, s, l, s, l, s, l, s, s], Some(6), gregorian(2039, 1, 24)), + PackedEastAsianTraditionalYearData::new(2040, [l, s, l, l, s, l, l, s, l, s, l, s, s], None, gregorian(2040, 2, 12)), + PackedEastAsianTraditionalYearData::new(2041, [l, s, s, l, s, l, l, s, l, l, s, l, s], None, gregorian(2041, 2, 1)), + PackedEastAsianTraditionalYearData::new(2042, [s, l, s, s, l, s, l, s, l, l, s, l, l], Some(3), gregorian(2042, 1, 22)), + PackedEastAsianTraditionalYearData::new(2043, [s, l, s, s, l, s, s, l, l, s, l, l, s], None, gregorian(2043, 2, 10)), + PackedEastAsianTraditionalYearData::new(2044, [l, s, l, s, s, l, s, s, l, s, l, l, l], Some(8), gregorian(2044, 1, 30)), + PackedEastAsianTraditionalYearData::new(2045, [l, s, l, s, s, l, s, s, l, s, l, l, s], None, gregorian(2045, 2, 17)), + PackedEastAsianTraditionalYearData::new(2046, [l, s, l, l, s, s, l, s, s, l, s, l, s], None, gregorian(2046, 2, 6)), + PackedEastAsianTraditionalYearData::new(2047, [l, s, l, l, s, l, s, l, s, s, l, s, l], Some(6), gregorian(2047, 1, 26)), + PackedEastAsianTraditionalYearData::new(2048, [s, l, l, s, l, l, s, l, s, l, s, s, s], None, gregorian(2048, 2, 14)), + PackedEastAsianTraditionalYearData::new(2049, [l, s, l, s, l, l, s, l, l, s, l, s, s], None, gregorian(2049, 2, 2)), + PackedEastAsianTraditionalYearData::new(2050, [l, s, s, l, s, l, s, l, l, s, l, l, s], Some(4), gregorian(2050, 1, 23)), + PackedEastAsianTraditionalYearData::new(2051, [l, s, s, l, s, l, s, l, s, l, l, l, s], None, gregorian(2051, 2, 11)), + PackedEastAsianTraditionalYearData::new(2052, [s, l, s, s, l, s, s, l, l, s, l, l, l], Some(9), gregorian(2052, 2, 1)), + PackedEastAsianTraditionalYearData::new(2053, [s, l, s, s, l, s, s, l, s, l, l, l, s], None, gregorian(2053, 2, 19)), + PackedEastAsianTraditionalYearData::new(2054, [s, l, l, s, s, l, s, s, l, s, l, l, s], None, gregorian(2054, 2, 8)), + PackedEastAsianTraditionalYearData::new(2055, [s, l, l, s, l, s, l, s, s, l, s, l, s], Some(7), gregorian(2055, 1, 28)), + PackedEastAsianTraditionalYearData::new(2056, [l, l, l, s, l, s, l, s, s, l, s, l, s], None, gregorian(2056, 2, 15)), + PackedEastAsianTraditionalYearData::new(2057, [s, l, l, s, l, s, l, l, s, s, l, s, s], None, gregorian(2057, 2, 4)), + PackedEastAsianTraditionalYearData::new(2058, [l, s, l, s, l, l, s, l, s, l, l, s, s], Some(5), gregorian(2058, 1, 24)), + PackedEastAsianTraditionalYearData::new(2059, [l, s, l, s, l, s, l, l, s, l, l, s, s], None, gregorian(2059, 2, 12)), + PackedEastAsianTraditionalYearData::new(2060, [l, s, s, l, s, s, l, l, s, l, l, l, s], None, gregorian(2060, 2, 2)), + PackedEastAsianTraditionalYearData::new(2061, [s, l, s, s, l, s, s, l, s, l, l, l, s], Some(4), gregorian(2061, 1, 22)), + PackedEastAsianTraditionalYearData::new(2062, [l, l, s, s, l, s, s, l, s, l, l, s, s], None, gregorian(2062, 2, 9)), + PackedEastAsianTraditionalYearData::new(2063, [l, l, s, l, s, l, s, s, l, s, l, s, l], Some(8), gregorian(2063, 1, 29)), + PackedEastAsianTraditionalYearData::new(2064, [l, l, s, l, s, l, s, s, l, s, l, s, s], None, gregorian(2064, 2, 17)), + PackedEastAsianTraditionalYearData::new(2065, [l, l, s, l, l, s, l, s, s, l, s, l, s], None, gregorian(2065, 2, 5)), + PackedEastAsianTraditionalYearData::new(2066, [s, l, s, l, l, s, l, s, l, s, l, s, l], Some(6), gregorian(2066, 1, 26)), + PackedEastAsianTraditionalYearData::new(2067, [s, l, s, l, s, l, l, s, l, s, l, s, s], None, gregorian(2067, 2, 14)), + PackedEastAsianTraditionalYearData::new(2068, [l, s, l, s, l, s, l, s, l, l, s, l, s], None, gregorian(2068, 2, 3)), + PackedEastAsianTraditionalYearData::new(2069, [l, s, s, l, s, s, l, s, l, l, l, s, l], Some(5), gregorian(2069, 1, 23)), + PackedEastAsianTraditionalYearData::new(2070, [l, s, s, l, s, s, l, s, l, l, s, l, s], None, gregorian(2070, 2, 11)), + PackedEastAsianTraditionalYearData::new(2071, [l, l, s, s, l, s, s, l, s, l, s, l, l], Some(9), gregorian(2071, 1, 31)), + PackedEastAsianTraditionalYearData::new(2072, [l, s, l, s, l, s, s, l, s, l, s, l, s], None, gregorian(2072, 2, 19)), + PackedEastAsianTraditionalYearData::new(2073, [l, s, l, l, s, l, s, s, l, s, l, s, s], None, gregorian(2073, 2, 7)), + PackedEastAsianTraditionalYearData::new(2074, [l, s, l, l, s, l, s, l, s, l, s, l, s], Some(7), gregorian(2074, 1, 27)), + PackedEastAsianTraditionalYearData::new(2075, [l, s, l, s, l, l, s, l, s, l, s, l, s], None, gregorian(2075, 2, 15)), + PackedEastAsianTraditionalYearData::new(2076, [s, l, s, l, s, l, s, l, l, s, l, s, s], None, gregorian(2076, 2, 5)), + PackedEastAsianTraditionalYearData::new(2077, [l, s, l, s, s, l, s, l, l, l, s, l, s], Some(5), gregorian(2077, 1, 24)), + PackedEastAsianTraditionalYearData::new(2078, [l, s, l, s, s, l, s, l, l, s, l, l, s], None, gregorian(2078, 2, 12)), + PackedEastAsianTraditionalYearData::new(2079, [s, l, s, l, s, s, l, s, l, s, l, l, s], None, gregorian(2079, 2, 2)), + PackedEastAsianTraditionalYearData::new(2080, [l, s, l, s, l, s, s, l, s, l, s, l, l], Some(4), gregorian(2080, 1, 22)), + PackedEastAsianTraditionalYearData::new(2081, [l, s, l, s, l, s, s, l, s, s, l, l, s], None, gregorian(2081, 2, 9)), + PackedEastAsianTraditionalYearData::new(2082, [s, l, l, l, s, l, s, s, l, s, l, s, l], Some(8), gregorian(2082, 1, 29)), + PackedEastAsianTraditionalYearData::new(2083, [s, l, l, s, l, s, l, s, l, s, l, s, s], None, gregorian(2083, 2, 17)), + PackedEastAsianTraditionalYearData::new(2084, [l, s, l, s, l, l, s, l, s, l, s, l, s], None, gregorian(2084, 2, 6)), + PackedEastAsianTraditionalYearData::new(2085, [s, l, s, s, l, l, s, l, l, s, l, s, l], Some(6), gregorian(2085, 1, 26)), + PackedEastAsianTraditionalYearData::new(2086, [s, l, s, s, l, s, l, l, s, l, l, s, s], None, gregorian(2086, 2, 14)), + PackedEastAsianTraditionalYearData::new(2087, [l, s, l, s, s, l, s, l, s, l, l, l, s], None, gregorian(2087, 2, 3)), + PackedEastAsianTraditionalYearData::new(2088, [s, l, s, l, s, s, l, s, s, l, l, l, l], Some(5), gregorian(2088, 1, 24)), + PackedEastAsianTraditionalYearData::new(2089, [s, l, s, l, s, s, l, s, s, l, l, s, s], None, gregorian(2089, 2, 11)), + PackedEastAsianTraditionalYearData::new(2090, [l, l, l, s, l, s, s, l, s, s, l, l, s], Some(9), gregorian(2090, 1, 30)), + PackedEastAsianTraditionalYearData::new(2091, [l, l, s, l, s, l, s, l, s, s, l, l, s], None, gregorian(2091, 2, 18)), + PackedEastAsianTraditionalYearData::new(2092, [s, l, s, l, l, s, l, s, l, s, l, s, s], None, gregorian(2092, 2, 8)), + PackedEastAsianTraditionalYearData::new(2093, [l, s, l, s, l, s, l, l, s, l, s, l, s], Some(7), gregorian(2093, 1, 27)), + PackedEastAsianTraditionalYearData::new(2094, [l, s, s, l, s, l, l, s, l, l, s, l, s], None, gregorian(2094, 2, 15)), + PackedEastAsianTraditionalYearData::new(2095, [s, l, s, s, l, s, l, s, l, l, l, s, s], None, gregorian(2095, 2, 5)), + PackedEastAsianTraditionalYearData::new(2096, [l, s, l, s, s, l, s, l, s, l, l, s, l], Some(5), gregorian(2096, 1, 25)), + PackedEastAsianTraditionalYearData::new(2097, [l, s, l, s, s, l, s, s, l, l, s, l, s], None, gregorian(2097, 2, 12)), + PackedEastAsianTraditionalYearData::new(2098, [l, l, s, l, s, s, l, s, s, l, l, s, s], None, gregorian(2098, 2, 1)), + PackedEastAsianTraditionalYearData::new(2099, [l, l, l, s, l, s, s, l, s, s, l, s, l], Some(4), gregorian(2099, 1, 21)), + PackedEastAsianTraditionalYearData::new(2100, [l, l, s, l, s, l, s, l, s, s, l, s, s], None, gregorian(2100, 2, 9)), + // Extra two years of correct data because the simple calculation lines up at the beginning of 2103 + PackedEastAsianTraditionalYearData::new(2101, [l, l, s, l, l, s, l, s, l, s, l, s, s], Some(8), gregorian(2101, 1, 29)), + PackedEastAsianTraditionalYearData::new(2102, [l, s, l, l, s, l, s, l, l, s, l, s, s], None, gregorian(2102, 2, 17)), + ] +}; + +#[test] +fn test_against_calendrical_calculations() { + use calendrical_calculations::chinese_based::Dangi; + for (i, &data) in DATA.iter().enumerate() { + assert_eq!( + data, + super::EastAsianTraditionalYearData::calendrical_calculations::( + STARTING_YEAR + i as i32 + ) + .packed + ); + } +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/east_asian_traditional/qing_data.rs b/deps/crates/vendor/icu_calendar/src/cal/east_asian_traditional/qing_data.rs new file mode 100644 index 00000000000000..c107d7f82118ef --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/east_asian_traditional/qing_data.rs @@ -0,0 +1,32 @@ +// 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 data is confirmed by both the [Korea Astronomy and Space Science Institute](https://astro.kasi.re.kr/life/pageView/5), +//! as well as the [Hong Kong Observatory](https://www.hko.gov.hk/en/gts/time/conversion.htm). + +use super::PackedEastAsianTraditionalYearData; + +pub const STARTING_YEAR: i32 = 1900; + +#[rustfmt::skip] +#[allow(clippy::unwrap_used)] // const +pub const DATA: &[PackedEastAsianTraditionalYearData] = { + use calendrical_calculations::gregorian::fixed_from_gregorian as gregorian; + let l = true; // long + let s = false; // short + &[ + PackedEastAsianTraditionalYearData::new(1900, [s, l, s, s, l, s, l, l, s, l, l, s, l], Some(9), gregorian(1900, 1, 31)), + PackedEastAsianTraditionalYearData::new(1901, [s, l, s, s, l, s, l, s, l, l, l, s, s], None, gregorian(1901, 2, 19)), + PackedEastAsianTraditionalYearData::new(1902, [l, s, l, s, s, l, s, l, s, l, l, l, s], None, gregorian(1902, 2, 8)), + PackedEastAsianTraditionalYearData::new(1903, [s, l, s, l, s, s, l, s, s, l, l, s, l], Some(6), gregorian(1903, 1, 29)), + PackedEastAsianTraditionalYearData::new(1904, [l, l, s, l, s, s, l, s, s, l, l, s, s], None, gregorian(1904, 2, 16)), + PackedEastAsianTraditionalYearData::new(1905, [l, l, s, l, l, s, s, l, s, l, s, l, s], None, gregorian(1905, 2, 4)), + PackedEastAsianTraditionalYearData::new(1906, [s, l, l, s, l, s, l, s, l, s, l, s, l], Some(5), gregorian(1906, 1, 25)), + PackedEastAsianTraditionalYearData::new(1907, [s, l, s, l, s, l, l, s, l, s, l, s, s], None, gregorian(1907, 2, 13)), + PackedEastAsianTraditionalYearData::new(1908, [l, s, s, l, l, s, l, s, l, l, s, l, s], None, gregorian(1908, 2, 2)), + PackedEastAsianTraditionalYearData::new(1909, [s, l, s, s, l, s, l, s, l, l, l, s, l], Some(3), gregorian(1909, 1, 22)), + PackedEastAsianTraditionalYearData::new(1910, [s, l, s, s, l, s, l, s, l, l, l, s, s], None, gregorian(1910, 2, 10)), + PackedEastAsianTraditionalYearData::new(1911, [l, s, l, s, s, l, s, s, l, l, s, l, l], Some(7), gregorian(1911, 1, 30)), + ] +}; diff --git a/deps/crates/vendor/icu_calendar/src/cal/east_asian_traditional/simple.rs b/deps/crates/vendor/icu_calendar/src/cal/east_asian_traditional/simple.rs new file mode 100644 index 00000000000000..851e7371349a7b --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/east_asian_traditional/simple.rs @@ -0,0 +1,190 @@ +// 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 super::EastAsianTraditionalYearData; +use calendrical_calculations::{gregorian::DAYS_IN_400_YEAR_CYCLE, rata_die::RataDie}; + +macro_rules! day_fraction_to_ms { + ($n:tt $(/ $d:tt)+) => {{ + Milliseconds((MILLISECONDS_IN_EPHEMERIS_DAY as i128 * $n as i128 $( / $d as i128)+) as i64) + }}; + ($n:tt $(/ $d:tt)+, exact) => {{ + let d = day_fraction_to_ms!($n $(/ $d)+); + assert!((d.0 as i128 $(* $d as i128)+) % MILLISECONDS_IN_EPHEMERIS_DAY as i128 == 0, "inexact"); + d + }}; +} + +pub(super) const UTC_PLUS_8: Milliseconds = day_fraction_to_ms!(8 / 24); +pub(super) const UTC_PLUS_9: Milliseconds = day_fraction_to_ms!(9 / 24); +// Reference time was UTC+(1397/180) +pub(super) const BEIJING_UTC_OFFSET: Milliseconds = day_fraction_to_ms!(1397 / 180 / 24); + +/// The mean year length according to the Gregorian solar cycle. +const MEAN_GREGORIAN_YEAR_LENGTH: Milliseconds = + day_fraction_to_ms!(DAYS_IN_400_YEAR_CYCLE / 400, exact); + +/// The mean solar term length according to the Gregorian solar cycle +const MEAN_GREGORIAN_SOLAR_TERM_LENGTH: Milliseconds = + day_fraction_to_ms!(DAYS_IN_400_YEAR_CYCLE / 400 / 12, exact); + +/// The mean synodic length on Jan 1 2000 according to the [Astronomical Almanac (1992)]. +/// +/// [Astronomical Almanac (1992)]: https://archive.org/details/131123ExplanatorySupplementAstronomicalAlmanac/page/n302/mode/1up +const MEAN_SYNODIC_MONTH_LENGTH: Milliseconds = day_fraction_to_ms!(295305888531 / 10000000000i64); + +/// Number of milliseconds in a day. +const MILLISECONDS_IN_EPHEMERIS_DAY: i64 = 24 * 60 * 60 * 1000; + +// 1999-12-22T07:44, https://aa.usno.navy.mil/calculated/seasons?year=2024&tz=0.00&tz_sign=-1&tz_label=false&dst=false +const UTC_SOLSTICE: LocalMoment = LocalMoment { + rata_die: calendrical_calculations::gregorian::fixed_from_gregorian(1999, 12, 22), + local_milliseconds: ((7 * 60) + 44) * 60 * 1000, +}; + +// 2000-01-06T18:14 https://aa.usno.navy.mil/calculated/moon/phases?date=2000-01-01&nump=1&format=t +const UTC_NEW_MOON: LocalMoment = LocalMoment { + rata_die: calendrical_calculations::gregorian::fixed_from_gregorian(2000, 1, 6), + local_milliseconds: ((18 * 60) + 14) * 60 * 1000, +}; + +#[derive(Debug, Copy, Clone, Default)] +pub(super) struct Milliseconds(i64); + +#[derive(Debug, Copy, Clone)] +struct LocalMoment { + rata_die: RataDie, + local_milliseconds: u32, +} + +impl core::ops::Add for LocalMoment { + type Output = Self; + + fn add(self, Milliseconds(duration): Milliseconds) -> Self::Output { + let temp = self.local_milliseconds as i64 + duration; + Self { + rata_die: self.rata_die + temp.div_euclid(MILLISECONDS_IN_EPHEMERIS_DAY), + local_milliseconds: temp.rem_euclid(MILLISECONDS_IN_EPHEMERIS_DAY) as u32, + } + } +} + +impl super::EastAsianTraditionalYearData { + /// A fast approximation for the Chinese calendar, inspired by the _píngqì_ (平氣) rule + /// used in the Ming dynasty. + /// + /// Stays anchored in the Gregorian calendar, even as the Gregorian calendar drifts + /// from the seasons in the distant future and distant past. + pub(super) fn simple( + utc_offset: Milliseconds, + related_iso: i32, + ) -> EastAsianTraditionalYearData { + /// calculates the largest moment such that moment = base_moment + n * duration lands on rata_die (< rata_die + 1) + fn periodic_duration_on_or_before( + rata_die: RataDie, + base_moment: LocalMoment, + duration: Milliseconds, + ) -> LocalMoment { + let diff_millis = (rata_die - base_moment.rata_die) * MILLISECONDS_IN_EPHEMERIS_DAY + - base_moment.local_milliseconds as i64; + + let num_periods = + (diff_millis + MILLISECONDS_IN_EPHEMERIS_DAY - 1).div_euclid(duration.0); + + let millis = base_moment.rata_die.to_i64_date() * MILLISECONDS_IN_EPHEMERIS_DAY + + base_moment.local_milliseconds as i64 + + num_periods * duration.0; + + // Note: this is Euclidean div/rem, but this more optimized, because + // we know that our divisor is positive + let rata_die = millis / MILLISECONDS_IN_EPHEMERIS_DAY - (millis < 0) as i64; + let local_milliseconds = millis % MILLISECONDS_IN_EPHEMERIS_DAY + + (millis < 0) as i64 * MILLISECONDS_IN_EPHEMERIS_DAY; + + LocalMoment { + rata_die: RataDie::new(rata_die), + local_milliseconds: local_milliseconds as u32, + } + } + + let mut major_solar_term = periodic_duration_on_or_before( + calendrical_calculations::iso::day_before_year(related_iso), + UTC_SOLSTICE + utc_offset, + MEAN_GREGORIAN_YEAR_LENGTH, + ); + + let mut new_moon = periodic_duration_on_or_before( + major_solar_term.rata_die, + UTC_NEW_MOON + utc_offset, + MEAN_SYNODIC_MONTH_LENGTH, + ); + + let mut next_new_moon = new_moon + MEAN_SYNODIC_MONTH_LENGTH; + + // The solstice is in the month of the 11th solar term of the previous year + let mut solar_term = -2; + let mut had_leap_in_sui = false; + + // Skip the months before the year (M11, maybe M11L, M12, maybe M12L) + while solar_term < 0 + || (next_new_moon.rata_die <= major_solar_term.rata_die && !had_leap_in_sui) + { + if next_new_moon.rata_die <= major_solar_term.rata_die && !had_leap_in_sui { + had_leap_in_sui = true; + } else { + solar_term += 1; + major_solar_term = major_solar_term + MEAN_GREGORIAN_SOLAR_TERM_LENGTH; + } + + (new_moon, next_new_moon) = (next_new_moon, next_new_moon + MEAN_SYNODIC_MONTH_LENGTH); + } + + debug_assert_eq!(solar_term, 0); + + let start_day = new_moon.rata_die; + let mut month_lengths = [false; 13]; + let mut leap_month = None; + + // Iterate over the 12 solar terms, producing potentially 13 months + while solar_term < 12 + || (next_new_moon.rata_die <= major_solar_term.rata_die && !had_leap_in_sui) + { + *month_lengths + .get_mut(solar_term as usize + leap_month.is_some() as usize) + .unwrap_or(&mut false) = next_new_moon.rata_die - new_moon.rata_die == 30; + + if next_new_moon.rata_die <= major_solar_term.rata_die && !had_leap_in_sui { + had_leap_in_sui = true; + leap_month = Some(solar_term as u8 + 1); + } else { + solar_term += 1; + major_solar_term = major_solar_term + MEAN_GREGORIAN_SOLAR_TERM_LENGTH; + } + + (new_moon, next_new_moon) = (next_new_moon, next_new_moon + MEAN_SYNODIC_MONTH_LENGTH); + } + + debug_assert_eq!(solar_term, 12); + + EastAsianTraditionalYearData::new(related_iso, start_day, month_lengths, leap_month) + } +} + +#[test] +fn bounds() { + EastAsianTraditionalYearData::simple(UTC_PLUS_9, 292_277_025); + assert!( + std::panic::catch_unwind(|| EastAsianTraditionalYearData::simple(UTC_PLUS_9, 292_277_026)) + .is_err() + ); + + EastAsianTraditionalYearData::simple(BEIJING_UTC_OFFSET, -292_275_024); + assert!( + std::panic::catch_unwind(|| EastAsianTraditionalYearData::simple( + BEIJING_UTC_OFFSET, + -292_275_025 + )) + .is_err() + ); +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/ethiopian.rs b/deps/crates/vendor/icu_calendar/src/cal/ethiopian.rs index 3fd0cb96a07b58..559864e2f765c5 100644 --- a/deps/crates/vendor/icu_calendar/src/cal/ethiopian.rs +++ b/deps/crates/vendor/icu_calendar/src/cal/ethiopian.rs @@ -2,33 +2,27 @@ // 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 crate::cal::coptic::CopticDateInner; +use crate::cal::Coptic; +use crate::calendar_arithmetic::{ArithmeticDate, DateFieldsResolver}; +use crate::error::{ + DateError, DateFromFieldsError, EcmaReferenceYearError, MonthCodeError, UnknownEraError, +}; +use crate::options::DateFromFieldsOptions; +use crate::options::{DateAddOptions, DateDifferenceOptions}; +use crate::types::DateFields; +use crate::{types, Calendar, Date, RangeError}; 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; +/// The Coptic year of the Amete Mihret epoch +const AMETE_MIHRET_OFFSET: i32 = -276; + +/// The Coptic year of the Amete Alem epoch +const AMETE_ALEM_OFFSET: i32 = -5776; /// Which era style the ethiopian calendar uses -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] #[non_exhaustive] pub enum EthiopianEraStyle { /// Use the Anno Mundi era, anchored at the date of Creation, followed by the @@ -38,74 +32,110 @@ pub enum EthiopianEraStyle { AmeteAlem, } -/// The [Ethiopian Calendar] +/// The [Ethiopian Calendar](https://en.wikipedia.org/wiki/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. +/// The Ethiopian calendar is a variant of the [`Coptic`] calendar. It differs +/// from the Coptic calendar by the names of the months as well as the era. /// -/// This type can be used with [`Date`] to represent dates in this calendar. +/// This implementation 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. /// -/// 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. +/// This implementation extends proleptically for dates before the calendar's creation. /// -/// [Ethiopian calendar]: https://en.wikipedia.org/wiki/Ethiopian_calendar +/// This corresponds to the `"ethiopic"` and `"ethioaa"` [CLDR calendars](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier), +/// with `"ethiopic"` being for [`EthiopianEraStyle::AmeteMihret`] /// /// # 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 +/// # Months and days +/// +/// The 13 months are called Mäskäräm (`M01`, 30 days), Ṭəqəmt (`M02`, 30 days), +/// Ḫədar (`M03`, 30 days), Taḫśaś (`M04`, 30 days), Ṭərr (`M05`, 30 days), Yäkatit (`M06`, 30 days), +/// Mägabit (`M07`, 30 days), Miyazya (`M08`, 30 days), Gənbo (`M09`, 30 days), +/// Säne (`M10`, 30 days), Ḥamle (`M11`, 30 days), Nähase (`M12`, 30 days), Ṗagʷəmen (`M13`, 5 days). +/// +/// In leap years (years divisible by 4), Ṗagʷəmen gains a 6th day. /// -/// 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); +/// Standard years thus have 365 days, and leap years 366. +/// +/// # Calendar drift +/// +/// The Ethiopian calendar has the same year lengths and leap year rules as the [`Coptic`] and +/// [`Julian`](crate::cal::Julian) calendars, so it experiences the same drift of 1 day in ~128 +/// years with respect to the seasons. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +pub struct Ethiopian(EthiopianEraStyle); -/// The inner date type used for representing [`Date`]s of [`Ethiopian`]. See [`Date`] and [`Ethiopian`] for more details. +impl Default for Ethiopian { + fn default() -> Self { + Self(EthiopianEraStyle::AmeteMihret) + } +} + +#[allow(missing_docs)] // not actually public #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] -pub struct EthiopianDateInner(ArithmeticDate); +pub struct EthiopianDateInner(CopticDateInner); -impl CalendarArithmetic for Ethiopian { +impl DateFieldsResolver for Ethiopian { + // Coptic year 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 days_in_provided_month(year: Self::YearInfo, month: u8) -> u8 { + Coptic::days_in_provided_month(year, month) } - fn months_in_provided_year(_: i32) -> u8 { - 13 + fn months_in_provided_year(year: Self::YearInfo) -> u8 { + Coptic::months_in_provided_year(year) } - fn provided_year_is_leap(year: i32) -> bool { - year.rem_euclid(4) == 3 + #[inline] + fn year_info_from_era( + &self, + era: &[u8], + era_year: i32, + ) -> Result { + match (self.era_style(), era) { + (EthiopianEraStyle::AmeteMihret, b"am") => Ok(era_year + AMETE_MIHRET_OFFSET), + (_, b"aa") => Ok(era_year + AMETE_ALEM_OFFSET), + (_, _) => Err(UnknownEraError), + } } - fn last_month_day_in_provided_year(year: i32) -> (u8, u8) { - if Self::provided_year_is_leap(year) { - (13, 6) - } else { - (13, 5) - } + #[inline] + fn year_info_from_extended(&self, extended_year: i32) -> Self::YearInfo { + extended_year + + if self.0 == EthiopianEraStyle::AmeteMihret { + AMETE_MIHRET_OFFSET + } else { + AMETE_ALEM_OFFSET + } } - fn days_in_provided_year(year: i32) -> u16 { - if Self::provided_year_is_leap(year) { - 366 - } else { - 365 + #[inline] + fn reference_year_from_month_day( + &self, + month_code: types::ValidMonthCode, + day: u8, + ) -> Result { + crate::cal::Coptic::reference_year_from_month_day(month_code, day) + } + + #[inline] + fn ordinal_month_from_code( + &self, + _year: &Self::YearInfo, + month_code: types::ValidMonthCode, + _options: DateFromFieldsOptions, + ) -> Result { + match month_code.to_tuple() { + (month_number @ 1..=13, false) => Ok(month_number), + _ => Err(MonthCodeError::NotInCalendar), } } } @@ -113,7 +143,9 @@ impl CalendarArithmetic for Ethiopian { impl crate::cal::scaffold::UnstableSealed for Ethiopian {} impl Calendar for Ethiopian { type DateInner = EthiopianDateInner; - type Year = types::EraYear; + type Year = ::Year; + type DifferenceError = ::DifferenceError; + fn from_codes( &self, era: Option<&str>, @@ -121,123 +153,111 @@ impl Calendar for Ethiopian { 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) + ArithmeticDate::from_codes(era, year, month_code, day, self) + .map(ArithmeticDate::cast) + .map(CopticDateInner) + .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, - ), - }, - ) + #[cfg(feature = "unstable")] + fn from_fields( + &self, + fields: DateFields, + options: DateFromFieldsOptions, + ) -> Result { + ArithmeticDate::from_fields(fields, options, self) + .map(ArithmeticDate::cast) + .map(CopticDateInner) + .map(EthiopianDateInner) } - 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_rata_die(&self, rd: RataDie) -> Self::DateInner { + EthiopianDateInner(Coptic.from_rata_die(rd)) } - fn from_iso(&self, iso: IsoDateInner) -> EthiopianDateInner { - self.from_rata_die(Iso.to_rata_die(&iso)) + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + Coptic.to_rata_die(&date.0) } - fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { - Iso.from_rata_die(self.to_rata_die(date)) + fn has_cheap_iso_conversion(&self) -> bool { + false } fn months_in_year(&self, date: &Self::DateInner) -> u8 { - date.0.months_in_year() + Coptic.months_in_year(&date.0) } fn days_in_year(&self, date: &Self::DateInner) -> u16 { - date.0.days_in_year() + Coptic.days_in_year(&date.0) } fn days_in_month(&self, date: &Self::DateInner) -> u8 { - date.0.days_in_month() + Coptic.days_in_month(&date.0) } - fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { - date.0.offset_date(offset, &()); + #[cfg(feature = "unstable")] + fn add( + &self, + date: &Self::DateInner, + duration: types::DateDuration, + options: DateAddOptions, + ) -> Result { + Coptic + .add(&date.0, duration, options) + .map(EthiopianDateInner) } - #[allow(clippy::field_reassign_with_default)] + #[cfg(feature = "unstable")] 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) + options: DateDifferenceOptions, + ) -> Result { + Coptic.until(&date1.0, &date2.0, options) } fn year_info(&self, date: &Self::DateInner) -> Self::Year { - let year = date.0.year; - if self.0 || year <= INCARNATION_OFFSET { + let coptic_year = date.0 .0.year; + let extended_year = if self.0 == EthiopianEraStyle::AmeteAlem { + coptic_year - AMETE_ALEM_OFFSET + } else { + coptic_year - AMETE_MIHRET_OFFSET + }; + + if self.0 == EthiopianEraStyle::AmeteAlem || extended_year <= 0 { types::EraYear { era: tinystr!(16, "aa"), era_index: Some(0), - year, + year: coptic_year - AMETE_ALEM_OFFSET, + extended_year, ambiguity: types::YearAmbiguity::CenturyRequired, } } else { types::EraYear { era: tinystr!(16, "am"), era_index: Some(1), - year: year - INCARNATION_OFFSET, + year: coptic_year - AMETE_MIHRET_OFFSET, + extended_year, 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) + Coptic.is_in_leap_year(&date.0) } fn month(&self, date: &Self::DateInner) -> types::MonthInfo { - date.0.month() + Coptic.month(&date.0) } fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { - date.0.day_of_month() + Coptic.day_of_month(&date.0) } fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { - date.0.day_of_year() + Coptic.day_of_year(&date.0) } fn debug_name(&self) -> &'static str { @@ -252,20 +272,17 @@ impl Calendar for Ethiopian { impl Ethiopian { /// Construct a new Ethiopian Calendar for the Amete Mihret era naming scheme pub const fn new() -> Self { - Self(false) + Self(EthiopianEraStyle::AmeteMihret) } - /// Construct a new Ethiopian Calendar with a value specifying whether or not it is Amete Alem + + /// Construct a new Ethiopian Calendar with an explicit [`EthiopianEraStyle`]. pub const fn new_with_era_style(era_style: EthiopianEraStyle) -> Self { - Self(matches!(era_style, EthiopianEraStyle::AmeteAlem)) + Self(era_style) } - /// Returns whether this has the Amete Alem era + /// Returns the [`EthiopianEraStyle`] used by this calendar. pub fn era_style(&self) -> EthiopianEraStyle { - if self.0 { - EthiopianEraStyle::AmeteAlem - } else { - EthiopianEraStyle::AmeteMihret - } + self.0 } } @@ -286,16 +303,15 @@ impl Date { /// ``` pub fn try_new_ethiopian( era_style: EthiopianEraStyle, - mut year: i32, + year: i32, month: u8, day: u8, ) -> Result, RangeError> { - if era_style == EthiopianEraStyle::AmeteAlem { - year -= INCARNATION_OFFSET; - } - ArithmeticDate::new_from_ordinals(year, month, day) + let year = Ethiopian(era_style).year_info_from_extended(year); + ArithmeticDate::try_from_ymd(year, month, day) + .map(CopticDateInner) .map(EthiopianDateInner) - .map(|inner| Date::from_raw(inner, Ethiopian::new_with_era_style(era_style))) + .map(|inner| Date::from_raw(inner, Ethiopian(era_style))) } } @@ -331,10 +347,7 @@ mod test { #[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), - ); + let date_ethiopian = Date::new_from_iso(iso_date, Ethiopian(EthiopianEraStyle::AmeteAlem)); assert_eq!(date_ethiopian.extended_year(), 7462); assert_eq!(date_ethiopian.month().ordinal, 4); @@ -360,7 +373,7 @@ mod test { assert_eq!( Date::new_from_iso( Date::try_new_iso(-5500 + 9, 1, 1).unwrap(), - Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteAlem) + Ethiopian(EthiopianEraStyle::AmeteAlem) ) .extended_year(), 1 @@ -368,7 +381,7 @@ mod test { assert_eq!( Date::new_from_iso( Date::try_new_iso(9, 1, 1).unwrap(), - Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteAlem) + Ethiopian(EthiopianEraStyle::AmeteAlem) ) .extended_year(), 5501 @@ -377,7 +390,7 @@ mod test { assert_eq!( Date::new_from_iso( Date::try_new_iso(-5500 + 9, 1, 1).unwrap(), - Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteMihret) + Ethiopian(EthiopianEraStyle::AmeteMihret) ) .extended_year(), -5499 @@ -385,7 +398,7 @@ mod test { assert_eq!( Date::new_from_iso( Date::try_new_iso(9, 1, 1).unwrap(), - Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteMihret) + Ethiopian(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 index 0466be71743ba5..2475fd562a5c27 100644 --- a/deps/crates/vendor/icu_calendar/src/cal/gregorian.rs +++ b/deps/crates/vendor/icu_calendar/src/cal/gregorian.rs @@ -2,122 +2,39 @@ // 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::cal::abstract_gregorian::{impl_with_abstract_gregorian, GregorianYears}; 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 crate::error::UnknownEraError; +use crate::preferences::CalendarAlgorithm; +use crate::{types, Date, DateError, RangeError}; 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; +impl_with_abstract_gregorian!(crate::cal::Gregorian, GregorianDateInner, CeBce, _x, CeBce); -#[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); +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) struct CeBce; -impl crate::cal::scaffold::UnstableSealed for Gregorian {} -impl Calendar for Gregorian { - type DateInner = GregorianDateInner; - type Year = types::EraYear; - fn from_codes( +impl GregorianYears for CeBce { + fn extended_from_era_year( &self, - era: Option<&str>, + era: Option<&[u8]>, 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()) + ) -> Result { + match era { + None => Ok(year), + Some(b"ad" | b"ce") => Ok(year), + Some(b"bce" | b"bc") => Ok(1 - year), + Some(_) => Err(UnknownEraError), + } } - #[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); + fn era_year_from_extended(&self, extended_year: i32, _month: u8, _day: u8) -> types::EraYear { if extended_year > 0 { types::EraYear { era: tinystr!(16, "ce"), era_index: Some(1), year: extended_year, + extended_year, ambiguity: match extended_year { ..=999 => types::YearAmbiguity::EraAndCenturyRequired, 1000..=1949 => types::YearAmbiguity::CenturyRequired, @@ -129,44 +46,77 @@ impl Calendar for Gregorian { types::EraYear { era: tinystr!(16, "bce"), era_index: Some(0), - year: 1_i32.saturating_sub(extended_year), + year: 1 - extended_year, + 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) + fn calendar_algorithm(&self) -> Option { + Some(CalendarAlgorithm::Gregory) } } +/// The [Gregorian Calendar](https://en.wikipedia.org/wiki/Gregorian_calendar) +/// +/// The Gregorian calendar is an improvement over the [`Julian`](super::Julian) calendar. +/// It was adopted under Pope Gregory XIII in 1582 CE by much of Roman Catholic Europe, +/// and over the following centuries by all other countries that had been using +/// the Julian calendar. Eventually even countries that had been using other calendars +/// adopted this calendar, and today it is used as the international civil calendar. +/// +/// This implementation extends proleptically for dates before the calendar's creation. +/// +/// This corresponds to the `"gregory"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). +/// +/// # Era codes +/// +/// This calendar uses two era codes: `bce` (alias `bc`), and `ce` (alias `ad`), corresponding to the BCE and CE eras. +/// +/// # Months and days +/// +/// The 12 months are called January (`M01`, 31 days), February (`M02`, 28 days), +/// March (`M03`, 31 days), April (`M04`, 30 days), May (`M05`, 31 days), June (`M06`, 30 days), +/// July (`M07`, 31 days), August (`M08`, 31 days), September (`M09`, 30 days), +/// October (`M10`, 31 days), November (`M11`, 30 days), December (`M12`, 31 days). +/// +/// In leap years (years divisible by 4 but not 100 except when divisble by 400), February gains a 29th day. +/// +/// Standard years thus have 365 days, and leap years 366. +/// +/// # Calendar drift +/// +/// The Gregorian calendar has an average year length of 365.2425, slightly longer than +/// the mean solar year, so this calendar drifts 1 day in ~7700 years with respect +/// to the seasons. +/// +/// # Historical accuracy +/// +/// This type implements the [*proleptic* Gregorian calendar]( +/// https://en.wikipedia.org/wiki/Gregorian_calendar#Proleptic_Gregorian_calendar), +/// with dates before 1582 CE using the rules projected backwards. Care needs to be taken +/// when intepreting historical dates before or during the transition from the Julian to +/// the Gregorian calendar. [Some regions](https://en.wikipedia.org/wiki/Adoption_of_the_Gregorian_calendar) +/// continued using the Julian calendar as late as the 20th century. Sources often +/// mark dates as "New Style" (Gregorian) or "Old Style" (Julian) if there is ambiguity. +/// +/// Historically, the Julian/Gregorian calendars were used with a variety of year reckoning +/// schemes (see [`Julian`](super::Julian) for more detail). The Gregorian calendar has generally +/// been used with the [Anno Domini](https://en.wikipedia.org/wiki/Anno_Domini)/[Common era]( +/// https://en.wikipedia.org/wiki/Common_Era) since its inception. However, some countries +/// that have adopted the Gregorian calendar more recently are still using their traditional +/// year-reckoning schemes. This crate implements some of these as different types, i.e the Thai +/// [`Buddhist`](super::Buddhist) calendar, the [`Japanese`](super::Japanese) calendar, and the +/// Chinese Republican Calendar ([`Roc`](super::Roc)). +#[derive(Copy, Clone, Debug, Default)] +#[allow(clippy::exhaustive_structs)] // this type is stable +pub struct Gregorian; + impl Date { /// Construct a new Gregorian Date. /// @@ -184,12 +134,22 @@ impl Date { /// 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)) + ArithmeticDate::new_gregorian::(year, month, day) + .map(GregorianDateInner) + .map(|i| Date::from_raw(i, Gregorian)) + } +} + +impl Gregorian { + /// Returns the date of Easter in the given year. + pub fn easter(year: i32) -> Date { + Date::from_rata_die(calendrical_calculations::gregorian::easter(year), Self) } } #[cfg(test)] mod test { + use crate::cal::Iso; use calendrical_calculations::rata_die::RataDie; use super::*; diff --git a/deps/crates/vendor/icu_calendar/src/cal/hebrew.rs b/deps/crates/vendor/icu_calendar/src/cal/hebrew.rs index e0464a2c1af691..e1e43953ca8866 100644 --- a/deps/crates/vendor/icu_calendar/src/cal/hebrew.rs +++ b/deps/crates/vendor/icu_calendar/src/cal/hebrew.rs @@ -2,26 +2,15 @@ // 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::calendar_arithmetic::{ArithmeticDate, DateFieldsResolver, ToExtendedYear}; +use crate::error::{ + DateError, DateFromFieldsError, EcmaReferenceYearError, MonthCodeError, UnknownEraError, +}; +use crate::options::{DateAddOptions, DateDifferenceOptions}; +use crate::options::{DateFromFieldsOptions, Overflow}; +use crate::types::{DateFields, MonthInfo, ValidMonthCode}; use crate::RangeError; -use crate::{types, Calendar, Date, DateDuration, DateDurationUnit}; +use crate::{types, Calendar, Date}; use ::tinystr::tinystr; use calendrical_calculations::hebrew_keviyah::{Keviyah, YearInfo}; use calendrical_calculations::rata_die::RataDie; @@ -31,21 +20,35 @@ use calendrical_calculations::rata_die::RataDie; /// 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. +/// This implementation uses civil month numbering, where Tishrei is the first month of the year. +/// +/// The precise algorithm used to calculate the Hebrew Calendar has [changed over time], with +/// the modern one being in place since about 4536 AM (776 CE). This implementation extends +/// proleptically for dates before that. +/// +/// [changed over time]: https://hakirah.org/vol20AjdlerAppendices.pdf +/// +/// This corresponds to the `"hebrew"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). /// /// # Era codes /// /// This calendar uses a single era code `am`, Anno Mundi. Dates before this era use negative years. /// -/// # Month codes +/// # Months and days /// -/// 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"`. +/// The 12 months are called Tishrei (`M01`, 30 days), Ḥešvan (`M02`, 29/30 days), +/// Kīslev (`M03`, 30/29 days), Ṭevet (`M04`, 29 days), Šəvaṭ (`M05`, 30 days), ʾĂdār (`M06`, 29 days), +/// Nīsān (`M07`, 30 days), ʾĪyyar (`M08`, 29 days), Sivan (`M09`, 30 days), Tammūz (`M10`, 29 days), +/// ʾAv (`M11`, 30 days), ʾElūl (`M12`, 29 days). /// -/// [`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)] +/// Due to Rosh Hashanah postponement rules, Ḥešvan and Kislev vary in length. +/// +/// In leap years (years 3, 6, 8, 11, 17, 19 in a 19-year cycle), the leap month Adar I (`M05L`, 30 days) +/// is inserted before Adar, and Adar is called Adar II (the `formatting_code` returned by [`MonthInfo`] +/// will be `M06L` to mark this, while the `standard_code` remains `M06`). +/// +/// Standard years thus have 353-355 days, and leap years 383-385. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Default)] #[allow(clippy::exhaustive_structs)] // unit struct pub struct Hebrew; @@ -63,42 +66,29 @@ impl 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 ToExtendedYear for HebrewYearInfo { + fn to_extended_year(&self) -> i32 { + self.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; + fn compute(value: i32) -> Self { Self { - keviyah, - prev_keviyah, - value: h_year, + keviyah: YearInfo::compute_for(value).keviyah, + value, } } } -// HEBREW CALENDAR -impl CalendarArithmetic for Hebrew { +impl DateFieldsResolver for Hebrew { type YearInfo = HebrewYearInfo; - fn days_in_provided_month(info: HebrewYearInfo, ordinal_month: u8) -> u8 { info.keviyah.month_len(ordinal_month) } @@ -111,22 +101,91 @@ impl CalendarArithmetic for Hebrew { } } - fn days_in_provided_year(info: HebrewYearInfo) -> u16 { - info.keviyah.year_length() + #[inline] + fn year_info_from_era( + &self, + era: &[u8], + era_year: i32, + ) -> Result { + match era { + b"am" => Ok(HebrewYearInfo::compute(era_year)), + _ => Err(UnknownEraError), + } + } + + #[inline] + fn year_info_from_extended(&self, extended_year: i32) -> Self::YearInfo { + HebrewYearInfo::compute(extended_year) } - fn provided_year_is_leap(info: HebrewYearInfo) -> bool { - info.keviyah.is_leap() + fn reference_year_from_month_day( + &self, + month_code: types::ValidMonthCode, + day: u8, + ) -> Result { + // December 31, 1972 occurs on 4th month, 26th day, 5733 AM + let hebrew_year = match month_code.to_tuple() { + (1, false) => 5733, + (2, false) => match day { + // There is no day 30 in 5733 (there is in 5732) + ..=29 => 5733, + // Note (here and below): this must be > 29, not just == 30, + // since we have not yet applied a potential Overflow::Constrain. + _ => 5732, + }, + (3, false) => match day { + // There is no day 30 in 5733 (there is in 5732) + ..=29 => 5733, + _ => 5732, + }, + (4, false) => match day { + ..=26 => 5733, + _ => 5732, + }, + (5..=12, false) => 5732, + // Neither 5731 nor 5732 is a leap year + (5, true) => 5730, + _ => { + return Err(EcmaReferenceYearError::MonthCodeNotInCalendar); + } + }; + Ok(HebrewYearInfo::compute(hebrew_year)) } - fn last_month_day_in_provided_year(info: HebrewYearInfo) -> (u8, u8) { - info.keviyah.last_month_day_in_year() + fn ordinal_month_from_code( + &self, + year: &Self::YearInfo, + month_code: types::ValidMonthCode, + options: DateFromFieldsOptions, + ) -> Result { + let is_leap_year = year.keviyah.is_leap(); + let ordinal_month = match month_code.to_tuple() { + (n @ 1..=12, false) => n + (n >= 6 && is_leap_year) as u8, + (5, true) => { + if is_leap_year { + 6 + } else if matches!(options.overflow, Some(Overflow::Constrain)) { + // M05L maps to M06 in a common year + 6 + } else { + return Err(MonthCodeError::NotInYear); + } + } + _ => return Err(MonthCodeError::NotInCalendar), + }; + Ok(ordinal_month) } -} -impl PrecomputedDataSource for () { - fn load_or_compute_info(&self, h_year: i32) -> HebrewYearInfo { - HebrewYearInfo::compute(h_year) + fn month_code_from_ordinal( + &self, + year: &Self::YearInfo, + ordinal_month: u8, + ) -> types::ValidMonthCode { + let is_leap = year.keviyah.is_leap(); + ValidMonthCode::new_unchecked( + ordinal_month - (is_leap && ordinal_month >= 6) as u8, + ordinal_month == 6 && is_leap, + ) } } @@ -134,6 +193,7 @@ impl crate::cal::scaffold::UnstableSealed for Hebrew {} impl Calendar for Hebrew { type DateInner = HebrewDateInner; type Year = types::EraYear; + type DifferenceError = core::convert::Infallible; fn from_codes( &self, @@ -142,118 +202,78 @@ impl Calendar for Hebrew { 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)); - } - } - }; + ArithmeticDate::from_codes(era, year, month_code, day, self).map(HebrewDateInner) + } - Ok(HebrewDateInner(ArithmeticDate::new_from_ordinals( - year, - month_ordinal, - day, - )?)) + #[cfg(feature = "unstable")] + fn from_fields( + &self, + fields: DateFields, + options: DateFromFieldsOptions, + ) -> Result { + ArithmeticDate::from_fields(fields, options, self).map(HebrewDateInner) } 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_info, year) = YearInfo::year_containing_rd(rd); + let keviyah = year_info.keviyah; - 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)) + // Obtaining a 1-indexed day-in-year value + let day_in_year = u16::try_from(rd - year_info.new_year() + 1).unwrap_or(u16::MAX); + let (month, day) = keviyah.month_day_for(day_in_year); + + HebrewDateInner(ArithmeticDate::new_unchecked( + HebrewYearInfo { + keviyah, + value: 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); + let ny = date.0.year.keviyah.year_info(date.0.year.value).new_year(); + let days_preceding = date.0.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 has_cheap_iso_conversion(&self) -> bool { + false } fn months_in_year(&self, date: &Self::DateInner) -> u8 { - date.0.months_in_year() + Self::months_in_provided_year(date.0.year) } fn days_in_year(&self, date: &Self::DateInner) -> u16 { - date.0.days_in_year() + date.0.year.keviyah.year_length() } fn days_in_month(&self, date: &Self::DateInner) -> u8 { - date.0.days_in_month() + Self::days_in_provided_month(date.0.year, date.0.month) } - fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { - date.0.offset_date(offset, &()) + #[cfg(feature = "unstable")] + fn add( + &self, + date: &Self::DateInner, + duration: types::DateDuration, + options: DateAddOptions, + ) -> Result { + date.0.added(duration, self, options).map(HebrewDateInner) } + #[cfg(feature = "unstable")] 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) + options: DateDifferenceOptions, + ) -> Result { + Ok(date1.0.until(&date2.0, self, options)) } fn debug_name(&self) -> &'static str { @@ -261,76 +281,44 @@ impl Calendar for Hebrew { } fn year_info(&self, date: &Self::DateInner) -> Self::Year { + let extended_year = date.0.year.value; types::EraYear { era_index: Some(0), era: tinystr!(16, "am"), - year: self.extended_year(date), + year: extended_year, + extended_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) + date.0.year.keviyah.is_leap() } 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")), - }; - } - } + let valid_standard_code = self.month_code_from_ordinal(&date.0.year, date.0.month); - 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"), + let valid_formatting_code = if valid_standard_code.number() == 6 && date.0.month == 7 { + ValidMonthCode::new_unchecked(6, true) // M06L + } else { + valid_standard_code }; types::MonthInfo { ordinal: date.0.month, - standard_code: types::MonthCode(code), - formatting_code: types::MonthCode(code), + standard_code: valid_standard_code.to_month_code(), + valid_standard_code, + formatting_code: valid_formatting_code.to_month_code(), + valid_formatting_code, } } fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { - date.0.day_of_month() + types::DayOfMonth(date.0.day) } fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { - date.0.day_of_year() + types::DayOfYear(date.0.year.keviyah.days_preceding(date.0.month) + date.0.day as u16) } fn calendar_algorithm(&self) -> Option { @@ -339,26 +327,18 @@ impl Calendar for 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) - /// + /// This method uses an ordinal month, which is probably not what you want. /// - /// ```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> { + /// Use [`Date::try_new_from_codes`] + #[deprecated(since = "2.1.0", note = "use `Date::try_new_from_codes`")] + pub fn try_new_hebrew( + year: i32, + ordinal_month: u8, + day: u8, + ) -> Result, RangeError> { let year = HebrewYearInfo::compute(year); - ArithmeticDate::new_from_ordinals(year, month, day) + ArithmeticDate::try_from_ymd(year, ordinal_month, day) .map(HebrewDateInner) .map(|inner| Date::from_raw(inner, Hebrew)) } @@ -369,21 +349,28 @@ 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; + pub const TISHREI: ValidMonthCode = ValidMonthCode::new_unchecked(1, false); + pub const ḤESHVAN: ValidMonthCode = ValidMonthCode::new_unchecked(2, false); + pub const KISLEV: ValidMonthCode = ValidMonthCode::new_unchecked(3, false); + pub const TEVET: ValidMonthCode = ValidMonthCode::new_unchecked(4, false); + pub const SHEVAT: ValidMonthCode = ValidMonthCode::new_unchecked(5, false); + pub const ADARI: ValidMonthCode = ValidMonthCode::new_unchecked(5, true); + pub const ADAR: ValidMonthCode = ValidMonthCode::new_unchecked(6, false); + pub const NISAN: ValidMonthCode = ValidMonthCode::new_unchecked(7, false); + pub const IYYAR: ValidMonthCode = ValidMonthCode::new_unchecked(8, false); + pub const SIVAN: ValidMonthCode = ValidMonthCode::new_unchecked(9, false); + pub const TAMMUZ: ValidMonthCode = ValidMonthCode::new_unchecked(10, false); + pub const AV: ValidMonthCode = ValidMonthCode::new_unchecked(11, false); + pub const ELUL: ValidMonthCode = ValidMonthCode::new_unchecked(12, false); /// 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] = [ + #[expect(clippy::type_complexity)] + const ISO_HEBREW_DATE_PAIRS: [((i32, u8, u8), (i32, ValidMonthCode, u8)); 48] = [ ((2021, 1, 10), (5781, TEVET, 26)), ((2021, 1, 25), (5781, SHEVAT, 12)), ((2021, 2, 10), (5781, SHEVAT, 28)), @@ -438,17 +425,12 @@ mod tests { 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) + let hebrew_date = Date::try_new_from_codes(Some("am"), y, m.to_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); + let hebrew_to_iso = hebrew_date.to_iso(); assert_eq!( hebrew_to_iso, iso_date, @@ -459,19 +441,16 @@ mod tests { "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 - } + let ordinal_month = if (m == ADARI || m.number() >= ADAR.number()) + && LEAP_YEARS_IN_TESTS.contains(&y) + { + m.number() + 1 } else { assert!(m != ADARI); - m + m.number() }; + #[allow(deprecated)] // should still test let ordinal_hebrew_date = Date::try_new_hebrew(y, ordinal_month, d) .expect("Construction of date must succeed"); @@ -489,7 +468,7 @@ mod tests { 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_date.inner.0.year, -5000); assert_eq!(greg_year.era, "bce"); // In Gregorian, era year is 1 - extended year assert_eq!(greg_year.year, 5001); @@ -506,7 +485,7 @@ mod tests { // https://github.com/unicode-org/icu4x/issues/4893 let cal = Hebrew::new(); let era = "am"; - let month_code = MonthCode(tinystr!(4, "M01")); + let month_code = MonthCode::new_normal(1).unwrap(); let dt = Date::try_new_from_codes(Some(era), 3760, month_code, 1, cal).unwrap(); // Should be Saturday per: diff --git a/deps/crates/vendor/icu_calendar/src/cal/hijri.rs b/deps/crates/vendor/icu_calendar/src/cal/hijri.rs index 02a5d920269fa7..cd445acd34067a 100644 --- a/deps/crates/vendor/icu_calendar/src/cal/hijri.rs +++ b/deps/crates/vendor/icu_calendar/src/cal/hijri.rs @@ -2,533 +2,191 @@ // 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::calendar_arithmetic::ArithmeticDate; +use crate::calendar_arithmetic::DateFieldsResolver; +use crate::calendar_arithmetic::ToExtendedYear; +use crate::error::{DateError, DateFromFieldsError, EcmaReferenceYearError, UnknownEraError}; +use crate::options::DateFromFieldsOptions; +use crate::options::{DateAddOptions, DateDifferenceOptions}; +use crate::types::DateFields; +use crate::{types, Calendar, Date}; use crate::{AsCalendar, RangeError}; -use calendrical_calculations::islamic::{ISLAMIC_EPOCH_FRIDAY, ISLAMIC_EPOCH_THURSDAY}; +use calendrical_calculations::islamic::{ + ISLAMIC_EPOCH_FRIDAY, ISLAMIC_EPOCH_THURSDAY, WELL_BEHAVED_ASTRONOMICAL_RANGE, +}; use calendrical_calculations::rata_die::RataDie; -use icu_provider::marker::ErasedMarker; +use core::fmt::Debug; +use icu_locale_core::preferences::extensions::unicode::keywords::{ + CalendarAlgorithm, HijriCalendarAlgorithm, +}; use icu_provider::prelude::*; use tinystr::tinystr; -use ummalqura_data::{UMMALQURA_DATA, UMMALQURA_DATA_STARTING_YEAR}; +#[path = "hijri/simulated_mecca_data.rs"] +mod simulated_mecca_data; +#[path = "hijri/ummalqura_data.rs"] 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 +/// The [Hijri Calendar](https://en.wikipedia.org/wiki/Islamic_calendar) /// -/// # Month codes +/// There are many variants of this calendar, using different lunar observations or calculations +/// (see [`Rules`]). Currently, [`Rules`] is an unstable trait, but some of its implementors +/// are stable, and can be constructed via the various `Hijri::new_*` constructors. Please comment +/// on [this issue](https://github.com/unicode-org/icu4x/issues/6962) +/// if you would like to see this the ability to implement custom [`Rules`] stabilized. /// -/// 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 implementation supports only variants where months are either 29 or 30 days. /// -/// This calendar is the official calendar in Saudi Arabia. +/// This corresponds to various `"islamic-*"` [CLDR calendars](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier), +/// see the individual implementors of [`Rules`] ([`TabularAlgorithm`], [`UmmAlQura`], [`AstronomicalSimulation`]) for more information. /// /// # Era codes /// /// This calendar uses two era codes: `ah`, and `bh`, corresponding to the Anno Hegirae and Before Hijrah eras /// -/// # Month codes +/// # Months and days /// -/// 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). +/// The 12 months are called al-Muḥarram (`M01`), Ṣafar (`M02`), Rabīʿ al-ʾAwwal (`M03`), +/// Rabīʿ ath-Thānī or Rabīʿ al-ʾĀkhir (`M04`), Jumādā al-ʾŪlā (`M05`), Jumādā ath-Thāniyah +/// or Jumādā al-ʾĀkhirah (`M06`), Rajab (`M07`), Shaʿbān (`M08`), Ramaḍān (`M09`), Shawwāl (`M10`), +/// Ḏū al-Qaʿdah (`M11`), Ḏū al-Ḥijjah (`M12`). /// -/// See [`HijriTabularEpoch`] and [`HijriTabularLeapYears`] for customization. +/// As a true lunar calendar, the lengths of the months depend on the lunar cycle (a month starts on the day +/// where the waxing crescent is first observed), and will be either 29 or 30 days. /// -/// The most common version of this calendar uses [`HijriTabularEpoch::Friday`] and [`HijriTabularLeapYears::TypeII`]. +/// The lengths of the months are determined by the concrete [`Rules`] implementation. /// -/// # Era codes -/// -/// This calendar uses two era codes: `ah`, and `bh`, corresponding to the Anno Hegirae and Before Hijrah eras +/// There are either 6 or 7 30-day months, so the length of the year is 354 or 355 days. /// -/// # Month codes +/// # Calendar drift /// -/// 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, -} +/// As a lunar calendar, this calendar does not intend to follow the solar year, and drifts more +/// than 10 days per year with respect to the seasons. +#[derive(Clone, Debug, Default, Copy)] +#[allow(clippy::exhaustive_structs)] // newtype +pub struct Hijri(pub S); -impl HijriSimulated { - /// Creates a new [`HijriSimulated`] for reference location Mecca, with some compiled data containing precomputed calendrical calculations. +/// Defines a variant of the [`Hijri`] calendar. +/// +/// This crate includes the [`UmmAlQura`], [`AstronomicalSimulation`], and [`TabularAlgorithm`] +/// rules, other rules can be implemented by users. +/// +///
+/// 🚫 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 Rules: Clone + Debug + crate::cal::scaffold::UnstableSealed { + /// Returns data about the given year. + fn year_data(&self, extended_year: i32) -> HijriYearData; + + /// Returns an ECMA reference year that contains the given month-day combination. /// - /// ✨ *Enabled with the `compiled_data` Cargo feature.* + /// If the day is out of range, it will return a year that contains the given month + /// and the maximum day possible for that month. See [the spec][spec] for the + /// precise algorithm used. /// - /// [📚 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, - } + /// This API only matters when using [`MissingFieldsStrategy::Ecma`] to compute + /// a date without providing a year in [`Date::try_from_fields()`]. The default impl + /// will just error, and custom calendars who do not care about ECMA/Temporal + /// reference years do not need to override this. + /// + /// [spec]: https://tc39.es/proposal-temporal/#sec-temporal-nonisomonthdaytoisoreferencedate + /// [`MissingFieldsStrategy::Ecma`]: crate::options::MissingFieldsStrategy::Ecma + fn ecma_reference_year( + &self, + // TODO: Consider accepting ValidMonthCode + _month_code: (u8, bool), + _day: u8, + ) -> Result { + Err(EcmaReferenceYearError::Unimplemented) } -} -impl HijriUmmAlQura { - /// Creates a new [`HijriUmmAlQura`]. - pub const fn new() -> Self { - Self + /// The BCP-47 [`CalendarAlgorithm`] for the Hijri calendar using these rules, if defined. + fn calendar_algorithm(&self) -> Option { + None } -} -/// 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 debug name for these rules. + fn debug_name(&self) -> &'static str { + "Hijri (custom rules)" } } -/// The leap year rule for the [`HijriTabular`] calendar. +/// [`Hijri`] [`Rules`] based on an astronomical simulation for a particular location. /// -/// 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 - } +/// These simulations are unofficial and are known to not necessarily match sightings +/// on the ground. Unless you know otherwise for sure, instead of this variant, use +/// [`UmmAlQura`], which uses the results of KACST's Mecca-based calculations. +/// +/// As floating point arithmetic degenerates for far-away dates, this falls back to +/// the tabular calendar at some point. +/// +/// The precise behavior of this calendar may change in the future if: +/// - We decide to tweak the precise astronomical simulation used +/// - We decide to expand or reduce the range where we are using the astronomical simulation. +/// +/// This corresponds to the `"islamic-rgsa"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier) +/// if constructed with [`Hijri::new_simulated_mecca()`]. +#[derive(Copy, Clone, Debug)] +pub struct AstronomicalSimulation { + pub(crate) location: SimulatedLocation, } -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()?)?, - )) - } +#[derive(Clone, Debug, Copy, PartialEq)] +pub(crate) enum SimulatedLocation { + Mecca, } -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 +impl crate::cal::scaffold::UnstableSealed for AstronomicalSimulation {} +impl Rules for AstronomicalSimulation { + fn debug_name(&self) -> &'static str { + match self.location { + SimulatedLocation::Mecca => "Hijri (simulated, Mecca)", } } - 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); + fn year_data(&self, extended_year: i32) -> HijriYearData { + if let Some(data) = HijriYearData::lookup( + extended_year, + simulated_mecca_data::STARTING_YEAR, + simulated_mecca_data::DATA, + ) { + return data; } - 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 location = match self.location { + SimulatedLocation::Mecca => calendrical_calculations::islamic::MECCA, }; - 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(), + location, ); let next_start_day = calendrical_calculations::islamic::fixed_from_observational_islamic( extended_year + 1, 1, 1, - self.location(), + location, ); match (next_start_day - start_day) as u16 { - LONG_YEAR_LEN | SHORT_YEAR_LEN => (), + 355 | 354 => (), 353 => { icu_provider::log::trace!( "({}) Found year {extended_year} AH with length {}. See ", - HijriSimulated::DEBUG_NAME, + self.debug_name(), next_start_day - start_day ); } other => { debug_assert!( - false, + !WELL_BEHAVED_ASTRONOMICAL_RANGE.contains(&start_day), "({}) Found year {extended_year} AH with length {}!", - HijriSimulated::DEBUG_NAME, + self.debug_name(), other ) } @@ -541,7 +199,7 @@ impl HijriSimulatedLocation { calendrical_calculations::islamic::observational_islamic_month_days( extended_year, month_idx as u8 + 1, - self.location(), + location, ); match days_in_month { 29 => false, @@ -549,7 +207,7 @@ impl HijriSimulatedLocation { 31 => { icu_provider::log::trace!( "({}) Found year {extended_year} AH with month length {days_in_month} for month {}.", - HijriSimulated::DEBUG_NAME, + self.debug_name(), month_idx + 1 ); excess_days += 1; @@ -557,9 +215,9 @@ impl HijriSimulatedLocation { } _ => { debug_assert!( - false, + !WELL_BEHAVED_ASTRONOMICAL_RANGE.contains(&start_day), "({}) Found year {extended_year} AH with month length {days_in_month} for month {}!", - HijriSimulated::DEBUG_NAME, + self.debug_name(), month_idx + 1 ); false @@ -570,11 +228,10 @@ impl HijriSimulatedLocation { // 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, + debug_assert!( + excess_days == 1 || !WELL_BEHAVED_ASTRONOMICAL_RANGE.contains(&start_day), "({}) Found year {extended_year} AH with more than one excess day!", - HijriSimulated::DEBUG_NAME + self.debug_name() ); if let Some(l) = month_lengths.iter_mut().find(|l| !(**l)) { *l = true; @@ -582,307 +239,627 @@ impl HijriSimulatedLocation { } month_lengths }; - HijriYearInfo { - month_lengths, - start_day, - value: extended_year, + HijriYearData::try_new(extended_year, start_day, month_lengths) + .unwrap_or_else(|| UmmAlQura.year_data(extended_year)) + } +} + +/// [`Hijri`] [`Rules`] for the [Umm al-Qura](https://en.wikipedia.org/wiki/Islamic_calendar#Saudi_Arabia's_Umm_al-Qura_calendar) calendar. +/// +/// From the start of 1300 AH (1882-11-12 ISO) to the end of 1600 AH (2174-11-25 ISO), this +/// `Rules` implementation uses Umm al-Qura month lengths obtained from +/// [KACST](https://kacst.gov.sa/). Outside this range, this implementation falls back to +/// [`TabularAlgorithm`] with [`TabularAlgorithmLeapYears::TypeII`] and [`TabularAlgorithmEpoch::Friday`]. +/// +/// The precise behavior of this calendar may change in the future if: +/// - New ground truth is established by published government sources +/// - We decide to use a different algorithm outside the KACST range +/// - We decide to expand or reduce the range where we are correctly handling past dates. +/// +/// This corresponds to the `"islamic-umalqura"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). +#[derive(Copy, Clone, Debug, Default)] +#[non_exhaustive] +pub struct UmmAlQura; + +impl crate::cal::scaffold::UnstableSealed for UmmAlQura {} +impl Rules for UmmAlQura { + fn calendar_algorithm(&self) -> Option { + Some(CalendarAlgorithm::Hijri(Some( + HijriCalendarAlgorithm::Umalqura, + ))) + } + + fn ecma_reference_year( + &self, + month_code: (u8, bool), + day: u8, + ) -> Result { + let (ordinal_month, false) = month_code else { + return Err(EcmaReferenceYearError::MonthCodeNotInCalendar); + }; + + let extended_year = match (ordinal_month, day) { + (1, _) => 1392, + (2, 30..) => 1390, + (2, _) => 1392, + (3, 30..) => 1391, + (3, _) => 1392, + (4, _) => 1392, + (5, 30..) => 1391, + (5, _) => 1392, + (6, _) => 1392, + (7, 30..) => 1389, + (7, _) => 1392, + (8, _) => 1392, + (9, _) => 1392, + (10, 30..) => 1390, + (10, _) => 1392, + (11, ..=25) => 1392, + (11, _) => 1391, + (12, 30..) => 1390, + (12, _) => 1391, + _ => return Err(EcmaReferenceYearError::MonthCodeNotInCalendar), + }; + Ok(extended_year) + } + + fn debug_name(&self) -> &'static str { + "Hijri (Umm al-Qura)" + } + + fn year_data(&self, extended_year: i32) -> HijriYearData { + if let Some(data) = HijriYearData::lookup( + extended_year, + ummalqura_data::STARTING_YEAR, + ummalqura_data::DATA, + ) { + data + } else { + TabularAlgorithm { + leap_years: TabularAlgorithmLeapYears::TypeII, + epoch: TabularAlgorithmEpoch::Friday, + } + .year_data(extended_year) + } + } +} + +/// [`Hijri`] [`Rules`] for the [Tabular Hijri Algorithm](https://en.wikipedia.org/wiki/Tabular_Islamic_calendar). +/// +/// See [`TabularAlgorithmEpoch`] and [`TabularAlgorithmLeapYears`] for customization. +/// +/// The most common version of these rules uses [`TabularAlgorithmEpoch::Friday`] and [`TabularAlgorithmLeapYears::TypeII`]. +/// +/// When constructed with [`TabularAlgorithmLeapYears::TypeII`], and either [`TabularAlgorithmEpoch::Friday`] or [`TabularAlgorithmEpoch::Thursday`], +/// this corresponds to the `"islamic-civil"` and `"islamic-tbla"` [CLDR calendars](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier) respectively. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +pub struct TabularAlgorithm { + pub(crate) leap_years: TabularAlgorithmLeapYears, + pub(crate) epoch: TabularAlgorithmEpoch, +} + +impl TabularAlgorithm { + /// Construct a new [`TabularAlgorithm`] with the given leap year rule and epoch. + pub const fn new(leap_years: TabularAlgorithmLeapYears, epoch: TabularAlgorithmEpoch) -> Self { + Self { epoch, leap_years } + } +} + +impl crate::cal::scaffold::UnstableSealed for TabularAlgorithm {} +impl Rules for TabularAlgorithm { + fn calendar_algorithm(&self) -> Option { + Some(match (self.epoch, self.leap_years) { + (TabularAlgorithmEpoch::Friday, TabularAlgorithmLeapYears::TypeII) => { + CalendarAlgorithm::Hijri(Some(HijriCalendarAlgorithm::Civil)) + } + (TabularAlgorithmEpoch::Thursday, TabularAlgorithmLeapYears::TypeII) => { + CalendarAlgorithm::Hijri(Some(HijriCalendarAlgorithm::Tbla)) + } + }) + } + + fn ecma_reference_year( + &self, + month_code: (u8, bool), + day: u8, + ) -> Result { + let (ordinal_month, false) = month_code else { + return Err(EcmaReferenceYearError::MonthCodeNotInCalendar); + }; + + Ok(match (ordinal_month, day) { + (1, _) => 1392, + (2, 30..) => 1389, + (2, _) => 1392, + (3, _) => 1392, + (4, 30..) => 1389, + (4, _) => 1392, + (5, _) => 1392, + (6, 30..) => 1389, + (6, _) => 1392, + (7, _) => 1392, + (8, 30..) => 1389, + (8, _) => 1392, + (9, _) => 1392, + (10, 30..) => 1389, + (10, _) => 1392, + (11, ..=26) if self.epoch == TabularAlgorithmEpoch::Thursday => 1392, + (11, ..=25) if self.epoch == TabularAlgorithmEpoch::Friday => 1392, + (11, _) => 1391, + (12, 30..) => 1390, + (12, _) => 1391, + _ => return Err(EcmaReferenceYearError::MonthCodeNotInCalendar), + }) + } + + fn debug_name(&self) -> &'static str { + match self.epoch { + TabularAlgorithmEpoch::Friday => "Hijri (civil)", + TabularAlgorithmEpoch::Thursday => "Hijri (astronomical)", + } + } + + fn year_data(&self, extended_year: i32) -> HijriYearData { + let start_day = calendrical_calculations::islamic::fixed_from_tabular_islamic( + extended_year, + 1, + 1, + self.epoch.rata_die(), + ); + let month_lengths = core::array::from_fn(|m| { + m % 2 == 0 + || m == 11 + && match self.leap_years { + TabularAlgorithmLeapYears::TypeII => { + (14 + 11 * extended_year as i64).rem_euclid(30) < 11 + } + } + }); + HijriYearData { + // start_day is within 5 days of the tabular start day (trivial), and month lengths + // has either 6 or 7 long months. + packed: PackedHijriYearData::new_unchecked(extended_year, month_lengths, start_day), + extended_year, } } } -impl HijriSimulated { - pub(crate) const DEBUG_NAME: &'static str = "Hijri (simulated)"; -} +impl Hijri { + /// Use [`Self::new_simulated_mecca`]. + #[cfg(feature = "compiled_data")] + #[deprecated(since = "2.1.0", note = "use `Hijri::new_simulated_mecca`")] + pub const fn new_mecca() -> Self { + Self::new_simulated_mecca() + } -impl> Date
{ - /// Construct new simulated Hijri Date. - /// - /// ```rust - /// use icu::calendar::cal::HijriSimulated; - /// use icu::calendar::Date; + /// Creates a [`Hijri`] calendar using simulated sightings at Mecca. /// - /// 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)) + /// These simulations are unofficial and are known to not necessarily match sightings + /// on the ground. Unless you know otherwise for sure, instead of this variant, use + /// [`Hijri::new_umm_al_qura`], which uses the results of KACST's Mecca-based calculations. + pub const fn new_simulated_mecca() -> Self { + Self(AstronomicalSimulation { + location: SimulatedLocation::Mecca, + }) } -} - -#[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; + #[cfg(feature = "serde")] + #[doc = icu_provider::gen_buffer_unstable_docs!(BUFFER,Self::new)] + #[deprecated(since = "2.1.0", note = "use `Hijri::new_simulated_mecca`")] + pub fn try_new_mecca_with_buffer_provider( + _provider: &(impl icu_provider::buf::BufferProvider + ?Sized), + ) -> Result { + Ok(Self::new_simulated_mecca()) + } - fn days_in_provided_month(year: Self::YearInfo, month: u8) -> u8 { - year.days_in_month(month) + #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new_mecca)] + #[deprecated(since = "2.1.0", note = "use `Hijri::new_simulated_mecca`")] + pub fn try_new_mecca_unstable(_provider: &D) -> Result { + Ok(Self::new_simulated_mecca()) } - fn months_in_provided_year(_year: HijriYearInfo) -> u8 { - 12 + /// Use [`Self::new_simulated_mecca`]. + #[deprecated(since = "2.1.0", note = "use `Hijri::new_simulated_mecca`")] + pub const fn new_mecca_always_calculating() -> Self { + Self::new_simulated_mecca() } +} - fn days_in_provided_year(year: Self::YearInfo) -> u16 { - year.days_in_year() +impl Hijri { + /// Use [`Self::new_umm_al_qura`] + #[deprecated(since = "2.1.0", note = "use `Self::new_umm_al_qura`")] + pub const fn new() -> Self { + Self(UmmAlQura) } - // 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 + /// Creates a [`Hijri`] calendar using [`UmmAlQura`] rules. + pub const fn new_umm_al_qura() -> Self { + Self(UmmAlQura) } +} - fn last_month_day_in_provided_year(year: HijriYearInfo) -> (u8, u8) { - let days = Self::days_in_provided_month(year, 12); +/// The epoch for the [`TabularAlgorithm`] rules. +#[non_exhaustive] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] +pub enum TabularAlgorithmEpoch { + /// Thusday July 15, 622 AD Julian (0622-07-18 ISO) + Thursday, + /// Friday July 16, 622 AD Julian (0622-07-19 ISO) + Friday, +} - (12, days) +impl TabularAlgorithmEpoch { + fn rata_die(self) -> RataDie { + match self { + Self::Thursday => ISLAMIC_EPOCH_THURSDAY, + Self::Friday => ISLAMIC_EPOCH_FRIDAY, + } } } -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, - )?)) +/// The leap year rule for the [`TabularAlgorithm`] rules. +/// +/// 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 TabularAlgorithmLeapYears { + /// Leap years 2, 5, 7, 10, 13, 16, 18, 21, 24, 26, 29 + TypeII, +} + +impl Hijri { + /// Use [`Self::new_tabular`] + #[deprecated(since = "2.1.0", note = "use `Hijri::new_tabular`")] + pub const fn new(leap_years: TabularAlgorithmLeapYears, epoch: TabularAlgorithmEpoch) -> Self { + Hijri::new_tabular(leap_years, epoch) } - 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; + /// Creates a [`Hijri`] calendar with tabular rules and the given leap year rule and epoch. + pub const fn new_tabular( + leap_years: TabularAlgorithmLeapYears, + epoch: TabularAlgorithmEpoch, + ) -> Self { + Self(TabularAlgorithm::new(leap_years, epoch)) + } +} - let year = self.load_or_compute_info(extended_year); +/// Information about a Hijri year. +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct HijriYearData { + packed: PackedHijriYearData, + extended_year: i32, +} - 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)) +impl ToExtendedYear for HijriYearData { + fn to_extended_year(&self) -> i32 { + self.extended_year } +} - fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { - date.0.year.md_to_rd(date.0.month, date.0.day) +impl HijriYearData { + /// Creates [`HijriYearData`] from the given parts. + /// + /// `start_day` is the date for the first day of the year, see [`Date::to_rata_die`] + /// to obtain a [`RataDie`] from a [`Date`] in an arbitrary calendar. `start_day` has + /// to be within 5 days of the start of the year of the [`TabularAlgorithm`]. + /// + /// `month_lengths[n - 1]` is true if the nth month has 30 days, and false otherwise. + /// Either 6 or 7 months need to have 30 days. + pub fn try_new( + extended_year: i32, + start_day: RataDie, + month_lengths: [bool; 12], + ) -> Option { + Some(Self { + packed: PackedHijriYearData::try_new(extended_year, month_lengths, start_day)?, + extended_year, + }) } - fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner { - self.from_rata_die(Iso.to_rata_die(&iso)) + fn lookup( + extended_year: i32, + starting_year: i32, + data: &[PackedHijriYearData], + ) -> Option { + Some(extended_year) + .and_then(|e| usize::try_from(e.checked_sub(starting_year)?).ok()) + .and_then(|i| data.get(i)) + .map(|&packed| Self { + extended_year, + packed, + }) } - fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { - Iso.from_rata_die(self.to_rata_die(date)) + fn new_year(self) -> RataDie { + self.packed.new_year(self.extended_year) } +} - fn months_in_year(&self, date: &Self::DateInner) -> u8 { - date.0.months_in_year() - } +/// The struct containing compiled Hijri YearInfo +/// +/// * `start_day` has to be within 5 days of the start of the year of the [`TabularAlgorithm`]. +/// * `month_lengths[n - 1]` has either 6 or 7 long months. +/// +/// 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_tabular_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)] +struct PackedHijriYearData(u16); + +impl PackedHijriYearData { + const fn try_new( + extended_year: i32, + month_lengths: [bool; 12], + start_day: RataDie, + ) -> Option { + let start_offset = start_day.since(Self::mean_tabular_start_day(extended_year)); + + if !(-8 < start_offset && start_offset < 8 + || calendrical_calculations::islamic::WELL_BEHAVED_ASTRONOMICAL_RANGE + .start + .to_i64_date() + > start_day.to_i64_date() + || calendrical_calculations::islamic::WELL_BEHAVED_ASTRONOMICAL_RANGE + .end + .to_i64_date() + < start_day.to_i64_date()) + { + return None; + } + let start_offset = start_offset as i8 & 0b1000_0111u8 as i8; - fn days_in_year(&self, date: &Self::DateInner) -> u16 { - date.0.days_in_year() - } + let mut all = 0u16; - fn days_in_month(&self, date: &Self::DateInner) -> u8 { - date.0.days_in_month() - } + let mut num_days = 29 * 12; - fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { - date.0.offset_date(offset, &HijriUmmAlQura) - } + let mut i = 0; + while i < 12 { + #[expect(clippy::indexing_slicing)] + if month_lengths[i] { + all |= 1 << i; + num_days += 1; + } + i += 1; + } - 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) + if !matches!(num_days, 354 | 355) { + return None; + } + + if start_offset < 0 { + all |= 1 << 12; + } + all |= (start_offset.unsigned_abs() as u16) << 13; + Some(Self(all)) } - fn debug_name(&self) -> &'static str { - Self::DEBUG_NAME + const fn new_unchecked( + extended_year: i32, + month_lengths: [bool; 12], + start_day: RataDie, + ) -> Self { + let start_offset = start_day.since(Self::mean_tabular_start_day(extended_year)); + + let start_offset = start_offset as i8 & 0b1000_0111u8 as i8; + + let mut all = 0u16; + + let mut i = 0; + while i < 12 { + #[expect(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) } - fn year_info(&self, date: &Self::DateInner) -> Self::Year { - era_year(self.extended_year(date)) + fn new_year(self, extended_year: i32) -> RataDie { + let start_offset = if (self.0 & 0b1_0000_0000_0000) != 0 { + -((self.0 >> 13) as i64) + } else { + (self.0 >> 13) as i64 + }; + Self::mean_tabular_start_day(extended_year) + start_offset } - fn extended_year(&self, date: &Self::DateInner) -> i32 { - date.0.extended_year() + fn month_has_30_days(self, month: u8) -> bool { + self.0 & (1 << (month - 1) as u16) != 0 } - fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { - Self::provided_year_is_leap(date.0.year) + fn is_leap(self) -> bool { + (self.0 & ((1 << 12) - 1)).count_ones() == 7 } - fn month(&self, date: &Self::DateInner) -> types::MonthInfo { - date.0.month() + // month is 1-indexed, but 0 is a valid input, producing 0 + fn last_day_of_month(self, month: u8) -> u16 { + // 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 = self.0 & ((1 << month as u16) - 1); + prev_month_lengths += long_month_bits.count_ones().try_into().unwrap_or(0); + prev_month_lengths } - fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { - date.0.day_of_month() + fn days_in_year(self) -> u16 { + self.last_day_of_month(12) } - fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { - date.0.day_of_year() + const fn mean_tabular_start_day(extended_year: i32) -> RataDie { + // -1 because the epoch is new year of year 1 + calendrical_calculations::islamic::ISLAMIC_EPOCH_FRIDAY + .add((extended_year as i64 - 1) * (354 * 30 + 11) / 30) } +} - fn calendar_algorithm(&self) -> Option { - let expected_calendar = crate::preferences::CalendarAlgorithm::Hijri(Some( - crate::preferences::HijriCalendarAlgorithm::Umalqura, - )); - Some(expected_calendar) +impl>> Date
{ + /// Deprecated + #[deprecated(since = "2.1.0", note = "use `Date::try_new_hijri_with_calendar`")] + pub fn try_new_simulated_hijri_with_calendar( + year: i32, + month: u8, + day: u8, + calendar: A, + ) -> Result, RangeError> { + Date::try_new_hijri_with_calendar(year, month, day, 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, - ), +#[test] +fn computer_reference_years() { + let rules = UmmAlQura; + + fn compute_hijri_reference_year( + ordinal_month: u8, + day: u8, + cal: &C, + year_info_from_extended: impl Fn(i32) -> C::YearInfo, + ) -> Result + where + C: DateFieldsResolver, + { + let dec_31 = Date::from_rata_die( + crate::cal::abstract_gregorian::LAST_DAY_OF_REFERENCE_YEAR, + crate::Ref(cal), + ); + // December 31, 1972 occurs in the 11th month, 1392 AH, but the day could vary + debug_assert_eq!(dec_31.month().ordinal, 11); + let (y0, y1, y2, y3) = + if ordinal_month < 11 || (ordinal_month == 11 && day <= dec_31.day_of_month().0) { + (1389, 1390, 1391, 1392) + } else { + (1388, 1389, 1390, 1391) + }; + let year_info = year_info_from_extended(y3); + if day <= C::days_in_provided_month(year_info, ordinal_month) { + return Ok(year_info); + } + let year_info = year_info_from_extended(y2); + if day <= C::days_in_provided_month(year_info, ordinal_month) { + return Ok(year_info); + } + let year_info = year_info_from_extended(y1); + if day <= C::days_in_provided_month(year_info, ordinal_month) { + return Ok(year_info); + } + let year_info = year_info_from_extended(y0); + // This function might be called with out-of-range days that are handled later. + // Some calendars don't have day 30s in every month so we don't check those. + if day <= 29 { + debug_assert!( + day <= C::days_in_provided_month(year_info, ordinal_month), + "{ordinal_month}/{day}" + ); + } + Ok(year_info) + } + for month in 1..=12 { + for day in [30, 29] { + let y = compute_hijri_reference_year(month, day, &Hijri(rules), |e| rules.year_data(e)) + .unwrap() + .extended_year; + + if day == 30 { + println!("({month}, {day}) => {y},") + } else { + println!("({month}, _) => {y},") } } } } -impl HijriUmmAlQura { - pub(crate) const DEBUG_NAME: &'static str = "Hijri (Umm al-Qura)"; -} +#[allow(clippy::derived_hash_with_manual_eq)] // bounds +#[derive(Clone, Debug, Hash)] +/// The inner date type used for representing [`Date`]s of [`Hijri`]. See [`Date`] and [`Hijri`] for more details. +pub struct HijriDateInner(ArithmeticDate>); -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, - )) +impl Copy for HijriDateInner {} +impl PartialEq for HijriDateInner { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} +impl Eq for HijriDateInner {} +impl PartialOrd for HijriDateInner { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} +impl Ord for HijriDateInner { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.0.cmp(&other.0) } } -/// The inner date type used for representing [`Date`]s of [`HijriTabular`]. See [`Date`] and [`HijriTabular`] for more details. +impl DateFieldsResolver for Hijri { + type YearInfo = HijriYearData; -#[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 days_in_provided_month(year: Self::YearInfo, month: u8) -> u8 { + 29 + year.packed.month_has_30_days(month) as u8 } 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 - } + #[inline] + fn year_info_from_era( + &self, + era: &[u8], + era_year: i32, + ) -> Result { + let extended_year = match era { + b"ah" => era_year, + b"bh" => 1 - era_year, + _ => return Err(UnknownEraError), + }; + Ok(self.year_info_from_extended(extended_year)) } - fn provided_year_is_leap(year: i32) -> bool { - (14 + 11 * year).rem_euclid(30) < 11 + #[inline] + fn year_info_from_extended(&self, extended_year: i32) -> Self::YearInfo { + self.0.year_data(extended_year) } - fn last_month_day_in_provided_year(year: i32) -> (u8, u8) { - if Self::provided_year_is_leap(year) { - (12, 30) - } else { - (12, 29) - } + #[inline] + fn reference_year_from_month_day( + &self, + month_code: types::ValidMonthCode, + day: u8, + ) -> Result { + self.0 + .ecma_reference_year(month_code.to_tuple(), day) + .map(|y| self.0.year_data(y)) } } -impl crate::cal::scaffold::UnstableSealed for HijriTabular {} -impl Calendar for HijriTabular { - type DateInner = HijriTabularDateInner; +impl crate::cal::scaffold::UnstableSealed for Hijri {} +impl Calendar for Hijri { + type DateInner = HijriDateInner; type Year = types::EraYear; + type DifferenceError = core::convert::Infallible; fn from_codes( &self, @@ -891,157 +868,200 @@ impl Calendar for HijriTabular { 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::from_codes(era, year, month_code, day, self).map(HijriDateInner) + } - ArithmeticDate::new_from_codes(self, year, month_code, day).map(HijriTabularDateInner) + #[cfg(feature = "unstable")] + fn from_fields( + &self, + fields: DateFields, + options: DateFromFieldsOptions, + ) -> Result { + ArithmeticDate::from_fields(fields, options, self).map(HijriDateInner) } 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(), - ) - } - }; + // (354 * 30 + 11) / 30 is the mean year length for a tabular year + // This is slightly different from the `calendrical_calculations::islamic::MEAN_YEAR_LENGTH`, which is based on + // the (current) synodic month length. + // + // +1 because the epoch is new year of year 1 + // Before the epoch the division will round up (towards 0), so we need to + // subtract 1, which is the same as not adding the 1. + let extended_year = (rd - calendrical_calculations::islamic::ISLAMIC_EPOCH_FRIDAY) * 30 + / (354 * 30 + 11) + + (rd >= calendrical_calculations::islamic::ISLAMIC_EPOCH_FRIDAY) as i64; - debug_assert!(Date::try_new_hijri_tabular_with_calendar(y, m, d, crate::Ref(self)).is_ok()); - HijriTabularDateInner(ArithmeticDate::new_unchecked(y, m, d)) - } + let extended_year = extended_year.clamp(i32::MIN as i64, i32::MAX as i64) as i32; - 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(), - ) - } + let mut year = self.0.year_data(extended_year); + + // We rounded the extended year down, so we might need to use the next year + if rd >= year.new_year() + year.packed.days_in_year() as i64 && extended_year < i32::MAX { + year = self.0.year_data(year.extended_year + 1) + } + + // Clamp the RD to our year + let rd = rd.clamp( + year.new_year(), + year.new_year() + year.packed.days_in_year() as i64, + ); + + let day_of_year = (rd - year.new_year()) as u16; + + // 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 mut last_day_of_month = year.packed.last_day_of_month(month); + let mut last_day_of_prev_month = year.packed.last_day_of_month(month - 1); + + while day_of_year >= last_day_of_month { + month += 1; + last_day_of_prev_month = last_day_of_month; + last_day_of_month = year.packed.last_day_of_month(month); } + + let day = (day_of_year + 1 - last_day_of_prev_month) as u8; + + HijriDateInner(ArithmeticDate::new_unchecked(year, month, day)) } - fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner { - self.from_rata_die(Iso.to_rata_die(&iso)) + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + date.0.year.new_year() + + date.0.year.packed.last_day_of_month(date.0.month - 1) as i64 + + (date.0.day - 1) as i64 } - fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { - Iso.from_rata_die(self.to_rata_die(date)) + fn has_cheap_iso_conversion(&self) -> bool { + false } fn months_in_year(&self, date: &Self::DateInner) -> u8 { - date.0.months_in_year() + Self::months_in_provided_year(date.0.year) } fn days_in_year(&self, date: &Self::DateInner) -> u16 { - date.0.days_in_year() + date.0.year.packed.days_in_year() } fn days_in_month(&self, date: &Self::DateInner) -> u8 { - date.0.days_in_month() + Self::days_in_provided_month(date.0.year, date.0.month) } - fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { - date.0.offset_date(offset, &()) + #[cfg(feature = "unstable")] + fn add( + &self, + date: &Self::DateInner, + duration: types::DateDuration, + options: DateAddOptions, + ) -> Result { + date.0.added(duration, self, options).map(HijriDateInner) } + #[cfg(feature = "unstable")] 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) + options: DateDifferenceOptions, + ) -> Result { + Ok(date1.0.until(&date2.0, self, options)) } fn debug_name(&self) -> &'static str { - match self.epoch { - HijriTabularEpoch::Friday => "Hijri (civil)", - HijriTabularEpoch::Thursday => "Hijri (astronomical)", - } + self.0.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() + let extended_year = date.0.year.extended_year; + if extended_year > 0 { + types::EraYear { + era: tinystr!(16, "ah"), + era_index: Some(0), + year: extended_year, + extended_year, + ambiguity: types::YearAmbiguity::CenturyRequired, + } + } else { + types::EraYear { + era: tinystr!(16, "bh"), + era_index: Some(1), + year: 1 - extended_year, + extended_year, + ambiguity: types::YearAmbiguity::CenturyRequired, + } + } } fn is_in_leap_year(&self, date: &Self::DateInner) -> bool { - Self::provided_year_is_leap(date.0.year) + date.0.year.packed.is_leap() } fn month(&self, date: &Self::DateInner) -> types::MonthInfo { - date.0.month() + types::MonthInfo::non_lunisolar(date.0.month) } fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { - date.0.day_of_month() + types::DayOfMonth(date.0.day) } fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { - date.0.day_of_year() + types::DayOfYear(date.0.year.packed.last_day_of_month(date.0.month - 1) + date.0.day as u16) } 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) + self.0.calendar_algorithm() } } -impl> Date { - /// Construct new Tabular Hijri Date. +impl>, R: Rules> Date { + /// Construct new Hijri Date. /// /// ```rust - /// use icu::calendar::cal::{ - /// HijriTabular, HijriTabularEpoch, HijriTabularLeapYears, - /// }; + /// use icu::calendar::cal::Hijri; /// use icu::calendar::Date; /// - /// let hijri = HijriTabular::new( - /// HijriTabularLeapYears::TypeII, - /// HijriTabularEpoch::Thursday, - /// ); + /// let hijri = Hijri::new_simulated_mecca(); /// - /// let date_hijri = - /// Date::try_new_hijri_tabular_with_calendar(1392, 4, 25, hijri) - /// .expect("Failed to initialize Hijri Date instance."); + /// let date_hijri = Date::try_new_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_hijri_with_calendar( + year: i32, + month: u8, + day: u8, + calendar: A, + ) -> Result { + let y = calendar.as_calendar().0.year_data(year); + Ok(Date::from_raw( + HijriDateInner(ArithmeticDate::try_from_ymd(y, month, day)?), + calendar, + )) + } +} + +impl Date> { + /// Deprecated + #[deprecated(since = "2.1.0", note = "use `Date::try_new_hijri_with_calendar")] + pub fn try_new_ummalqura(year: i32, month: u8, day: u8) -> Result { + Date::try_new_hijri_with_calendar(year, month, day, Hijri::new_umm_al_qura()) + } +} + +impl>> Date { + /// Deprecated + #[deprecated(since = "2.1.0", note = "use `Date::try_new_hijri_with_calendar")] 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)) + Date::try_new_hijri_with_calendar(year, month, day, calendar) } } @@ -1050,7 +1070,6 @@ mod test { use types::MonthCode; use super::*; - use crate::Ref; const START_YEAR: i32 = -1245; const END_YEAR: i32 = 1518; @@ -1742,14 +1761,11 @@ mod test { #[test] fn test_simulated_hijri_from_rd() { - let calendar = HijriSimulated::new_mecca(); - let calendar = Ref(&calendar); + let calendar = Hijri::new_simulated_mecca(); 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); + let date = Date::try_new_hijri_with_calendar(case.year, case.month, case.day, calendar) + .unwrap(); + let iso = Date::from_rata_die(RataDie::new(*f_date), crate::Iso); assert_eq!(iso.to_calendar(calendar).inner, date.inner, "{case:?}"); } @@ -1757,39 +1773,36 @@ mod test { #[test] fn test_rd_from_simulated_hijri() { - let calendar = HijriSimulated::new_mecca(); - let calendar = Ref(&calendar); + let calendar = Hijri::new_simulated_mecca(); 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 date = Date::try_new_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); + let calendar = Hijri::new_tabular( + TabularAlgorithmLeapYears::TypeII, + TabularAlgorithmEpoch::Friday, + ); 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 = Date::try_new_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_hijri_from_rd() { - let calendar = HijriTabular::new(HijriTabularLeapYears::TypeII, HijriTabularEpoch::Friday); - let calendar = Ref(&calendar); + let calendar = Hijri::new_tabular( + TabularAlgorithmLeapYears::TypeII, + TabularAlgorithmEpoch::Friday, + ); 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 = Date::try_new_hijri_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:?}"); @@ -1798,28 +1811,26 @@ mod test { #[test] fn test_rd_from_hijri_tbla() { - let calendar = - HijriTabular::new(HijriTabularLeapYears::TypeII, HijriTabularEpoch::Thursday); - let calendar = Ref(&calendar); + let calendar = Hijri::new_tabular( + TabularAlgorithmLeapYears::TypeII, + TabularAlgorithmEpoch::Thursday, + ); 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 = Date::try_new_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_hijri_tbla_from_rd() { - let calendar = - HijriTabular::new(HijriTabularLeapYears::TypeII, HijriTabularEpoch::Thursday); - let calendar = Ref(&calendar); + let calendar = Hijri::new_tabular( + TabularAlgorithmLeapYears::TypeII, + TabularAlgorithmEpoch::Thursday, + ); 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 = Date::try_new_hijri_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:?}"); @@ -1828,10 +1839,10 @@ mod test { #[test] fn test_saudi_hijri_from_rd() { - let calendar = HijriUmmAlQura::new(); - let calendar = Ref(&calendar); + let calendar = Hijri::new_umm_al_qura(); 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 = Date::try_new_hijri_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:?}"); @@ -1840,8 +1851,10 @@ mod test { #[test] fn test_rd_from_saudi_hijri() { + let calendar = Hijri::new_umm_al_qura(); 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 = Date::try_new_hijri_with_calendar(case.year, case.month, case.day, calendar) + .unwrap(); assert_eq!(date.to_rata_die(), RataDie::new(*f_date), "{case:?}"); } } @@ -1849,24 +1862,24 @@ mod test { #[ignore] // slow #[test] fn test_days_in_provided_year_simulated() { - let calendar = HijriSimulated::new_mecca(); - let calendar = Ref(&calendar); + let calendar = Hijri::new_simulated_mecca(); // -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 + Hijri::new_simulated_mecca() + .0 + .year_data(year) + .packed + .days_in_year() as i64 }) .sum(); - let expected_number_of_days = - Date::try_new_simulated_hijri_with_calendar(END_YEAR, 1, 1, calendar) + let expected_number_of_days = Date::try_new_hijri_with_calendar(END_YEAR, 1, 1, calendar) + .unwrap() + .to_rata_die() + - Date::try_new_hijri_with_calendar(START_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 + .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!( @@ -1878,18 +1891,17 @@ mod test { #[ignore] // slow #[test] fn test_days_in_provided_year_ummalqura() { + let calendar = Hijri::new_umm_al_qura(); // -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 - }) + .map(|year| calendar.0.year_data(year).packed.days_in_year() as i64) .sum(); - let expected_number_of_days = Date::try_new_ummalqura(END_YEAR, 1, 1) + let expected_number_of_days = Date::try_new_hijri_with_calendar(END_YEAR, 1, 1, calendar) .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 + - (Date::try_new_hijri_with_calendar(START_YEAR, 1, 1, calendar).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); } @@ -1898,7 +1910,7 @@ mod 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()); + let hijri = iso.to_calendar(Hijri::new_umm_al_qura()); // Data from https://www.ummulqura.org.sa/Index.aspx assert_eq!(hijri.day_of_month().0, 30); assert_eq!(hijri.month().ordinal, 4); @@ -1908,143 +1920,96 @@ mod test { #[test] fn test_regression_4914() { // https://github.com/unicode-org/icu4x/issues/4914 - let dt = HijriUmmAlQura::new() + let dt = Hijri::new_umm_al_qura() .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); + assert_eq!(dt.0.year.extended_year, -6823); } #[test] - fn test_regression_5069_uaq() { - let cached = HijriUmmAlQura::new(); + fn test_regression_7056() { + // https://github.com/unicode-org/icu4x/issues/7056 + let calendar = Hijri::new_tabular( + TabularAlgorithmLeapYears::TypeII, + TabularAlgorithmEpoch::Friday, + ); + let iso = Date::try_new_iso(-62971, 3, 19).unwrap(); + let _dt = iso.to_calendar(calendar); + let _dt = iso.to_calendar(Hijri::new_umm_al_qura()); + } - let cached = crate::Ref(&cached); + #[test] + fn test_regression_5069_uaq() { + let calendar = Hijri::new_umm_al_qura(); - let dt_cached = Date::try_new_ummalqura(1391, 1, 29).unwrap(); + let dt = Date::try_new_hijri_with_calendar(1391, 1, 29, calendar).unwrap(); - assert_eq!(dt_cached.to_iso().to_calendar(cached), dt_cached); + assert_eq!(dt.to_iso().to_calendar(calendar), dt); } #[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 cal = Hijri::new_simulated_mecca(); - 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(); + let dt = Date::try_new_hijri_with_calendar(1390, 1, 30, cal).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); + assert_eq!(dt.to_iso().to_calendar(cal), dt); 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); + assert!(dt.to_calendar(cal).day_of_month().0 > 0); } #[test] fn test_regression_6197() { - let cached = HijriUmmAlQura::new(); - - let cached = crate::Ref(&cached); + let calendar = Hijri::new_umm_al_qura(); let iso = Date::try_new_iso(2025, 2, 26).unwrap(); - let cached = iso.to_calendar(cached); + let date = iso.to_calendar(calendar); // Data from https://www.ummulqura.org.sa/ assert_eq!( ( - cached.day_of_month().0, - cached.month().ordinal, - cached.era_year().year + date.day_of_month().0, + date.month().ordinal, + date.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::>(); + fn test_hijri_packed_roundtrip() { + fn single_roundtrip(month_lengths: [bool; 12], start_day: RataDie) -> Option<()> { + let packed = PackedHijriYearData::try_new(1600, month_lengths, start_day)?; + for i in 0..12 { + assert_eq!(packed.month_has_30_days(i + 1), month_lengths[i as usize]); + } + assert_eq!(packed.new_year(1600), start_day); + Some(()) + } - assert_eq!(icu4x, icu4c); + 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 = PackedHijriYearData::mean_tabular_start_day(1600); + assert_eq!(single_roundtrip(all_short, start_1600), None); + assert_eq!(single_roundtrip(all_long, start_1600), None); + single_roundtrip(mixed1, start_1600).unwrap(); + single_roundtrip(mixed2, start_1600).unwrap(); + + single_roundtrip(mixed1, start_1600 - 7).unwrap(); + single_roundtrip(mixed2, start_1600 + 7).unwrap(); + single_roundtrip(mixed2, start_1600 + 4).unwrap(); + single_roundtrip(mixed2, start_1600 + 1).unwrap(); + single_roundtrip(mixed2, start_1600 - 1).unwrap(); + single_roundtrip(mixed2, start_1600 - 4).unwrap(); } } diff --git a/deps/crates/vendor/icu_calendar/src/cal/hijri/simulated_mecca_data.rs b/deps/crates/vendor/icu_calendar/src/cal/hijri/simulated_mecca_data.rs new file mode 100644 index 00000000000000..895ffd46eb9c89 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/cal/hijri/simulated_mecca_data.rs @@ -0,0 +1,269 @@ +// 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 obtained from [`calendrical_calculations`]. + +use super::PackedHijriYearData; + +pub const STARTING_YEAR: i32 = 1317; + +#[rustfmt::skip] +#[allow(clippy::unwrap_used)] // const +pub const DATA: &[PackedHijriYearData] = { + use calendrical_calculations::gregorian::fixed_from_gregorian as gregorian; + let l = true; // long + let s = false; // short + &[ + PackedHijriYearData::try_new(1317, [l, l, l, l, s, s, l, s, l, s, s, l], gregorian(1899, 5, 11)).unwrap(), + PackedHijriYearData::try_new(1318, [s, l, l, l, s, l, s, l, s, l, s, s], gregorian(1900, 5, 1)).unwrap(), + PackedHijriYearData::try_new(1319, [l, s, l, l, s, l, s, l, l, s, l, s], gregorian(1901, 4, 20)).unwrap(), + PackedHijriYearData::try_new(1320, [l, s, s, l, s, l, s, l, l, s, l, l], gregorian(1902, 4, 10)).unwrap(), + PackedHijriYearData::try_new(1321, [s, l, s, s, l, s, s, l, l, s, l, l], gregorian(1903, 3, 31)).unwrap(), + PackedHijriYearData::try_new(1322, [l, s, l, s, s, s, l, s, l, s, l, l], gregorian(1904, 3, 19)).unwrap(), + PackedHijriYearData::try_new(1323, [l, s, l, l, s, s, s, l, s, l, s, l], gregorian(1905, 3, 8)).unwrap(), + PackedHijriYearData::try_new(1324, [l, s, l, l, s, l, s, s, l, s, l, s], gregorian(1906, 2, 25)).unwrap(), + PackedHijriYearData::try_new(1325, [l, s, l, l, s, l, l, s, l, s, l, s], gregorian(1907, 2, 14)).unwrap(), + PackedHijriYearData::try_new(1326, [s, l, s, l, s, l, l, s, l, l, s, l], gregorian(1908, 2, 4)).unwrap(), + PackedHijriYearData::try_new(1327, [s, s, l, s, l, s, l, s, l, l, l, s], gregorian(1909, 1, 24)).unwrap(), + PackedHijriYearData::try_new(1328, [l, s, s, l, s, s, l, s, l, l, l, s], gregorian(1910, 1, 13)).unwrap(), + PackedHijriYearData::try_new(1329, [l, l, s, l, s, s, s, l, s, l, l, l], gregorian(1911, 1, 2)).unwrap(), + PackedHijriYearData::try_new(1330, [s, l, l, s, s, l, s, s, l, s, l, l], gregorian(1911, 12, 23)).unwrap(), + PackedHijriYearData::try_new(1331, [s, l, l, s, l, s, l, s, l, s, l, s], gregorian(1912, 12, 11)).unwrap(), + PackedHijriYearData::try_new(1332, [s, l, l, l, s, l, s, l, s, l, s, l], gregorian(1913, 11, 30)).unwrap(), + PackedHijriYearData::try_new(1333, [s, s, l, l, s, l, l, s, l, l, s, s], gregorian(1914, 11, 20)).unwrap(), + PackedHijriYearData::try_new(1334, [s, l, s, l, s, l, l, s, l, l, l, s], gregorian(1915, 11, 9)).unwrap(), + PackedHijriYearData::try_new(1335, [s, s, l, s, l, s, l, s, l, l, l, s], gregorian(1916, 10, 29)).unwrap(), + PackedHijriYearData::try_new(1336, [l, s, l, s, s, l, s, l, s, l, l, s], gregorian(1917, 10, 18)).unwrap(), + PackedHijriYearData::try_new(1337, [l, s, l, l, s, s, l, s, l, s, l, s], gregorian(1918, 10, 7)).unwrap(), + PackedHijriYearData::try_new(1338, [l, s, l, l, l, s, l, s, s, l, s, l], gregorian(1919, 9, 26)).unwrap(), + PackedHijriYearData::try_new(1339, [s, s, l, l, l, s, l, s, l, s, l, s], gregorian(1920, 9, 15)).unwrap(), + PackedHijriYearData::try_new(1340, [s, l, s, l, l, l, s, l, s, l, s, l], gregorian(1921, 9, 4)).unwrap(), + PackedHijriYearData::try_new(1341, [s, s, l, s, l, l, s, l, l, s, l, s], gregorian(1922, 8, 25)).unwrap(), + PackedHijriYearData::try_new(1342, [s, l, s, l, s, l, s, l, l, s, l, l], gregorian(1923, 8, 14)).unwrap(), + PackedHijriYearData::try_new(1343, [s, s, l, s, l, s, l, s, l, s, l, l], gregorian(1924, 8, 3)).unwrap(), + PackedHijriYearData::try_new(1344, [s, l, s, l, s, l, s, l, s, l, s, l], gregorian(1925, 7, 23)).unwrap(), + PackedHijriYearData::try_new(1345, [s, l, l, s, l, l, s, s, l, s, s, l], gregorian(1926, 7, 12)).unwrap(), + PackedHijriYearData::try_new(1346, [s, l, l, s, l, l, s, l, s, l, s, s], gregorian(1927, 7, 1)).unwrap(), + PackedHijriYearData::try_new(1347, [l, s, l, s, l, l, l, s, l, s, l, s], gregorian(1928, 6, 19)).unwrap(), + PackedHijriYearData::try_new(1348, [s, l, s, l, s, l, l, l, s, l, s, l], gregorian(1929, 6, 9)).unwrap(), + PackedHijriYearData::try_new(1349, [s, s, l, s, l, s, l, s, l, l, l, s], gregorian(1930, 5, 30)).unwrap(), + PackedHijriYearData::try_new(1350, [l, s, s, l, s, l, s, l, s, l, l, s], gregorian(1931, 5, 19)).unwrap(), + PackedHijriYearData::try_new(1351, [l, l, s, l, s, l, s, s, l, s, l, s], gregorian(1932, 5, 7)).unwrap(), + PackedHijriYearData::try_new(1352, [l, l, s, l, l, s, l, s, s, l, s, l], gregorian(1933, 4, 26)).unwrap(), + PackedHijriYearData::try_new(1353, [s, l, l, s, l, l, s, s, l, s, l, s], gregorian(1934, 4, 16)).unwrap(), + PackedHijriYearData::try_new(1354, [s, l, l, s, l, l, l, s, s, l, s, l], gregorian(1935, 4, 5)).unwrap(), + PackedHijriYearData::try_new(1355, [s, s, l, l, s, l, l, s, l, s, l, s], gregorian(1936, 3, 25)).unwrap(), + PackedHijriYearData::try_new(1356, [l, s, s, l, l, s, l, s, l, l, s, l], gregorian(1937, 3, 14)).unwrap(), + PackedHijriYearData::try_new(1357, [s, l, s, l, s, s, l, s, l, l, s, l], gregorian(1938, 3, 4)).unwrap(), + PackedHijriYearData::try_new(1358, [l, s, l, s, l, s, s, l, s, l, s, l], gregorian(1939, 2, 21)).unwrap(), + PackedHijriYearData::try_new(1359, [l, l, s, l, s, l, s, s, l, s, s, l], gregorian(1940, 2, 10)).unwrap(), + PackedHijriYearData::try_new(1360, [l, l, s, l, l, s, l, s, s, l, s, l], gregorian(1941, 1, 29)).unwrap(), + PackedHijriYearData::try_new(1361, [s, l, s, l, l, s, l, s, l, s, l, s], gregorian(1942, 1, 19)).unwrap(), + PackedHijriYearData::try_new(1362, [l, s, l, s, l, s, l, l, s, l, s, l], gregorian(1943, 1, 8)).unwrap(), + PackedHijriYearData::try_new(1363, [s, l, s, s, l, s, l, l, s, l, l, s], gregorian(1943, 12, 29)).unwrap(), + PackedHijriYearData::try_new(1364, [l, s, l, s, s, l, s, l, s, l, l, l], gregorian(1944, 12, 17)).unwrap(), + PackedHijriYearData::try_new(1365, [s, l, s, l, s, s, l, s, s, l, l, l], gregorian(1945, 12, 7)).unwrap(), + PackedHijriYearData::try_new(1366, [s, l, l, s, l, s, s, l, s, s, l, l], gregorian(1946, 11, 26)).unwrap(), + PackedHijriYearData::try_new(1367, [s, l, l, l, s, l, s, s, l, s, s, l], gregorian(1947, 11, 15)).unwrap(), + PackedHijriYearData::try_new(1368, [l, s, l, l, s, l, l, s, s, l, s, l], gregorian(1948, 11, 3)).unwrap(), + PackedHijriYearData::try_new(1369, [s, l, s, l, s, l, l, s, l, s, l, s], gregorian(1949, 10, 24)).unwrap(), + PackedHijriYearData::try_new(1370, [l, s, s, l, l, s, l, s, l, l, s, l], gregorian(1950, 10, 13)).unwrap(), + PackedHijriYearData::try_new(1371, [l, s, s, l, s, s, l, s, l, l, l, l], gregorian(1951, 10, 3)).unwrap(), + PackedHijriYearData::try_new(1372, [s, s, l, s, l, s, s, l, s, l, l, l], gregorian(1952, 9, 22)).unwrap(), + PackedHijriYearData::try_new(1373, [s, l, s, l, s, l, s, s, l, s, l, l], gregorian(1953, 9, 11)).unwrap(), + PackedHijriYearData::try_new(1374, [s, l, s, l, l, s, l, s, s, l, s, l], gregorian(1954, 8, 31)).unwrap(), + PackedHijriYearData::try_new(1375, [s, l, s, l, l, l, s, l, s, s, l, s], gregorian(1955, 8, 20)).unwrap(), + PackedHijriYearData::try_new(1376, [l, s, l, s, l, l, s, l, l, s, l, s], gregorian(1956, 8, 8)).unwrap(), + PackedHijriYearData::try_new(1377, [s, l, s, s, l, l, s, l, l, l, s, l], gregorian(1957, 7, 29)).unwrap(), + PackedHijriYearData::try_new(1378, [s, s, l, s, s, l, s, l, l, l, s, l], gregorian(1958, 7, 19)).unwrap(), + PackedHijriYearData::try_new(1379, [l, s, s, l, s, s, l, s, l, l, s, l], gregorian(1959, 7, 8)).unwrap(), + PackedHijriYearData::try_new(1380, [l, s, l, s, l, s, s, l, s, l, s, l], gregorian(1960, 6, 26)).unwrap(), + PackedHijriYearData::try_new(1381, [l, s, l, s, l, l, s, l, s, s, l, s], gregorian(1961, 6, 15)).unwrap(), + PackedHijriYearData::try_new(1382, [l, s, l, l, s, l, l, s, l, s, s, l], gregorian(1962, 6, 4)).unwrap(), + PackedHijriYearData::try_new(1383, [s, l, s, l, s, l, l, l, s, l, s, s], gregorian(1963, 5, 25)).unwrap(), + PackedHijriYearData::try_new(1384, [l, s, s, l, s, l, l, l, s, l, l, s], gregorian(1964, 5, 13)).unwrap(), + PackedHijriYearData::try_new(1385, [s, l, s, s, l, s, l, l, s, l, l, l], gregorian(1965, 5, 3)).unwrap(), + PackedHijriYearData::try_new(1386, [s, s, l, s, s, l, s, l, s, l, l, l], gregorian(1966, 4, 23)).unwrap(), + PackedHijriYearData::try_new(1387, [s, l, s, l, s, l, s, s, l, s, l, l], gregorian(1967, 4, 12)).unwrap(), + PackedHijriYearData::try_new(1388, [s, l, l, s, l, s, l, s, s, l, s, l], gregorian(1968, 3, 31)).unwrap(), + PackedHijriYearData::try_new(1389, [s, l, l, s, l, l, s, l, s, s, l, s], gregorian(1969, 3, 20)).unwrap(), + PackedHijriYearData::try_new(1390, [l, s, l, s, l, l, l, s, l, s, l, s], gregorian(1970, 3, 9)).unwrap(), + PackedHijriYearData::try_new(1391, [s, l, s, l, s, l, l, l, s, l, s, l], gregorian(1971, 2, 27)).unwrap(), + PackedHijriYearData::try_new(1392, [s, s, l, s, s, l, l, l, s, l, s, l], gregorian(1972, 2, 17)).unwrap(), + PackedHijriYearData::try_new(1393, [l, s, s, l, s, l, s, l, s, l, s, l], gregorian(1973, 2, 5)).unwrap(), + PackedHijriYearData::try_new(1394, [l, l, s, s, l, s, l, s, s, l, s, l], gregorian(1974, 1, 25)).unwrap(), + PackedHijriYearData::try_new(1395, [l, l, s, l, s, l, s, l, s, s, l, s], gregorian(1975, 1, 14)).unwrap(), + PackedHijriYearData::try_new(1396, [l, l, l, s, l, s, l, s, l, s, s, l], gregorian(1976, 1, 3)).unwrap(), + PackedHijriYearData::try_new(1397, [s, l, l, s, l, l, s, l, s, l, s, s], gregorian(1976, 12, 23)).unwrap(), + PackedHijriYearData::try_new(1398, [l, s, l, s, l, l, s, l, l, s, s, l], gregorian(1977, 12, 12)).unwrap(), + PackedHijriYearData::try_new(1399, [s, l, s, l, s, l, s, l, l, s, l, s], gregorian(1978, 12, 2)).unwrap(), + PackedHijriYearData::try_new(1400, [l, l, s, s, l, s, l, s, l, s, l, l], gregorian(1979, 11, 21)).unwrap(), + PackedHijriYearData::try_new(1401, [s, l, l, s, s, l, s, s, l, s, l, l], gregorian(1980, 11, 10)).unwrap(), + PackedHijriYearData::try_new(1402, [s, l, l, l, s, s, l, s, s, l, s, l], gregorian(1981, 10, 30)).unwrap(), + PackedHijriYearData::try_new(1403, [s, l, l, l, s, l, s, l, s, s, l, s], gregorian(1982, 10, 19)).unwrap(), + PackedHijriYearData::try_new(1404, [l, s, l, l, s, l, l, s, l, s, s, l], gregorian(1983, 10, 8)).unwrap(), + PackedHijriYearData::try_new(1405, [s, l, s, l, s, l, l, l, s, l, s, s], gregorian(1984, 9, 27)).unwrap(), + PackedHijriYearData::try_new(1406, [l, s, l, s, l, s, l, l, s, l, s, l], gregorian(1985, 9, 16)).unwrap(), + PackedHijriYearData::try_new(1407, [l, s, s, l, s, l, s, l, s, l, l, s], gregorian(1986, 9, 6)).unwrap(), + PackedHijriYearData::try_new(1408, [l, l, s, s, l, s, l, s, l, s, l, s], gregorian(1987, 8, 26)).unwrap(), + PackedHijriYearData::try_new(1409, [l, l, l, s, s, l, s, l, s, s, l, s], gregorian(1988, 8, 14)).unwrap(), + PackedHijriYearData::try_new(1410, [l, l, l, s, l, l, s, s, l, s, s, l], gregorian(1989, 8, 3)).unwrap(), + PackedHijriYearData::try_new(1411, [l, s, l, s, l, l, s, l, s, l, s, s], gregorian(1990, 7, 24)).unwrap(), + PackedHijriYearData::try_new(1412, [l, l, s, l, s, l, l, s, l, s, l, s], gregorian(1991, 7, 13)).unwrap(), + PackedHijriYearData::try_new(1413, [l, s, s, l, s, l, l, s, l, l, s, l], gregorian(1992, 7, 2)).unwrap(), + PackedHijriYearData::try_new(1414, [s, l, s, s, l, s, l, s, l, l, l, s], gregorian(1993, 6, 22)).unwrap(), + PackedHijriYearData::try_new(1415, [l, s, l, s, s, l, s, l, s, l, l, s], gregorian(1994, 6, 11)).unwrap(), + PackedHijriYearData::try_new(1416, [l, l, s, l, s, s, l, s, l, s, l, s], gregorian(1995, 5, 31)).unwrap(), + PackedHijriYearData::try_new(1417, [l, l, s, l, s, l, s, l, s, l, s, s], gregorian(1996, 5, 19)).unwrap(), + PackedHijriYearData::try_new(1418, [l, l, s, l, l, s, l, s, l, s, l, s], gregorian(1997, 5, 8)).unwrap(), + PackedHijriYearData::try_new(1419, [s, l, s, l, s, l, l, l, s, l, s, l], gregorian(1998, 4, 28)).unwrap(), + PackedHijriYearData::try_new(1420, [s, s, l, s, l, s, l, l, l, s, l, s], gregorian(1999, 4, 18)).unwrap(), + PackedHijriYearData::try_new(1421, [l, s, s, l, s, s, l, l, l, s, l, l], gregorian(2000, 4, 6)).unwrap(), + PackedHijriYearData::try_new(1422, [s, l, s, s, l, s, s, l, l, s, l, l], gregorian(2001, 3, 27)).unwrap(), + PackedHijriYearData::try_new(1423, [l, s, l, s, s, l, s, s, l, l, s, l], gregorian(2002, 3, 16)).unwrap(), + PackedHijriYearData::try_new(1424, [l, s, l, s, l, s, l, s, l, s, s, l], gregorian(2003, 3, 5)).unwrap(), + PackedHijriYearData::try_new(1425, [l, s, l, l, s, l, s, l, s, l, s, s], gregorian(2004, 2, 22)).unwrap(), + PackedHijriYearData::try_new(1426, [l, l, s, l, s, l, l, s, l, s, l, s], gregorian(2005, 2, 10)).unwrap(), + PackedHijriYearData::try_new(1427, [l, s, s, l, s, l, l, l, s, l, s, l], gregorian(2006, 1, 31)).unwrap(), + PackedHijriYearData::try_new(1428, [s, l, s, s, l, s, l, l, l, s, l, s], gregorian(2007, 1, 21)).unwrap(), + PackedHijriYearData::try_new(1429, [l, s, l, s, s, l, s, l, l, s, l, s], gregorian(2008, 1, 10)).unwrap(), + PackedHijriYearData::try_new(1430, [l, l, s, l, s, s, l, s, l, s, l, s], gregorian(2008, 12, 29)).unwrap(), + PackedHijriYearData::try_new(1431, [l, l, l, s, l, s, s, l, s, l, s, s], gregorian(2009, 12, 18)).unwrap(), + PackedHijriYearData::try_new(1432, [l, l, l, s, l, l, s, l, s, s, l, s], gregorian(2010, 12, 7)).unwrap(), + PackedHijriYearData::try_new(1433, [s, l, l, s, l, l, s, l, l, s, s, l], gregorian(2011, 11, 27)).unwrap(), + PackedHijriYearData::try_new(1434, [s, s, l, s, l, l, s, l, l, l, s, s], gregorian(2012, 11, 16)).unwrap(), + PackedHijriYearData::try_new(1435, [l, s, s, l, s, l, s, l, l, l, s, l], gregorian(2013, 11, 5)).unwrap(), + PackedHijriYearData::try_new(1436, [s, l, s, l, s, s, l, s, l, l, s, l], gregorian(2014, 10, 26)).unwrap(), + PackedHijriYearData::try_new(1437, [s, l, l, s, l, s, s, l, s, l, s, l], gregorian(2015, 10, 15)).unwrap(), + PackedHijriYearData::try_new(1438, [s, l, l, l, s, l, s, s, l, s, s, l], gregorian(2016, 10, 3)).unwrap(), + PackedHijriYearData::try_new(1439, [s, l, l, l, l, s, l, s, s, l, s, s], gregorian(2017, 9, 22)).unwrap(), + PackedHijriYearData::try_new(1440, [l, s, l, l, l, s, l, l, s, s, l, s], gregorian(2018, 9, 11)).unwrap(), + PackedHijriYearData::try_new(1441, [s, l, s, l, l, s, l, l, s, l, s, l], gregorian(2019, 9, 1)).unwrap(), + PackedHijriYearData::try_new(1442, [s, s, l, s, l, s, l, l, l, s, l, s], gregorian(2020, 8, 21)).unwrap(), + PackedHijriYearData::try_new(1443, [l, s, l, s, s, l, s, l, l, s, l, s], gregorian(2021, 8, 10)).unwrap(), + PackedHijriYearData::try_new(1444, [l, l, s, l, s, s, l, s, l, s, l, s], gregorian(2022, 7, 30)).unwrap(), + PackedHijriYearData::try_new(1445, [l, l, l, s, l, s, l, s, s, l, s, l], gregorian(2023, 7, 19)).unwrap(), + PackedHijriYearData::try_new(1446, [s, l, l, l, s, l, s, l, s, s, l, s], gregorian(2024, 7, 8)).unwrap(), + PackedHijriYearData::try_new(1447, [s, l, l, l, s, l, l, s, l, s, s, l], gregorian(2025, 6, 27)).unwrap(), + PackedHijriYearData::try_new(1448, [s, s, l, l, s, l, l, s, l, l, s, s], gregorian(2026, 6, 17)).unwrap(), + PackedHijriYearData::try_new(1449, [l, s, l, s, l, s, l, s, l, l, s, l], gregorian(2027, 6, 6)).unwrap(), + PackedHijriYearData::try_new(1450, [s, l, s, l, s, s, l, s, l, l, l, s], gregorian(2028, 5, 26)).unwrap(), + PackedHijriYearData::try_new(1451, [l, s, l, l, s, s, s, l, s, l, l, s], gregorian(2029, 5, 15)).unwrap(), + PackedHijriYearData::try_new(1452, [l, l, l, s, s, l, s, s, l, s, l, s], gregorian(2030, 5, 4)).unwrap(), + PackedHijriYearData::try_new(1453, [l, l, l, s, l, s, l, s, s, l, s, l], gregorian(2031, 4, 23)).unwrap(), + PackedHijriYearData::try_new(1454, [s, l, l, s, l, l, s, l, s, s, l, s], gregorian(2032, 4, 12)).unwrap(), + PackedHijriYearData::try_new(1455, [l, s, l, s, l, l, s, l, s, l, l, s], gregorian(2033, 4, 1)).unwrap(), + PackedHijriYearData::try_new(1456, [s, l, s, l, s, l, s, l, l, s, l, l], gregorian(2034, 3, 22)).unwrap(), + PackedHijriYearData::try_new(1457, [s, s, l, s, s, l, s, l, l, s, l, l], gregorian(2035, 3, 12)).unwrap(), + PackedHijriYearData::try_new(1458, [l, s, s, l, s, s, l, s, l, s, l, l], gregorian(2036, 2, 29)).unwrap(), + PackedHijriYearData::try_new(1459, [l, s, l, s, l, s, s, l, s, l, s, l], gregorian(2037, 2, 17)).unwrap(), + PackedHijriYearData::try_new(1460, [l, s, l, l, s, l, s, s, l, s, l, s], gregorian(2038, 2, 6)).unwrap(), + PackedHijriYearData::try_new(1461, [l, s, l, l, s, l, s, l, s, l, s, l], gregorian(2039, 1, 26)).unwrap(), + PackedHijriYearData::try_new(1462, [s, l, s, l, l, s, l, s, l, l, s, s], gregorian(2040, 1, 16)).unwrap(), + PackedHijriYearData::try_new(1463, [l, s, l, s, l, s, l, s, l, l, l, s], gregorian(2041, 1, 4)).unwrap(), + PackedHijriYearData::try_new(1464, [s, l, s, l, s, s, l, s, l, l, l, l], gregorian(2041, 12, 25)).unwrap(), + PackedHijriYearData::try_new(1465, [s, l, s, s, l, s, s, l, s, l, l, l], gregorian(2042, 12, 15)).unwrap(), + PackedHijriYearData::try_new(1466, [s, l, l, s, s, l, s, s, l, l, s, l], gregorian(2043, 12, 4)).unwrap(), + PackedHijriYearData::try_new(1467, [s, l, l, s, l, s, l, s, s, l, l, s], gregorian(2044, 11, 22)).unwrap(), + PackedHijriYearData::try_new(1468, [s, l, l, l, s, l, s, l, s, l, s, s], gregorian(2045, 11, 11)).unwrap(), + PackedHijriYearData::try_new(1469, [l, s, l, s, l, l, l, s, l, s, l, s], gregorian(2046, 10, 31)).unwrap(), + PackedHijriYearData::try_new(1470, [s, l, s, l, s, l, l, s, l, l, s, l], gregorian(2047, 10, 21)).unwrap(), + PackedHijriYearData::try_new(1471, [s, s, l, s, l, s, l, s, l, l, l, s], gregorian(2048, 10, 10)).unwrap(), + PackedHijriYearData::try_new(1472, [l, s, s, l, s, l, s, l, s, l, l, s], gregorian(2049, 9, 29)).unwrap(), + PackedHijriYearData::try_new(1473, [l, s, l, s, l, s, l, s, s, l, l, s], gregorian(2050, 9, 18)).unwrap(), + PackedHijriYearData::try_new(1474, [l, s, l, l, s, l, s, l, s, s, l, s], gregorian(2051, 9, 7)).unwrap(), + PackedHijriYearData::try_new(1475, [l, s, l, l, l, s, l, s, l, s, s, l], gregorian(2052, 8, 26)).unwrap(), + PackedHijriYearData::try_new(1476, [s, l, s, l, l, l, s, l, s, l, s, s], gregorian(2053, 8, 16)).unwrap(), + PackedHijriYearData::try_new(1477, [l, s, s, l, l, l, s, l, l, s, l, s], gregorian(2054, 8, 5)).unwrap(), + PackedHijriYearData::try_new(1478, [s, l, s, s, l, l, s, l, l, s, l, l], gregorian(2055, 7, 26)).unwrap(), + PackedHijriYearData::try_new(1479, [s, s, l, s, l, s, l, s, l, s, l, l], gregorian(2056, 7, 15)).unwrap(), + PackedHijriYearData::try_new(1480, [s, l, s, l, s, l, s, s, l, l, s, l], gregorian(2057, 7, 4)).unwrap(), + PackedHijriYearData::try_new(1481, [s, l, l, s, l, s, l, s, l, s, s, l], gregorian(2058, 6, 23)).unwrap(), + PackedHijriYearData::try_new(1482, [s, l, l, s, l, l, s, l, s, l, s, s], gregorian(2059, 6, 12)).unwrap(), + PackedHijriYearData::try_new(1483, [l, s, l, s, l, l, l, s, l, s, l, s], gregorian(2060, 5, 31)).unwrap(), + PackedHijriYearData::try_new(1484, [s, l, s, l, l, s, l, s, l, l, s, l], gregorian(2061, 5, 21)).unwrap(), + PackedHijriYearData::try_new(1485, [s, s, l, s, l, s, l, l, s, l, l, s], gregorian(2062, 5, 11)).unwrap(), + PackedHijriYearData::try_new(1486, [l, s, s, l, s, l, s, l, s, l, l, s], gregorian(2063, 4, 30)).unwrap(), + PackedHijriYearData::try_new(1487, [l, l, s, l, s, s, l, s, l, s, l, s], gregorian(2064, 4, 18)).unwrap(), + PackedHijriYearData::try_new(1488, [l, l, s, l, l, s, s, l, s, s, l, l], gregorian(2065, 4, 7)).unwrap(), + PackedHijriYearData::try_new(1489, [s, l, l, s, l, l, s, s, l, s, s, l], gregorian(2066, 3, 28)).unwrap(), + PackedHijriYearData::try_new(1490, [s, l, l, s, l, l, l, s, s, l, s, s], gregorian(2067, 3, 17)).unwrap(), + PackedHijriYearData::try_new(1491, [l, s, l, s, l, l, l, s, l, s, l, s], gregorian(2068, 3, 5)).unwrap(), + PackedHijriYearData::try_new(1492, [l, s, s, l, s, l, l, s, l, s, l, l], gregorian(2069, 2, 23)).unwrap(), + PackedHijriYearData::try_new(1493, [s, l, s, s, l, s, l, s, l, s, l, l], gregorian(2070, 2, 13)).unwrap(), + PackedHijriYearData::try_new(1494, [l, s, l, s, s, l, s, s, l, s, l, l], gregorian(2071, 2, 2)).unwrap(), + PackedHijriYearData::try_new(1495, [l, l, s, l, s, s, l, s, s, l, s, l], gregorian(2072, 1, 22)).unwrap(), + PackedHijriYearData::try_new(1496, [l, l, s, l, l, s, s, l, s, s, l, s], gregorian(2073, 1, 10)).unwrap(), + PackedHijriYearData::try_new(1497, [l, l, s, l, l, s, l, s, l, s, s, l], gregorian(2073, 12, 30)).unwrap(), + PackedHijriYearData::try_new(1498, [s, l, s, l, l, s, l, l, s, l, s, l], gregorian(2074, 12, 20)).unwrap(), + PackedHijriYearData::try_new(1499, [s, s, l, s, l, s, l, l, s, l, l, s], gregorian(2075, 12, 10)).unwrap(), + PackedHijriYearData::try_new(1500, [l, s, s, l, s, l, s, l, s, l, l, l], gregorian(2076, 11, 28)).unwrap(), + PackedHijriYearData::try_new(1501, [s, l, s, l, s, s, l, s, s, l, l, l], gregorian(2077, 11, 18)).unwrap(), + PackedHijriYearData::try_new(1502, [s, l, l, s, l, s, s, l, s, s, l, l], gregorian(2078, 11, 7)).unwrap(), + PackedHijriYearData::try_new(1503, [l, s, l, l, s, l, s, s, l, s, s, l], gregorian(2079, 10, 27)).unwrap(), + PackedHijriYearData::try_new(1504, [l, s, l, l, s, l, l, s, s, l, s, l], gregorian(2080, 10, 15)).unwrap(), + PackedHijriYearData::try_new(1505, [s, s, l, l, s, l, l, s, l, s, l, s], gregorian(2081, 10, 5)).unwrap(), + PackedHijriYearData::try_new(1506, [l, s, s, l, s, l, l, s, l, l, s, l], gregorian(2082, 9, 24)).unwrap(), + PackedHijriYearData::try_new(1507, [l, s, s, s, l, s, l, s, l, l, l, l], gregorian(2083, 9, 14)).unwrap(), + PackedHijriYearData::try_new(1508, [s, s, l, s, s, l, s, l, s, l, l, l], gregorian(2084, 9, 3)).unwrap(), + PackedHijriYearData::try_new(1509, [s, l, s, l, s, s, l, s, l, s, l, l], gregorian(2085, 8, 23)).unwrap(), + PackedHijriYearData::try_new(1510, [s, l, s, l, l, s, l, s, s, l, s, l], gregorian(2086, 8, 12)).unwrap(), + PackedHijriYearData::try_new(1511, [s, l, s, l, l, s, l, l, s, s, l, s], gregorian(2087, 8, 1)).unwrap(), + PackedHijriYearData::try_new(1512, [l, s, s, l, l, l, s, l, l, s, s, l], gregorian(2088, 7, 20)).unwrap(), + PackedHijriYearData::try_new(1513, [s, s, l, s, l, l, s, l, l, s, l, s], gregorian(2089, 7, 10)).unwrap(), + PackedHijriYearData::try_new(1514, [l, s, s, l, s, l, s, l, l, l, s, l], gregorian(2090, 6, 29)).unwrap(), + PackedHijriYearData::try_new(1515, [s, l, s, s, l, s, l, s, l, l, s, l], gregorian(2091, 6, 19)).unwrap(), + PackedHijriYearData::try_new(1516, [l, s, l, s, s, l, s, l, s, l, s, l], gregorian(2092, 6, 7)).unwrap(), + PackedHijriYearData::try_new(1517, [l, s, l, s, l, s, l, s, l, s, l, s], gregorian(2093, 5, 27)).unwrap(), + PackedHijriYearData::try_new(1518, [l, s, l, l, s, l, l, s, s, l, s, l], gregorian(2094, 5, 16)).unwrap(), + PackedHijriYearData::try_new(1519, [s, s, l, l, s, l, l, s, l, s, l, s], gregorian(2095, 5, 6)).unwrap(), + PackedHijriYearData::try_new(1520, [l, s, s, l, s, l, l, l, s, l, l, s], gregorian(2096, 4, 24)).unwrap(), + PackedHijriYearData::try_new(1521, [s, l, s, s, l, s, l, l, s, l, l, l], gregorian(2097, 4, 14)).unwrap(), + PackedHijriYearData::try_new(1522, [s, s, l, s, s, l, s, l, s, l, l, l], gregorian(2098, 4, 4)).unwrap(), + PackedHijriYearData::try_new(1523, [s, l, s, l, s, s, l, s, l, s, l, l], gregorian(2099, 3, 24)).unwrap(), + PackedHijriYearData::try_new(1524, [s, l, l, s, l, s, l, s, s, l, s, l], gregorian(2100, 3, 13)).unwrap(), + PackedHijriYearData::try_new(1525, [s, l, l, s, l, l, s, l, s, s, l, s], gregorian(2101, 3, 2)).unwrap(), + PackedHijriYearData::try_new(1526, [l, s, l, s, l, l, l, s, l, s, s, l], gregorian(2102, 2, 19)).unwrap(), + PackedHijriYearData::try_new(1527, [s, l, s, l, s, l, l, l, s, s, l, s], gregorian(2103, 2, 9)).unwrap(), + PackedHijriYearData::try_new(1528, [l, s, l, s, s, l, l, l, s, l, s, l], gregorian(2104, 1, 29)).unwrap(), + PackedHijriYearData::try_new(1529, [s, l, s, l, s, l, s, l, s, l, s, l], gregorian(2105, 1, 18)).unwrap(), + PackedHijriYearData::try_new(1530, [l, s, l, s, l, s, l, s, s, l, s, l], gregorian(2106, 1, 7)).unwrap(), + PackedHijriYearData::try_new(1531, [l, l, s, l, s, l, s, l, s, s, l, s], gregorian(2106, 12, 27)).unwrap(), + PackedHijriYearData::try_new(1532, [l, l, l, s, l, s, l, s, s, l, s, s], gregorian(2107, 12, 16)).unwrap(), + PackedHijriYearData::try_new(1533, [l, l, l, s, l, l, s, l, s, s, l, s], gregorian(2108, 12, 4)).unwrap(), + PackedHijriYearData::try_new(1534, [l, s, l, s, l, l, s, l, s, l, s, l], gregorian(2109, 11, 24)).unwrap(), + PackedHijriYearData::try_new(1535, [s, l, s, l, s, l, s, l, l, s, l, s], gregorian(2110, 11, 14)).unwrap(), + PackedHijriYearData::try_new(1536, [l, s, l, s, l, s, s, l, l, s, l, l], gregorian(2111, 11, 3)).unwrap(), + PackedHijriYearData::try_new(1537, [s, l, s, l, s, l, s, s, l, s, l, l], gregorian(2112, 10, 23)).unwrap(), + PackedHijriYearData::try_new(1538, [s, l, l, s, l, s, l, s, s, l, s, l], gregorian(2113, 10, 12)).unwrap(), + PackedHijriYearData::try_new(1539, [s, l, l, l, s, l, s, l, s, s, s, l], gregorian(2114, 10, 1)).unwrap(), + PackedHijriYearData::try_new(1540, [l, s, l, l, s, l, l, s, l, s, s, l], gregorian(2115, 9, 20)).unwrap(), + PackedHijriYearData::try_new(1541, [s, l, s, l, s, l, l, l, s, l, s, s], gregorian(2116, 9, 9)).unwrap(), + PackedHijriYearData::try_new(1542, [l, s, l, s, l, s, l, l, s, l, s, l], gregorian(2117, 8, 29)).unwrap(), + PackedHijriYearData::try_new(1543, [l, s, s, l, s, l, s, l, s, l, l, s], gregorian(2118, 8, 19)).unwrap(), + PackedHijriYearData::try_new(1544, [l, l, s, s, l, s, l, s, s, l, l, s], gregorian(2119, 8, 8)).unwrap(), + PackedHijriYearData::try_new(1545, [l, l, l, s, s, l, s, s, l, s, l, s], gregorian(2120, 7, 27)).unwrap(), + PackedHijriYearData::try_new(1546, [l, l, l, s, l, s, l, s, l, s, s, l], gregorian(2121, 7, 16)).unwrap(), + PackedHijriYearData::try_new(1547, [l, s, l, s, l, l, s, l, s, l, s, s], gregorian(2122, 7, 6)).unwrap(), + PackedHijriYearData::try_new(1548, [l, s, l, s, l, l, s, l, l, s, l, s], gregorian(2123, 6, 25)).unwrap(), + PackedHijriYearData::try_new(1549, [s, l, s, l, s, l, s, l, l, l, s, l], gregorian(2124, 6, 14)).unwrap(), + PackedHijriYearData::try_new(1550, [s, l, s, s, s, l, s, l, l, l, l, s], gregorian(2125, 6, 4)).unwrap(), + PackedHijriYearData::try_new(1551, [l, s, l, s, s, s, l, s, l, l, l, s], gregorian(2126, 5, 24)).unwrap(), + PackedHijriYearData::try_new(1552, [l, l, s, s, l, s, s, l, s, l, l, s], gregorian(2127, 5, 13)).unwrap(), + PackedHijriYearData::try_new(1553, [l, l, s, l, s, l, s, l, s, s, l, s], gregorian(2128, 5, 1)).unwrap(), + PackedHijriYearData::try_new(1554, [l, l, s, l, s, l, l, s, l, s, s, l], gregorian(2129, 4, 20)).unwrap(), + PackedHijriYearData::try_new(1555, [s, l, s, l, s, l, l, l, s, l, s, l], gregorian(2130, 4, 10)).unwrap(), + PackedHijriYearData::try_new(1556, [s, s, l, s, l, s, l, l, l, s, l, s], gregorian(2131, 3, 31)).unwrap(), + PackedHijriYearData::try_new(1557, [l, s, s, l, s, s, l, l, l, s, l, l], gregorian(2132, 3, 19)).unwrap(), + PackedHijriYearData::try_new(1558, [s, l, s, s, s, l, s, l, l, s, l, l], gregorian(2133, 3, 9)).unwrap(), + PackedHijriYearData::try_new(1559, [l, s, l, s, s, l, s, s, l, s, l, l], gregorian(2134, 2, 26)).unwrap(), + PackedHijriYearData::try_new(1560, [l, s, l, s, l, s, l, s, l, s, s, l], gregorian(2135, 2, 15)).unwrap(), + PackedHijriYearData::try_new(1561, [l, s, l, l, s, l, s, l, s, l, s, s], gregorian(2136, 2, 4)).unwrap(), + PackedHijriYearData::try_new(1562, [l, s, l, l, s, l, l, s, l, s, l, s], gregorian(2137, 1, 23)).unwrap(), + PackedHijriYearData::try_new(1563, [s, l, s, l, s, l, l, l, l, s, s, l], gregorian(2138, 1, 13)).unwrap(), + PackedHijriYearData::try_new(1564, [s, s, l, s, l, s, l, l, l, s, l, s], gregorian(2139, 1, 3)).unwrap(), + PackedHijriYearData::try_new(1565, [l, s, l, s, s, l, s, l, l, s, l, s], gregorian(2139, 12, 23)).unwrap(), + PackedHijriYearData::try_new(1566, [l, l, s, l, s, s, l, s, l, s, l, s], gregorian(2140, 12, 11)).unwrap(), + ] +}; 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 index 718286a8c1f830..884d851795d8da 100644 --- a/deps/crates/vendor/icu_calendar/src/cal/hijri/ummalqura_data.rs +++ b/deps/crates/vendor/icu_calendar/src/cal/hijri/ummalqura_data.rs @@ -2,316 +2,401 @@ // 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; +//! Data obtained from ICU4C: +//! -pub const UMMALQURA_DATA_STARTING_YEAR: i32 = 1300; +use super::PackedHijriYearData; + +pub const 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; +#[allow(clippy::unwrap_used)] // const +pub const DATA: &[PackedHijriYearData] = { + use calendrical_calculations::gregorian::fixed_from_gregorian as gregorian; 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)), + &[ + PackedHijriYearData::try_new(1300, [l, s, l, s, l, s, l, s, l, s, l, s], gregorian(1882, 11, 12)).unwrap(), + PackedHijriYearData::try_new(1301, [l, l, s, l, s, l, s, l, s, l, s, s], gregorian(1883, 11, 1)).unwrap(), + PackedHijriYearData::try_new(1302, [l, l, l, s, l, l, s, s, l, s, s, l], gregorian(1884, 10, 20)).unwrap(), + PackedHijriYearData::try_new(1303, [s, l, l, s, l, l, s, l, s, l, s, s], gregorian(1885, 10, 10)).unwrap(), + PackedHijriYearData::try_new(1304, [s, l, l, s, l, l, l, s, l, s, l, s], gregorian(1886, 9, 29)).unwrap(), + PackedHijriYearData::try_new(1305, [s, s, l, l, s, l, l, s, l, l, s, s], gregorian(1887, 9, 19)).unwrap(), + PackedHijriYearData::try_new(1306, [l, s, l, s, l, s, l, s, l, l, s, l], gregorian(1888, 9, 7)).unwrap(), + PackedHijriYearData::try_new(1307, [s, l, s, l, s, l, s, l, s, l, s, l], gregorian(1889, 8, 28)).unwrap(), + PackedHijriYearData::try_new(1308, [s, l, l, s, l, s, l, s, l, s, s, l], gregorian(1890, 8, 17)).unwrap(), + PackedHijriYearData::try_new(1309, [s, l, l, l, l, s, s, l, s, s, l, s], gregorian(1891, 8, 6)).unwrap(), + PackedHijriYearData::try_new(1310, [l, s, l, l, l, s, l, s, l, s, s, l], gregorian(1892, 7, 25)).unwrap(), + PackedHijriYearData::try_new(1311, [s, l, s, l, l, l, s, l, s, l, s, s], gregorian(1893, 7, 15)).unwrap(), + PackedHijriYearData::try_new(1312, [l, s, l, s, l, l, s, l, l, s, l, s], gregorian(1894, 7, 4)).unwrap(), + PackedHijriYearData::try_new(1313, [s, l, s, l, s, l, s, l, l, l, s, s], gregorian(1895, 6, 24)).unwrap(), + PackedHijriYearData::try_new(1314, [l, l, s, l, s, s, l, s, l, l, s, l], gregorian(1896, 6, 12)).unwrap(), + PackedHijriYearData::try_new(1315, [s, l, l, s, l, s, s, l, s, l, s, l], gregorian(1897, 6, 2)).unwrap(), + PackedHijriYearData::try_new(1316, [s, l, l, l, s, l, s, s, l, s, l, s], gregorian(1898, 5, 22)).unwrap(), + PackedHijriYearData::try_new(1317, [l, s, l, l, s, l, s, l, s, l, s, s], gregorian(1899, 5, 11)).unwrap(), + PackedHijriYearData::try_new(1318, [l, s, l, l, s, l, l, s, l, s, l, s], gregorian(1900, 4, 30)).unwrap(), + PackedHijriYearData::try_new(1319, [s, l, s, l, l, s, l, s, l, l, s, l], gregorian(1901, 4, 20)).unwrap(), + PackedHijriYearData::try_new(1320, [s, l, s, s, l, s, l, s, l, l, l, s], gregorian(1902, 4, 10)).unwrap(), + PackedHijriYearData::try_new(1321, [l, s, l, s, s, l, s, s, l, l, l, l], gregorian(1903, 3, 30)).unwrap(), + PackedHijriYearData::try_new(1322, [s, l, s, l, s, s, s, l, s, l, l, l], gregorian(1904, 3, 19)).unwrap(), + PackedHijriYearData::try_new(1323, [s, l, l, s, l, s, s, s, l, s, l, l], gregorian(1905, 3, 8)).unwrap(), + PackedHijriYearData::try_new(1324, [s, l, l, s, l, s, l, s, s, l, s, l], gregorian(1906, 2, 25)).unwrap(), + PackedHijriYearData::try_new(1325, [l, s, l, s, l, l, s, l, s, l, s, l], gregorian(1907, 2, 14)).unwrap(), + PackedHijriYearData::try_new(1326, [s, s, l, s, l, l, s, l, s, l, l, s], gregorian(1908, 2, 4)).unwrap(), + PackedHijriYearData::try_new(1327, [l, s, s, l, s, l, s, l, l, s, l, l], gregorian(1909, 1, 23)).unwrap(), + PackedHijriYearData::try_new(1328, [s, l, s, s, l, s, s, l, l, l, s, l], gregorian(1910, 1, 13)).unwrap(), + PackedHijriYearData::try_new(1329, [l, s, l, s, s, l, s, s, l, l, s, l], gregorian(1911, 1, 2)).unwrap(), + PackedHijriYearData::try_new(1330, [l, l, s, l, s, s, l, s, s, l, l, s], gregorian(1911, 12, 22)).unwrap(), + PackedHijriYearData::try_new(1331, [l, l, s, l, l, s, s, l, s, l, s, l], gregorian(1912, 12, 10)).unwrap(), + PackedHijriYearData::try_new(1332, [s, l, s, l, l, s, l, s, l, l, s, s], gregorian(1913, 11, 30)).unwrap(), + PackedHijriYearData::try_new(1333, [l, s, s, l, l, s, l, l, s, l, l, s], gregorian(1914, 11, 19)).unwrap(), + PackedHijriYearData::try_new(1334, [s, s, l, s, l, s, l, l, l, s, l, s], gregorian(1915, 11, 9)).unwrap(), + PackedHijriYearData::try_new(1335, [l, s, l, s, s, l, s, l, l, s, l, l], gregorian(1916, 10, 28)).unwrap(), + PackedHijriYearData::try_new(1336, [s, l, s, l, s, s, l, s, l, s, l, l], gregorian(1917, 10, 18)).unwrap(), + PackedHijriYearData::try_new(1337, [l, s, l, s, l, s, s, l, s, l, s, l], gregorian(1918, 10, 7)).unwrap(), + PackedHijriYearData::try_new(1338, [s, l, l, s, l, l, s, s, l, s, l, s], gregorian(1919, 9, 26)).unwrap(), + PackedHijriYearData::try_new(1339, [l, s, l, s, l, l, l, s, l, s, s, l], gregorian(1920, 9, 14)).unwrap(), + PackedHijriYearData::try_new(1340, [s, s, l, s, l, l, l, l, s, l, s, s], gregorian(1921, 9, 4)).unwrap(), + PackedHijriYearData::try_new(1341, [l, s, s, l, s, l, l, l, s, l, l, s], gregorian(1922, 8, 24)).unwrap(), + PackedHijriYearData::try_new(1342, [s, s, l, s, l, s, l, l, s, l, l, s], gregorian(1923, 8, 14)).unwrap(), + PackedHijriYearData::try_new(1343, [l, s, s, l, s, l, s, l, s, l, l, s], gregorian(1924, 8, 2)).unwrap(), + PackedHijriYearData::try_new(1344, [l, s, l, s, l, l, s, s, l, s, l, s], gregorian(1925, 7, 22)).unwrap(), + PackedHijriYearData::try_new(1345, [l, s, l, l, l, s, l, s, s, l, s, s], gregorian(1926, 7, 11)).unwrap(), + PackedHijriYearData::try_new(1346, [l, s, l, l, l, l, s, l, s, s, l, s], gregorian(1927, 6, 30)).unwrap(), + PackedHijriYearData::try_new(1347, [s, l, s, l, l, l, s, l, l, s, s, l], gregorian(1928, 6, 19)).unwrap(), + PackedHijriYearData::try_new(1348, [s, s, l, s, l, l, s, l, l, l, s, s], gregorian(1929, 6, 9)).unwrap(), + PackedHijriYearData::try_new(1349, [l, s, s, l, s, l, l, s, l, l, s, l], gregorian(1930, 5, 29)).unwrap(), + PackedHijriYearData::try_new(1350, [s, l, s, l, s, l, s, s, l, l, s, l], gregorian(1931, 5, 19)).unwrap(), + PackedHijriYearData::try_new(1351, [l, s, l, s, l, s, l, s, s, l, s, l], gregorian(1932, 5, 7)).unwrap(), + PackedHijriYearData::try_new(1352, [l, s, l, l, s, l, s, l, s, s, l, s], gregorian(1933, 4, 26)).unwrap(), + PackedHijriYearData::try_new(1353, [l, s, l, l, l, s, l, s, s, l, s, l], gregorian(1934, 4, 15)).unwrap(), + PackedHijriYearData::try_new(1354, [s, l, s, l, l, s, l, l, s, l, s, s], gregorian(1935, 4, 5)).unwrap(), + PackedHijriYearData::try_new(1355, [l, s, s, l, l, s, l, l, s, l, l, s], gregorian(1936, 3, 24)).unwrap(), + PackedHijriYearData::try_new(1356, [s, l, s, l, s, l, s, l, s, l, l, l], gregorian(1937, 3, 14)).unwrap(), + PackedHijriYearData::try_new(1357, [s, s, l, s, l, s, s, l, s, l, l, l], gregorian(1938, 3, 4)).unwrap(), + PackedHijriYearData::try_new(1358, [s, l, s, l, s, l, s, s, l, s, l, l], gregorian(1939, 2, 21)).unwrap(), + PackedHijriYearData::try_new(1359, [s, l, l, s, l, s, l, s, s, s, l, l], gregorian(1940, 2, 10)).unwrap(), + PackedHijriYearData::try_new(1360, [s, l, l, l, s, l, s, l, s, s, l, s], gregorian(1941, 1, 29)).unwrap(), + PackedHijriYearData::try_new(1361, [l, s, l, l, s, l, l, s, s, l, s, l], gregorian(1942, 1, 18)).unwrap(), + PackedHijriYearData::try_new(1362, [s, l, s, l, s, l, l, s, l, s, l, s], gregorian(1943, 1, 8)).unwrap(), + PackedHijriYearData::try_new(1363, [l, s, l, s, l, s, l, s, l, s, l, l], gregorian(1943, 12, 28)).unwrap(), + PackedHijriYearData::try_new(1364, [s, l, s, l, s, s, l, s, l, s, l, l], gregorian(1944, 12, 17)).unwrap(), + PackedHijriYearData::try_new(1365, [l, l, s, s, l, s, s, l, s, l, s, l], gregorian(1945, 12, 6)).unwrap(), + PackedHijriYearData::try_new(1366, [l, l, s, l, s, l, s, s, l, s, l, s], gregorian(1946, 11, 25)).unwrap(), + PackedHijriYearData::try_new(1367, [l, l, s, l, l, s, l, s, s, l, s, l], gregorian(1947, 11, 14)).unwrap(), + PackedHijriYearData::try_new(1368, [s, l, s, l, l, l, s, s, l, s, l, s], gregorian(1948, 11, 3)).unwrap(), + PackedHijriYearData::try_new(1369, [l, s, l, s, l, l, s, l, s, l, l, s], gregorian(1949, 10, 23)).unwrap(), + PackedHijriYearData::try_new(1370, [l, s, s, l, s, l, s, l, s, l, l, l], gregorian(1950, 10, 13)).unwrap(), + PackedHijriYearData::try_new(1371, [s, l, s, s, l, s, l, s, l, s, l, l], gregorian(1951, 10, 3)).unwrap(), + PackedHijriYearData::try_new(1372, [l, s, s, l, s, l, s, s, l, s, l, l], gregorian(1952, 9, 21)).unwrap(), + PackedHijriYearData::try_new(1373, [l, s, l, s, l, s, l, s, s, l, s, l], gregorian(1953, 9, 10)).unwrap(), + PackedHijriYearData::try_new(1374, [l, s, l, l, s, l, s, l, s, s, l, s], gregorian(1954, 8, 30)).unwrap(), + PackedHijriYearData::try_new(1375, [l, s, l, l, s, l, l, s, l, s, l, s], gregorian(1955, 8, 19)).unwrap(), + PackedHijriYearData::try_new(1376, [s, l, s, l, s, l, l, l, s, l, s, l], gregorian(1956, 8, 8)).unwrap(), + PackedHijriYearData::try_new(1377, [s, s, l, s, s, l, l, l, s, l, l, s], gregorian(1957, 7, 29)).unwrap(), + PackedHijriYearData::try_new(1378, [l, s, s, s, l, s, l, l, s, l, l, l], gregorian(1958, 7, 18)).unwrap(), + PackedHijriYearData::try_new(1379, [s, l, s, s, s, l, s, l, l, s, l, l], gregorian(1959, 7, 8)).unwrap(), + PackedHijriYearData::try_new(1380, [s, l, s, l, s, l, s, l, s, l, s, l], gregorian(1960, 6, 26)).unwrap(), + PackedHijriYearData::try_new(1381, [s, l, s, l, l, s, l, s, l, s, s, l], gregorian(1961, 6, 15)).unwrap(), + PackedHijriYearData::try_new(1382, [s, l, s, l, l, s, l, l, s, l, s, s], gregorian(1962, 6, 4)).unwrap(), + PackedHijriYearData::try_new(1383, [l, s, s, l, l, l, s, l, l, s, l, s], gregorian(1963, 5, 24)).unwrap(), + PackedHijriYearData::try_new(1384, [s, l, s, s, l, l, s, l, l, l, s, l], gregorian(1964, 5, 13)).unwrap(), + PackedHijriYearData::try_new(1385, [s, s, l, s, s, l, l, s, l, l, l, s], gregorian(1965, 5, 3)).unwrap(), + PackedHijriYearData::try_new(1386, [l, s, s, l, s, s, l, l, s, l, l, s], gregorian(1966, 4, 22)).unwrap(), + PackedHijriYearData::try_new(1387, [l, s, l, s, l, s, l, s, l, s, l, s], gregorian(1967, 4, 11)).unwrap(), + PackedHijriYearData::try_new(1388, [l, l, s, l, s, l, s, l, s, l, s, s], gregorian(1968, 3, 30)).unwrap(), + PackedHijriYearData::try_new(1389, [l, l, s, l, l, s, l, l, s, s, l, s], gregorian(1969, 3, 19)).unwrap(), + PackedHijriYearData::try_new(1390, [s, l, s, l, l, l, s, l, s, l, s, l], gregorian(1970, 3, 9)).unwrap(), + PackedHijriYearData::try_new(1391, [s, s, l, s, l, l, s, l, l, s, l, s], gregorian(1971, 2, 27)).unwrap(), + PackedHijriYearData::try_new(1392, [l, s, s, l, s, l, s, l, l, s, l, l], gregorian(1972, 2, 16)).unwrap(), + PackedHijriYearData::try_new(1393, [s, l, s, s, l, s, l, s, l, s, l, l], gregorian(1973, 2, 5)).unwrap(), + PackedHijriYearData::try_new(1394, [l, s, l, s, s, l, s, l, s, l, s, l], gregorian(1974, 1, 25)).unwrap(), + PackedHijriYearData::try_new(1395, [l, s, l, l, s, l, s, s, l, s, s, l], gregorian(1975, 1, 14)).unwrap(), + PackedHijriYearData::try_new(1396, [l, s, l, l, s, l, l, s, s, l, s, s], gregorian(1976, 1, 3)).unwrap(), + PackedHijriYearData::try_new(1397, [l, s, l, l, s, l, l, l, s, s, s, l], gregorian(1976, 12, 22)).unwrap(), + PackedHijriYearData::try_new(1398, [s, l, s, l, l, s, l, l, s, l, s, s], gregorian(1977, 12, 12)).unwrap(), + PackedHijriYearData::try_new(1399, [l, s, l, s, l, s, l, l, s, l, s, l], gregorian(1978, 12, 1)).unwrap(), + PackedHijriYearData::try_new(1400, [l, s, l, s, s, l, s, l, s, l, s, l], gregorian(1979, 11, 21)).unwrap(), + PackedHijriYearData::try_new(1401, [l, l, s, l, s, s, l, s, s, l, s, l], gregorian(1980, 11, 9)).unwrap(), + PackedHijriYearData::try_new(1402, [l, l, l, s, l, s, s, l, s, s, l, s], gregorian(1981, 10, 29)).unwrap(), + PackedHijriYearData::try_new(1403, [l, l, l, s, l, l, s, s, l, s, s, l], gregorian(1982, 10, 18)).unwrap(), + PackedHijriYearData::try_new(1404, [s, l, l, s, l, l, s, l, s, l, s, s], gregorian(1983, 10, 8)).unwrap(), + PackedHijriYearData::try_new(1405, [l, s, l, s, l, l, l, s, l, s, s, l], gregorian(1984, 9, 26)).unwrap(), + PackedHijriYearData::try_new(1406, [l, s, s, l, s, l, l, s, l, s, l, l], gregorian(1985, 9, 16)).unwrap(), + PackedHijriYearData::try_new(1407, [s, l, s, s, l, s, l, s, l, s, l, l], gregorian(1986, 9, 6)).unwrap(), + PackedHijriYearData::try_new(1408, [l, s, l, s, l, s, s, l, s, s, l, l], gregorian(1987, 8, 26)).unwrap(), + PackedHijriYearData::try_new(1409, [l, l, s, l, s, l, s, s, l, s, s, l], gregorian(1988, 8, 14)).unwrap(), + PackedHijriYearData::try_new(1410, [l, l, s, l, l, s, l, s, s, l, s, s], gregorian(1989, 8, 3)).unwrap(), + PackedHijriYearData::try_new(1411, [l, l, s, l, l, s, l, l, s, s, l, s], gregorian(1990, 7, 23)).unwrap(), + PackedHijriYearData::try_new(1412, [l, s, l, s, l, s, l, l, l, s, s, l], gregorian(1991, 7, 13)).unwrap(), + PackedHijriYearData::try_new(1413, [s, l, s, s, l, s, l, l, l, s, l, s], gregorian(1992, 7, 2)).unwrap(), + PackedHijriYearData::try_new(1414, [l, s, l, s, s, l, s, l, l, s, l, l], gregorian(1993, 6, 21)).unwrap(), + PackedHijriYearData::try_new(1415, [s, l, s, l, s, s, l, s, l, s, l, l], gregorian(1994, 6, 11)).unwrap(), + PackedHijriYearData::try_new(1416, [l, s, l, s, l, s, s, l, s, l, s, l], gregorian(1995, 5, 31)).unwrap(), + PackedHijriYearData::try_new(1417, [l, s, l, l, s, s, l, s, l, s, l, s], gregorian(1996, 5, 19)).unwrap(), + PackedHijriYearData::try_new(1418, [l, s, l, l, s, l, s, l, s, l, s, l], gregorian(1997, 5, 8)).unwrap(), + PackedHijriYearData::try_new(1419, [s, l, s, l, s, l, s, l, l, l, s, s], gregorian(1998, 4, 28)).unwrap(), + PackedHijriYearData::try_new(1420, [s, l, s, s, l, s, l, l, l, l, s, l], gregorian(1999, 4, 17)).unwrap(), + PackedHijriYearData::try_new(1421, [s, s, l, s, s, s, l, l, l, l, s, l], gregorian(2000, 4, 6)).unwrap(), + PackedHijriYearData::try_new(1422, [l, s, s, l, s, s, s, l, l, l, s, l], gregorian(2001, 3, 26)).unwrap(), + PackedHijriYearData::try_new(1423, [l, s, l, s, l, s, s, l, s, l, s, l], gregorian(2002, 3, 15)).unwrap(), + PackedHijriYearData::try_new(1424, [l, s, l, l, s, l, s, s, l, s, l, s], gregorian(2003, 3, 4)).unwrap(), + PackedHijriYearData::try_new(1425, [l, s, l, l, s, l, s, l, l, s, l, s], gregorian(2004, 2, 21)).unwrap(), + PackedHijriYearData::try_new(1426, [s, l, s, l, s, l, l, s, l, l, s, l], gregorian(2005, 2, 10)).unwrap(), + PackedHijriYearData::try_new(1427, [s, s, l, s, l, s, l, l, s, l, l, s], gregorian(2006, 1, 31)).unwrap(), + PackedHijriYearData::try_new(1428, [l, s, s, l, s, s, l, l, l, s, l, l], gregorian(2007, 1, 20)).unwrap(), + PackedHijriYearData::try_new(1429, [s, l, s, s, l, s, s, l, l, s, l, l], gregorian(2008, 1, 10)).unwrap(), + PackedHijriYearData::try_new(1430, [s, l, l, s, s, l, s, l, s, l, s, l], gregorian(2008, 12, 29)).unwrap(), + PackedHijriYearData::try_new(1431, [s, l, l, s, l, s, l, s, l, s, s, l], gregorian(2009, 12, 18)).unwrap(), + PackedHijriYearData::try_new(1432, [s, l, l, l, s, l, s, l, s, l, s, s], gregorian(2010, 12, 7)).unwrap(), + PackedHijriYearData::try_new(1433, [l, s, l, l, s, l, l, s, l, s, l, s], gregorian(2011, 11, 26)).unwrap(), + PackedHijriYearData::try_new(1434, [s, l, s, l, s, l, l, s, l, l, s, s], gregorian(2012, 11, 15)).unwrap(), + PackedHijriYearData::try_new(1435, [l, s, l, s, l, s, l, s, l, l, s, l], gregorian(2013, 11, 4)).unwrap(), + PackedHijriYearData::try_new(1436, [s, l, s, l, s, l, s, l, s, l, s, l], gregorian(2014, 10, 25)).unwrap(), + PackedHijriYearData::try_new(1437, [l, s, l, l, s, s, l, s, l, s, s, l], gregorian(2015, 10, 14)).unwrap(), + PackedHijriYearData::try_new(1438, [l, s, l, l, l, s, s, l, s, s, l, s], gregorian(2016, 10, 2)).unwrap(), + PackedHijriYearData::try_new(1439, [l, s, l, l, l, s, l, s, l, s, s, l], gregorian(2017, 9, 21)).unwrap(), + PackedHijriYearData::try_new(1440, [s, l, s, l, l, l, s, l, s, l, s, s], gregorian(2018, 9, 11)).unwrap(), + PackedHijriYearData::try_new(1441, [l, s, l, s, l, l, s, l, l, s, l, s], gregorian(2019, 8, 31)).unwrap(), + PackedHijriYearData::try_new(1442, [s, l, s, l, s, l, s, l, l, s, l, s], gregorian(2020, 8, 20)).unwrap(), + PackedHijriYearData::try_new(1443, [l, s, l, s, l, s, l, s, l, s, l, l], gregorian(2021, 8, 9)).unwrap(), + PackedHijriYearData::try_new(1444, [s, l, s, l, l, s, s, l, s, l, s, l], gregorian(2022, 7, 30)).unwrap(), + PackedHijriYearData::try_new(1445, [s, l, l, l, s, l, s, s, l, s, s, l], gregorian(2023, 7, 19)).unwrap(), + PackedHijriYearData::try_new(1446, [s, l, l, l, s, l, l, s, s, l, s, s], gregorian(2024, 7, 7)).unwrap(), + PackedHijriYearData::try_new(1447, [l, s, l, l, l, s, l, s, l, s, l, s], gregorian(2025, 6, 26)).unwrap(), + PackedHijriYearData::try_new(1448, [s, l, s, l, l, s, l, l, s, l, s, l], gregorian(2026, 6, 16)).unwrap(), + PackedHijriYearData::try_new(1449, [s, s, l, s, l, s, l, l, s, l, l, s], gregorian(2027, 6, 6)).unwrap(), + PackedHijriYearData::try_new(1450, [l, s, l, s, s, l, s, l, s, l, l, s], gregorian(2028, 5, 25)).unwrap(), + PackedHijriYearData::try_new(1451, [l, l, l, s, s, l, s, s, l, l, s, l], gregorian(2029, 5, 14)).unwrap(), + PackedHijriYearData::try_new(1452, [l, s, l, l, s, s, l, s, s, l, s, l], gregorian(2030, 5, 4)).unwrap(), + PackedHijriYearData::try_new(1453, [l, s, l, l, s, l, s, l, s, s, l, s], gregorian(2031, 4, 23)).unwrap(), + PackedHijriYearData::try_new(1454, [l, s, l, l, s, l, l, s, l, s, l, s], gregorian(2032, 4, 11)).unwrap(), + PackedHijriYearData::try_new(1455, [s, l, s, l, l, s, l, s, l, l, s, l], gregorian(2033, 4, 1)).unwrap(), + PackedHijriYearData::try_new(1456, [s, s, l, s, l, s, l, s, l, l, l, s], gregorian(2034, 3, 22)).unwrap(), + PackedHijriYearData::try_new(1457, [l, s, s, l, s, s, l, s, l, l, l, l], gregorian(2035, 3, 11)).unwrap(), + PackedHijriYearData::try_new(1458, [s, l, s, s, l, s, s, l, s, l, l, l], gregorian(2036, 2, 29)).unwrap(), + PackedHijriYearData::try_new(1459, [s, l, l, s, s, l, s, s, l, s, l, l], gregorian(2037, 2, 17)).unwrap(), + PackedHijriYearData::try_new(1460, [s, l, l, s, l, s, l, s, s, l, s, l], gregorian(2038, 2, 6)).unwrap(), + PackedHijriYearData::try_new(1461, [s, l, l, s, l, s, l, s, l, l, s, s], gregorian(2039, 1, 26)).unwrap(), + PackedHijriYearData::try_new(1462, [l, s, l, s, l, l, s, l, s, l, l, s], gregorian(2040, 1, 15)).unwrap(), + PackedHijriYearData::try_new(1463, [s, l, s, l, s, l, s, l, l, l, s, l], gregorian(2041, 1, 4)).unwrap(), + PackedHijriYearData::try_new(1464, [s, l, s, s, l, s, s, l, l, l, s, l], gregorian(2041, 12, 25)).unwrap(), + PackedHijriYearData::try_new(1465, [l, s, l, s, s, l, s, s, l, l, s, l], gregorian(2042, 12, 14)).unwrap(), + PackedHijriYearData::try_new(1466, [l, l, s, l, s, s, s, l, s, l, l, s], gregorian(2043, 12, 3)).unwrap(), + PackedHijriYearData::try_new(1467, [l, l, s, l, l, s, s, l, s, l, s, l], gregorian(2044, 11, 21)).unwrap(), + PackedHijriYearData::try_new(1468, [s, l, s, l, l, s, l, s, l, s, l, s], gregorian(2045, 11, 11)).unwrap(), + PackedHijriYearData::try_new(1469, [s, l, s, l, l, s, l, l, s, l, s, l], gregorian(2046, 10, 31)).unwrap(), + PackedHijriYearData::try_new(1470, [s, s, l, s, l, l, s, l, l, s, l, s], gregorian(2047, 10, 21)).unwrap(), + PackedHijriYearData::try_new(1471, [l, s, s, l, s, l, s, l, l, s, l, l], gregorian(2048, 10, 9)).unwrap(), + PackedHijriYearData::try_new(1472, [s, l, s, s, l, s, l, s, l, l, s, l], gregorian(2049, 9, 29)).unwrap(), + PackedHijriYearData::try_new(1473, [s, l, s, l, l, s, s, l, s, l, s, l], gregorian(2050, 9, 18)).unwrap(), + PackedHijriYearData::try_new(1474, [s, l, l, s, l, l, s, s, l, s, l, s], gregorian(2051, 9, 7)).unwrap(), + PackedHijriYearData::try_new(1475, [s, l, l, s, l, l, l, s, s, l, s, s], gregorian(2052, 8, 26)).unwrap(), + PackedHijriYearData::try_new(1476, [l, s, l, s, l, l, l, s, l, s, l, s], gregorian(2053, 8, 15)).unwrap(), + PackedHijriYearData::try_new(1477, [s, l, s, s, l, l, l, l, s, l, s, l], gregorian(2054, 8, 5)).unwrap(), + PackedHijriYearData::try_new(1478, [s, s, l, s, l, s, l, l, s, l, l, s], gregorian(2055, 7, 26)).unwrap(), + PackedHijriYearData::try_new(1479, [l, s, s, l, s, l, s, l, s, l, l, s], gregorian(2056, 7, 14)).unwrap(), + PackedHijriYearData::try_new(1480, [l, s, l, s, l, s, l, s, l, s, l, s], gregorian(2057, 7, 3)).unwrap(), + PackedHijriYearData::try_new(1481, [l, s, l, l, s, l, s, l, s, l, s, s], gregorian(2058, 6, 22)).unwrap(), + PackedHijriYearData::try_new(1482, [l, s, l, l, l, l, s, l, s, s, l, s], gregorian(2059, 6, 11)).unwrap(), + PackedHijriYearData::try_new(1483, [s, l, s, l, l, l, s, l, l, s, s, l], gregorian(2060, 5, 31)).unwrap(), + PackedHijriYearData::try_new(1484, [s, s, l, s, l, l, l, s, l, s, l, s], gregorian(2061, 5, 21)).unwrap(), + PackedHijriYearData::try_new(1485, [l, s, s, l, s, l, l, s, l, l, s, l], gregorian(2062, 5, 10)).unwrap(), + PackedHijriYearData::try_new(1486, [s, l, s, s, l, s, l, s, l, l, s, l], gregorian(2063, 4, 30)).unwrap(), + PackedHijriYearData::try_new(1487, [l, s, l, s, l, s, s, l, s, l, s, l], gregorian(2064, 4, 18)).unwrap(), + PackedHijriYearData::try_new(1488, [l, s, l, l, s, l, s, s, l, s, l, s], gregorian(2065, 4, 7)).unwrap(), + PackedHijriYearData::try_new(1489, [l, s, l, l, l, s, l, s, s, l, s, l], gregorian(2066, 3, 27)).unwrap(), + PackedHijriYearData::try_new(1490, [s, l, s, l, l, s, l, l, s, s, l, s], gregorian(2067, 3, 17)).unwrap(), + PackedHijriYearData::try_new(1491, [l, s, s, l, l, s, l, l, s, l, s, l], gregorian(2068, 3, 5)).unwrap(), + PackedHijriYearData::try_new(1492, [s, l, s, s, l, l, s, l, s, l, l, s], gregorian(2069, 2, 23)).unwrap(), + PackedHijriYearData::try_new(1493, [l, s, l, s, l, s, s, l, s, l, l, l], gregorian(2070, 2, 12)).unwrap(), + PackedHijriYearData::try_new(1494, [s, l, s, l, s, l, s, s, s, l, l, l], gregorian(2071, 2, 2)).unwrap(), + PackedHijriYearData::try_new(1495, [s, l, l, s, l, s, s, l, s, s, l, l], gregorian(2072, 1, 22)).unwrap(), + PackedHijriYearData::try_new(1496, [s, l, l, l, s, l, s, s, l, s, s, l], gregorian(2073, 1, 10)).unwrap(), + PackedHijriYearData::try_new(1497, [l, s, l, l, s, l, s, l, s, l, s, l], gregorian(2073, 12, 30)).unwrap(), + PackedHijriYearData::try_new(1498, [s, l, s, l, s, l, l, s, l, s, l, s], gregorian(2074, 12, 20)).unwrap(), + PackedHijriYearData::try_new(1499, [l, s, l, s, s, l, l, s, l, s, l, l], gregorian(2075, 12, 9)).unwrap(), + PackedHijriYearData::try_new(1500, [s, l, s, l, s, s, l, s, l, s, l, l], gregorian(2076, 11, 28)).unwrap(), + PackedHijriYearData::try_new(1501, [l, s, l, s, l, s, s, s, l, s, l, l], gregorian(2077, 11, 17)).unwrap(), + PackedHijriYearData::try_new(1502, [l, l, s, l, s, l, s, s, s, l, l, s], gregorian(2078, 11, 6)).unwrap(), + PackedHijriYearData::try_new(1503, [l, l, s, l, l, s, l, s, s, s, l, l], gregorian(2079, 10, 26)).unwrap(), + PackedHijriYearData::try_new(1504, [s, l, s, l, l, l, s, s, l, s, l, s], gregorian(2080, 10, 15)).unwrap(), + PackedHijriYearData::try_new(1505, [l, s, l, s, l, l, s, l, s, l, l, s], gregorian(2081, 10, 4)).unwrap(), + PackedHijriYearData::try_new(1506, [s, l, s, s, l, l, s, l, l, s, l, l], gregorian(2082, 9, 24)).unwrap(), + PackedHijriYearData::try_new(1507, [s, s, l, s, s, l, l, s, l, s, l, l], gregorian(2083, 9, 14)).unwrap(), + PackedHijriYearData::try_new(1508, [l, s, s, l, s, l, s, s, l, s, l, l], gregorian(2084, 9, 2)).unwrap(), + PackedHijriYearData::try_new(1509, [l, s, l, s, l, s, l, s, s, l, s, l], gregorian(2085, 8, 22)).unwrap(), + PackedHijriYearData::try_new(1510, [l, s, l, l, s, l, s, l, s, s, l, s], gregorian(2086, 8, 11)).unwrap(), + PackedHijriYearData::try_new(1511, [l, s, l, l, s, l, l, s, l, s, s, l], gregorian(2087, 7, 31)).unwrap(), + PackedHijriYearData::try_new(1512, [s, l, s, l, s, l, l, l, s, l, s, l], gregorian(2088, 7, 20)).unwrap(), + PackedHijriYearData::try_new(1513, [s, s, s, l, s, l, l, l, s, l, l, s], gregorian(2089, 7, 10)).unwrap(), + PackedHijriYearData::try_new(1514, [l, s, s, s, l, s, l, l, s, l, l, l], gregorian(2090, 6, 29)).unwrap(), + PackedHijriYearData::try_new(1515, [s, s, l, s, s, l, s, l, l, s, l, l], gregorian(2091, 6, 19)).unwrap(), + PackedHijriYearData::try_new(1516, [s, l, s, l, s, s, l, s, l, s, l, l], gregorian(2092, 6, 7)).unwrap(), + PackedHijriYearData::try_new(1517, [s, l, s, l, s, l, l, s, s, l, s, l], gregorian(2093, 5, 27)).unwrap(), + PackedHijriYearData::try_new(1518, [s, l, s, l, l, s, l, l, s, l, s, s], gregorian(2094, 5, 16)).unwrap(), + PackedHijriYearData::try_new(1519, [l, s, s, l, l, l, s, l, l, s, l, s], gregorian(2095, 5, 5)).unwrap(), + PackedHijriYearData::try_new(1520, [s, l, s, s, l, l, l, s, l, l, s, l], gregorian(2096, 4, 24)).unwrap(), + PackedHijriYearData::try_new(1521, [s, s, s, l, s, l, l, s, l, l, s, l], gregorian(2097, 4, 14)).unwrap(), + PackedHijriYearData::try_new(1522, [l, s, s, s, l, s, l, l, s, l, l, s], gregorian(2098, 4, 3)).unwrap(), + PackedHijriYearData::try_new(1523, [l, s, l, s, l, s, l, s, s, l, l, s], gregorian(2099, 3, 23)).unwrap(), + PackedHijriYearData::try_new(1524, [l, l, s, l, s, l, s, l, s, s, l, s], gregorian(2100, 3, 12)).unwrap(), + PackedHijriYearData::try_new(1525, [l, l, s, l, l, s, l, s, l, s, s, l], gregorian(2101, 3, 1)).unwrap(), + PackedHijriYearData::try_new(1526, [s, l, s, l, l, l, s, l, s, l, s, s], gregorian(2102, 2, 19)).unwrap(), + PackedHijriYearData::try_new(1527, [l, s, l, s, l, l, s, l, l, s, l, s], gregorian(2103, 2, 8)).unwrap(), + PackedHijriYearData::try_new(1528, [l, s, s, l, s, l, s, l, l, s, l, l], gregorian(2104, 1, 29)).unwrap(), + PackedHijriYearData::try_new(1529, [s, l, s, s, l, s, l, s, l, s, l, l], gregorian(2105, 1, 18)).unwrap(), + PackedHijriYearData::try_new(1530, [s, l, l, s, s, l, s, l, s, s, l, l], gregorian(2106, 1, 7)).unwrap(), + PackedHijriYearData::try_new(1531, [s, l, l, l, s, s, l, s, l, s, s, l], gregorian(2106, 12, 27)).unwrap(), + PackedHijriYearData::try_new(1532, [s, l, l, l, s, l, l, s, s, s, l, s], gregorian(2107, 12, 16)).unwrap(), + PackedHijriYearData::try_new(1533, [l, s, l, l, l, s, l, s, l, s, s, l], gregorian(2108, 12, 4)).unwrap(), + PackedHijriYearData::try_new(1534, [s, l, s, l, l, s, l, l, s, s, l, s], gregorian(2109, 11, 24)).unwrap(), + PackedHijriYearData::try_new(1535, [l, s, l, s, l, s, l, l, s, l, s, l], gregorian(2110, 11, 13)).unwrap(), + PackedHijriYearData::try_new(1536, [s, l, s, l, s, l, s, l, s, l, s, l], gregorian(2111, 11, 3)).unwrap(), + PackedHijriYearData::try_new(1537, [l, s, l, l, s, s, l, s, s, l, s, l], gregorian(2112, 10, 22)).unwrap(), + PackedHijriYearData::try_new(1538, [l, l, s, l, l, s, s, l, s, s, l, s], gregorian(2113, 10, 11)).unwrap(), + PackedHijriYearData::try_new(1539, [l, l, l, s, l, l, s, s, l, s, s, l], gregorian(2114, 9, 30)).unwrap(), + PackedHijriYearData::try_new(1540, [s, l, l, s, l, l, s, l, s, s, l, s], gregorian(2115, 9, 20)).unwrap(), + PackedHijriYearData::try_new(1541, [l, s, l, s, l, l, l, s, l, s, s, l], gregorian(2116, 9, 8)).unwrap(), + PackedHijriYearData::try_new(1542, [s, l, s, l, s, l, l, s, l, s, l, l], gregorian(2117, 8, 29)).unwrap(), + PackedHijriYearData::try_new(1543, [s, l, s, s, l, s, l, s, l, s, l, l], gregorian(2118, 8, 19)).unwrap(), + PackedHijriYearData::try_new(1544, [l, s, l, s, s, l, s, l, s, l, s, l], gregorian(2119, 8, 8)).unwrap(), + PackedHijriYearData::try_new(1545, [l, l, s, l, s, s, l, s, l, s, s, l], gregorian(2120, 7, 27)).unwrap(), + PackedHijriYearData::try_new(1546, [l, l, s, l, s, l, s, l, s, l, s, s], gregorian(2121, 7, 16)).unwrap(), + PackedHijriYearData::try_new(1547, [l, l, s, l, l, s, l, s, l, s, l, s], gregorian(2122, 7, 5)).unwrap(), + PackedHijriYearData::try_new(1548, [l, s, s, l, l, s, l, l, s, l, s, l], gregorian(2123, 6, 25)).unwrap(), + PackedHijriYearData::try_new(1549, [s, l, s, s, l, s, l, l, l, s, l, s], gregorian(2124, 6, 14)).unwrap(), + PackedHijriYearData::try_new(1550, [l, s, l, s, s, s, l, l, l, s, l, l], gregorian(2125, 6, 3)).unwrap(), + PackedHijriYearData::try_new(1551, [s, l, s, s, l, s, s, l, l, s, l, l], gregorian(2126, 5, 24)).unwrap(), + PackedHijriYearData::try_new(1552, [l, s, l, s, s, l, s, s, l, l, s, l], gregorian(2127, 5, 13)).unwrap(), + PackedHijriYearData::try_new(1553, [l, s, l, s, l, s, l, s, l, s, l, s], gregorian(2128, 5, 1)).unwrap(), + PackedHijriYearData::try_new(1554, [l, s, l, s, l, l, s, l, s, l, s, l], gregorian(2129, 4, 20)).unwrap(), + PackedHijriYearData::try_new(1555, [s, s, l, s, l, l, s, l, l, s, l, s], gregorian(2130, 4, 10)).unwrap(), + PackedHijriYearData::try_new(1556, [l, s, s, l, s, l, s, l, l, l, s, l], gregorian(2131, 3, 30)).unwrap(), + PackedHijriYearData::try_new(1557, [s, l, s, s, s, l, s, l, l, l, l, s], gregorian(2132, 3, 19)).unwrap(), + PackedHijriYearData::try_new(1558, [l, s, l, s, s, s, l, s, l, l, l, s], gregorian(2133, 3, 8)).unwrap(), + PackedHijriYearData::try_new(1559, [l, l, s, s, l, s, s, l, l, s, l, s], gregorian(2134, 2, 25)).unwrap(), + PackedHijriYearData::try_new(1560, [l, l, s, l, s, l, s, l, s, l, s, l], gregorian(2135, 2, 14)).unwrap(), + PackedHijriYearData::try_new(1561, [s, l, l, s, l, s, l, l, s, s, l, s], gregorian(2136, 2, 4)).unwrap(), + PackedHijriYearData::try_new(1562, [s, l, l, s, l, s, l, l, l, s, s, l], gregorian(2137, 1, 23)).unwrap(), + PackedHijriYearData::try_new(1563, [s, l, s, s, l, s, l, l, l, s, l, s], gregorian(2138, 1, 13)).unwrap(), + PackedHijriYearData::try_new(1564, [l, s, l, s, s, l, s, l, l, l, s, l], gregorian(2139, 1, 2)).unwrap(), + PackedHijriYearData::try_new(1565, [s, l, s, l, s, s, l, s, l, l, s, l], gregorian(2139, 12, 23)).unwrap(), + PackedHijriYearData::try_new(1566, [l, s, l, s, l, s, s, l, s, l, s, l], gregorian(2140, 12, 11)).unwrap(), + PackedHijriYearData::try_new(1567, [l, s, l, l, s, l, s, l, s, s, l, s], gregorian(2141, 11, 30)).unwrap(), + PackedHijriYearData::try_new(1568, [l, s, l, l, l, s, l, s, l, s, s, s], gregorian(2142, 11, 19)).unwrap(), + PackedHijriYearData::try_new(1569, [l, s, l, l, l, s, l, l, s, l, s, s], gregorian(2143, 11, 8)).unwrap(), + PackedHijriYearData::try_new(1570, [s, l, s, l, l, s, l, l, l, s, s, l], gregorian(2144, 10, 28)).unwrap(), + PackedHijriYearData::try_new(1571, [s, s, l, s, l, l, s, l, l, s, l, s], gregorian(2145, 10, 18)).unwrap(), + PackedHijriYearData::try_new(1572, [l, s, s, l, s, l, s, l, l, s, l, s], gregorian(2146, 10, 7)).unwrap(), + PackedHijriYearData::try_new(1573, [l, s, l, l, s, l, s, s, l, s, l, s], gregorian(2147, 9, 26)).unwrap(), + PackedHijriYearData::try_new(1574, [l, l, s, l, l, s, l, s, s, l, s, s], gregorian(2148, 9, 14)).unwrap(), + PackedHijriYearData::try_new(1575, [l, l, l, s, l, l, s, l, s, s, s, l], gregorian(2149, 9, 3)).unwrap(), + PackedHijriYearData::try_new(1576, [s, l, l, s, l, l, l, s, l, s, s, s], gregorian(2150, 8, 24)).unwrap(), + PackedHijriYearData::try_new(1577, [l, s, l, l, s, l, l, s, l, s, l, s], gregorian(2151, 8, 13)).unwrap(), + PackedHijriYearData::try_new(1578, [s, l, s, l, s, l, l, s, l, l, s, l], gregorian(2152, 8, 2)).unwrap(), + PackedHijriYearData::try_new(1579, [s, l, s, l, s, s, l, l, s, l, s, l], gregorian(2153, 7, 23)).unwrap(), + PackedHijriYearData::try_new(1580, [s, l, l, s, l, s, s, l, s, l, s, l], gregorian(2154, 7, 12)).unwrap(), + PackedHijriYearData::try_new(1581, [l, l, s, l, s, l, s, s, l, s, l, s], gregorian(2155, 7, 1)).unwrap(), + PackedHijriYearData::try_new(1582, [l, l, s, l, l, s, l, s, l, s, s, s], gregorian(2156, 6, 19)).unwrap(), + PackedHijriYearData::try_new(1583, [l, l, s, l, l, l, s, l, s, l, s, s], gregorian(2157, 6, 8)).unwrap(), + PackedHijriYearData::try_new(1584, [s, l, l, s, l, l, s, l, l, s, l, s], gregorian(2158, 5, 29)).unwrap(), + PackedHijriYearData::try_new(1585, [s, l, s, l, s, l, s, l, l, s, l, l], gregorian(2159, 5, 19)).unwrap(), + PackedHijriYearData::try_new(1586, [s, s, l, s, l, s, s, l, l, l, s, l], gregorian(2160, 5, 8)).unwrap(), + PackedHijriYearData::try_new(1587, [s, l, l, s, s, s, l, s, l, s, l, l], gregorian(2161, 4, 27)).unwrap(), + PackedHijriYearData::try_new(1588, [l, s, l, l, s, s, s, l, s, l, s, l], gregorian(2162, 4, 16)).unwrap(), + PackedHijriYearData::try_new(1589, [l, s, l, l, s, l, s, s, l, s, l, s], gregorian(2163, 4, 5)).unwrap(), + PackedHijriYearData::try_new(1590, [l, s, l, l, l, s, s, l, s, l, s, l], gregorian(2164, 3, 24)).unwrap(), + PackedHijriYearData::try_new(1591, [s, l, s, l, l, s, l, s, l, s, l, s], gregorian(2165, 3, 14)).unwrap(), + PackedHijriYearData::try_new(1592, [l, s, l, s, l, s, l, s, l, l, l, s], gregorian(2166, 3, 3)).unwrap(), + PackedHijriYearData::try_new(1593, [l, s, s, l, s, s, l, s, l, l, l, s], gregorian(2167, 2, 21)).unwrap(), + PackedHijriYearData::try_new(1594, [l, l, s, s, l, s, s, s, l, l, l, l], gregorian(2168, 2, 10)).unwrap(), + PackedHijriYearData::try_new(1595, [s, l, s, l, s, s, l, s, s, l, l, l], gregorian(2169, 1, 30)).unwrap(), + PackedHijriYearData::try_new(1596, [s, l, l, s, l, s, s, l, s, l, s, l], gregorian(2170, 1, 19)).unwrap(), + PackedHijriYearData::try_new(1597, [s, l, l, s, l, s, l, s, l, s, l, s], gregorian(2171, 1, 8)).unwrap(), + PackedHijriYearData::try_new(1598, [l, s, l, s, l, l, s, l, s, l, l, s], gregorian(2171, 12, 28)).unwrap(), + PackedHijriYearData::try_new(1599, [s, l, s, l, s, l, s, l, l, l, s, l], gregorian(2172, 12, 17)).unwrap(), + PackedHijriYearData::try_new(1600, [s, s, l, s, l, s, s, l, l, l, s, l], gregorian(2173, 12, 7)).unwrap(), ] }; + +#[test] +fn test_icu4c_agreement() { + use calendrical_calculations::islamic::ISLAMIC_EPOCH_FRIDAY; + + // 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; + ( + 1300 + years_since_1300 as i32, + PackedHijriYearData::try_new( + 1300 + years_since_1300 as i32, + month_lengths, + ISLAMIC_EPOCH_FRIDAY + year_start, + ) + .unwrap(), + ) + }, + ) + .collect::>(); + + let icu4x = (1300..=1600).zip(DATA.iter().copied()).collect::>(); + + assert_eq!(icu4x, icu4c); +} diff --git a/deps/crates/vendor/icu_calendar/src/cal/indian.rs b/deps/crates/vendor/icu_calendar/src/cal/indian.rs index 608e85e2ead8c2..0b021d41970d93 100644 --- a/deps/crates/vendor/icu_calendar/src/cal/indian.rs +++ b/deps/crates/vendor/icu_calendar/src/cal/indian.rs @@ -2,40 +2,46 @@ // 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 crate::calendar_arithmetic::ArithmeticDate; +use crate::calendar_arithmetic::DateFieldsResolver; +use crate::error::{DateError, DateFromFieldsError, EcmaReferenceYearError, UnknownEraError}; +use crate::options::DateFromFieldsOptions; +use crate::options::{DateAddOptions, DateDifferenceOptions}; +use crate::types::DateFields; +use crate::{types, Calendar, Date, 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. +/// The Indian National calendar is a solar calendar created by the Indian government. /// -/// This type can be used with [`Date`] to represent dates in this calendar. +/// This implementation extends proleptically for dates before the calendar's creation +/// in 1879 Śaka (1957 CE). +/// +/// This corresponds to the `"indian"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). /// /// # 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 +/// # Months and days +/// +/// The 12 months are called Chaitra (`M01`, 30 days), Vaisakha (`M02`, 31 days), +/// Jyaishtha (`M03`, 31 days), Ashadha (`M04`, 31 days), Sravana (`M05`, 31 days), +/// Bhadra (`M06`, 31 days), Asvina (`M07`, 30 days), Kartika (`M08`, 30 days), +/// Agrahayana or Margasirsha (`M09`, 30 days), Pausha (`M10`, 30 days), Magha (`M11`, 30 days), +/// Phalguna (`M12`, 30 days). +/// +/// In leap years (years where the concurrent [`Gregorian`](crate::cal::Gregorian) year (`year + 78`) is leap), +/// Chaitra gains a 31st day. +/// +/// Standard years thus have 365 days, and leap years 366. /// -/// This calendar supports 12 solar month codes (`"M01" - "M12"`) +/// # Calendar drift +/// +/// The Indian calendar has the same year lengths and leap year rules as the Gregorian calendar, +/// so it experiences the same drift of 1 day in ~7700 years with respect to the seasons. #[derive(Copy, Clone, Debug, Hash, Default, Eq, PartialEq, PartialOrd, Ord)] #[allow(clippy::exhaustive_structs)] // this type is stable pub struct Indian; @@ -44,16 +50,18 @@ pub struct Indian; #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] pub struct IndianDateInner(ArithmeticDate); -impl CalendarArithmetic for Indian { +/// 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 DateFieldsResolver 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 - } + 30 + calendrical_calculations::gregorian::is_leap_year(year + YEAR_OFFSET) as u8 } else if (2..=6).contains(&month) { 31 } else if (7..=12).contains(&month) { @@ -67,33 +75,49 @@ impl CalendarArithmetic for Indian { 12 } - fn provided_year_is_leap(year: i32) -> bool { - Iso::provided_year_is_leap(year + 78) + #[inline] + fn year_info_from_era( + &self, + era: &[u8], + era_year: i32, + ) -> Result { + match era { + b"shaka" => Ok(era_year), + _ => Err(UnknownEraError), + } } - fn last_month_day_in_provided_year(_year: i32) -> (u8, u8) { - (12, 30) + #[inline] + fn year_info_from_extended(&self, extended_year: i32) -> Self::YearInfo { + extended_year } - fn days_in_provided_year(year: i32) -> u16 { - if Self::provided_year_is_leap(year) { - 366 + #[inline] + fn reference_year_from_month_day( + &self, + month_code: types::ValidMonthCode, + day: u8, + ) -> Result { + let (ordinal_month, false) = month_code.to_tuple() else { + return Err(EcmaReferenceYearError::MonthCodeNotInCalendar); + }; + // December 31, 1972 occurs on 10th month, 10th day, 1894 Shaka + // Note: 1894 Shaka is also a leap year + let shaka_year = if ordinal_month < 10 || (ordinal_month == 10 && day <= 10) { + 1894 } else { - 365 - } + 1893 + }; + Ok(shaka_year) } } -/// 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; + type DifferenceError = core::convert::Infallible; + fn from_codes( &self, era: Option<&str>, @@ -101,115 +125,147 @@ impl Calendar for Indian { 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) + ArithmeticDate::from_codes(era, year, month_code, day, self).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)) + #[cfg(feature = "unstable")] + fn from_fields( + &self, + fields: DateFields, + options: DateFromFieldsOptions, + ) -> Result { + ArithmeticDate::from_fields(fields, options, self).map(IndianDateInner) } // Algorithms directly implemented in icu_calendar since they're not from the book - fn from_iso(&self, iso: IsoDateInner) -> IndianDateInner { + fn from_rata_die(&self, rd: RataDie) -> Self::DateInner { + let iso_year = calendrical_calculations::gregorian::year_from_fixed(rd) + .unwrap_or_else(|e| e.saturate()); // Get day number in year (1 indexed) - let day_of_year_iso = Iso::day_of_year(iso); + let day_of_year_iso = + (rd - calendrical_calculations::gregorian::day_before_year(iso_year)) as u16; // Convert to Śaka year - let mut year = iso.0.year - YEAR_OFFSET; + let mut year = iso_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); + let n_days = if calendrical_calculations::gregorian::is_leap_year(year + YEAR_OFFSET) { + 366 + } else { + 365 + }; // 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, - )) + let mut month = 1; + let mut day = day_of_year_indian as i32; + while month <= 12 { + let month_days = Self::days_in_provided_month(year, month) as i32; + if day <= month_days { + break; + } else { + day -= month_days; + month += 1; + } + } + + debug_assert!(day <= Self::days_in_provided_month(year, month) as i32); + let day = day.try_into().unwrap_or(1); + + IndianDateInner(ArithmeticDate::new_unchecked(year, month, day)) } // 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(); + fn to_rata_die(&self, date: &Self::DateInner) -> RataDie { + let day_of_year_indian = self.day_of_year(date).0; // 1-indexed + let days_in_year = self.days_in_year(date); - let mut year = date.0.year + YEAR_OFFSET; + let mut year_iso = 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; + year_iso += 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) + + calendrical_calculations::gregorian::day_before_year(year_iso) + day_of_year_iso as i64 + } + + fn has_cheap_iso_conversion(&self) -> bool { + false } fn months_in_year(&self, date: &Self::DateInner) -> u8 { - date.0.months_in_year() + Self::months_in_provided_year(date.0.year) } fn days_in_year(&self, date: &Self::DateInner) -> u16 { - date.0.days_in_year() + if self.is_in_leap_year(date) { + 366 + } else { + 365 + } } fn days_in_month(&self, date: &Self::DateInner) -> u8 { - date.0.days_in_month() + Self::days_in_provided_month(date.0.year, date.0.month) } - fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { - date.0.offset_date(offset, &()); + #[cfg(feature = "unstable")] + fn add( + &self, + date: &Self::DateInner, + duration: types::DateDuration, + options: DateAddOptions, + ) -> Result { + date.0.added(duration, self, options).map(IndianDateInner) } - #[allow(clippy::field_reassign_with_default)] + #[cfg(feature = "unstable")] 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) + options: DateDifferenceOptions, + ) -> Result { + Ok(date1.0.until(&date2.0, self, options)) } fn year_info(&self, date: &Self::DateInner) -> Self::Year { + let extended_year = date.0.year; types::EraYear { era_index: Some(0), era: tinystr!(16, "shaka"), - year: self.extended_year(date), + year: extended_year, + extended_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) + calendrical_calculations::gregorian::is_leap_year(date.0.year + YEAR_OFFSET) } fn month(&self, date: &Self::DateInner) -> types::MonthInfo { - date.0.month() + types::MonthInfo::non_lunisolar(date.0.month) } fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { - date.0.day_of_month() + types::DayOfMonth(date.0.day) } fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { - date.0.day_of_year() + types::DayOfYear( + (1..date.0.month) + .map(|m| Self::days_in_provided_month(date.0.year, m) as u16) + .sum::() + + date.0.day as u16, + ) } fn debug_name(&self) -> &'static str { @@ -242,7 +298,7 @@ impl Date { /// 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) + ArithmeticDate::try_from_ymd(year, month, day) .map(IndianDateInner) .map(|inner| Date::from_raw(inner, Indian)) } @@ -450,10 +506,7 @@ mod tests { 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(); + let result = Date::from_rata_die(initial, Indian).to_rata_die(); assert_eq!( initial, result, "Roundtrip failed for initial: {initial:?}, result: {result:?}" @@ -466,10 +519,7 @@ mod tests { // 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(); + let result = Date::from_rata_die(initial, Indian).to_rata_die(); assert_eq!( initial, result, "Roundtrip failed for initial: {initial:?}, result: {result:?}" diff --git a/deps/crates/vendor/icu_calendar/src/cal/iso.rs b/deps/crates/vendor/icu_calendar/src/cal/iso.rs index 989485dc7a1733..ebb361817d70a6 100644 --- a/deps/crates/vendor/icu_calendar/src/cal/iso.rs +++ b/deps/crates/vendor/icu_calendar/src/cal/iso.rs @@ -2,186 +2,56 @@ // 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 crate::cal::abstract_gregorian::{impl_with_abstract_gregorian, GregorianYears}; +use crate::calendar_arithmetic::ArithmeticDate; +use crate::error::UnknownEraError; +use crate::{types, Date, DateError, RangeError}; 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 calendar is identical to the [`Gregorian`](super::Gregorian) calendar, +/// except that it uses a single `default` era instead of `bce` and `ce`. /// -/// This type can be used with [`Date`] to represent dates in this calendar. +/// This corresponds to the `"iso8601"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). /// /// # 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 - } +impl_with_abstract_gregorian!(crate::cal::Iso, IsoDateInner, IsoEra, _x, IsoEra); - 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 - } - } -} +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) struct IsoEra; -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( +impl GregorianYears for IsoEra { + fn extended_from_era_year( &self, - era: Option<&str>, + era: Option<&[u8]>, 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) + ) -> Result { + match era { + Some(b"default") | None => Ok(year), + Some(_) => Err(UnknownEraError), + } } - fn year_info(&self, date: &Self::DateInner) -> Self::Year { + fn era_year_from_extended(&self, extended_year: i32, _month: u8, _day: u8) -> types::EraYear { types::EraYear { era_index: Some(0), era: tinystr!(16, "default"), - year: self.extended_year(date), + year: extended_year, + extended_year, 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 { @@ -198,9 +68,9 @@ impl Date { /// 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) + ArithmeticDate::new_gregorian::(year, month, day) .map(IsoDateInner) - .map(|inner| Date::from_raw(inner, Iso)) + .map(|i| Date::from_raw(i, Iso)) } } @@ -209,46 +79,13 @@ impl Iso { 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; + use crate::types::{DateDuration, RataDie, Weekday}; + use crate::Calendar; #[test] fn iso_overflow() { @@ -435,31 +272,20 @@ mod test { 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)); + let offset = today + .try_added_with_options(DateDuration::for_days(5000), Default::default()) + .unwrap(); 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)); + let offset = today + .try_added_with_options(DateDuration::for_days(-5000), Default::default()) + .unwrap(); assert_eq!(offset, today_minus_5000); } @@ -467,32 +293,44 @@ mod 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)); + let offset = today + .try_added_with_options(DateDuration::for_days(2), Default::default()) + .unwrap(); 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)); + let offset = today + .try_added_with_options(DateDuration::for_days(3), Default::default()) + .unwrap(); 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)); + let offset = today + .try_added_with_options(DateDuration::for_days(1), Default::default()) + .unwrap(); 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)); + let offset = today + .try_added_with_options(DateDuration::for_days(2), Default::default()) + .unwrap(); 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)); + let offset = today + .try_added_with_options(DateDuration::for_days(1), Default::default()) + .unwrap(); 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)); + let offset = today + .try_added_with_options(DateDuration::for_days(-1), Default::default()) + .unwrap(); assert_eq!(offset, today_minus_1); } @@ -500,37 +338,57 @@ mod 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)); + let offset = today + .try_added_with_options(DateDuration::for_months(-2), Default::default()) + .unwrap(); 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)); + let offset = today + .try_added_with_options(DateDuration::for_months(-4), Default::default()) + .unwrap(); 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)); + let offset = today + .try_added_with_options(DateDuration::for_months(-24), Default::default()) + .unwrap(); 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)); + let offset = today + .try_added_with_options(DateDuration::for_months(-27), Default::default()) + .unwrap(); 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)); + // since 2021/02/31 isn't a valid date, `offset_date` auto-adjusts by constraining to the last day in February + let today_plus_1_month = Date::try_new_iso(2021, 2, 28).unwrap(); + let offset = today + .try_added_with_options(DateDuration::for_months(1), Default::default()) + .unwrap(); 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)); + // since 2021/02/31 isn't a valid date, `offset_date` auto-adjusts by constraining to the last day in February + // and then adding the days + let today_plus_1_month_1_day = Date::try_new_iso(2021, 3, 1).unwrap(); + let offset = today + .try_added_with_options( + DateDuration { + months: 1, + days: 1, + ..Default::default() + }, + Default::default(), + ) + .unwrap(); assert_eq!(offset, today_plus_1_month_1_day); } diff --git a/deps/crates/vendor/icu_calendar/src/cal/japanese.rs b/deps/crates/vendor/icu_calendar/src/cal/japanese.rs index d52874b265413d..37ad427b9dd334 100644 --- a/deps/crates/vendor/icu_calendar/src/cal/japanese.rs +++ b/deps/crates/vendor/icu_calendar/src/cal/japanese.rs @@ -2,59 +2,41 @@ // 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::cal::abstract_gregorian::{impl_with_abstract_gregorian, GregorianYears}; +use crate::cal::gregorian::CeBce; +use crate::calendar_arithmetic::ArithmeticDate; +use crate::error::{DateError, UnknownEraError}; use crate::provider::{CalendarJapaneseExtendedV1, CalendarJapaneseModernV1, EraStartDate}; -use crate::{types, AsCalendar, Calendar, Date, DateDuration, DateDurationUnit, Ref}; -use calendrical_calculations::rata_die::RataDie; +use crate::{types, AsCalendar, Date}; use icu_provider::prelude::*; -use tinystr::{tinystr, TinyStr16}; +use tinystr::tinystr; /// 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. +/// The [Japanese Calendar] is a variant of the [`Gregorian`](crate::cal::Gregorian) calendar +/// created by the Japanese government. It is identical to the Gregorian calendar except that +/// is uses Japanese eras instead of the Common Era. /// -/// This calendar only contains eras after Meiji, for all historical eras, check out [`JapaneseExtended`]. +/// This implementation extends proleptically for dates before the calendar's creation +/// in 6 Meiji (1873 CE). +/// The Meiji era is used proleptically back to and including 1868-10-23, Gregorian eras are used before that. /// -/// This type can be used with [`Date`] to represent dates in this calendar. +/// For a variant that uses approximations of historical Japanese eras proleptically, check out [`JapaneseExtended`]. +/// +/// This corresponds to the `"japanese"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). /// /// [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. +/// This calendar currently supports seven era codes. It supports the five eras since its +/// introduction (`meiji`, `taisho`, `showa`, `heisei`, `reiwa`), as well as the Gregorian +/// `bce` (alias `bc`), and `ce` (alias `ad`) for earlier dates. /// /// 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, @@ -62,40 +44,35 @@ pub struct Japanese { /// 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. +/// The [Japanese Calendar] is a variant of the [`Gregorian`](crate::cal::Gregorian) calendar +/// created by the Japanese government. It is identical to the Gregorian calendar except that +/// is uses Japanese eras instead of the Common Era. +/// +/// This implementation extends proleptically for dates before the calendar's creation +/// in 6 Meiji (1873 CE). +/// This implementation uses approximations of earlier Japanese eras proleptically and uses the Gregorian eras for +/// even earlier dates that don't have an approximate Japanese era. +/// +/// For a variant whose Japanese eras start with Meiji, check out [`Japanese`]. /// -/// This type can be used with [`Date`] to represent dates in this calendar. +/// This corresponds to the `"japanext"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). /// /// [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'ō* +/// This calendar supports a large number of era codes. It supports the five eras since its introduction +/// (`meiji`, `taisho`, `showa`, `heisei`, `reiwa`). Proleptic 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. /// @@ -127,8 +104,6 @@ impl Japanese { eras: provider.load(Default::default())?.payload, }) } - - pub(crate) const DEBUG_NAME: &'static str = "Japanese"; } impl JapaneseExtended { @@ -162,232 +137,165 @@ impl JapaneseExtended { 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; +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, +}; - fn from_codes( +impl GregorianYears for &'_ Japanese { + fn extended_from_era_year( &self, - era: Option<&str>, + era: Option<&[u8]>, year: i32, - month_code: types::MonthCode, - day: u8, - ) -> Result { - let Some((month, false)) = month_code.parsed() else { - return Err(DateError::UnknownMonthCode(month_code)); + ) -> Result { + if let Ok(g) = CeBce.extended_from_era_year(era, year) { + return Ok(g); + } + let Some(era) = era else { + // unreachable, handled by CeBce + return Err(UnknownEraError); }; - if month > 12 { - return Err(DateError::UnknownMonthCode(month_code)); + // Avoid linear search by trying well known eras + if era == b"reiwa" { + return Ok(year - 1 + REIWA_START.year); + } else if era == b"heisei" { + return Ok(year - 1 + HEISEI_START.year); + } else if era == b"showa" { + return Ok(year - 1 + SHOWA_START.year); + } else if era == b"taisho" { + return Ok(year - 1 + TAISHO_START.year); + } else if era == b"meiji" { + return Ok(year - 1 + MEIJI_START.year); } - self.new_japanese_date_inner(era.unwrap_or("ce"), year, month, day) - } + let data = &self.eras.get().dates_to_eras; - 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, + // Try to avoid linear search by binary searching for the year suffix + if let Some(start_year) = era + .split(|x| *x == b'-') + .nth(1) + .and_then(|y| core::str::from_utf8(y).ok()?.parse::().ok()) + { + if let Ok(index) = data.binary_search_by(|(d, _)| d.year.cmp(&start_year)) { + // 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 + #[expect(clippy::unwrap_used)] // binary search + if data.get(index).unwrap().1.as_bytes() == era { + return Ok(start_year + year - 1); + } + } } - } - - 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() - } + // Avoidance didn't work. Let's find the era manually, searching back from the present + let era_start = data + .iter() + .rev() + .find_map(|(s, e)| (e.as_bytes() == era).then_some(s)) + .ok_or(UnknownEraError)?; + Ok(era_start.year + year - 1) + } + + fn era_year_from_extended(&self, year: i32, month: u8, day: u8) -> types::EraYear { + let date: EraStartDate = EraStartDate { year, month, day }; + + let (start, era) = if date >= MEIJI_START + && self + .eras + .get() + .dates_to_eras + .last() + .is_some_and(|(_, e)| e == tinystr!(16, "reiwa")) + { + // 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 >= 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")) + } + } else { + let data = &self.eras.get().dates_to_eras; + #[allow(clippy::unwrap_used)] // binary search + match data.binary_search_by(|(d, _)| d.cmp(&date)) { + Err(0) => { + return types::EraYear { + // TODO: return era indices? + era_index: None, + ..CeBce.era_year_from_extended(year, month, day) + }; + } + Ok(index) => data.get(index).unwrap(), + Err(index) => data.get(index - 1).unwrap(), + } + }; - fn year_info(&self, date: &Self::DateInner) -> Self::Year { types::EraYear { - era: date.era, + era, era_index: None, - year: date.adjusted_year, + year: year - start.year + 1, + extended_year: 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 + if self.eras.get().dates_to_eras.len() > 10 { + "Japanese (historical era data)" + } else { + "Japanese" + } } fn calendar_algorithm(&self) -> Option { - Some(crate::preferences::CalendarAlgorithm::Japanese) + if self.eras.get().dates_to_eras.len() > 10 { + None + } else { + 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) - } +impl_with_abstract_gregorian!(Japanese, JapaneseDateInner, Japanese, this, this); - 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_with_abstract_gregorian!( + JapaneseExtended, + JapaneseExtendedDateInner, + Japanese, + this, + &this.0 +); impl Date { /// Construct a new Japanese Date. @@ -418,13 +326,7 @@ impl Date { /// 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 + /// // This function will error for unknown eras /// let fake_era = "neko"; // 🐱 /// let fake_date = Date::try_new_japanese_with_calendar( /// fake_era, @@ -442,10 +344,15 @@ impl Date { day: u8, japanese_calendar: A, ) -> Result, DateError> { - let inner = japanese_calendar + let extended = japanese_calendar .as_calendar() - .new_japanese_date_inner(era, year, month, day)?; - Ok(Date::from_raw(inner, japanese_calendar)) + .extended_from_era_year(Some(era.as_bytes()), year)?; + Ok(Date::from_raw( + JapaneseDateInner(ArithmeticDate::new_gregorian::<&Japanese>( + extended, month, day, + )?), + japanese_calendar, + )) } } @@ -490,248 +397,14 @@ impl Date { 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, - }) + let extended = (&japanext_calendar.as_calendar().0) + .extended_from_era_year(Some(era.as_bytes()), year)?; + Ok(Date::from_raw( + JapaneseExtendedDateInner(ArithmeticDate::new_gregorian::<&Japanese>( + extended, month, day, + )?), + japanext_calendar, + )) } } @@ -776,9 +449,9 @@ mod tests { ) } - // test that the Gregorian eras roundtrip to Japanese ones - fn single_test_gregorian_roundtrip_ext( - calendar: Ref, + // test that out-of-range era values roundtrip to other eras + fn single_test_era_range_roundtrip( + calendar: Ref, era: &str, year: i32, month: u8, @@ -786,14 +459,14 @@ mod tests { era2: &str, year2: i32, ) { - let expected = Date::try_new_japanese_extended_with_calendar(era2, year2, month, day, calendar) + let expected = Date::try_new_japanese_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) + 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:?}") }); @@ -804,32 +477,43 @@ mod tests { "Failed to roundtrip with {era:?}, {year}, {month}, {day} == {era2:?}, {year}" ) } - - fn single_test_error( - calendar: Ref, + fn single_test_era_range_roundtrip_ext( + calendar: Ref, era: &str, year: i32, month: u8, day: u8, - error: DateError, + era2: &str, + year2: i32, ) { - let date = Date::try_new_japanese_with_calendar(era, year, month, day, calendar); + 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!( - date, - Err(error), - "Construction with {era:?}, {year}, {month}, {day} did not return {error:?}" + expected, reconstructed, + "Failed to roundtrip with {era:?}, {year}, {month}, {day} == {era2:?}, {year}" ) } - fn single_test_error_ext( - calendar: Ref, + fn single_test_error( + 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); + let date = Date::try_new_japanese_with_calendar(era, year, month, day, calendar); assert_eq!( date, Err(error), @@ -847,35 +531,11 @@ mod tests { 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_era_range_roundtrip(calendar, "heisei", 1, 1, 1, "showa", 64); 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_era_range_roundtrip_ext(calendar_ext, "heisei", 1, 1, 1, "showa", 64); single_test_roundtrip_ext(calendar_ext, "hakuho-672", 4, 3, 1); single_test_error(calendar, "hakuho-672", 4, 3, 1, DateError::UnknownEra); @@ -887,69 +547,38 @@ mod tests { 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, - }, - ); + single_test_era_range_roundtrip(calendar, "ce", 0, 3, 1, "bce", 1); + single_test_era_range_roundtrip(calendar, "bce", -1, 3, 1, "ce", 2); // 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); + single_test_era_range_roundtrip_ext(calendar_ext, "ce", 1000, 3, 1, "choho-999", 2); + single_test_era_range_roundtrip_ext(calendar_ext, "ce", 749, 5, 10, "tenpyokampo-749", 1); + single_test_era_range_roundtrip_ext(calendar_ext, "bce", 10, 3, 1, "bce", 10); + single_test_era_range_roundtrip_ext(calendar_ext, "ce", -1, 3, 1, "bce", 2); // 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( + single_test_era_range_roundtrip_ext( calendar_ext, "tenpyokampo-749", 1, 7, 5, - DateError::Range { - field: "month", - value: 7, - min: 1, - max: 6, - }, + "tenpyoshoho-749", + 1, ); - single_test_error_ext( + single_test_era_range_roundtrip_ext( calendar_ext, "tenpyokampo-749", 1, 4, 13, - DateError::Range { - field: "day", - value: 13, - min: 14, - max: 31, - }, + "tenpyoshoho-749", + 1, ); } } diff --git a/deps/crates/vendor/icu_calendar/src/cal/julian.rs b/deps/crates/vendor/icu_calendar/src/cal/julian.rs index 92379e0bde1f22..f0a48379d6fe22 100644 --- a/deps/crates/vendor/icu_calendar/src/cal/julian.rs +++ b/deps/crates/vendor/icu_calendar/src/cal/julian.rs @@ -2,59 +2,90 @@ // 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 crate::calendar_arithmetic::ArithmeticDate; +use crate::calendar_arithmetic::DateFieldsResolver; +use crate::error::{DateError, DateFromFieldsError, EcmaReferenceYearError, UnknownEraError}; +use crate::options::DateFromFieldsOptions; +use crate::options::{DateAddOptions, DateDifferenceOptions}; +use crate::types::DateFields; +use crate::{types, Calendar, Date, RangeError}; use calendrical_calculations::helpers::I32CastError; use calendrical_calculations::rata_die::RataDie; use tinystr::tinystr; -/// The [Julian Calendar] +/// The [Julian Calendar](https://en.wikipedia.org/wiki/Julian_calendar). /// -/// The [Julian calendar] is a solar calendar that was used commonly historically, with twelve months. +/// The Julian calendar is a solar calendar that was introduced in the Roman Republic under +/// Julius Caesar in 45 BCE, and used in Europe and much of the western world until it was +/// eventually replaced by the more accurate [`Gregorian`](super::Gregorian) calendar. /// -/// This type can be used with [`Date`] to represent dates in this calendar. +/// This implementation extends proleptically for dates before the calendar's creation. /// -/// [Julian calendar]: https://en.wikipedia.org/wiki/Julian_calendar +/// While no country uses the Julian calendar as its civil calendar today, it is still +/// used by eastern Christian churches to determine lithurgical dates like Christmas and +/// Easter. /// /// # Era codes /// /// This calendar uses two era codes: `bce` (alias `bc`), and `ce` (alias `ad`), corresponding to the BCE and CE eras. /// -/// # Month codes +/// # Months and days /// -/// This calendar supports 12 solar month codes (`"M01" - "M12"`) +/// The 12 months are called January (`M01`, 31 days), February (`M02`, 28 days), +/// March (`M03`, 31 days), April (`M04`, 30 days), May (`M05`, 31 days), June (`M06`, 30 days), +/// July (`M07`, 31 days), August (`M08`, 31 days), September (`M09`, 30 days), +/// October (`M10`, 31 days), November (`M11`, 30 days), December (`M12`, 31 days). +/// +/// In leap years (years divisible by 4), February gains a 29th day. +/// +/// Standard years thus have 365 days, and leap years 366. +/// +/// # Calendar drift +/// +/// The Julian calendar has an average year length of 365.25, slightly longer than +/// the mean solar year, so this calendar drifts 1 day in ~128 years with +/// respect to the seasons. This significant drift was the reason for its replacement +/// by the Gregorian calendar. The Julian calendar is currently 14 days ahead of the +/// Gregorian calendar and the solar year. +/// +/// # Historical accuracy +/// +/// Historically, a variety of year reckoning schemes have been used with the Julian +/// calendar, such as Roman consular years, regnal years, [indictions]( +/// https://en.wikipedia.org/wiki/Indiction), [Anno Mundi]( +/// https://en.wikipedia.org/wiki/Anno_Mundi#Byzantine_era), the [Diocletian era]( +/// https://en.wikipedia.org/wiki/Era_of_the_Martyrs), [Anno Domini]( +/// https://en.wikipedia.org/wiki/Anno_Domini), and the (equivalent) [Common era]( +/// https://en.wikipedia.org/wiki/Common_Era). +/// The latter, which is used today and by this implementation, has been used by +/// western European authorities since the early middle ages, however some eastern +/// European countries/churches have not adopted it until fairly recently, or, in +/// some cases, are still using a different year reckoning scheme. +/// +/// Also during the middle ages, [some countries](https://en.wikipedia.org/wiki/New_Year#Historical_European_new_year_dates) +/// used different dates for the first day of the year, ranging from late December to +/// late March. Care has to be taken when interpreting year numbers with dates in this +/// range. +/// +/// The calendar was used [incorrectly](https://en.wikipedia.org/wiki/Julian_calendar#Leap_year_error) +/// for a while after adoption, so the first year where the months align with this proleptic +/// implementation is probably 4 CE. #[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)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] // The inner date type used for representing Date pub struct JulianDateInner(pub(crate) ArithmeticDate); -impl CalendarArithmetic for Julian { +impl DateFieldsResolver 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 if calendrical_calculations::julian::is_leap_year(year) => 29, 2 => 28, 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31, _ => 0, @@ -65,20 +96,41 @@ impl CalendarArithmetic for Julian { 12 } - fn provided_year_is_leap(year: i32) -> bool { - calendrical_calculations::julian::is_leap_year(year) + #[inline] + fn year_info_from_era( + &self, + era: &[u8], + era_year: i32, + ) -> Result { + match era { + b"ad" | b"ce" => Ok(era_year), + b"bc" | b"bce" => Ok(1 - era_year), + _ => Err(UnknownEraError), + } } - fn last_month_day_in_provided_year(_year: i32) -> (u8, u8) { - (12, 31) + #[inline] + fn year_info_from_extended(&self, extended_year: i32) -> Self::YearInfo { + extended_year } - fn days_in_provided_year(year: i32) -> u16 { - if Self::provided_year_is_leap(year) { - 366 + #[inline] + fn reference_year_from_month_day( + &self, + month_code: types::ValidMonthCode, + day: u8, + ) -> Result { + let (ordinal_month, false) = month_code.to_tuple() else { + return Err(EcmaReferenceYearError::MonthCodeNotInCalendar); + }; + // December 31, 1972 occurs on 12th month, 18th day, 1972 Old Style + // Note: 1972 is a leap year + let julian_year = if ordinal_month < 12 || (ordinal_month == 12 && day <= 18) { + 1972 } else { - 365 - } + 1971 + }; + Ok(julian_year) } } @@ -86,6 +138,7 @@ impl crate::cal::scaffold::UnstableSealed for Julian {} impl Calendar for Julian { type DateInner = JulianDateInner; type Year = types::EraYear; + type DifferenceError = core::convert::Infallible; fn from_codes( &self, @@ -94,20 +147,23 @@ impl Calendar for Julian { 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::from_codes(era, year, month_code, day, self).map(JulianDateInner) + } - ArithmeticDate::new_from_codes(self, year, month_code, day).map(JulianDateInner) + #[cfg(feature = "unstable")] + fn from_fields( + &self, + fields: DateFields, + options: DateFromFieldsOptions, + ) -> Result { + ArithmeticDate::from_fields(fields, options, self).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(), + Err(I32CastError::BelowMin) => ArithmeticDate::new_unchecked(i32::MIN, 1, 1), + Err(I32CastError::AboveMax) => ArithmeticDate::new_unchecked(i32::MAX, 12, 31), Ok((year, month, day)) => ArithmeticDate::new_unchecked(year, month, day), }, ) @@ -117,83 +173,90 @@ impl Calendar for Julian { 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 has_cheap_iso_conversion(&self) -> bool { + false } fn months_in_year(&self, date: &Self::DateInner) -> u8 { - date.0.months_in_year() + Self::months_in_provided_year(date.0.year) } fn days_in_year(&self, date: &Self::DateInner) -> u16 { - date.0.days_in_year() + if self.is_in_leap_year(date) { + 366 + } else { + 365 + } } fn days_in_month(&self, date: &Self::DateInner) -> u8 { - date.0.days_in_month() + Self::days_in_provided_month(date.0.year, date.0.month) } - fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { - date.0.offset_date(offset, &()); + #[cfg(feature = "unstable")] + fn add( + &self, + date: &Self::DateInner, + duration: types::DateDuration, + options: DateAddOptions, + ) -> Result { + date.0.added(duration, self, options).map(JulianDateInner) } - #[allow(clippy::field_reassign_with_default)] + #[cfg(feature = "unstable")] 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) + options: DateDifferenceOptions, + ) -> Result { + Ok(date1.0.until(&date2.0, self, options)) } /// 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); + let extended_year = date.0.year; if extended_year > 0 { types::EraYear { era: tinystr!(16, "ce"), era_index: Some(1), year: extended_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), + year: 1 - extended_year, + 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) + calendrical_calculations::julian::is_leap_year(date.0.year) } /// The calendar-specific month represented by `date` fn month(&self, date: &Self::DateInner) -> types::MonthInfo { - date.0.month() + types::MonthInfo::non_lunisolar(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() + types::DayOfMonth(date.0.day) } fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { - date.0.day_of_year() + types::DayOfYear( + (1..date.0.month) + .map(|m| Self::days_in_provided_month(date.0.year, m) as u16) + .sum::() + + date.0.day as u16, + ) } fn debug_name(&self) -> &'static str { @@ -210,6 +273,11 @@ impl Julian { pub fn new() -> Self { Self } + + /// Returns the date of (Orthodox) Easter in the given year. + pub fn easter(year: i32) -> Date { + Date::from_rata_die(calendrical_calculations::julian::easter(year), Self) + } } impl Date { @@ -228,7 +296,7 @@ impl Date { /// 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) + ArithmeticDate::try_from_ymd(year, month, day) .map(JulianDateInner) .map(|inner| Date::from_raw(inner, Julian)) } @@ -474,20 +542,11 @@ mod test { } } - #[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(4, 2, 29).unwrap(); + Date::try_new_julian(0, 2, 29).unwrap(); + Date::try_new_julian(-4, 2, 29).unwrap(); 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 index 0014aac559b5e3..cd442f6f979116 100644 --- a/deps/crates/vendor/icu_calendar/src/cal/mod.rs +++ b/deps/crates/vendor/icu_calendar/src/cal/mod.rs @@ -4,14 +4,14 @@ //! 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; +#[path = "east_asian_traditional.rs"] +pub(crate) mod east_asian_traditional_internal; pub(crate) mod ethiopian; pub(crate) mod gregorian; pub(crate) mod hebrew; -pub(crate) mod hijri; +#[path = "hijri.rs"] +pub(crate) mod hijri_internal; pub(crate) mod indian; pub(crate) mod iso; pub(crate) mod japanese; @@ -19,16 +19,42 @@ pub(crate) mod julian; pub(crate) mod persian; pub(crate) mod roc; +pub(crate) mod abstract_gregorian; + pub use buddhist::Buddhist; -pub use chinese::Chinese; +/// Customizations for the [`EastAsianTraditional`](east_asian_traditional::EastAsianTraditional) calendar. +pub mod east_asian_traditional { + pub use super::east_asian_traditional_internal::{China, EastAsianTraditional, Korea}; + + // TODO(#6962) Stabilize + #[cfg(feature = "unstable")] + pub use super::east_asian_traditional_internal::{EastAsianTraditionalYearData, Rules}; +} pub use coptic::Coptic; -pub use dangi::Dangi; +pub use east_asian_traditional_internal::{ChineseTraditional, KoreanTraditional}; pub use ethiopian::{Ethiopian, EthiopianEraStyle}; pub use gregorian::Gregorian; pub use hebrew::Hebrew; -pub use hijri::{ - HijriSimulated, HijriTabular, HijriTabularEpoch, HijriTabularLeapYears, HijriUmmAlQura, -}; +pub use hijri_internal::Hijri; +/// Customizations for the [`Hijri`] calendar. +pub mod hijri { + pub use super::hijri_internal::{ + AstronomicalSimulation, TabularAlgorithm, TabularAlgorithmEpoch, TabularAlgorithmLeapYears, + UmmAlQura, + }; + + // TODO(#6962) Stabilize + #[cfg(feature = "unstable")] + pub use super::hijri_internal::{HijriYearData, Rules}; + + #[doc(hidden)] + /// These are unstable traits but we expose them on stable to + /// icu_datetime. + pub mod unstable_internal { + pub use super::super::hijri_internal::Rules; + } +} + pub use indian::Indian; pub use iso::Iso; pub use japanese::{Japanese, JapaneseExtended}; @@ -36,9 +62,31 @@ pub use julian::Julian; pub use persian::Persian; pub use roc::Roc; -pub use crate::any_calendar::{AnyCalendar, AnyCalendarKind}; +/// Deprecated +#[deprecated] +pub use hijri::{ + TabularAlgorithmEpoch as HijriTabularEpoch, TabularAlgorithmLeapYears as HijriTabularLeapYears, +}; +/// Deprecated +#[deprecated] +pub type HijriSimulated = Hijri; +/// Deprecated +#[deprecated] +pub type HijriUmmAlQura = Hijri; +/// Deprecated +#[deprecated] +pub type HijriTabular = Hijri; +/// Use [`KoreanTraditional`] +#[deprecated(since = "2.1.0", note = "use `KoreanTraditional`")] +pub type Dangi = KoreanTraditional; +/// Use [`ChineseTraditional`] +#[deprecated(since = "2.1.0", note = "use `ChineseTraditional`")] +pub type Chinese = ChineseTraditional; + +pub use crate::any_calendar::{AnyCalendar, AnyCalendarDifferenceError, AnyCalendarKind}; /// Internal scaffolding types +#[cfg_attr(not(feature = "unstable"), doc(hidden))] pub mod scaffold { /// Trait marking other traits that are considered unstable and should not generally be /// implemented outside of the calendar crate. diff --git a/deps/crates/vendor/icu_calendar/src/cal/persian.rs b/deps/crates/vendor/icu_calendar/src/cal/persian.rs index fc58e879925737..0e1a95b111953f 100644 --- a/deps/crates/vendor/icu_calendar/src/cal/persian.rs +++ b/deps/crates/vendor/icu_calendar/src/cal/persian.rs @@ -2,41 +2,46 @@ // 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 crate::calendar_arithmetic::ArithmeticDate; +use crate::calendar_arithmetic::DateFieldsResolver; +use crate::error::{DateError, DateFromFieldsError, EcmaReferenceYearError, UnknownEraError}; +use crate::options::DateFromFieldsOptions; +use crate::options::{DateAddOptions, DateDifferenceOptions}; +use crate::types::DateFields; +use crate::{types, Calendar, Date, 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. +/// The Persian Calendar is a solar calendar used officially by the countries of Iran and +/// Afghanistan and many Persian-speaking regions. /// -/// This type can be used with [`Date`] to represent dates in this calendar. +/// This implementation extends proleptically for dates before the calendar's creation +/// in 458 AP (1079 CE). +/// +/// This corresponds to the `"persian"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). /// /// # 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. +/// This calendar uses a single era code `ap`, with Anno Persico/Anno Persarum starting the year of the Hijra. Dates before this era use negative years. +/// +/// # Months and days +/// +/// The 12 months are called Farvardin (`M01`, 31 days), Ordibehesht (`M02`, 31 days), +/// Khordad (`M03`, 31 days), Tir (`M04`, 31 days), Mordad (`M05`, 31 days), Shahrivar (`M06`, 31 days), +/// Mehr (`M07`, 30 days), Aban (`M08`, 30 days), Azar (`M09`, 30 days), +/// Dey (`M10`, 30 days), Bahman (`M11`, 30 days), Esfand (`M12`, 29 days). +/// +/// In leap years (determined astronomically with respect to the vernal equinox), Esfand gains a 30th day. +/// +/// Standard years thus have 365 days, and leap years 366. /// -/// # Month codes +/// # Calendar drift /// -/// This calendar supports 12 solar month codes (`"M01" - "M12"`) +/// As leap years are determined with respect to the solar year, this calendar stays anchored +/// to the seasons. #[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq, PartialOrd, Ord)] #[allow(clippy::exhaustive_structs)] pub struct Persian; @@ -46,14 +51,14 @@ pub struct Persian; /// 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 { +impl DateFieldsResolver 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 if calendrical_calculations::persian::is_leap_year(year) => 30, 12 => 29, _ => 0, } @@ -63,24 +68,40 @@ impl CalendarArithmetic for Persian { 12 } - fn provided_year_is_leap(p_year: i32) -> bool { - calendrical_calculations::persian::is_leap_year(p_year) + #[inline] + fn year_info_from_era( + &self, + era: &[u8], + era_year: i32, + ) -> Result { + match era { + b"ap" => Ok(era_year), + _ => Err(UnknownEraError), + } } - fn days_in_provided_year(year: i32) -> u16 { - if Self::provided_year_is_leap(year) { - 366 - } else { - 365 - } + #[inline] + fn year_info_from_extended(&self, extended_year: i32) -> Self::YearInfo { + extended_year } - fn last_month_day_in_provided_year(year: i32) -> (u8, u8) { - if Self::provided_year_is_leap(year) { - (12, 30) + #[inline] + fn reference_year_from_month_day( + &self, + month_code: types::ValidMonthCode, + day: u8, + ) -> Result { + let (ordinal_month, false) = month_code.to_tuple() else { + return Err(EcmaReferenceYearError::MonthCodeNotInCalendar); + }; + // December 31, 1972 occurs on 10th month, 10th day, 1351 AP + let persian_year = if ordinal_month < 10 || (ordinal_month == 10 && day <= 10) { + 1351 } else { - (12, 29) - } + // Note: 1350 is a leap year + 1350 + }; + Ok(persian_year) } } @@ -88,6 +109,7 @@ impl crate::cal::scaffold::UnstableSealed for Persian {} impl Calendar for Persian { type DateInner = PersianDateInner; type Year = types::EraYear; + type DifferenceError = core::convert::Infallible; fn from_codes( &self, @@ -96,19 +118,23 @@ impl Calendar for Persian { month_code: types::MonthCode, day: u8, ) -> Result { - let year = match era { - Some("ap" | "sh" | "hs") | None => year, - Some(_) => return Err(DateError::UnknownEra), - }; + ArithmeticDate::from_codes(era, year, month_code, day, self).map(PersianDateInner) + } - ArithmeticDate::new_from_codes(self, year, month_code, day).map(PersianDateInner) + #[cfg(feature = "unstable")] + fn from_fields( + &self, + fields: DateFields, + options: DateFromFieldsOptions, + ) -> Result { + ArithmeticDate::from_fields(fields, options, self).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(), + Err(I32CastError::BelowMin) => ArithmeticDate::new_unchecked(i32::MIN, 1, 1), + Err(I32CastError::AboveMax) => ArithmeticDate::new_unchecked(i32::MAX, 12, 29), Ok((year, month, day)) => ArithmeticDate::new_unchecked(year, month, day), }, ) @@ -122,69 +148,74 @@ impl Calendar for Persian { ) } - 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 has_cheap_iso_conversion(&self) -> bool { + false } fn months_in_year(&self, date: &Self::DateInner) -> u8 { - date.0.months_in_year() + Self::months_in_provided_year(date.0.year) } fn days_in_year(&self, date: &Self::DateInner) -> u16 { - date.0.days_in_year() + if self.is_in_leap_year(date) { + 366 + } else { + 365 + } } fn days_in_month(&self, date: &Self::DateInner) -> u8 { - date.0.days_in_month() + Self::days_in_provided_month(date.0.year, date.0.month) } - fn offset_date(&self, date: &mut Self::DateInner, offset: DateDuration) { - date.0.offset_date(offset, &()) + #[cfg(feature = "unstable")] + fn add( + &self, + date: &Self::DateInner, + duration: types::DateDuration, + options: DateAddOptions, + ) -> Result { + date.0.added(duration, self, options).map(PersianDateInner) } - #[allow(clippy::field_reassign_with_default)] + #[cfg(feature = "unstable")] 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) + options: DateDifferenceOptions, + ) -> Result { + Ok(date1.0.until(&date2.0, self, options)) } fn year_info(&self, date: &Self::DateInner) -> Self::Year { + let extended_year = date.0.year; types::EraYear { era: tinystr!(16, "ap"), era_index: Some(0), - year: self.extended_year(date), + year: extended_year, + extended_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) + calendrical_calculations::persian::is_leap_year(date.0.year) } fn month(&self, date: &Self::DateInner) -> types::MonthInfo { - date.0.month() + types::MonthInfo::non_lunisolar(date.0.month) } fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth { - date.0.day_of_month() + types::DayOfMonth(date.0.day) } fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear { - date.0.day_of_year() + types::DayOfYear( + (date.0.month as u16 - 1) * 31 - (date.0.month as u16 - 1).saturating_sub(6) + + date.0.day as u16, + ) } fn debug_name(&self) -> &'static str { @@ -219,7 +250,7 @@ impl Date { /// 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) + ArithmeticDate::try_from_ymd(year, month, day) .map(PersianDateInner) .map(|inner| Date::from_raw(inner, Persian)) } @@ -358,15 +389,6 @@ mod tests { }, ]; - 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]; @@ -379,8 +401,11 @@ mod tests { 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); + for (&year, &is_leap) in leap_years.iter().zip(expected_values.iter()) { + assert_eq!( + Date::try_new_persian(year, 1, 1).unwrap().is_in_leap_year(), + is_leap + ); } } @@ -388,8 +413,12 @@ mod tests { 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) + Date::try_new_persian(case.year, 1, 1) + .unwrap() + .days_in_year(), + (calendrical_calculations::persian::fixed_from_fast_persian(case.year + 1, 1, 1) + - calendrical_calculations::persian::fixed_from_fast_persian(case.year, 1, 1)) + as u16 ); } } @@ -714,13 +743,13 @@ mod tests { #[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); + for &(p_year, leap, iso_year, iso_month, iso_day) in CALENDAR_UT_AC_IR_TEST_DATA.iter() { + let persian_date = Date::try_new_persian(p_year, 1, 1).unwrap(); + assert_eq!(persian_date.is_in_leap_year(), leap); + let iso_date = persian_date.to_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 index 1c81c0a2646620..1ae6cdbf4e461c 100644 --- a/deps/crates/vendor/icu_calendar/src/cal/roc.rs +++ b/deps/crates/vendor/icu_calendar/src/cal/roc.rs @@ -2,136 +2,63 @@ // 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 crate::cal::abstract_gregorian::{impl_with_abstract_gregorian, GregorianYears}; +use crate::calendar_arithmetic::ArithmeticDate; +use crate::error::UnknownEraError; +use crate::preferences::CalendarAlgorithm; +use crate::{types, Date, DateError, RangeError}; 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 is a variant of the [`Gregorian`](crate::cal::Gregorian) calendar +/// created by the government of the Republic of China. It is identical to the Gregorian +/// calendar except that is uses the ROC/Minguo/民国/民國 Era (1912 CE) instead of the Common Era. +/// +/// This implementation extends proleptically for dates before the calendar's creation +/// in 1 Minguo (1912 CE). /// -/// The ROC calendar should not be confused with the Chinese traditional lunar calendar -/// (see [`Chinese`](crate::cal::Chinese)). +/// The ROC calendar should not be confused with the [`ChineseTraditional`](crate::cal::ChineseTraditional) +/// lunisolar calendar. +/// +/// This corresponds to the `"roc"` [CLDR calendar](https://unicode.org/reports/tr35/#UnicodeCalendarIdentifier). /// /// # 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; +impl_with_abstract_gregorian!(crate::cal::Roc, RocDateInner, RocEra, _x, RocEra); - 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), - }; +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) struct RocEra; - ArithmeticDate::new_from_codes(self, year, month_code, day) - .map(IsoDateInner) - .map(RocDateInner) - } +impl GregorianYears for RocEra { + const EXTENDED_YEAR_OFFSET: i32 = 1911; - 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( + fn extended_from_era_year( &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" + era: Option<&[u8]>, + year: i32, + ) -> Result { + match era { + None => Ok(year), + Some(b"roc") => Ok(year), + Some(b"broc") => Ok(1 - year), + Some(_) => Err(UnknownEraError), + } } - fn year_info(&self, date: &Self::DateInner) -> Self::Year { - let extended_year = self.extended_year(date); + fn era_year_from_extended(&self, extended_year: i32, _month: u8, _day: u8) -> types::EraYear { if extended_year > 0 { types::EraYear { era: tinystr!(16, "roc"), era_index: Some(1), year: extended_year, + extended_year, ambiguity: types::YearAmbiguity::CenturyRequired, } } else { @@ -139,33 +66,18 @@ impl Calendar for Roc { era: tinystr!(16, "broc"), era_index: Some(0), year: 1 - extended_year, + 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 debug_name(&self) -> &'static str { + "ROC" } - fn calendar_algorithm(&self) -> Option { - Some(crate::preferences::CalendarAlgorithm::Roc) + fn calendar_algorithm(&self) -> Option { + Some(CalendarAlgorithm::Roc) } } @@ -185,7 +97,7 @@ impl 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().era, "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!"); @@ -197,8 +109,9 @@ impl Date { /// 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)) + ArithmeticDate::new_gregorian::(year, month, day) + .map(RocDateInner) + .map(|i| Date::from_raw(i, Roc)) } } @@ -206,6 +119,7 @@ impl Date { mod test { use super::*; + use crate::cal::Iso; use calendrical_calculations::rata_die::RataDie; #[derive(Debug)] diff --git a/deps/crates/vendor/icu_calendar/src/calendar.rs b/deps/crates/vendor/icu_calendar/src/calendar.rs index 5b0ea851d1388e..716121b5fac28c 100644 --- a/deps/crates/vendor/icu_calendar/src/calendar.rs +++ b/deps/crates/vendor/icu_calendar/src/calendar.rs @@ -5,8 +5,10 @@ use calendrical_calculations::rata_die::RataDie; use crate::cal::iso::IsoDateInner; -use crate::error::DateError; -use crate::{types, DateDuration, DateDurationUnit}; +use crate::error::{DateError, DateFromFieldsError}; +use crate::options::DateFromFieldsOptions; +use crate::options::{DateAddOptions, DateDifferenceOptions}; +use crate::{types, Iso}; use core::fmt; /// A calendar implementation @@ -26,14 +28,18 @@ use core::fmt; /// pub trait Calendar: crate::cal::scaffold::UnstableSealed { /// The internal type used to represent dates - type DateInner: Eq + Copy + fmt::Debug; + /// + /// Equality and ordering should observe normal calendar semantics. + type DateInner: Eq + Copy + PartialOrd + fmt::Debug; /// The type of YearInfo returned by the date type Year: fmt::Debug + Into; + /// The type of error returned by `until` + type DifferenceError; /// Construct a date from era/month codes and fields /// - /// The year is extended_year if no era is provided - #[allow(clippy::wrong_self_convention)] + /// The year is the [extended year](crate::Date::extended_year) if no era is provided + #[expect(clippy::wrong_self_convention)] fn from_codes( &self, era: Option<&str>, @@ -42,14 +48,44 @@ pub trait Calendar: crate::cal::scaffold::UnstableSealed { 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 a date from a bag of date fields. + /// + ///
+ /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, + /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. + /// + /// Graduation tracking issue: [issue #7161](https://github.com/unicode-org/icu4x/issues/7161). + ///
+ /// + /// ✨ *Enabled with the `unstable` Cargo feature.* + #[expect(clippy::wrong_self_convention)] + #[cfg(feature = "unstable")] + fn from_fields( + &self, + fields: types::DateFields, + options: DateFromFieldsOptions, + ) -> Result; + + /// Whether `from_iso`/`to_iso` is more efficient + /// than `from_rata_die`/`to_rata_die`. + fn has_cheap_iso_conversion(&self) -> bool; + + /// Construct the date from an ISO date. + /// + /// Only called if `HAS_CHEAP_ISO_CONVERSION` is set. + #[expect(clippy::wrong_self_convention)] + fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner { + self.from_rata_die(Iso.to_rata_die(&iso)) + } + /// Obtain an ISO date from this date. + /// + /// Only called if `HAS_CHEAP_ISO_CONVERSION` is set. + fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner { + Iso.from_rata_die(self.to_rata_die(date)) + } /// Construct the date from a [`RataDie`] - #[allow(clippy::wrong_self_convention)] + #[expect(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; @@ -68,8 +104,11 @@ pub trait Calendar: crate::cal::scaffold::UnstableSealed { /// 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 [extended year](crate::Date::extended_year). + fn extended_year(&self, date: &Self::DateInner) -> i32 { + self.year_info(date).into().extended_year() + } /// The calendar-specific month represented by `date` fn month(&self, date: &Self::DateInner) -> types::MonthInfo; /// The calendar-specific day-of-month represented by `date` @@ -77,22 +116,44 @@ pub trait Calendar: crate::cal::scaffold::UnstableSealed { /// 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 + /// Add `duration` to `date` + /// + ///
+ /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, + /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. + /// + /// Graduation tracking issue: [issue #3964](https://github.com/unicode-org/icu4x/issues/3964). + ///
+ /// + /// ✨ *Enabled with the `unstable` Cargo feature.* + #[cfg(feature = "unstable")] + fn add( + &self, + date: &Self::DateInner, + duration: types::DateDuration, + options: DateAddOptions, + ) -> Result; + /// 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. + /// + ///
+ /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, + /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. + /// + /// Graduation tracking issue: [issue #3964](https://github.com/unicode-org/icu4x/issues/3964). + ///
+ /// + /// ✨ *Enabled with the `unstable` Cargo feature.* + #[cfg(feature = "unstable")] fn until( &self, date1: &Self::DateInner, date2: &Self::DateInner, - calendar2: &Self, - largest_unit: DateDurationUnit, - smallest_unit: DateDurationUnit, - ) -> DateDuration; + options: DateDifferenceOptions, + ) -> Result; /// Returns the [`CalendarAlgorithm`](crate::preferences::CalendarAlgorithm) that is required to match /// when parsing into this calendar. diff --git a/deps/crates/vendor/icu_calendar/src/calendar_arithmetic.rs b/deps/crates/vendor/icu_calendar/src/calendar_arithmetic.rs index fc1da7d8c6823a..3e3078d11f663c 100644 --- a/deps/crates/vendor/icu_calendar/src/calendar_arithmetic.rs +++ b/deps/crates/vendor/icu_calendar/src/calendar_arithmetic.rs @@ -2,66 +2,78 @@ // 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 crate::duration::{DateDuration, DateDurationUnit}; +use crate::error::{ + range_check, range_check_with_overflow, DateFromFieldsError, EcmaReferenceYearError, + MonthCodeError, MonthCodeParseError, UnknownEraError, +}; +use crate::options::{DateAddOptions, DateDifferenceOptions}; +use crate::options::{DateFromFieldsOptions, MissingFieldsStrategy, Overflow}; +use crate::types::{DateFields, ValidMonthCode}; +use crate::{types, Calendar, DateError, 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; +use core::ops::RangeInclusive; + +/// The range ±2²⁷. We use i32::MIN since it is -2³¹ +/// +/// This range is currently global, and applied to both era years and +/// extended years, but may be replaced with a per-calendar check in the future. +/// +/// +const VALID_YEAR_RANGE: RangeInclusive = (i32::MIN / 16)..=-(i32::MIN / 16); #[derive(Debug)] -#[allow(clippy::exhaustive_structs)] // this type is stable -pub(crate) struct ArithmeticDate { +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 { +impl Copy for ArithmeticDate {} +impl Clone for ArithmeticDate { fn clone(&self) -> Self { *self } } -impl PartialEq for ArithmeticDate { +impl PartialEq for ArithmeticDate { fn eq(&self, other: &Self) -> bool { - self.year.into() == other.year.into() && self.month == other.month && self.day == other.day + self.year.to_extended_year() == other.year.to_extended_year() + && self.month == other.month + && self.day == other.day } } -impl Eq for ArithmeticDate {} +impl Eq for ArithmeticDate {} -impl Ord for ArithmeticDate { +impl Ord for ArithmeticDate { fn cmp(&self, other: &Self) -> Ordering { self.year - .into() - .cmp(&other.year.into()) + .to_extended_year() + .cmp(&other.year.to_extended_year()) .then(self.month.cmp(&other.month)) .then(self.day.cmp(&other.day)) } } -impl PartialOrd for ArithmeticDate { +impl PartialOrd for ArithmeticDate { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Hash for ArithmeticDate { +impl Hash for ArithmeticDate { fn hash(&self, state: &mut H) where H: Hasher, { - self.year.into().hash(state); + self.year.to_extended_year().hash(state); self.month.hash(state); self.day.hash(state); } @@ -71,341 +83,613 @@ impl Hash for ArithmeticDate { #[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 { +pub(crate) trait ToExtendedYear { + fn to_extended_year(&self) -> i32; +} + +impl ToExtendedYear for i32 { + fn to_extended_year(&self) -> i32 { + *self + } +} + +/// Trait for converting from era codes, month codes, and other fields to year/month/day ordinals. +pub(crate) trait DateFieldsResolver: Calendar { /// This stores the year as either an i32, or a type containing more /// useful computational information. - type YearInfo: Copy + Debug + Into; + type YearInfo: Copy + Debug + PartialEq + ToExtendedYear; - // 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; -} + fn months_in_provided_year(year: Self::YearInfo) -> u8; -impl PrecomputedDataSource for () { - fn load_or_compute_info(&self, year: i32) -> i32 { - year - } -} + /// Converts the era and era year to a YearInfo. If the calendar does not have eras, + /// this should always return an Err result. + fn year_info_from_era( + &self, + era: &[u8], + era_year: i32, + ) -> Result; -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, - } - } + /// Converts an extended year to a YearInfo. + fn year_info_from_extended(&self, extended_year: i32) -> Self::YearInfo; - #[inline] - pub fn min_date() -> Self - where - C: CalendarArithmetic, - { - ArithmeticDate { - year: i32::MIN, - month: 1, - day: 1, - marker: PhantomData, - } - } + /// Calculates the ECMA reference year for the month code and day, or an error + /// if the month code and day are invalid. + /// + /// Note that this is called before any potential Overflow::Constrain application, + /// so this should accept out-of-range day values as if they are the highest possible + /// day for the given month. + fn reference_year_from_month_day( + &self, + month_code: ValidMonthCode, + day: u8, + ) -> Result; + /// Calculates the ordinal month for the given year and month code. + /// + /// The default impl is for non-lunisolar calendars with 12 months! #[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, + fn ordinal_month_from_code( + &self, + _year: &Self::YearInfo, + month_code: ValidMonthCode, + _options: DateFromFieldsOptions, + ) -> Result { + match month_code.to_tuple() { + (month_number @ 1..=12, false) => Ok(month_number), + _ => Err(MonthCodeError::NotInCalendar), } } + /// Calculates the month code from the given ordinal month and year. + /// + /// The caller must ensure that the ordinal is in range. + /// + /// The default impl is for non-lunisolar calendars! #[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; - } - } + fn month_code_from_ordinal(&self, _year: &Self::YearInfo, ordinal_month: u8) -> ValidMonthCode { + ValidMonthCode::new_unchecked(ordinal_month, false) } +} +impl ArithmeticDate { #[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 - } - } + pub(crate) const fn new_unchecked(year: C::YearInfo, month: u8, day: u8) -> Self { + ArithmeticDate { year, month, day } } - #[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); + pub(crate) const fn cast>( + self, + ) -> ArithmeticDate { + ArithmeticDate { + year: self.year, + month: self.month, + day: self.day, } - - 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, - ) + pub(crate) fn from_codes( + era: Option<&str>, + year: i32, + month_code: types::MonthCode, + day: u8, + calendar: &C, + ) -> Result { + let year = range_check(year, "year", VALID_YEAR_RANGE)?; + let year = if let Some(era) = era { + calendar.year_info_from_era(era.as_bytes(), year)? + } else { + calendar.year_info_from_extended(year) + }; + let validated = + ValidMonthCode::try_from_utf8(month_code.0.as_bytes()).map_err(|e| match e { + MonthCodeParseError::InvalidSyntax => DateError::UnknownMonthCode(month_code), + })?; + let month = calendar + .ordinal_month_from_code(&year, validated, Default::default()) + .map_err(|e| match e { + MonthCodeError::NotInCalendar | MonthCodeError::NotInYear => { + DateError::UnknownMonthCode(month_code) + } + })?; + + let day = range_check(day, "day", 1..=C::days_in_provided_month(year, month))?; + + Ok(ArithmeticDate::new_unchecked(year, month, day)) } - #[inline] - pub fn days_in_year(&self) -> u16 { - C::days_in_provided_year(self.year) - } + pub(crate) fn from_fields( + fields: DateFields, + options: DateFromFieldsOptions, + calendar: &C, + ) -> Result { + let missing_fields_strategy = options.missing_fields_strategy.unwrap_or_default(); + + let day = match fields.day { + Some(day) => day, + None => match missing_fields_strategy { + MissingFieldsStrategy::Reject => return Err(DateFromFieldsError::NotEnoughFields), + MissingFieldsStrategy::Ecma => { + if fields.extended_year.is_some() || fields.era_year.is_some() { + // The ECMAScript strategy is to pick day 1, always, regardless of whether + // that day exists for the month/year combo + 1 + } else { + return Err(DateFromFieldsError::NotEnoughFields); + } + } + }, + }; - #[inline] - pub fn months_in_year(&self) -> u8 { - C::months_in_provided_year(self.year) - } + if fields.month_code.is_none() && fields.ordinal_month.is_none() { + // We're returning this error early so that we return structural type + // errors before range errors, see comment in the year code below. + return Err(DateFromFieldsError::NotEnoughFields); + } - #[inline] - pub fn days_in_month(&self) -> u8 { - C::days_in_provided_month(self.year, self.month) - } + let mut valid_month_code = None; + + // NOTE: The year/extendedyear range check is important to avoid arithmetic + // overflow in `year_info_from_era` and `year_info_from_extended`. It + // must happen before they are called. + // + // To better match the Temporal specification's order of operations, we try + // to return structural type errors (`NotEnoughFields`) before checking for range errors. + // This isn't behavior we *must* have, but it is not much additional work to maintain + // so we make an attempt. + let year = match (fields.era, fields.era_year) { + (None, None) => match fields.extended_year { + Some(extended_year) => calendar.year_info_from_extended(range_check( + extended_year, + "year", + VALID_YEAR_RANGE, + )?), + None => match missing_fields_strategy { + MissingFieldsStrategy::Reject => { + return Err(DateFromFieldsError::NotEnoughFields) + } + MissingFieldsStrategy::Ecma => { + match (fields.month_code, fields.ordinal_month) { + (Some(month_code), None) => { + let validated = ValidMonthCode::try_from_utf8(month_code)?; + valid_month_code = Some(validated); + calendar.reference_year_from_month_day(validated, day)? + } + _ => return Err(DateFromFieldsError::NotEnoughFields), + } + } + }, + }, + (Some(era), Some(era_year)) => { + let era_year_as_year_info = calendar + .year_info_from_era(era, range_check(era_year, "year", VALID_YEAR_RANGE)?)?; + if let Some(extended_year) = fields.extended_year { + if era_year_as_year_info + != calendar.year_info_from_extended(range_check( + extended_year, + "year", + VALID_YEAR_RANGE, + )?) + { + return Err(DateFromFieldsError::InconsistentYear); + } + } + era_year_as_year_info + } + // Era and Era Year must be both or neither + (Some(_), None) | (None, Some(_)) => return Err(DateFromFieldsError::NotEnoughFields), + }; - #[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; + let month = match fields.month_code { + Some(month_code) => { + let validated = match valid_month_code { + Some(validated) => validated, + None => ValidMonthCode::try_from_utf8(month_code)?, + }; + let computed_month = calendar.ordinal_month_from_code(&year, validated, options)?; + if let Some(ordinal_month) = fields.ordinal_month { + if computed_month != ordinal_month { + return Err(DateFromFieldsError::InconsistentMonth); + } + } + computed_month } - } + None => match fields.ordinal_month { + Some(month) => month, + None => { + debug_assert!(false, "Already checked above"); + return Err(DateFromFieldsError::NotEnoughFields); + } + }, + }; - 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, + let constrained_month = range_check_with_overflow( month, - day: day.try_into().unwrap_or(1), - marker: PhantomData, - } + "month", + 1..=C::months_in_provided_year(year), + options.overflow.unwrap_or_default(), + )?; + Ok(Self::new_unchecked( + year, + constrained_month, + range_check_with_overflow( + day, + "day", + 1..=C::days_in_provided_month(year, constrained_month), + options.overflow.unwrap_or_default(), + )?, + )) } - #[inline] - pub fn day_of_month(&self) -> types::DayOfMonth { - types::DayOfMonth(self.day) + pub(crate) fn try_from_ymd(year: C::YearInfo, month: u8, day: u8) -> Result { + range_check(month, "month", 1..=C::months_in_provided_year(year))?; + range_check(day, "day", 1..=C::days_in_provided_month(year, month))?; + Ok(ArithmeticDate::new_unchecked(year, month, 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; + /// Implements the Temporal abstract operation BalanceNonISODate. + /// + /// This takes a year, month, and day, where the month and day might be out of range, then + /// balances excess months into the year field and excess days into the month field. + pub(crate) fn new_balanced(year: C::YearInfo, ordinal_month: i64, day: i64, cal: &C) -> Self { + // 1. Let _resolvedYear_ be _arithmeticYear_. + // 1. Let _resolvedMonth_ be _ordinalMonth_. + let mut resolved_year = year; + let mut resolved_month = ordinal_month; + // 1. Let _monthsInYear_ be CalendarMonthsInYear(_calendar_, _resolvedYear_). + let mut months_in_year = C::months_in_provided_year(resolved_year); + // 1. Repeat, while _resolvedMonth_ ≤ 0, + // 1. Set _resolvedYear_ to _resolvedYear_ - 1. + // 1. Set _monthsInYear_ to CalendarMonthsInYear(_calendar_, _resolvedYear_). + // 1. Set _resolvedMonth_ to _resolvedMonth_ + _monthsInYear_. + while resolved_month <= 0 { + resolved_year = cal.year_info_from_extended(resolved_year.to_extended_year() - 1); + months_in_year = C::months_in_provided_year(resolved_year); + resolved_month += i64::from(months_in_year); } - DayOfYear(day_of_year + (self.day as u16)) - } - - pub fn extended_year(&self) -> i32 { - self.year.into() + // 1. Repeat, while _resolvedMonth_ > _monthsInYear_, + // 1. Set _resolvedMonth_ to _resolvedMonth_ - _monthsInYear_. + // 1. Set _resolvedYear_ to _resolvedYear_ + 1. + // 1. Set _monthsInYear_ to CalendarMonthsInYear(_calendar_, _resolvedYear_). + while resolved_month > i64::from(months_in_year) { + resolved_month -= i64::from(months_in_year); + resolved_year = cal.year_info_from_extended(resolved_year.to_extended_year() + 1); + months_in_year = C::months_in_provided_year(resolved_year); + } + debug_assert!(u8::try_from(resolved_month).is_ok()); + let mut resolved_month = resolved_month as u8; + // 1. Let _resolvedDay_ be _day_. + let mut resolved_day = day; + // 1. Let _daysInMonth_ be CalendarDaysInMonth(_calendar_, _resolvedYear_, _resolvedMonth_). + let mut days_in_month = C::days_in_provided_month(resolved_year, resolved_month); + // 1. Repeat, while _resolvedDay_ ≤ 0, + while resolved_day <= 0 { + // 1. Set _resolvedMonth_ to _resolvedMonth_ - 1. + // 1. If _resolvedMonth_ is 0, then + resolved_month -= 1; + if resolved_month == 0 { + // 1. Set _resolvedYear_ to _resolvedYear_ - 1. + // 1. Set _monthsInYear_ to CalendarMonthsInYear(_calendar_, _resolvedYear_). + // 1. Set _resolvedMonth_ to _monthsInYear_. + resolved_year = cal.year_info_from_extended(resolved_year.to_extended_year() - 1); + months_in_year = C::months_in_provided_year(resolved_year); + resolved_month = months_in_year; + } + // 1. Set _daysInMonth_ to CalendarDaysInMonth(_calendar_, _resolvedYear_, _resolvedMonth_). + // 1. Set _resolvedDay_ to _resolvedDay_ + _daysInMonth_. + days_in_month = C::days_in_provided_month(resolved_year, resolved_month); + resolved_day += i64::from(days_in_month); + } + // 1. Repeat, while _resolvedDay_ > _daysInMonth_, + while resolved_day > i64::from(days_in_month) { + // 1. Set _resolvedDay_ to _resolvedDay_ - _daysInMonth_. + // 1. Set _resolvedMonth_ to _resolvedMonth_ + 1. + // 1. If _resolvedMonth_ > _monthsInYear_, then + resolved_day -= i64::from(days_in_month); + resolved_month += 1; + if resolved_month > months_in_year { + // 1. Set _resolvedYear_ to _resolvedYear_ + 1. + // 1. Set _monthsInYear_ to CalendarMonthsInYear(_calendar_, _resolvedYear_). + // 1. Set _resolvedMonth_ to 1. + resolved_year = cal.year_info_from_extended(resolved_year.to_extended_year() + 1); + months_in_year = C::months_in_provided_year(resolved_year); + resolved_month = 1; + } + // 1. Set _daysInMonth_ to CalendarDaysInMonth(_calendar_, _resolvedYear_, _resolvedMonth_). + days_in_month = C::days_in_provided_month(resolved_year, resolved_month); + } + debug_assert!(u8::try_from(resolved_day).is_ok()); + let resolved_day = resolved_day as u8; + // 1. Return the Record { [[Year]]: _resolvedYear_, [[Month]]: _resolvedMonth_, [[Day]]: _resolvedDay_ }. + Self::new_unchecked(resolved_year, resolved_month, resolved_day) } - /// 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 + /// Implements the Temporal abstract operation NonISODateSurpasses. /// - /// 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"), + /// This takes two dates (`self` and `other`), `duration`, and `sign` (either -1 or 1), then + /// returns whether adding the duration to `self` results in a year/month/day that exceeds + /// `other` in the direction indicated by `sign`, constraining the month but not the day. + pub(crate) fn surpasses( + &self, + other: &Self, + duration: DateDuration, + sign: i64, + cal: &C, + ) -> bool { + // 1. Let _parts_ be CalendarISOToDate(_calendar_, _fromIsoDate_). + // 1. Let _y0_ be _parts_.[[Year]] + _years_. + let y0 = cal.year_info_from_extended(duration.add_years_to(self.year.to_extended_year())); + // 1. Let _m0_ be MonthCodeToOrdinal(_calendar_, _y0_, ! ConstrainMonthCode(_calendar_, _y0_, _parts_.[[MonthCode]], ~constrain~)). + let base_month_code = cal.month_code_from_ordinal(&self.year, self.month); + let constrain = DateFromFieldsOptions { + overflow: Some(Overflow::Constrain), + ..Default::default() + }; + let m0_result = cal.ordinal_month_from_code(&y0, base_month_code, constrain); + let m0 = match m0_result { + Ok(m0) => m0, + Err(_) => { + debug_assert!( + false, + "valid month code for calendar, and constrained to the year" + ); + 1 + } }; - types::MonthInfo { - ordinal: self.month, - standard_code: types::MonthCode(code), - formatting_code: types::MonthCode(code), + // 1. Let _endOfMonth_ be BalanceNonISODate(_calendar_, _y0_, _m0_ + _months_ + 1, 0). + let end_of_month = Self::new_balanced(y0, duration.add_months_to(m0) + 1, 0, cal); + // 1. Let _baseDay_ be _parts_.[[Day]]. + let base_day = self.day; + let y1; + let m1; + let d1; + // 1. If _weeks_ is not 0 or _days_ is not 0, then + if duration.weeks != 0 || duration.days != 0 { + // 1. If _baseDay_ < _endOfMonth_.[[Day]], then + // 1. Let _regulatedDay_ be _baseDay_. + // 1. Else, + // 1. Let _regulatedDay_ be _endOfMonth_.[[Day]]. + let regulated_day = if base_day < end_of_month.day { + base_day + } else { + end_of_month.day + }; + // 1. Let _balancedDate_ be BalanceNonISODate(_calendar_, _endOfMonth_.[[Year]], _endOfMonth_.[[Month]], _regulatedDay_ + 7 * _weeks_ + _days_). + // 1. Let _y1_ be _balancedDate_.[[Year]]. + // 1. Let _m1_ be _balancedDate_.[[Month]]. + // 1. Let _d1_ be _balancedDate_.[[Day]]. + let balanced_date = Self::new_balanced( + end_of_month.year, + i64::from(end_of_month.month), + duration.add_weeks_and_days_to(regulated_day), + cal, + ); + y1 = balanced_date.year; + m1 = balanced_date.month; + d1 = balanced_date.day; + } else { + // 1. Else, + // 1. Let _y1_ be _endOfMonth_.[[Year]]. + // 1. Let _m1_ be _endOfMonth_.[[Month]]. + // 1. Let _d1_ be _baseDay_. + y1 = end_of_month.year; + m1 = end_of_month.month; + d1 = base_day; } + // 1. Let _calDate2_ be CalendarISOToDate(_calendar_, _toIsoDate_). + // 1. If _y1_ ≠ _calDate2_.[[Year]], then + // 1. If _sign_ × (_y1_ - _calDate2_.[[Year]]) > 0, return *true*. + // 1. Else if _m1_ ≠ _calDate2_.[[Month]], then + // 1. If _sign_ × (_m1_ - _calDate2_.[[Month]]) > 0, return *true*. + // 1. Else if _d1_ ≠ _calDate2_.[[Day]], then + // 1. If _sign_ × (_d1_ - _calDate2_.[[Day]]) > 0, return *true*. + #[allow(clippy::collapsible_if)] // to align with the spec + if y1 != other.year { + if sign * (i64::from(y1.to_extended_year()) - i64::from(other.year.to_extended_year())) + > 0 + { + return true; + } + } else if m1 != other.month { + if sign * (i64::from(m1) - i64::from(other.month)) > 0 { + return true; + } + } else if d1 != other.day { + if sign * (i64::from(d1) - i64::from(other.day)) > 0 { + return true; + } + } + // 1. Return *false*. + false } - /// 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 + /// Implements the Temporal abstract operation NonISODateAdd. + /// + /// This takes a date (`self`) and `duration`, then returns a new date resulting from + /// adding `duration` to `self`, constrained according to `options`. + pub(crate) fn added( + &self, + duration: DateDuration, + cal: &C, + options: DateAddOptions, + ) -> Result { + // 1. Let _parts_ be CalendarISOToDate(_calendar_, _isoDate_). + // 1. Let _y0_ be _parts_.[[Year]] + _duration_.[[Years]]. + let y0 = cal.year_info_from_extended(duration.add_years_to(self.year.to_extended_year())); + // 1. Let _m0_ be MonthCodeToOrdinal(_calendar_, _y0_, ! ConstrainMonthCode(_calendar_, _y0_, _parts_.[[MonthCode]], _overflow_)). + let base_month = cal.month_code_from_ordinal(&self.year, self.month); + let m0 = cal + .ordinal_month_from_code( + &y0, + base_month, + DateFromFieldsOptions::from_add_options(options), + ) + .map_err(|e| { + // TODO: Use a narrower error type here. For now, convert into DateError. + match e { + MonthCodeError::NotInCalendar => { + DateError::UnknownMonthCode(base_month.to_month_code()) + } + MonthCodeError::NotInYear => { + DateError::UnknownMonthCode(base_month.to_month_code()) + } + } + })?; + // 1. Let _endOfMonth_ be BalanceNonISODate(_calendar_, _y0_, _m0_ + _duration_.[[Months]] + 1, 0). + let end_of_month = Self::new_balanced(y0, duration.add_months_to(m0) + 1, 0, cal); + // 1. Let _baseDay_ be _parts_.[[Day]]. + let base_day = self.day; + // 1. If _baseDay_ < _endOfMonth_.[[Day]], then + // 1. Let _regulatedDay_ be _baseDay_. + let regulated_day = if base_day < end_of_month.day { + base_day } else { - return Err(DateError::UnknownMonthCode(month_code)); + // 1. Else, + // 1. If _overflow_ is ~reject~, throw a *RangeError* exception. + // Note: ICU4X default is constrain here + if matches!(options.overflow, Some(Overflow::Reject)) { + return Err(DateError::Range { + field: "day", + value: i32::from(base_day), + min: 1, + max: i32::from(end_of_month.day), + }); + } + end_of_month.day }; + // 1. Let _balancedDate_ be BalanceNonISODate(_calendar_, _endOfMonth_.[[Year]], _endOfMonth_.[[Month]], _regulatedDay_ + 7 * _duration_.[[Weeks]] + _duration_.[[Days]]). + // 1. Let _result_ be ? CalendarIntegersToISO(_calendar_, _balancedDate_.[[Year]], _balancedDate_.[[Month]], _balancedDate_.[[Day]]). + // 1. Return _result_. + Ok(Self::new_balanced( + end_of_month.year, + i64::from(end_of_month.month), + duration.add_weeks_and_days_to(regulated_day), + cal, + )) + } - if month > C::months_in_provided_year(year) { - return Err(DateError::UnknownMonthCode(month_code)); + /// Implements the Temporal abstract operation NonISODateUntil. + /// + /// This takes a duration (`self`) and a date (`other`), then returns a duration that, when + /// added to `self`, results in `other`, with largest unit according to `options`. + pub(crate) fn until( + &self, + other: &Self, + cal: &C, + options: DateDifferenceOptions, + ) -> DateDuration { + // 1. Let _sign_ be -1 × CompareISODate(_one_, _two_). + // 1. If _sign_ = 0, return ZeroDateDuration(). + let sign = match other.cmp(self) { + Ordering::Greater => 1i64, + Ordering::Equal => return DateDuration::default(), + Ordering::Less => -1i64, + }; + // 1. Let _years_ be 0. + // 1. If _largestUnit_ is ~year~, then + // 1. Let _candidateYears_ be _sign_. + // 1. Repeat, while NonISODateSurpasses(_calendar_, _sign_, _one_, _two_, _candidateYears_, 0, 0, 0) is *false*, + // 1. Set _years_ to _candidateYears_. + // 1. Set _candidateYears_ to _candidateYears_ + _sign_. + let mut years = 0; + if matches!(options.largest_unit, Some(DateDurationUnit::Years)) { + let mut candidate_years = sign; + while !self.surpasses( + other, + DateDuration::from_signed_ymwd(candidate_years, 0, 0, 0), + sign, + cal, + ) { + years = candidate_years; + candidate_years += sign; + } } - - 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, - }); + // 1. Let _months_ be 0. + // 1. If _largestUnit_ is ~year~ or _largestUnit_ is ~month~, then + // 1. Let _candidateMonths_ be _sign_. + // 1. Repeat, while NonISODateSurpasses(_calendar_, _sign_, _one_, _two_, _years_, _candidateMonths_, 0, 0) is *false*, + // 1. Set _months_ to _candidateMonths_. + // 1. Set _candidateMonths_ to _candidateMonths_ + _sign_. + let mut months = 0; + if matches!( + options.largest_unit, + Some(DateDurationUnit::Years) | Some(DateDurationUnit::Months) + ) { + let mut candidate_months = sign; + while !self.surpasses( + other, + DateDuration::from_signed_ymwd(years, candidate_months, 0, 0), + sign, + cal, + ) { + months = candidate_months; + candidate_months += sign; + } } - - 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, - }); + // 1. Let _weeks_ be 0. + // 1. If _largestUnit_ is ~week~, then + // 1. Let _candidateWeeks_ be _sign_. + // 1. Repeat, while NonISODateSurpasses(_calendar_, _sign_, _one_, _two_, _years_, _months_, _candidateWeeks_, 0) is *false*, + // 1. Set _weeks_ to _candidateWeeks_. + // 1. Set _candidateWeeks_ to _candidateWeeks_ + sign. + let mut weeks = 0; + if matches!(options.largest_unit, Some(DateDurationUnit::Weeks)) { + let mut candidate_weeks = sign; + while !self.surpasses( + other, + DateDuration::from_signed_ymwd(years, months, candidate_weeks, 0), + sign, + cal, + ) { + weeks = candidate_weeks; + candidate_weeks += sign; + } } - 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, - }); + // 1. Let _days_ be 0. + // 1. Let _candidateDays_ be _sign_. + // 1. Repeat, while NonISODateSurpasses(_calendar_, _sign_, _one_, _two_, _years_, _months_, _weeks_, _candidateDays_) is *false*, + // 1. Set _days_ to _candidateDays_. + // 1. Set _candidateDays_ to _candidateDays_ + _sign_. + let mut days = 0; + let mut candidate_days = sign; + while !self.surpasses( + other, + DateDuration::from_signed_ymwd(years, months, weeks, candidate_days), + sign, + cal, + ) { + days = candidate_days; + candidate_days += sign; } - - Ok(Self::new_unchecked(year, month, day)) + // 1. Return ! CreateDateDurationRecord(_years_, _months_, _weeks_, _days_). + DateDuration::from_signed_ymwd(years, months, weeks, days) } } #[cfg(test)] mod tests { use super::*; - use crate::cal::Iso; + use crate::cal::{abstract_gregorian::AbstractGregorian, iso::IsoEra}; #[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), + 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() { diff --git a/deps/crates/vendor/icu_calendar/src/date.rs b/deps/crates/vendor/icu_calendar/src/date.rs index 5c4c0cf5d9fcab..5b65612c260b75 100644 --- a/deps/crates/vendor/icu_calendar/src/date.rs +++ b/deps/crates/vendor/icu_calendar/src/date.rs @@ -3,11 +3,12 @@ // (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::error::{DateError, DateFromFieldsError}; +use crate::options::DateFromFieldsOptions; +use crate::options::{DateAddOptions, DateDifferenceOptions}; use crate::types::{CyclicYear, EraYear, IsoWeekOfYear}; use crate::week::{RelativeUnit, WeekCalculator, WeekOf}; -use crate::{types, Calendar, DateDuration, DateDurationUnit, Iso}; +use crate::{types, Calendar, Iso}; #[cfg(feature = "alloc")] use alloc::rc::Rc; #[cfg(feature = "alloc")] @@ -36,6 +37,7 @@ impl AsCalendar for C { } #[cfg(feature = "alloc")] +/// ✨ *Enabled with the `alloc` Cargo feature.* impl AsCalendar for Rc { type Calendar = C::Calendar; #[inline] @@ -45,6 +47,7 @@ impl AsCalendar for Rc { } #[cfg(feature = "alloc")] +/// ✨ *Enabled with the `alloc` Cargo feature.* impl AsCalendar for Arc { type Calendar = C::Calendar; #[inline] @@ -119,7 +122,11 @@ pub struct Date { 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 + /// The year is `extended_year` if no era is provided. + /// + /// This function will not accept year/extended_year values that are outside of the range `[-2²⁷, 2²⁷]`, + /// regardless of the calendar, instead returning a [`DateError::Range`]. See [`Date::try_from_fields()`] for more + /// information. #[inline] pub fn try_new_from_codes( era: Option<&str>, @@ -134,6 +141,59 @@ impl Date { Ok(Date { inner, calendar }) } + /// Construct a date from from a bag of fields. + /// + /// This function allows specifying the year as either extended year or era + era year, + /// and the month as either ordinal or month code. It can constrain out-of-bounds values + /// and fill in missing fields. See [`DateFromFieldsOptions`] for more information. + /// + /// This function will not accept year/extended_year values that are outside of the range `[-2²⁷, 2²⁷]`, + /// regardless of the calendar, instead returning a [`DateFromFieldsError::Range`]. This allows us to to keep + /// all operations on [`Date`]s infallible by staying clear of integer limits. + /// Currently, calendar-specific `Date::try_new_calendarname()` constructors + /// do not do this, and it is possible to obtain such extreme dates via calendar conversion or arithmetic, + /// though [we may change that behavior in the future](https://github.com/unicode-org/icu4x/issues/7076). + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::cal::Gregorian; + /// use icu::calendar::types::DateFields; + /// use icu::calendar::Date; + /// + /// let mut fields = DateFields::default(); + /// fields.extended_year = Some(2000); + /// fields.ordinal_month = Some(1); + /// fields.day = Some(1); + /// + /// let d1 = Date::try_from_fields(fields, Default::default(), Gregorian) + /// .expect("Jan 1 in year 2000"); + /// + /// let d2 = Date::try_new_gregorian(2000, 1, 1).unwrap(); + /// assert_eq!(d1, d2); + /// ``` + /// + /// See [`DateFromFieldsError`] for examples of error conditions. + /// + ///
+ /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, + /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. + /// + /// Graduation tracking issue: [issue #7161](https://github.com/unicode-org/icu4x/issues/7161). + ///
+ /// + /// ✨ *Enabled with the `unstable` Cargo feature.* + #[cfg(feature = "unstable")] + #[inline] + pub fn try_from_fields( + fields: types::DateFields, + options: DateFromFieldsOptions, + calendar: A, + ) -> Result { + let inner = calendar.as_calendar().from_fields(fields, options)?; + 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 { @@ -152,20 +212,26 @@ impl Date
{ /// 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 } + iso.to_calendar(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) + self.to_calendar(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) + let c1 = self.calendar.as_calendar(); + let c2 = calendar.as_calendar(); + let inner = if c1.has_cheap_iso_conversion() && c2.has_cheap_iso_conversion() { + c2.from_iso(c1.to_iso(self.inner())) + } else { + c2.from_rata_die(c1.to_rata_die(self.inner())) + }; + Date { inner, calendar } } /// The number of months in the year of this date @@ -193,38 +259,95 @@ impl Date { } /// Add a `duration` to this date, mutating it - #[doc(hidden)] // unstable + /// + ///
+ /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, + /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. + /// + /// Graduation tracking issue: [issue #3964](https://github.com/unicode-org/icu4x/issues/3964). + ///
+ /// + /// ✨ *Enabled with the `unstable` Cargo feature.* + #[cfg(feature = "unstable")] #[inline] - pub fn add(&mut self, duration: DateDuration) { - self.calendar + pub fn try_add_with_options( + &mut self, + duration: types::DateDuration, + options: DateAddOptions, + ) -> Result<(), DateError> { + let inner = self + .calendar .as_calendar() - .offset_date(&mut self.inner, duration) + .add(&self.inner, duration, options)?; + self.inner = inner; + Ok(()) } /// Add a `duration` to this date, returning the new one - #[doc(hidden)] // unstable + /// + ///
+ /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, + /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. + /// + /// Graduation tracking issue: [issue #3964](https://github.com/unicode-org/icu4x/issues/3964). + ///
+ /// + /// ✨ *Enabled with the `unstable` Cargo feature.* + #[cfg(feature = "unstable")] #[inline] - pub fn added(mut self, duration: DateDuration) -> Self { - self.add(duration); - self + pub fn try_added_with_options( + mut self, + duration: types::DateDuration, + options: DateAddOptions, + ) -> Result { + self.try_add_with_options(duration, options)?; + Ok(self) } /// Calculating the duration between `other - self` - #[doc(hidden)] // unstable + /// + /// Although this returns a [`Result`], with most fixed calendars, this operation can't fail. + /// In such cases, the error type is [`Infallible`], and the inner value can be safely + /// unwrapped using [`Result::into_ok()`], which is available in nightly Rust as of this + /// writing. In stable Rust, the value can be unwrapped using [pattern matching]. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::types::DateDuration; + /// use icu::calendar::Date; + /// + /// let d1 = Date::try_new_iso(2020, 1, 1).unwrap(); + /// let d2 = Date::try_new_iso(2025, 10, 2).unwrap(); + /// let options = Default::default(); + /// + /// // The value can be unwrapped with destructuring syntax: + /// let Ok(duration) = d1.try_until_with_options(&d2, options); + /// + /// assert_eq!(duration, DateDuration::for_days(2101)); + /// ``` + /// + /// [`Infallible`]: core::convert::Infallible + /// [pattern matching]: https://doc.rust-lang.org/book/ch19-03-pattern-syntax.html + /// + ///
+ /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, + /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. + /// + /// Graduation tracking issue: [issue #3964](https://github.com/unicode-org/icu4x/issues/3964). + ///
+ /// + /// ✨ *Enabled with the `unstable` Cargo feature.* + #[cfg(feature = "unstable")] #[inline] - pub fn until>( + pub fn try_until_with_options>( &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, - ) + options: DateDifferenceOptions, + ) -> Result::DifferenceError> { + self.calendar + .as_calendar() + .until(self.inner(), other.inner(), options) } /// The calendar-specific year-info. @@ -236,13 +359,21 @@ impl Date
{ 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 + /// The "extended year". + /// + /// This year number can be used when you need a simple numeric representation + /// of the year, and can be meaningfully compared with extended years from other + /// eras or used in arithmetic. + /// + /// For calendars defined in Temporal, this will match the "arithmetic year" + /// as defined in . + /// This is 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) + self.year().extended_year() } /// Returns whether `self` is in a calendar-specific leap year @@ -339,7 +470,8 @@ impl Date { 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)), + 365 + calendrical_calculations::gregorian::is_leap_year(self.inner.0.year - 1) + as u16, self.days_in_year(), self.day_of_year().0, self.day_of_week(), @@ -357,8 +489,8 @@ impl Date { 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), + RelativeUnit::Next => self.inner.0.year + 1, + RelativeUnit::Previous => self.inner.0.year - 1, }, } } @@ -378,6 +510,8 @@ 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>` + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] pub fn into_ref_counted(self) -> Date> { Date::from_raw(self.inner, Rc::new(self.calendar)) @@ -386,6 +520,8 @@ impl Date { /// 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>` + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] pub fn into_atomic_ref_counted(self) -> Date> { Date::from_raw(self.inner, Arc::new(self.calendar)) @@ -395,7 +531,7 @@ impl Date { /// /// Useful for converting a `&Date` into an equivalent `Date` without cloning /// the calendar. - pub fn as_borrowed(&self) -> Date> { + pub fn as_borrowed(&self) -> Date> { Date::from_raw(self.inner, Ref(&self.calendar)) } } @@ -416,7 +552,6 @@ impl Eq for Date {} impl PartialOrd> for Date where C: Calendar, - C::DateInner: PartialOrd, A: AsCalendar, B: AsCalendar, { diff --git a/deps/crates/vendor/icu_calendar/src/duration.rs b/deps/crates/vendor/icu_calendar/src/duration.rs index b8f21743d1460a..d089dd0644ac99 100644 --- a/deps/crates/vendor/icu_calendar/src/duration.rs +++ b/deps/crates/vendor/icu_calendar/src/duration.rs @@ -2,18 +2,25 @@ // 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 +/// A signed length of time in terms of days, weeks, months, and years. +/// +/// This type represents the abstract concept of a date duration. For example, a duration of +/// "1 month" is represented as "1 month" in the data model, without any context of how many +/// days the month might be. +/// +/// Use [`DateDuration`] for calculating the difference between two [`Date`]s and adding +/// date units to a [`Date`]. /// -/// Can be used to perform date arithmetic +/// [`Date`]: crate::Date /// /// # Example /// /// ```rust -/// use icu::calendar::{types::Weekday, Date, DateDuration, DateDurationUnit}; +/// use icu::calendar::options::DateDifferenceOptions; +/// use icu::calendar::types::DateDuration; +/// use icu::calendar::types::DateDurationUnit; +/// use icu::calendar::types::Weekday; +/// use icu::calendar::Date; /// /// // Creating ISO date: 1992-09-02. /// let mut date_iso = Date::try_new_iso(1992, 9, 2) @@ -29,70 +36,116 @@ use core::marker::PhantomData; /// 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)); +/// date_iso +/// .try_add_with_options( +/// DateDuration { +/// is_negative: false, +/// years: 1, +/// months: 2, +/// weeks: 3, +/// days: 4, +/// }, +/// Default::default(), +/// ) +/// .unwrap(); /// 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)); +/// date_iso +/// .try_add_with_options( +/// DateDuration { +/// is_negative: true, +/// years: 1, +/// months: 2, +/// weeks: 3, +/// days: 4, +/// }, +/// Default::default(), +/// ) +/// .unwrap(); /// 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) +/// let newer_date_iso = Date::try_new_iso(2022, 10, 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, -/// ); +/// let mut options = DateDifferenceOptions::default(); +/// options.largest_unit = Some(DateDurationUnit::Years); +/// let Ok(duration) = +/// newer_date_iso.try_until_with_options(&date_iso, options); /// assert_eq!(duration.years, 30); -/// assert_eq!(duration.months, -8); +/// assert_eq!(duration.months, 1); /// 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)); +/// let mutated_date_iso = date_iso +/// .try_added_with_options( +/// DateDuration { +/// is_negative: false, +/// years: 1, +/// months: 2, +/// weeks: 3, +/// days: 4, +/// }, +/// Default::default(), +/// ) +/// .unwrap(); /// 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 { +/// +///
+/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, +/// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. +/// +/// Graduation tracking issue: [issue #3964](https://github.com/unicode-org/icu4x/issues/3964). +///
+/// +/// ✨ *Enabled with the `unstable` Cargo feature.* +#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)] +#[allow(clippy::exhaustive_structs)] // spec-defined in Temporal +pub struct DateDuration { + /// Whether the duration is negative. + /// + /// A negative duration is an abstract concept that could result, for example, from + /// taking the difference between two [`Date`](crate::Date)s. + /// + /// The fields of the duration are either all positive or all negative. Mixed signs + /// are not allowed. + /// + /// By convention, this field should be `false` if the duration is zero. + pub is_negative: bool, /// The number of years - pub years: i32, + pub years: u32, /// The number of months - pub months: i32, + pub months: u32, /// The number of weeks - pub weeks: i32, + pub weeks: u32, /// The number of days - pub days: i32, - /// A marker for the calendar - pub marker: PhantomData, + pub days: u64, } -// 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 +/// +///
+/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, +/// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. +/// +/// Graduation tracking issue: [issue #3964](https://github.com/unicode-org/icu4x/issues/3964). +///
+/// +/// ✨ *Enabled with the `unstable` Cargo feature.* #[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, @@ -104,55 +157,134 @@ pub enum DateDurationUnit { Days, } -impl Default for DateDuration { - fn default() -> Self { +impl DateDuration { + /// Returns a new [`DateDuration`] representing a number of years. + pub fn for_years(years: i32) -> Self { Self { - years: 0, - months: 0, - weeks: 0, - days: 0, - marker: PhantomData, + is_negative: years.is_negative(), + years: years.unsigned_abs(), + ..Default::default() } } -} -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, + /// Returns a new [`DateDuration`] representing a number of months. + pub fn for_months(months: i32) -> Self { + Self { + is_negative: months.is_negative(), + months: months.unsigned_abs(), + ..Default::default() } } - /// 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, + /// Returns a new [`DateDuration`] representing a number of weeks. + pub fn for_weeks(weeks: i32) -> Self { + Self { + is_negative: weeks.is_negative(), + weeks: weeks.unsigned_abs(), + ..Default::default() + } + } + + /// Returns a new [`DateDuration`] representing a number of days. + pub fn for_days(days: i64) -> Self { + Self { + is_negative: days.is_negative(), + days: days.unsigned_abs(), + ..Default::default() + } + } + + /// Do NOT pass this function values of mixed signs! + pub(crate) fn from_signed_ymwd(years: i64, months: i64, weeks: i64, days: i64) -> Self { + let is_negative = years.is_negative() + || months.is_negative() + || weeks.is_negative() + || days.is_negative(); + if is_negative + && (years.is_positive() + || months.is_positive() + || weeks.is_positive() + || days.is_positive()) + { + debug_assert!(false, "mixed signs in from_signed_ymd"); + } + Self { + is_negative, + years: match u32::try_from(years.unsigned_abs()) { + Ok(x) => x, + Err(_) => { + debug_assert!(false, "years out of range"); + u32::MAX + } + }, + months: match u32::try_from(months.unsigned_abs()) { + Ok(x) => x, + Err(_) => { + debug_assert!(false, "months out of range"); + u32::MAX + } + }, + weeks: match u32::try_from(weeks.unsigned_abs()) { + Ok(x) => x, + Err(_) => { + debug_assert!(false, "weeks out of range"); + u32::MAX + } + }, + days: days.unsigned_abs(), + } + } + + #[inline] + pub(crate) fn add_years_to(&self, year: i32) -> i32 { + if !self.is_negative { + match year.checked_add_unsigned(self.years) { + Some(x) => x, + None => { + debug_assert!(false, "{year} + {self:?} out of year range"); + i32::MAX + } + } + } else { + match year.checked_sub_unsigned(self.years) { + Some(x) => x, + None => { + debug_assert!(false, "{year} - {self:?} out of year range"); + i32::MIN + } + } } } -} -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() + #[inline] + pub(crate) fn add_months_to(&self, month: u8) -> i64 { + if !self.is_negative { + i64::from(month) + i64::from(self.months) + } else { + i64::from(month) - i64::from(self.months) + } + } + + #[inline] + pub(crate) fn add_weeks_and_days_to(&self, day: u8) -> i64 { + if !self.is_negative { + let day = i64::from(day) + i64::from(self.weeks) * 7; + match day.checked_add_unsigned(self.days) { + Some(x) => x, + None => { + debug_assert!(false, "{day} + {self:?} out of day range"); + i64::MAX + } + } + } else { + let day = i64::from(day) - i64::from(self.weeks) * 7; + match day.checked_sub_unsigned(self.days) { + Some(x) => x, + None => { + debug_assert!(false, "{day} - {self:?} out of day range"); + i64::MIN + } + } + } } } diff --git a/deps/crates/vendor/icu_calendar/src/error.rs b/deps/crates/vendor/icu_calendar/src/error.rs index 2e050a93a3f04a..437700befb830f 100644 --- a/deps/crates/vendor/icu_calendar/src/error.rs +++ b/deps/crates/vendor/icu_calendar/src/error.rs @@ -2,11 +2,15 @@ // 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; +//! Error types for functions in the calendar crate + +use crate::{options::Overflow, types::MonthCode}; use displaydoc::Display; #[derive(Debug, Copy, Clone, PartialEq, Display)] -/// Error type for date creation. +/// Error type for date creation via [`Date::try_new_from_codes`]. +/// +/// [`Date::try_new_from_codes`]: crate::Date::try_new_from_codes #[non_exhaustive] pub enum DateError { /// A field is out of range for its domain. @@ -21,15 +25,351 @@ pub enum DateError { /// The maximum value (inclusive). This might not be tight. max: i32, }, - /// Unknown era + /// The era code is invalid for the calendar. #[displaydoc("Unknown era")] UnknownEra, - /// Unknown month code + /// The month code is invalid for the calendar or year. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::cal::Hebrew; + /// use icu::calendar::types::MonthCode; + /// use icu::calendar::Date; + /// use icu::calendar::DateError; + /// use tinystr::tinystr; + /// + /// Date::try_new_from_codes( + /// None, + /// 5784, + /// MonthCode::new_leap(5).unwrap(), + /// 1, + /// Hebrew, + /// ) + /// .expect("5784 is a leap year"); + /// + /// let err = Date::try_new_from_codes( + /// None, + /// 5785, + /// MonthCode::new_leap(5).unwrap(), + /// 1, + /// Hebrew, + /// ) + /// .expect_err("5785 is a common year"); + /// + /// assert!(matches!(err, DateError::UnknownMonthCode(_))); + /// ``` #[displaydoc("Unknown month code {0:?}")] UnknownMonthCode(MonthCode), } impl core::error::Error for DateError {} +#[cfg(feature = "unstable")] +pub use unstable::DateFromFieldsError; +#[cfg(not(feature = "unstable"))] +pub(crate) use unstable::DateFromFieldsError; + +mod unstable { + pub use super::*; + /// Error type for date creation via [`Date::try_from_fields`]. + /// + /// [`Date::try_from_fields`]: crate::Date::try_from_fields + /// + ///
+ /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, + /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. + /// + /// Graduation tracking issue: [issue #7161](https://github.com/unicode-org/icu4x/issues/7161). + ///
+ /// + /// ✨ *Enabled with the `unstable` Cargo feature.* + #[derive(Debug, Copy, Clone, PartialEq, Display)] + #[non_exhaustive] + pub enum DateFromFieldsError { + /// A field is out of range for its domain. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::error::DateFromFieldsError; + /// use icu::calendar::error::RangeError; + /// use icu::calendar::types::DateFields; + /// use icu::calendar::Date; + /// use icu::calendar::Iso; + /// + /// let mut fields = DateFields::default(); + /// fields.extended_year = Some(2000); + /// fields.ordinal_month = Some(13); + /// fields.day = Some(1); + /// + /// let err = Date::try_from_fields(fields, Default::default(), Iso) + /// .expect_err("no month 13 in the ISO calendar"); + /// + /// assert!(matches!( + /// err, + /// DateFromFieldsError::Range(RangeError { field: "month", .. }) + /// )); + /// ``` + #[displaydoc("{0}")] + Range(RangeError), + /// The era code is invalid for the calendar. + #[displaydoc("Unknown era or invalid syntax")] + UnknownEra, + /// The month code syntax is invalid. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::error::DateFromFieldsError; + /// use icu::calendar::types::DateFields; + /// use icu::calendar::Date; + /// use icu::calendar::Iso; + /// + /// let mut fields = DateFields::default(); + /// fields.extended_year = Some(2000); + /// fields.month_code = Some(b"????"); + /// fields.day = Some(1); + /// + /// let err = Date::try_from_fields(fields, Default::default(), Iso) + /// .expect_err("month code is invalid"); + /// + /// assert_eq!(err, DateFromFieldsError::MonthCodeInvalidSyntax); + /// ``` + #[displaydoc("Invalid month code syntax")] + MonthCodeInvalidSyntax, + /// The specified month code does not exist in this calendar. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::cal::Hebrew; + /// use icu::calendar::error::DateFromFieldsError; + /// use icu::calendar::types::DateFields; + /// use icu::calendar::Date; + /// + /// let mut fields = DateFields::default(); + /// fields.extended_year = Some(5783); + /// fields.month_code = Some(b"M13"); + /// fields.day = Some(1); + /// + /// let err = Date::try_from_fields(fields, Default::default(), Hebrew) + /// .expect_err("no month M13 in Hebrew"); + /// assert_eq!(err, DateFromFieldsError::MonthCodeNotInCalendar); + /// ``` + #[displaydoc("The specified month code does not exist in this calendar")] + MonthCodeNotInCalendar, + /// The specified month code exists in this calendar, but not in the specified year. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::cal::Hebrew; + /// use icu::calendar::error::DateFromFieldsError; + /// use icu::calendar::types::DateFields; + /// use icu::calendar::Date; + /// + /// let mut fields = DateFields::default(); + /// fields.extended_year = Some(5783); + /// fields.month_code = Some(b"M05L"); + /// fields.day = Some(1); + /// + /// let err = Date::try_from_fields(fields, Default::default(), Hebrew) + /// .expect_err("no month M05L in Hebrew year 5783"); + /// assert_eq!(err, DateFromFieldsError::MonthCodeNotInYear); + /// ``` + #[displaydoc("The specified month code exists in calendar, but not for this year")] + MonthCodeNotInYear, + /// The year was specified in multiple inconsistent ways. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::cal::Japanese; + /// use icu::calendar::error::DateFromFieldsError; + /// use icu::calendar::types::DateFields; + /// use icu::calendar::Date; + /// + /// let mut fields = DateFields::default(); + /// fields.era = Some(b"reiwa"); + /// fields.era_year = Some(6); + /// fields.ordinal_month = Some(1); + /// fields.day = Some(1); + /// + /// Date::try_from_fields(fields, Default::default(), Japanese::new()) + /// .expect("a well-defined Japanese date"); + /// + /// fields.extended_year = Some(1900); + /// + /// let err = + /// Date::try_from_fields(fields, Default::default(), Japanese::new()) + /// .expect_err("year 1900 is not the same as 6 Reiwa"); + /// + /// assert_eq!(err, DateFromFieldsError::InconsistentYear); + /// ``` + #[displaydoc("Inconsistent year")] + InconsistentYear, + /// The month was specified in multiple inconsistent ways. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::cal::Hebrew; + /// use icu::calendar::error::DateFromFieldsError; + /// use icu::calendar::types::DateFields; + /// use icu::calendar::Date; + /// use tinystr::tinystr; + /// + /// let mut fields = DateFields::default(); + /// fields.extended_year = Some(5783); + /// fields.month_code = Some(b"M06"); + /// fields.ordinal_month = Some(6); + /// fields.day = Some(1); + /// + /// Date::try_from_fields(fields, Default::default(), Hebrew) + /// .expect("a well-defined Hebrew date in a common year"); + /// + /// fields.extended_year = Some(5784); + /// + /// let err = Date::try_from_fields(fields, Default::default(), Hebrew) + /// .expect_err("month M06 is not the 6th month in leap year 5784"); + /// + /// assert_eq!(err, DateFromFieldsError::InconsistentMonth); + /// ``` + #[displaydoc("Inconsistent month")] + InconsistentMonth, + /// Not enough fields were specified to form a well-defined date. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::cal::Hebrew; + /// use icu::calendar::error::DateFromFieldsError; + /// use icu::calendar::types::DateFields; + /// use icu::calendar::Date; + /// use tinystr::tinystr; + /// + /// let mut fields = DateFields::default(); + /// + /// fields.ordinal_month = Some(3); + /// + /// let err = Date::try_from_fields(fields, Default::default(), Hebrew) + /// .expect_err("need more than just an ordinal month"); + /// assert_eq!(err, DateFromFieldsError::NotEnoughFields); + /// + /// fields.era_year = Some(5783); + /// + /// let err = Date::try_from_fields(fields, Default::default(), Hebrew) + /// .expect_err("need more than an ordinal month and an era year"); + /// assert_eq!(err, DateFromFieldsError::NotEnoughFields); + /// + /// fields.extended_year = Some(5783); + /// + /// let err = Date::try_from_fields(fields, Default::default(), Hebrew) + /// .expect_err("era year still needs an era"); + /// assert_eq!(err, DateFromFieldsError::NotEnoughFields); + /// + /// fields.era = Some(b"am"); + /// + /// let date = Date::try_from_fields(fields, Default::default(), Hebrew) + /// .expect_err("still missing the day"); + /// assert_eq!(err, DateFromFieldsError::NotEnoughFields); + /// + /// fields.day = Some(1); + /// let date = Date::try_from_fields(fields, Default::default(), Hebrew) + /// .expect("we have enough fields!"); + /// ``` + #[displaydoc("Not enough fields")] + NotEnoughFields, + } + + impl core::error::Error for DateFromFieldsError {} + + impl From for DateFromFieldsError { + #[inline] + fn from(value: RangeError) -> Self { + DateFromFieldsError::Range(value) + } + } +} + +/// Internal narrow error type for functions that only fail on unknown eras +pub(crate) struct UnknownEraError; + +impl From for DateError { + #[inline] + fn from(_value: UnknownEraError) -> Self { + DateError::UnknownEra + } +} + +impl From for DateFromFieldsError { + #[inline] + fn from(_value: UnknownEraError) -> Self { + DateFromFieldsError::UnknownEra + } +} + +/// Internal narrow error type for functions that only fail on parsing month codes +#[derive(Debug)] +pub(crate) enum MonthCodeParseError { + InvalidSyntax, +} + +impl From for DateFromFieldsError { + #[inline] + fn from(value: MonthCodeParseError) -> Self { + match value { + MonthCodeParseError::InvalidSyntax => DateFromFieldsError::MonthCodeInvalidSyntax, + } + } +} + +/// Internal narrow error type for functions that only fail on month code operations +#[derive(Debug, PartialEq)] +pub(crate) enum MonthCodeError { + NotInCalendar, + NotInYear, +} + +impl From for DateFromFieldsError { + #[inline] + fn from(value: MonthCodeError) -> Self { + match value { + MonthCodeError::NotInCalendar => DateFromFieldsError::MonthCodeNotInCalendar, + MonthCodeError::NotInYear => DateFromFieldsError::MonthCodeNotInYear, + } + } +} + +mod inner { + /// Internal narrow error type for calculating the ECMA reference year + /// + /// Public but unstable because it is used on hijri::Rules + #[derive(Debug, Copy, Clone, PartialEq, Eq)] + #[allow(missing_docs)] // TODO: fix when graduating + #[non_exhaustive] + pub enum EcmaReferenceYearError { + Unimplemented, + MonthCodeNotInCalendar, + } +} + +#[cfg(feature = "unstable")] +pub use inner::EcmaReferenceYearError; +#[cfg(not(feature = "unstable"))] +pub(crate) use inner::EcmaReferenceYearError; + +impl From for DateFromFieldsError { + #[inline] + fn from(value: EcmaReferenceYearError) -> Self { + match value { + EcmaReferenceYearError::Unimplemented => DateFromFieldsError::NotEnoughFields, + EcmaReferenceYearError::MonthCodeNotInCalendar => { + DateFromFieldsError::MonthCodeNotInCalendar + } + } + } +} #[derive(Debug, Copy, Clone, PartialEq, Display)] /// An argument is out of range for its domain. @@ -49,6 +389,7 @@ pub struct RangeError { impl core::error::Error for RangeError {} impl From for DateError { + #[inline] fn from(value: RangeError) -> Self { let RangeError { field, @@ -65,28 +406,31 @@ impl From for DateError { } } -pub(crate) fn year_check( - year: i32, - bounds: impl core::ops::RangeBounds, -) -> Result { - use core::ops::Bound::*; +pub(crate) fn range_check_with_overflow + Copy>( + value: T, + field: &'static str, + bounds: core::ops::RangeInclusive, + overflow: Overflow, +) -> Result { + if matches!(overflow, Overflow::Constrain) { + Ok(value.clamp(*bounds.start(), *bounds.end())) + } else { + range_check(value, field, bounds) + } +} - if !bounds.contains(&year) { +pub(crate) fn range_check + Copy>( + value: T, + field: &'static str, + bounds: core::ops::RangeInclusive, +) -> Result { + if !bounds.contains(&value) { 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, - }, + field, + value: value.into(), + min: (*bounds.start()).into(), + max: (*bounds.end()).into(), }); } - - Ok(year) + Ok(value) } diff --git a/deps/crates/vendor/icu_calendar/src/ixdtf.rs b/deps/crates/vendor/icu_calendar/src/ixdtf.rs index 0256dcd6c40eb6..1fe60d9720b68e 100644 --- a/deps/crates/vendor/icu_calendar/src/ixdtf.rs +++ b/deps/crates/vendor/icu_calendar/src/ixdtf.rs @@ -6,11 +6,12 @@ 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::encoding::Utf8; use ixdtf::parsers::IxdtfParser; +use ixdtf::records::IxdtfParseRecord; use ixdtf::ParseError as Rfc9557Error; -/// An error returned from parsing an RFC 9557 string to an `icu_calendar` type. +/// An error returned from parsing an RFC 9557 string to an `icu::calendar` type. #[derive(Debug, displaydoc::Display)] #[non_exhaustive] pub enum ParseError { @@ -68,10 +69,7 @@ impl Date
{ /// 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.month().standard_code.0, "M07"); /// assert_eq!(date.day_of_month().0, 17); /// ``` pub fn try_from_str(rfc_9557_str: &str, calendar: A) -> Result { @@ -93,7 +91,7 @@ impl Date { #[doc(hidden)] pub fn try_from_ixdtf_record( - ixdtf_record: &IxdtfParseRecord, + ixdtf_record: &IxdtfParseRecord<'_, Utf8>, calendar: A, ) -> Result { let date_record = ixdtf_record.date.ok_or(ParseError::MissingFields)?; diff --git a/deps/crates/vendor/icu_calendar/src/lib.rs b/deps/crates/vendor/icu_calendar/src/lib.rs index 77d5a4b46aeadf..ca8c9923881996 100644 --- a/deps/crates/vendor/icu_calendar/src/lib.rs +++ b/deps/crates/vendor/icu_calendar/src/lib.rs @@ -88,6 +88,9 @@ ) )] #![warn(missing_docs)] +// It's not worth it to try and maintain clean import lists for both +// stable and unstable mode when the code is so entangled. +#![cfg_attr(not(feature = "unstable"), allow(unused))] #[cfg(feature = "alloc")] extern crate alloc; @@ -98,6 +101,7 @@ mod date; // Public modules mod any_calendar; pub mod cal; +pub mod options; pub mod provider; pub mod types; pub mod week; @@ -105,7 +109,7 @@ pub mod week; mod calendar; mod calendar_arithmetic; mod duration; -mod error; +pub mod error; #[cfg(feature = "ixdtf")] mod ixdtf; @@ -113,8 +117,6 @@ mod ixdtf; 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; diff --git a/deps/crates/vendor/icu_calendar/src/options.rs b/deps/crates/vendor/icu_calendar/src/options.rs new file mode 100644 index 00000000000000..37eba042536a54 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/options.rs @@ -0,0 +1,559 @@ +// 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 ). + +//! Options used by types in this crate + +#[cfg(feature = "unstable")] +pub use unstable::{ + DateAddOptions, DateDifferenceOptions, DateFromFieldsOptions, MissingFieldsStrategy, Overflow, +}; +#[cfg(not(feature = "unstable"))] +pub(crate) use unstable::{ + DateAddOptions, DateDifferenceOptions, DateFromFieldsOptions, MissingFieldsStrategy, Overflow, +}; + +mod unstable { + /// Options bag for [`Date::try_from_fields`](crate::Date::try_from_fields). + /// + ///
+ /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, + /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. + /// + /// Graduation tracking issue: [issue #7161](https://github.com/unicode-org/icu4x/issues/7161). + ///
+ /// + /// ✨ *Enabled with the `unstable` Cargo feature.* + #[derive(Copy, Clone, Debug, PartialEq, Default)] + #[non_exhaustive] + pub struct DateFromFieldsOptions { + /// How to behave with out-of-bounds fields. + /// + /// Defaults to [`Overflow::Reject`]. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::options::DateFromFieldsOptions; + /// use icu::calendar::options::Overflow; + /// use icu::calendar::types::DateFields; + /// use icu::calendar::Date; + /// use icu::calendar::Iso; + /// + /// // There is no day 31 in September. + /// let mut fields = DateFields::default(); + /// fields.extended_year = Some(2025); + /// fields.ordinal_month = Some(9); + /// fields.day = Some(31); + /// + /// let options_default = DateFromFieldsOptions::default(); + /// assert!(Date::try_from_fields(fields, options_default, Iso).is_err()); + /// + /// let mut options_reject = options_default; + /// options_reject.overflow = Some(Overflow::Reject); + /// assert!(Date::try_from_fields(fields, options_reject, Iso).is_err()); + /// + /// let mut options_constrain = options_default; + /// options_constrain.overflow = Some(Overflow::Constrain); + /// assert_eq!( + /// Date::try_from_fields(fields, options_constrain, Iso).unwrap(), + /// Date::try_new_iso(2025, 9, 30).unwrap() + /// ); + /// ``` + pub overflow: Option, + /// How to behave when the fields that are present do not fully constitute a Date. + /// + /// This option can be used to fill in a missing year given a month and a day according to + /// the ECMAScript Temporal specification. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::options::DateFromFieldsOptions; + /// use icu::calendar::options::MissingFieldsStrategy; + /// use icu::calendar::types::DateFields; + /// use icu::calendar::Date; + /// use icu::calendar::Iso; + /// + /// // These options are missing a year. + /// let mut fields = DateFields::default(); + /// fields.month_code = Some(b"M02"); + /// fields.day = Some(1); + /// + /// let options_default = DateFromFieldsOptions::default(); + /// assert!(Date::try_from_fields(fields, options_default, Iso).is_err()); + /// + /// let mut options_reject = options_default; + /// options_reject.missing_fields_strategy = + /// Some(MissingFieldsStrategy::Reject); + /// assert!(Date::try_from_fields(fields, options_reject, Iso).is_err()); + /// + /// let mut options_ecma = options_default; + /// options_ecma.missing_fields_strategy = Some(MissingFieldsStrategy::Ecma); + /// assert_eq!( + /// Date::try_from_fields(fields, options_ecma, Iso).unwrap(), + /// Date::try_new_iso(1972, 2, 1).unwrap() + /// ); + /// ``` + pub missing_fields_strategy: Option, + } + + impl DateFromFieldsOptions { + pub(crate) fn from_add_options(options: DateAddOptions) -> Self { + Self { + overflow: options.overflow, + missing_fields_strategy: Default::default(), + } + } + } + + /// Options for adding a duration to a date. + /// + ///
+ /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, + /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. + /// + /// Graduation tracking issue: [issue #3964](https://github.com/unicode-org/icu4x/issues/3964). + ///
+ /// + /// ✨ *Enabled with the `unstable` Cargo feature.* + #[derive(Copy, Clone, PartialEq, Debug, Default)] + #[non_exhaustive] + pub struct DateAddOptions { + /// How to behave with out-of-bounds fields during arithmetic. + /// + /// Defaults to [`Overflow::Constrain`]. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::options::DateAddOptions; + /// use icu::calendar::options::Overflow; + /// use icu::calendar::types::DateDuration; + /// use icu::calendar::Date; + /// + /// // There is a day 31 in October but not in November. + /// let d1 = Date::try_new_iso(2025, 10, 31).unwrap(); + /// let duration = DateDuration::for_months(1); + /// + /// let options_default = DateAddOptions::default(); + /// assert_eq!( + /// d1.try_added_with_options(duration, options_default) + /// .unwrap(), + /// Date::try_new_iso(2025, 11, 30).unwrap() + /// ); + /// + /// let mut options_reject = options_default; + /// options_reject.overflow = Some(Overflow::Reject); + /// assert!(d1.try_added_with_options(duration, options_reject).is_err()); + /// + /// let mut options_constrain = options_default; + /// options_constrain.overflow = Some(Overflow::Constrain); + /// assert_eq!( + /// d1.try_added_with_options(duration, options_constrain) + /// .unwrap(), + /// Date::try_new_iso(2025, 11, 30).unwrap() + /// ); + /// ``` + pub overflow: Option, + } + + /// Options for taking the difference between two dates. + /// + ///
+ /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, + /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. + /// + /// Graduation tracking issue: [issue #3964](https://github.com/unicode-org/icu4x/issues/3964). + ///
+ /// + /// ✨ *Enabled with the `unstable` Cargo feature.* + #[derive(Copy, Clone, PartialEq, Debug, Default)] + #[non_exhaustive] + pub struct DateDifferenceOptions { + /// Which date field to allow as the largest in a duration when taking the difference. + /// + /// When choosing [`Months`] or [`Years`], the resulting [`DateDuration`] might not be + /// associative or commutative in subsequent arithmetic operations, and it might require + /// [`Overflow::Constrain`] in addition. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::options::DateDifferenceOptions; + /// use icu::calendar::types::DateDuration; + /// use icu::calendar::types::DateDurationUnit; + /// use icu::calendar::Date; + /// + /// let d1 = Date::try_new_iso(2025, 3, 31).unwrap(); + /// let d2 = Date::try_new_iso(2026, 5, 15).unwrap(); + /// + /// let options_default = DateDifferenceOptions::default(); + /// assert_eq!( + /// d1.try_until_with_options(&d2, options_default).unwrap(), + /// DateDuration::for_days(410) + /// ); + /// + /// let mut options_days = options_default; + /// options_days.largest_unit = Some(DateDurationUnit::Days); + /// assert_eq!( + /// d1.try_until_with_options(&d2, options_default).unwrap(), + /// DateDuration::for_days(410) + /// ); + /// + /// let mut options_weeks = options_default; + /// options_weeks.largest_unit = Some(DateDurationUnit::Weeks); + /// assert_eq!( + /// d1.try_until_with_options(&d2, options_weeks).unwrap(), + /// DateDuration { + /// weeks: 58, + /// days: 4, + /// ..Default::default() + /// } + /// ); + /// + /// let mut options_months = options_default; + /// options_months.largest_unit = Some(DateDurationUnit::Months); + /// assert_eq!( + /// d1.try_until_with_options(&d2, options_months).unwrap(), + /// DateDuration { + /// months: 13, + /// days: 15, + /// ..Default::default() + /// } + /// ); + /// + /// let mut options_years = options_default; + /// options_years.largest_unit = Some(DateDurationUnit::Years); + /// assert_eq!( + /// d1.try_until_with_options(&d2, options_years).unwrap(), + /// DateDuration { + /// years: 1, + /// months: 1, + /// days: 15, + /// ..Default::default() + /// } + /// ); + /// ``` + /// + /// [`Months`]: crate::types::DateDurationUnit::Months + /// [`Years`]: crate::types::DateDurationUnit::Years + /// [`DateDuration`]: crate::types::DateDuration + pub largest_unit: Option, + } + + /// Whether to constrain or reject out-of-bounds values when constructing a Date. + /// + /// The behavior conforms to the ECMAScript Temporal specification. + /// + ///
+ /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, + /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. + /// + /// Graduation tracking issue: [issue #7161](https://github.com/unicode-org/icu4x/issues/7161). + ///
+ /// + /// ✨ *Enabled with the `unstable` Cargo feature.* + #[derive(Copy, Clone, Debug, PartialEq, Default)] + #[non_exhaustive] + pub enum Overflow { + /// Constrain out-of-bounds fields to the nearest in-bounds value. + /// + /// Only the out-of-bounds field is constrained. If the other fields are not themselves + /// out of bounds, they are not changed. + /// + /// This is the [default option]( + /// https://tc39.es/proposal-temporal/#sec-temporal-gettemporaloverflowoption), + /// following the ECMAScript Temporal specification. See also the [docs on MDN]( + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/PlainDate#invalid_date_clamping). + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::cal::Hebrew; + /// use icu::calendar::options::DateFromFieldsOptions; + /// use icu::calendar::options::Overflow; + /// use icu::calendar::types::DateFields; + /// use icu::calendar::Date; + /// use icu::calendar::DateError; + /// + /// let mut options = DateFromFieldsOptions::default(); + /// options.overflow = Some(Overflow::Constrain); + /// + /// // 5784, a leap year, contains M05L, but the day is too big. + /// let mut fields = DateFields::default(); + /// fields.extended_year = Some(5784); + /// fields.month_code = Some(b"M05L"); + /// fields.day = Some(50); + /// + /// let date = Date::try_from_fields(fields, options, Hebrew).unwrap(); + /// + /// // Constrained to the 30th day of M05L of year 5784 + /// assert_eq!(date.year().extended_year(), 5784); + /// assert_eq!(date.month().standard_code.0, "M05L"); + /// assert_eq!(date.day_of_month().0, 30); + /// + /// // 5785, a common year, does not contain M05L. + /// fields.extended_year = Some(5785); + /// + /// let date = Date::try_from_fields(fields, options, Hebrew).unwrap(); + /// + /// // Constrained to the 29th day of M06 of year 5785 + /// assert_eq!(date.year().extended_year(), 5785); + /// assert_eq!(date.month().standard_code.0, "M06"); + /// assert_eq!(date.day_of_month().0, 29); + /// ``` + Constrain, + /// Return an error if any fields are out of bounds. + /// + /// # Examples + /// + /// ``` + /// use icu::calendar::cal::Hebrew; + /// use icu::calendar::error::DateFromFieldsError; + /// use icu::calendar::options::DateFromFieldsOptions; + /// use icu::calendar::options::Overflow; + /// use icu::calendar::types::DateFields; + /// use icu::calendar::Date; + /// use tinystr::tinystr; + /// + /// let mut options = DateFromFieldsOptions::default(); + /// options.overflow = Some(Overflow::Reject); + /// + /// // 5784, a leap year, contains M05L, but the day is too big. + /// let mut fields = DateFields::default(); + /// fields.extended_year = Some(5784); + /// fields.month_code = Some(b"M05L"); + /// fields.day = Some(50); + /// + /// let err = Date::try_from_fields(fields, options, Hebrew) + /// .expect_err("Day is out of bounds"); + /// assert!(matches!(err, DateFromFieldsError::Range { .. })); + /// + /// // Set the day to one that exists + /// fields.day = Some(1); + /// Date::try_from_fields(fields, options, Hebrew) + /// .expect("A valid Hebrew date"); + /// + /// // 5785, a common year, does not contain M05L. + /// fields.extended_year = Some(5785); + /// + /// let err = Date::try_from_fields(fields, options, Hebrew) + /// .expect_err("Month is out of bounds"); + /// assert!(matches!(err, DateFromFieldsError::MonthCodeNotInYear)); + /// ``` + #[default] + Reject, + } + + /// How to infer missing fields when the fields that are present do not fully constitute a Date. + /// + /// In order for the fields to fully constitute a Date, they must identify a year, a month, + /// and a day. The fields `era`, `era_year`, and `extended_year` identify the year: + /// + /// | Era? | Era Year? | Extended Year? | Outcome | + /// |------|-----------|----------------|---------| + /// | - | - | - | Error | + /// | Some | - | - | Error | + /// | - | Some | - | Error | + /// | - | - | Some | OK | + /// | Some | Some | - | OK | + /// | Some | - | Some | Error (era requires era year) | + /// | - | Some | Some | Error (era year requires era) | + /// | Some | Some | Some | OK (but error if inconsistent) | + /// + /// The fields `month_code` and `ordinal_month` identify the month: + /// + /// | Month Code? | Ordinal Month? | Outcome | + /// |-------------|----------------|---------| + /// | - | - | Error | + /// | Some | - | OK | + /// | - | Some | OK | + /// | Some | Some | OK (but error if inconsistent) | + /// + /// The field `day` identifies the day. + /// + /// If the fields identify a year, a month, and a day, then there are no missing fields, so + /// the strategy chosen here has no effect (fields that are out-of-bounds or inconsistent + /// are handled by other errors). + /// + ///
+ /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, + /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. + /// + /// Graduation tracking issue: [issue #7161](https://github.com/unicode-org/icu4x/issues/7161). + ///
+ /// + /// ✨ *Enabled with the `unstable` Cargo feature.* + #[derive(Copy, Clone, Debug, PartialEq, Default)] + #[non_exhaustive] + pub enum MissingFieldsStrategy { + /// If the fields that are present do not fully constitute a Date, + /// return [`DateFromFieldsError::NotEnoughFields`]. + /// + /// [`DateFromFieldsError::NotEnoughFields`]: crate::error::DateFromFieldsError::NotEnoughFields + #[default] + Reject, + /// If the fields that are present do not fully constitute a Date, + /// follow the ECMAScript specification when possible. + /// + /// ⚠️ This option causes a year or day to be implicitly added to the Date! + /// + /// This strategy makes the following changes: + /// + /// 1. If the fields identify a year and a month, but not a day, then set `day` to 1. + /// 2. If `month_code` and `day` are set but nothing else, then set the year to a + /// _reference year_: some year in the calendar that contains the specified month + /// and day, according to the ECMAScript specification. + /// + /// Note that the reference year is _not_ added if an ordinal month is present, since + /// the identity of an ordinal month changes from year to year. + Ecma, + } +} +#[cfg(test)] +mod tests { + use crate::{error::DateFromFieldsError, types::DateFields, Date, Gregorian}; + use itertools::Itertools; + use std::collections::{BTreeMap, BTreeSet}; + + use super::*; + + #[test] + #[allow(clippy::field_reassign_with_default)] // want out-of-crate code style + fn test_missing_fields_strategy() { + // The sets of fields that identify a year, according to the table in the docs + let valid_year_field_sets = [ + &["era", "era_year"][..], + &["extended_year"][..], + &["era", "era_year", "extended_year"][..], + ] + .into_iter() + .map(|field_names| field_names.iter().copied().collect()) + .collect::>>(); + + // The sets of fields that identify a month, according to the table in the docs + let valid_month_field_sets = [ + &["month_code"][..], + &["ordinal_month"][..], + &["month_code", "ordinal_month"][..], + ] + .into_iter() + .map(|field_names| field_names.iter().copied().collect()) + .collect::>>(); + + // The sets of fields that identify a day, according to the table in the docs + let valid_day_field_sets = [&["day"][..]] + .into_iter() + .map(|field_names| field_names.iter().copied().collect()) + .collect::>>(); + + // All possible valid sets of fields + let all_valid_field_sets = valid_year_field_sets + .iter() + .cartesian_product(valid_month_field_sets.iter()) + .cartesian_product(valid_day_field_sets.iter()) + .map(|((year_fields, month_fields), day_fields)| { + year_fields + .iter() + .chain(month_fields.iter()) + .chain(day_fields.iter()) + .copied() + .collect::>() + }) + .collect::>>(); + + // Field sets with year and month but without day that ECMA accepts + let field_sets_without_day = valid_year_field_sets + .iter() + .cartesian_product(valid_month_field_sets.iter()) + .map(|(year_fields, month_fields)| { + year_fields + .iter() + .chain(month_fields.iter()) + .copied() + .collect::>() + }) + .collect::>>(); + + // Field sets with month and day but without year that ECMA accepts + let field_sets_without_year = [&["month_code", "day"][..]] + .into_iter() + .map(|field_names| field_names.iter().copied().collect()) + .collect::>>(); + + // A map from field names to a function that sets that field + let mut field_fns = BTreeMap::<&str, &dyn Fn(&mut DateFields)>::new(); + field_fns.insert("era", &|fields| fields.era = Some(b"ad")); + field_fns.insert("era_year", &|fields| fields.era_year = Some(2000)); + field_fns.insert("extended_year", &|fields| fields.extended_year = Some(2000)); + field_fns.insert("month_code", &|fields| fields.month_code = Some(b"M04")); + field_fns.insert("ordinal_month", &|fields| fields.ordinal_month = Some(4)); + field_fns.insert("day", &|fields| fields.day = Some(20)); + + for field_set in field_fns.keys().copied().powerset() { + let field_set = field_set.into_iter().collect::>(); + + // Check whether this case should succeed: whether it identifies a year, + // a month, and a day. + let should_succeed_rejecting = all_valid_field_sets.contains(&field_set); + + // Check whether it should succeed in ECMA mode. + let should_succeed_ecma = should_succeed_rejecting + || field_sets_without_day.contains(&field_set) + || field_sets_without_year.contains(&field_set); + + // Populate the fields in the field set + let mut fields = Default::default(); + for field_name in field_set { + field_fns.get(field_name).unwrap()(&mut fields); + } + + // Check whether we were able to successfully construct the date + let mut options = DateFromFieldsOptions::default(); + options.missing_fields_strategy = Some(MissingFieldsStrategy::Reject); + match Date::try_from_fields(fields, options, Gregorian) { + Ok(_) => assert!( + should_succeed_rejecting, + "Succeeded, but should have rejected: {fields:?}" + ), + Err(DateFromFieldsError::NotEnoughFields) => assert!( + !should_succeed_rejecting, + "Rejected, but should have succeeded: {fields:?}" + ), + Err(e) => panic!("Unexpected error: {e} for {fields:?}"), + } + + // Check ECMA mode + let mut options = DateFromFieldsOptions::default(); + options.missing_fields_strategy = Some(MissingFieldsStrategy::Ecma); + match Date::try_from_fields(fields, options, Gregorian) { + Ok(_) => assert!( + should_succeed_ecma, + "Succeeded, but should have rejected (ECMA): {fields:?}" + ), + Err(DateFromFieldsError::NotEnoughFields) => assert!( + !should_succeed_ecma, + "Rejected, but should have succeeded (ECMA): {fields:?}" + ), + Err(e) => panic!("Unexpected error: {e} for {fields:?}"), + } + } + } + + #[test] + fn test_constrain_large_months() { + let fields = DateFields { + extended_year: Some(2004), + ordinal_month: Some(15), + day: Some(1), + ..Default::default() + }; + let options = DateFromFieldsOptions { + overflow: Some(Overflow::Constrain), + ..Default::default() + }; + + let _ = Date::try_from_fields(fields, options, crate::cal::Persian).unwrap(); + } +} diff --git a/deps/crates/vendor/icu_calendar/src/provider.rs b/deps/crates/vendor/icu_calendar/src/provider.rs index 71e7369abfd360..b8f7feaf9181be 100644 --- a/deps/crates/vendor/icu_calendar/src/provider.rs +++ b/deps/crates/vendor/icu_calendar/src/provider.rs @@ -15,11 +15,6 @@ // 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::*; @@ -46,9 +41,6 @@ const _: () = { 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); @@ -83,9 +75,6 @@ icu_provider::data_marker!( #[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, @@ -107,6 +96,7 @@ pub const MARKERS: &[DataMarkerInfo] = &[ #[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))] +#[cfg_attr(not(feature = "alloc"), zerovec::skip_derive(ZeroMapKV))] pub struct EraStartDate { /// The year the era started in pub year: i32, @@ -198,7 +188,7 @@ impl WeekdaySet { pub const fn new(days: &[Weekday]) -> Self { let mut i = 0; let mut w = 0; - #[allow(clippy::indexing_slicing)] + #[expect(clippy::indexing_slicing)] while i < days.len() { w |= days[i].bit_value(); i += 1; @@ -295,6 +285,7 @@ impl<'de> serde::Deserialize<'de> for WeekdaySet { } #[test] +#[cfg(feature = "datagen")] fn test_weekdayset_bake() { databake::test_bake!( WeekdaySet, diff --git a/deps/crates/vendor/icu_calendar/src/provider/chinese_based.rs b/deps/crates/vendor/icu_calendar/src/provider/chinese_based.rs deleted file mode 100644 index da6fbd372b069e..00000000000000 --- a/deps/crates/vendor/icu_calendar/src/provider/chinese_based.rs +++ /dev/null @@ -1,298 +0,0 @@ -// 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 deleted file mode 100644 index d0ff61f8b13b57..00000000000000 --- a/deps/crates/vendor/icu_calendar/src/provider/hijri.rs +++ /dev/null @@ -1,165 +0,0 @@ -// 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 index f157bdd28826ff..ba22c7c1e51de1 100644 --- a/deps/crates/vendor/icu_calendar/src/tests/continuity_test.rs +++ b/deps/crates/vendor/icu_calendar/src/tests/continuity_test.rs @@ -2,25 +2,20 @@ // 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, - }; +use crate::{types::*, *}; + +fn check_continuity(mut date: Date, years_to_check: usize) { + let duration = DateDuration::for_days(1); 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); + for _ in 0..(366 * years_to_check) { + let next_date = date + .try_added_with_options(duration, Default::default()) + .unwrap(); 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(); @@ -42,19 +37,15 @@ fn check_continuity(mut date: Date) { } } -fn check_every_250_days(mut date: Date) { - let one_thousand_days_duration = DateDuration:: { - years: 0, - months: 0, - weeks: 0, - days: 250, - marker: PhantomData, - }; +fn check_every_250_days(mut date: Date, iters: usize) { + let duration = DateDuration::for_days(250); let mut rata_die = date.to_rata_die(); - for _ in 0..2000 { - let next_date = date.added(one_thousand_days_duration); + for _ in 0..iters { + let next_date = date + .try_added_with_options(duration, Default::default()) + .unwrap(); 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:?}"); @@ -68,175 +59,192 @@ fn check_every_250_days(mut date: Date) { #[test] fn test_buddhist_continuity() { let date = Date::try_new_buddhist(-10, 1, 1); - check_continuity(date.unwrap()); + check_continuity(date.unwrap(), 20); let date = Date::try_new_buddhist(-300, 1, 1); - check_every_250_days(date.unwrap()); + check_every_250_days(date.unwrap(), 2000); } #[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()); + let cal = crate::cal::ChineseTraditional::new(); + let date = Date::try_new_from_codes(None, -10, MonthCode::new_normal(1).unwrap(), 1, cal); + check_continuity(date.unwrap(), 20); + let date = Date::try_new_from_codes(None, -300, MonthCode::new_normal(1).unwrap(), 1, cal); + check_every_250_days(date.unwrap(), 2000); + let date = Date::try_new_from_codes(None, -10000, MonthCode::new_normal(1).unwrap(), 1, cal); + check_every_250_days(date.unwrap(), 2000); + + let date = Date::try_new_from_codes(None, 1899, MonthCode::new_normal(1).unwrap(), 1, cal); + check_continuity(date.unwrap(), 20); + + let date = Date::try_new_from_codes(None, 2099, MonthCode::new_normal(1).unwrap(), 1, cal); + check_continuity(date.unwrap(), 20); } #[test] fn test_coptic_continuity() { let date = Date::try_new_coptic(-10, 1, 1); - check_continuity(date.unwrap()); + check_continuity(date.unwrap(), 20); let date = Date::try_new_coptic(-300, 1, 1); - check_every_250_days(date.unwrap()); + check_every_250_days(date.unwrap(), 2000); } #[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()); +fn test_korean_continuity() { + let cal = cal::KoreanTraditional::new(); + let date = Date::try_new_from_codes(None, -10, MonthCode::new_normal(1).unwrap(), 1, cal); + check_continuity(date.unwrap(), 20); + let date = Date::try_new_from_codes(None, -300, MonthCode::new_normal(1).unwrap(), 1, cal); + check_every_250_days(date.unwrap(), 2000); + + let date = Date::try_new_from_codes(None, 1900, MonthCode::new_normal(1).unwrap(), 1, cal); + check_continuity(date.unwrap(), 20); + + let date = Date::try_new_from_codes(None, 2100, MonthCode::new_normal(1).unwrap(), 1, cal); + check_continuity(date.unwrap(), 20); } #[test] fn test_ethiopian_continuity() { - use crate::cal::EthiopianEraStyle::*; + use cal::EthiopianEraStyle::*; let date = Date::try_new_ethiopian(AmeteMihret, -10, 1, 1); - check_continuity(date.unwrap()); + check_continuity(date.unwrap(), 20); let date = Date::try_new_ethiopian(AmeteMihret, -300, 1, 1); - check_every_250_days(date.unwrap()); + check_every_250_days(date.unwrap(), 2000); } #[test] fn test_ethiopian_amete_alem_continuity() { - use crate::cal::EthiopianEraStyle::*; + use cal::EthiopianEraStyle::*; let date = Date::try_new_ethiopian(AmeteAlem, -10, 1, 1); - check_continuity(date.unwrap()); + check_continuity(date.unwrap(), 20); let date = Date::try_new_ethiopian(AmeteAlem, -300, 1, 1); - check_every_250_days(date.unwrap()); + check_every_250_days(date.unwrap(), 2000); } #[test] fn test_gregorian_continuity() { let date = Date::try_new_gregorian(-10, 1, 1); - check_continuity(date.unwrap()); + check_continuity(date.unwrap(), 20); let date = Date::try_new_gregorian(-300, 1, 1); - check_every_250_days(date.unwrap()); + check_every_250_days(date.unwrap(), 2000); } #[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()); + let date = + Date::try_new_from_codes(None, -10, MonthCode::new_normal(1).unwrap(), 1, cal::Hebrew); + check_continuity(date.unwrap(), 20); + let date = Date::try_new_from_codes( + None, + -300, + MonthCode::new_normal(1).unwrap(), + 1, + cal::Hebrew, + ); + check_every_250_days(date.unwrap(), 2000); } #[test] fn test_indian_continuity() { let date = Date::try_new_indian(-10, 1, 1); - check_continuity(date.unwrap()); + check_continuity(date.unwrap(), 20); let date = Date::try_new_indian(-300, 1, 1); - check_every_250_days(date.unwrap()); + check_every_250_days(date.unwrap(), 2000); } #[test] fn test_hijri_civil_continuity() { - let cal = crate::cal::HijriTabular::new( - crate::cal::HijriTabularLeapYears::TypeII, - crate::cal::HijriTabularEpoch::Friday, + let cal = cal::Hijri::new_tabular( + cal::hijri::TabularAlgorithmLeapYears::TypeII, + cal::hijri::TabularAlgorithmEpoch::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()); + let date = Date::try_new_hijri_with_calendar(-10, 1, 1, cal); + check_continuity(date.unwrap(), 20); + let date = Date::try_new_hijri_with_calendar(-300, 1, 1, cal); + check_every_250_days(date.unwrap(), 2000); } #[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()); + let cal = cal::Hijri::new_simulated_mecca(); + let date = Date::try_new_hijri_with_calendar(-10, 1, 1, cal); + // This test is slow since it is doing astronomical calculations, so check only 3 years + check_continuity(date.unwrap(), 3); + let date = Date::try_new_hijri_with_calendar(-300, 1, 1, cal); + // This test is slow since it is doing astronomical calculations, so check only 100 dates + check_every_250_days(date.unwrap(), 100); } #[test] fn test_hijri_tabular_continuity() { - let cal = crate::cal::HijriTabular::new( - crate::cal::HijriTabularLeapYears::TypeII, - crate::cal::HijriTabularEpoch::Thursday, + let cal = cal::Hijri::new_tabular( + cal::hijri::TabularAlgorithmLeapYears::TypeII, + cal::hijri::TabularAlgorithmEpoch::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()); + let date = Date::try_new_hijri_with_calendar(-10, 1, 1, cal); + check_continuity(date.unwrap(), 20); + let date = Date::try_new_hijri_with_calendar(-300, 1, 1, cal); + check_every_250_days(date.unwrap(), 2000); } #[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()); + let cal = cal::Hijri::new_umm_al_qura(); + let date = Date::try_new_hijri_with_calendar(-10, 1, 1, cal); + check_continuity(date.unwrap(), 20); + let date = Date::try_new_hijri_with_calendar(1290, 1, 1, cal); + check_continuity(date.unwrap(), 20); + let date = Date::try_new_hijri_with_calendar(1590, 1, 1, cal); + check_continuity(date.unwrap(), 20); + let date = Date::try_new_hijri_with_calendar(-300, 1, 1, cal); + check_every_250_days(date.unwrap(), 2000); } #[test] fn test_iso_continuity() { let date = Date::try_new_iso(-10, 1, 1); - check_continuity(date.unwrap()); + check_continuity(date.unwrap(), 20); let date = Date::try_new_iso(-300, 1, 1); - check_every_250_days(date.unwrap()); + check_every_250_days(date.unwrap(), 2000); } #[test] fn test_japanese_continuity() { - let cal = crate::cal::Japanese::new(); + let cal = cal::Japanese::new(); let cal = Ref(&cal); let date = Date::try_new_japanese_with_calendar("heisei", 20, 1, 1, cal); - check_continuity(date.unwrap()); + check_continuity(date.unwrap(), 20); let date = Date::try_new_japanese_with_calendar("bce", 500, 1, 1, cal); - check_every_250_days(date.unwrap()); + check_every_250_days(date.unwrap(), 2000); } #[test] fn test_japanese_extended_continuity() { - let cal = crate::cal::JapaneseExtended::new(); + let cal = 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()); + check_continuity(date.unwrap(), 20); let date = Date::try_new_japanese_extended_with_calendar("bce", 500, 1, 1, cal); - check_every_250_days(date.unwrap()); + check_every_250_days(date.unwrap(), 2000); } #[test] fn test_persian_continuity() { let date = Date::try_new_persian(-10, 1, 1); - check_continuity(date.unwrap()); + check_continuity(date.unwrap(), 20); let date = Date::try_new_persian(-300, 1, 1); - check_every_250_days(date.unwrap()); + check_every_250_days(date.unwrap(), 2000); } #[test] fn test_roc_continuity() { let date = Date::try_new_roc(-10, 1, 1); - check_continuity(date.unwrap()); + check_continuity(date.unwrap(), 20); let date = Date::try_new_roc(-300, 1, 1); - check_every_250_days(date.unwrap()); + check_every_250_days(date.unwrap(), 2000); } diff --git a/deps/crates/vendor/icu_calendar/src/tests/extrema.rs b/deps/crates/vendor/icu_calendar/src/tests/extrema.rs new file mode 100644 index 00000000000000..d4bb47d395fc79 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/tests/extrema.rs @@ -0,0 +1,69 @@ +// 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::cal::*; +use crate::Calendar; +use crate::Date; +use crate::Ref; + +#[track_caller] +fn check_extrema(cal: C) { + // Minimum and maximum dates allowed in ECMA-262 Temporal. + let min_date_iso = Date::try_new_iso(-271821, 4, 19).unwrap(); + let max_date_iso = Date::try_new_iso(275760, 9, 13).unwrap(); + let min_date = min_date_iso.to_calendar(Ref(&cal)); + let max_date = max_date_iso.to_calendar(Ref(&cal)); + + println!( + "min.year = {:?}, max.year = {:?} (cal = {})", + min_date.year(), + max_date.year(), + cal.debug_name() + ); +} + +// Test all calendars that have any amount of tricky mathematics +// to ensure that they do not trigger debug assertions for large dates. + +#[test] +fn check_extrema_chinese() { + check_extrema(ChineseTraditional::new()) +} + +#[test] +fn check_extrema_korean() { + check_extrema(KoreanTraditional::new()) +} + +#[test] +fn check_extrema_hijri_simulated_mecca() { + check_extrema(Hijri::new_simulated_mecca()) +} + +#[test] +fn check_extrema_hijri_uaq() { + check_extrema(Hijri::new_umm_al_qura()) +} + +#[test] +fn check_extrema_hijri_tabular() { + check_extrema(Hijri::new_tabular( + hijri::TabularAlgorithmLeapYears::TypeII, + hijri::TabularAlgorithmEpoch::Thursday, + )); + check_extrema(Hijri::new_tabular( + hijri::TabularAlgorithmLeapYears::TypeII, + hijri::TabularAlgorithmEpoch::Friday, + )); +} + +#[test] +fn check_extrema_hebrew() { + check_extrema(Hebrew::new()) +} + +#[test] +fn check_extrema_persian() { + check_extrema(Persian::new()) +} diff --git a/deps/crates/vendor/icu_calendar/src/tests/mod.rs b/deps/crates/vendor/icu_calendar/src/tests/mod.rs index a4330b4af10b0c..b753567880b6ea 100644 --- a/deps/crates/vendor/icu_calendar/src/tests/mod.rs +++ b/deps/crates/vendor/icu_calendar/src/tests/mod.rs @@ -3,3 +3,5 @@ // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). mod continuity_test; +mod extrema; +mod not_enough_fields; diff --git a/deps/crates/vendor/icu_calendar/src/tests/not_enough_fields.rs b/deps/crates/vendor/icu_calendar/src/tests/not_enough_fields.rs new file mode 100644 index 00000000000000..34aebf6f8996cc --- /dev/null +++ b/deps/crates/vendor/icu_calendar/src/tests/not_enough_fields.rs @@ -0,0 +1,237 @@ +// 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::DateFromFieldsError; +use crate::options::{DateFromFieldsOptions, MissingFieldsStrategy, Overflow}; +use crate::types::DateFields; +use crate::Date; + +#[test] +fn test_from_fields_not_enough_fields() { + // Pick a sufficiently complex calendar. + let calendar = crate::cal::Hebrew::new(); + + let big_i32 = Some(i32::MAX); + let big_u8 = Some(u8::MAX); + let small_u8 = Some(1); + let small_i32 = Some(5000); + let valid_month_code: Option<&[_]> = Some(b"M01"); + let invalid_month_code: Option<&[_]> = Some(b"M99"); + + // We want to ensure that most NotEnoughFields cases return NotEnoughFields + // even when we're providing out-of-range values, so that + // this produces TypeError in Temporal as opposed to RangeError. + + for overflow in [Overflow::Reject, Overflow::Constrain] { + for missing_fields in [MissingFieldsStrategy::Reject, MissingFieldsStrategy::Ecma] { + let options = DateFromFieldsOptions { + overflow: Some(overflow), + missing_fields_strategy: Some(missing_fields), + }; + + // No month data always errors + assert_eq!( + Date::try_from_fields( + DateFields { + era: Some(b"hebrew"), + era_year: big_i32, + extended_year: None, + ordinal_month: None, + month_code: None, + day: small_u8, + }, + options, + calendar + ), + Err(DateFromFieldsError::NotEnoughFields), + "Test with {options:?}" + ); + assert_eq!( + Date::try_from_fields( + DateFields { + era: Some(b"hebrew"), + era_year: small_i32, + extended_year: None, + ordinal_month: None, + month_code: None, + day: big_u8, + }, + options, + calendar + ), + Err(DateFromFieldsError::NotEnoughFields), + "Test with {options:?}" + ); + assert_eq!( + Date::try_from_fields( + DateFields { + era: None, + era_year: None, + extended_year: big_i32, + ordinal_month: None, + month_code: None, + day: small_u8, + }, + options, + calendar + ), + Err(DateFromFieldsError::NotEnoughFields), + "Test with {options:?}" + ); + + // Insufficient era-year data always errors + assert_eq!( + Date::try_from_fields( + DateFields { + era: Some(b"hebrew"), + era_year: None, + extended_year: None, + ordinal_month: big_u8, + month_code: None, + day: small_u8, + }, + options, + calendar + ), + Err(DateFromFieldsError::NotEnoughFields), + "Test with {options:?}" + ); + assert_eq!( + Date::try_from_fields( + DateFields { + era: Some(b"hebrew"), + era_year: None, + extended_year: None, + ordinal_month: small_u8, + month_code: None, + day: big_u8, + }, + options, + calendar + ), + Err(DateFromFieldsError::NotEnoughFields), + "Test with {options:?}" + ); + + // No year info errors for ordinal months regardless of missing fields strategy + assert_eq!( + Date::try_from_fields( + DateFields { + era: None, + era_year: None, + extended_year: None, + ordinal_month: small_u8, + month_code: None, + day: big_u8, + }, + options, + calendar + ), + Err(DateFromFieldsError::NotEnoughFields), + "Test with {options:?}" + ); + assert_eq!( + Date::try_from_fields( + DateFields { + era: None, + era_year: None, + extended_year: None, + ordinal_month: big_u8, + month_code: None, + day: small_u8, + }, + options, + calendar + ), + Err(DateFromFieldsError::NotEnoughFields), + "Test with {options:?}" + ); + if missing_fields != MissingFieldsStrategy::Ecma { + // No year info errors only when there is no missing fields strategy + assert_eq!( + Date::try_from_fields( + DateFields { + era: None, + era_year: None, + extended_year: None, + ordinal_month: None, + month_code: valid_month_code, + day: big_u8, + }, + options, + calendar + ), + Err(DateFromFieldsError::NotEnoughFields), + "Test with {options:?}" + ); + assert_eq!( + Date::try_from_fields( + DateFields { + era: None, + era_year: None, + extended_year: None, + ordinal_month: None, + month_code: invalid_month_code, + day: small_u8, + }, + options, + calendar + ), + Err(DateFromFieldsError::NotEnoughFields), + "Test with {options:?}" + ); + + // No day info errors only when there is no missing field strategy + assert_eq!( + Date::try_from_fields( + DateFields { + era: None, + era_year: None, + extended_year: big_i32, + ordinal_month: small_u8, + month_code: None, + day: None, + }, + options, + calendar + ), + Err(DateFromFieldsError::NotEnoughFields), + "Test with {options:?}" + ); + assert_eq!( + Date::try_from_fields( + DateFields { + era: Some(b"hebrew"), + era_year: big_i32, + extended_year: None, + ordinal_month: small_u8, + month_code: None, + day: None, + }, + options, + calendar + ), + Err(DateFromFieldsError::NotEnoughFields), + "Test with {options:?}" + ); + assert_eq!( + Date::try_from_fields( + DateFields { + era: Some(b"hebrew"), + era_year: small_i32, + extended_year: None, + ordinal_month: big_u8, + month_code: None, + day: None, + }, + options, + calendar + ), + Err(DateFromFieldsError::NotEnoughFields), + "Test with {options:?}" + ); + } + } + } +} diff --git a/deps/crates/vendor/icu_calendar/src/types.rs b/deps/crates/vendor/icu_calendar/src/types.rs index c01f363694e57e..82c5164c6e9a0c 100644 --- a/deps/crates/vendor/icu_calendar/src/types.rs +++ b/deps/crates/vendor/icu_calendar/src/types.rs @@ -2,16 +2,220 @@ // 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` +//! 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; +// Export the duration types from here +#[cfg(feature = "unstable")] +pub use crate::duration::{DateDuration, DateDurationUnit}; +use crate::error::MonthCodeParseError; + +#[cfg(feature = "unstable")] +pub use unstable::DateFields; +#[cfg(not(feature = "unstable"))] +pub(crate) use unstable::DateFields; + +mod unstable { + /// A bag of various ways of expressing the year, month, and/or day. + /// + /// Pass this into [`Date::try_from_fields`](crate::Date::try_from_fields). + /// + ///
+ /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways, + /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break. + /// + /// Graduation tracking issue: [issue #7161](https://github.com/unicode-org/icu4x/issues/7161). + ///
+ /// + /// ✨ *Enabled with the `unstable` Cargo feature.* + #[derive(Copy, Clone, PartialEq, Default)] + #[non_exhaustive] + pub struct DateFields<'a> { + /// The era code as a UTF-8 string. + /// + /// The acceptable codes are defined by CLDR and documented on each calendar. + /// + /// If set, [`Self::era_year`] must also be set. + /// + /// # Examples + /// + /// To set the era field, use a byte string: + /// + /// ``` + /// use icu::calendar::types::DateFields; + /// + /// let mut fields = DateFields::default(); + /// + /// // As a byte string literal: + /// fields.era = Some(b"reiwa"); + /// + /// // Using str::as_bytes: + /// fields.era = Some("reiwa".as_bytes()); + /// ``` + /// + /// For a full example, see [`Self::extended_year`]. + pub era: Option<&'a [u8]>, + /// The numeric year in [`Self::era`]. + /// + /// If set, [`Self::era`] must also be set. + /// + /// For an example, see [`Self::extended_year`]. + pub era_year: Option, + /// See [`Date::extended_year()`](crate::Date::extended_year). + /// + /// If both this and [`Self::era`]/[`Self::era_year`] are set, they must + /// refer to the same year. + /// + /// # Examples + /// + /// Either `extended_year` or `era` + `era_year` can be used in DateFields: + /// + /// ``` + /// use icu::calendar::cal::Japanese; + /// use icu::calendar::types::DateFields; + /// use icu::calendar::Date; + /// + /// let mut fields1 = DateFields::default(); + /// fields1.era = Some(b"reiwa"); + /// fields1.era_year = Some(7); + /// fields1.ordinal_month = Some(1); + /// fields1.day = Some(1); + /// + /// let date1 = + /// Date::try_from_fields(fields1, Default::default(), Japanese::new()) + /// .expect("a well-defined Japanese date from era year"); + /// + /// let mut fields2 = DateFields::default(); + /// fields2.extended_year = Some(2025); + /// fields2.ordinal_month = Some(1); + /// fields2.day = Some(1); + /// + /// let date2 = + /// Date::try_from_fields(fields2, Default::default(), Japanese::new()) + /// .expect("a well-defined Japanese date from extended year"); + /// + /// assert_eq!(date1, date2); + /// + /// let year_info = date1.year().era().unwrap(); + /// assert_eq!(year_info.year, 7); + /// assert_eq!(year_info.era.as_str(), "reiwa"); + /// assert_eq!(year_info.extended_year, 2025); + /// ``` + pub extended_year: Option, + /// The month code representing a valid month in this calendar year, + /// as a UTF-8 string. + /// + /// See [`MonthCode`](crate::types::MonthCode) for information on the syntax. + /// + /// # Examples + /// + /// To set the month code field, use a byte string: + /// + /// ``` + /// use icu::calendar::types::DateFields; + /// + /// let mut fields = DateFields::default(); + /// + /// // As a byte string literal: + /// fields.era = Some(b"M02L"); + /// + /// // Using str::as_bytes: + /// fields.era = Some("M02L".as_bytes()); + /// ``` + /// + /// For a full example, see [`Self::ordinal_month`]. + pub month_code: Option<&'a [u8]>, + /// See [`MonthInfo::ordinal`](crate::types::MonthInfo::ordinal). + /// + /// If both this and [`Self::month_code`] are set, they must refer to + /// the same month. + /// + /// Note: using [`Self::month_code`] is recommended, because the ordinal month numbers + /// can vary from year to year, as illustrated in the following example. + /// + /// # Examples + /// + /// Either `month_code` or `ordinal_month` can be used in DateFields, but they + /// might not resolve to the same month number: + /// + /// ``` + /// use icu::calendar::cal::ChineseTraditional; + /// use icu::calendar::types::DateFields; + /// use icu::calendar::Date; + /// + /// // The 2023 Year of the Rabbit had a leap month after the 2nd month. + /// let mut fields1 = DateFields::default(); + /// fields1.extended_year = Some(2023); + /// fields1.month_code = Some(b"M02L"); + /// fields1.day = Some(1); + /// + /// let date1 = Date::try_from_fields( + /// fields1, + /// Default::default(), + /// ChineseTraditional::new(), + /// ) + /// .expect("a well-defined Chinese date from month code"); + /// + /// let mut fields2 = DateFields::default(); + /// fields2.extended_year = Some(2023); + /// fields2.ordinal_month = Some(3); + /// fields2.day = Some(1); + /// + /// let date2 = Date::try_from_fields( + /// fields2, + /// Default::default(), + /// ChineseTraditional::new(), + /// ) + /// .expect("a well-defined Chinese date from ordinal month"); + /// + /// assert_eq!(date1, date2); + /// + /// let month_info = date1.month(); + /// assert_eq!(month_info.ordinal, 3); + /// assert_eq!(month_info.standard_code.0, "M02L"); + /// ``` + pub ordinal_month: Option, + /// See [`DayOfMonth`](crate::types::DayOfMonth). + pub day: Option, + } +} + +// Custom impl to stringify era and month_code where possible. +impl fmt::Debug for DateFields<'_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // Ensures we catch future fields + let Self { + era, + era_year, + extended_year, + month_code, + ordinal_month, + day, + } = *self; + let mut builder = f.debug_struct("DateFields"); + if let Some(s) = era.and_then(|s| core::str::from_utf8(s).ok()) { + builder.field("era", &Some(s)); + } else { + builder.field("era", &era); + } + builder.field("era_year", &era_year); + builder.field("extended_year", &extended_year); + if let Some(s) = month_code.and_then(|s| core::str::from_utf8(s).ok()) { + builder.field("month_code", &Some(s)); + } else { + builder.field("month_code", &month_code); + } + builder.field("ordinal_month", &ordinal_month); + builder.field("day", &day); + builder.finish() + } +} + /// 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] @@ -48,6 +252,15 @@ impl YearInfo { } } + /// Get the extended year (See [`Date::extended_year`](crate::Date::extended_year)) + /// for more information + pub fn extended_year(self) -> i32 { + match self { + YearInfo::Era(e) => e.extended_year, + YearInfo::Cyclic(c) => c.related_iso, + } + } + /// Get the era year information, if available pub fn era(self) -> Option { match self { @@ -88,8 +301,10 @@ pub enum YearAmbiguity { pub struct EraYear { /// The numeric year in that era pub year: i32, + /// See [`YearInfo::extended_year()`] + pub extended_year: i32, /// The era code as defined by CLDR, expect for cases where CLDR does not define a code. - pub era: TinyStr16, + pub era: TinyAsciiStr<16>, /// 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* @@ -126,12 +341,13 @@ pub struct CyclicYear { #[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); +pub struct MonthCode(pub TinyAsciiStr<4>); 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. + #[deprecated(since = "2.1.0")] pub fn get_normal_if_leap(self) -> Option { let bytes = self.0.all_bytes(); if bytes[3] == b'L' { @@ -140,67 +356,65 @@ impl MonthCode { None } } + + #[deprecated(since = "2.1.0")] /// 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 + ValidMonthCode::try_from_utf8(self.0.as_bytes()) + .ok() + .map(ValidMonthCode::to_tuple) } /// 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; - } + (1..=99) + .contains(&number) + .then(|| ValidMonthCode::new_unchecked(number, false).to_month_code()) + } - let bytes = [b'M', b'0' + tens, b'0' + ones, 0]; - Some(MonthCode(TinyAsciiStr::try_from_raw(bytes).ok()?)) + /// Construct a "leap" month code given a number ("MxxL"). + /// + /// Returns an error for months greater than 99 + pub fn new_leap(number: u8) -> Option { + (1..=99) + .contains(&number) + .then(|| ValidMonthCode::new_unchecked(number, true).to_month_code()) } } #[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); + #![allow(deprecated)] + assert_eq!( + MonthCode::new_leap(1).unwrap().get_normal_if_leap(), + MonthCode::new_normal(1) + ); + + assert_eq!( + MonthCode::new_leap(11).unwrap().get_normal_if_leap(), + MonthCode::new_normal(11) + ); + + assert_eq!( + MonthCode::new_normal(10).unwrap().get_normal_if_leap(), + None + ); } impl AsULE for MonthCode { - type ULE = TinyStr4; - fn to_unaligned(self) -> TinyStr4 { + type ULE = TinyAsciiStr<4>; + fn to_unaligned(self) -> TinyAsciiStr<4> { self.0 } - fn from_unaligned(u: TinyStr4) -> Self { + fn from_unaligned(u: TinyAsciiStr<4>) -> Self { Self(u) } } -impl<'a> ZeroMapKV<'a> for MonthCode { +#[cfg(feature = "alloc")] +impl<'a> zerovec::maps::ZeroMapKV<'a> for MonthCode { type Container = zerovec::ZeroVec<'a, MonthCode>; type Slice = zerovec::ZeroSlice; type GetType = ::ULE; @@ -213,6 +427,89 @@ impl fmt::Display for MonthCode { } } +/// A [`MonthCode`] that has been parsed into its internal representation. +#[derive(Copy, Clone, Debug, PartialEq)] +pub(crate) struct ValidMonthCode { + /// Month number between 0 and 99 + number: u8, + is_leap: bool, +} + +impl ValidMonthCode { + #[inline] + pub(crate) fn try_from_utf8(bytes: &[u8]) -> Result { + match *bytes { + [b'M', tens, ones] => Ok(Self { + number: (tens - b'0') * 10 + ones - b'0', + is_leap: false, + }), + [b'M', tens, ones, b'L'] => Ok(Self { + number: (tens - b'0') * 10 + ones - b'0', + is_leap: true, + }), + _ => Err(MonthCodeParseError::InvalidSyntax), + } + } + + /// Create a new ValidMonthCode without checking that the number is between 1 and 99 + #[inline] + pub(crate) const fn new_unchecked(number: u8, is_leap: bool) -> Self { + debug_assert!(1 <= number && number <= 99); + Self { number, is_leap } + } + + /// Returns the month number according to the month code. + /// + /// This is NOT the same as the ordinal month! + /// + /// # Examples + /// + /// ```ignore + /// use icu::calendar::Date; + /// use icu::calendar::cal::Hebrew; + /// + /// let hebrew_date = Date::try_new_iso(2024, 7, 1).unwrap().to_calendar(Hebrew); + /// let month_info = hebrew_date.month(); + /// + /// // Hebrew year 5784 was a leap year, so the ordinal month and month number diverge. + /// assert_eq!(month_info.ordinal, 10); + /// assert_eq!(month_info.valid_month_code.number(), 9); + /// ``` + #[inline] + pub fn number(self) -> u8 { + self.number + } + + /// Returns whether the month is a leap month. + /// + /// This is true for intercalary months in [`Hebrew`] and [`LunarChinese`]. + /// + /// [`Hebrew`]: crate::cal::Hebrew + /// [`LunarChinese`]: crate::cal::LunarChinese + #[inline] + pub fn is_leap(self) -> bool { + self.is_leap + } + + #[inline] + pub(crate) fn to_tuple(self) -> (u8, bool) { + (self.number, self.is_leap) + } + + pub(crate) fn to_month_code(self) -> MonthCode { + #[allow(clippy::unwrap_used)] // by construction + MonthCode( + TinyAsciiStr::try_from_raw([ + b'M', + b'0' + self.number / 10, + b'0' + self.number % 10, + if self.is_leap { b'L' } else { 0 }, + ]) + .unwrap(), + ) + } +} + /// Representation of a formattable month. #[derive(Copy, Clone, Debug, PartialEq)] #[non_exhaustive] @@ -225,33 +522,71 @@ pub struct MonthInfo { /// The month code, used to distinguish months during leap years. /// + /// Round-trips through `Date` constructors like [`Date::try_new_from_codes`] and [`Date::try_from_fields`]. + /// /// 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 + /// are considered the same month and have the code M05. + /// + /// [`Date::try_new_from_codes`]: crate::Date::try_new_from_codes + /// [`Date::try_from_fields`]: crate::Date::try_from_fields pub standard_code: MonthCode, - /// A month code, useable for formatting + + /// Same as [`Self::standard_code`] but with invariants validated. + pub(crate) valid_standard_code: ValidMonthCode, + + /// A month code, useable for formatting. + /// + /// Does NOT necessarily round-trip through `Date` constructors like [`Date::try_new_from_codes`] and [`Date::try_from_fields`]. /// /// 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. + /// + /// [`Date::try_new_from_codes`]: crate::Date::try_new_from_codes + /// [`Date::try_from_fields`]: crate::Date::try_from_fields pub formatting_code: MonthCode, + + /// Same as [`Self::formatting_code`] but with invariants validated. + pub(crate) valid_formatting_code: ValidMonthCode, } impl MonthInfo { + pub(crate) fn non_lunisolar(number: u8) -> Self { + Self::for_code_and_ordinal(ValidMonthCode::new_unchecked(number, false), number) + } + + pub(crate) fn for_code_and_ordinal(code: ValidMonthCode, ordinal: u8) -> Self { + Self { + ordinal, + standard_code: code.to_month_code(), + valid_standard_code: code, + formatting_code: code.to_month_code(), + valid_formatting_code: code, + } + } + /// 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) + self.valid_standard_code.number() } /// Get whether the month is a leap month pub fn is_leap(self) -> bool { - self.standard_code.parsed().map(|(_, l)| l).unwrap_or(false) + self.valid_standard_code.is_leap() + } + + #[doc(hidden)] + pub fn formatting_month_number(self) -> u8 { + self.valid_formatting_code.number() + } + + #[doc(hidden)] + pub fn formatting_is_leap(self) -> bool { + self.valid_formatting_code.is_leap() } } diff --git a/deps/crates/vendor/icu_calendar/src/week.rs b/deps/crates/vendor/icu_calendar/src/week.rs index 384b4f55d99290..e835fa1c811362 100644 --- a/deps/crates/vendor/icu_calendar/src/week.rs +++ b/deps/crates/vendor/icu_calendar/src/week.rs @@ -144,7 +144,7 @@ fn add_to_weekday(weekday: Weekday, num_days: i32) -> Weekday { /// 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)] +#[expect(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, @@ -294,7 +294,7 @@ impl Iterator for WeekdaySetIterator { #[cfg(test)] mod tests { use super::*; - use crate::{types::Weekday, Date, DateDuration, RangeError}; + use crate::{types::DateDuration, types::Weekday, Date, RangeError}; static ISO_CALENDAR: WeekCalculator = WeekCalculator { first_weekday: Weekday::Monday, @@ -457,7 +457,9 @@ mod tests { 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)); + let previous_month = date + .try_added_with_options(DateDuration::for_months(-1), Default::default()) + .unwrap(); calendar.week_of( u16::from(previous_month.days_in_month()), @@ -646,7 +648,7 @@ fn test_iso_weeks() { use crate::types::IsoWeekOfYear; use crate::Date; - #[allow(clippy::zero_prefixed_literal)] + #[expect(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)), diff --git a/deps/crates/vendor/icu_calendar/tests/arithmetic.rs b/deps/crates/vendor/icu_calendar/tests/arithmetic.rs new file mode 100644 index 00000000000000..37c4b97ffb7926 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/tests/arithmetic.rs @@ -0,0 +1,251 @@ +// 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 std::convert::Infallible; + +use icu_calendar::{ + cal::Hebrew, + options::{DateAddOptions, DateDifferenceOptions, Overflow}, + types::{DateDuration, DateDurationUnit, MonthCode}, + AsCalendar, Calendar, Date, Iso, +}; + +#[rustfmt::skip] +#[allow(clippy::type_complexity)] +const ISO_DATE_PAIRS: &[(&str, &str, u64, (u32, u64), (u32, u64), (u32, u32, u64))] = &[ + // d0, d1, D, (W, D), (M, D), (Y, M, D) + ("2020-01-03", "2020-02-15", 43, (6, 1), (1, 12), (0, 1, 12)), + ("2020-01-31", "2020-06-30", 151, (21, 4), (4, 30), (0, 4, 30)), + ("2020-03-31", "2020-07-30", 121, (17, 2), (3, 30), (0, 3, 30)), + ("2020-03-31", "2020-07-31", 122, (17, 3), (4, 0), (0, 4, 0)), + ("2016-03-20", "2020-03-05", 1446, (206, 4), (47, 14), (3, 11, 14)), + ("2020-02-29", "2022-03-01", 731, (104, 3), (24, 1), (2, 0, 1)), + + // Negative direction: + ("2020-02-15", "2020-01-03", 43, (6, 1), (1, 12), (0, 1, 12)), + ("2020-06-30", "2020-01-31", 151, (21, 4), (4, 29), (0, 4, 29)), // DIFF +/- + ("2020-07-30", "2020-03-31", 121, (17, 2), (3, 30), (0, 3, 30)), + ("2020-07-31", "2020-03-31", 122, (17, 3), (4, 0), (0, 4, 0)), + ("2020-03-05", "2016-03-20", 1446, (206, 4), (47, 16), (3, 11, 16)), // DIFF +/- + ("2022-03-01", "2020-02-29", 731, (104, 3), (24, 1), (2, 0, 1)), +]; + +fn check
( + d0: &Date, + d1: &Date, + exp0: &u64, + exp1: &(u32, u64), + exp2: &(u32, u64), + exp3: &(u32, u32, u64), +) where + A: AsCalendar + Copy, + ::Calendar: Calendar, + <::Calendar as Calendar>::DateInner: PartialOrd, +{ + let is_negative = d0 > d1; + let mut add_options = DateAddOptions::default(); + add_options.overflow = Some(Overflow::Constrain); + let mut until_options0 = DateDifferenceOptions::default(); + until_options0.largest_unit = Some(DateDurationUnit::Days); + let mut until_options1 = DateDifferenceOptions::default(); + until_options1.largest_unit = Some(DateDurationUnit::Weeks); + let mut until_options2 = DateDifferenceOptions::default(); + until_options2.largest_unit = Some(DateDurationUnit::Months); + let mut until_options3 = DateDifferenceOptions::default(); + until_options3.largest_unit = Some(DateDurationUnit::Years); + + let Ok(p0) = d0.try_until_with_options(d1, until_options0); + assert_eq!( + p0, + DateDuration { + is_negative, + days: *exp0, + ..Default::default() + }, + "{d0:?}/{d1:?}" + ); + assert_eq!( + d0.try_added_with_options(p0, add_options).unwrap(), + *d1, + "{d0:?}/{d1:?}" + ); + + let Ok(p1) = d0.try_until_with_options(d1, until_options1); + assert_eq!( + p1, + DateDuration { + is_negative, + weeks: exp1.0, + days: exp1.1, + ..Default::default() + }, + "{d0:?}/{d1:?}" + ); + assert_eq!( + d0.try_added_with_options(p1, add_options).unwrap(), + *d1, + "{d0:?}/{d1:?}" + ); + + let Ok(p2) = d0.try_until_with_options(d1, until_options2); + assert_eq!( + p2, + DateDuration { + is_negative, + months: exp2.0, + days: exp2.1, + ..Default::default() + }, + "{d0:?}/{d1:?}" + ); + assert_eq!( + d0.try_added_with_options(p2, add_options).unwrap(), + *d1, + "{d0:?}/{d1:?}" + ); + + let Ok(p3) = d0.try_until_with_options(d1, until_options3); + assert_eq!( + p3, + DateDuration { + is_negative, + years: exp3.0, + months: exp3.1, + days: exp3.2, + ..Default::default() + }, + "{d0:?}/{d1:?}" + ); + assert_eq!( + d0.try_added_with_options(p3, add_options).unwrap(), + *d1, + "{d0:?}/{d1:?}" + ); + + // RataDie addition should be equivalent for largest unit Days and Weeks + let rd_diff = d1.to_rata_die() - d0.to_rata_die(); + if is_negative { + assert!(rd_diff.is_negative()); + } + assert_eq!(p0.days, rd_diff.unsigned_abs()); + assert_eq!(p1.days + u64::from(p1.weeks) * 7, rd_diff.unsigned_abs()); +} + +#[test] +fn test_arithmetic_cases() { + for (d0, d1, exp0, exp1, exp2, exp3) in ISO_DATE_PAIRS { + let d0 = Date::try_from_str(d0, Iso).unwrap(); + let d1 = Date::try_from_str(d1, Iso).unwrap(); + check(&d0, &d1, exp0, exp1, exp2, exp3); + } +} + +#[test] +fn test_hebrew() { + let m06z_20 = + Date::try_new_from_codes(None, 5783, MonthCode::new_normal(6).unwrap(), 20, Hebrew) + .unwrap(); + let m05l_15 = + Date::try_new_from_codes(None, 5784, MonthCode::new_leap(5).unwrap(), 15, Hebrew).unwrap(); + let m05l_30 = + Date::try_new_from_codes(None, 5784, MonthCode::new_leap(5).unwrap(), 30, Hebrew).unwrap(); + let m06a_29 = + Date::try_new_from_codes(None, 5784, MonthCode::new_normal(6).unwrap(), 29, Hebrew) + .unwrap(); + let m07a_10 = + Date::try_new_from_codes(None, 5784, MonthCode::new_normal(7).unwrap(), 10, Hebrew) + .unwrap(); + let m06b_15 = + Date::try_new_from_codes(None, 5785, MonthCode::new_normal(6).unwrap(), 15, Hebrew) + .unwrap(); + let m07b_20 = + Date::try_new_from_codes(None, 5785, MonthCode::new_normal(7).unwrap(), 20, Hebrew) + .unwrap(); + + #[rustfmt::skip] + #[allow(clippy::type_complexity)] + let cases: &[(&Date, &Date, u64, (u32, u64), (u32, u64), (u32, u32, u64))] = &[ + (&m06z_20, &m05l_15, 348, (49, 5), (11, 25), (0, 11, 25)), + (&m06z_20, &m05l_30, 363, (51, 6), (12, 10), (0, 12, 10)), + (&m06z_20, &m06a_29, 392, (56, 0), (13, 9), (1, 0, 9)), + (&m06z_20, &m07a_10, 402, (57, 3), (13, 19), (1, 0, 19)), + (&m06z_20, &m06b_15, 733, (104,5), (24, 25), (1, 11, 25)), + (&m06z_20, &m07b_20, 767, (109,4), (26, 0), (2, 1, 0)), + + (&m05l_15, &m05l_30, 15, (2, 1), (0, 15), (0, 0, 15)), + (&m05l_15, &m06a_29, 44, (6, 2), (1, 14), (0, 1, 14)), + (&m05l_15, &m07a_10, 54, (7, 5), (1, 24), (0, 1, 24)), + (&m05l_15, &m06b_15, 385, (55, 0), (13, 0), (1, 0, 0)), // M05L to M06 common year + (&m05l_15, &m07b_20, 419, (59, 6), (14, 5), (1, 1, 5)), // M05L to M07 common year + + (&m05l_30, &m06a_29, 29, (4, 1), (0, 29), (0, 0, 29)), + (&m05l_30, &m07a_10, 39, (5, 4), (1, 10), (0, 1, 10)), + (&m05l_30, &m06b_15, 370, (52, 6), (12, 15), (0, 12, 15)), // M05L to M06 common year + (&m05l_30, &m07b_20, 404, (57, 5), (13, 20), (1, 0, 20)), // M05L to M07 common year + + (&m06a_29, &m07a_10, 10, (1, 3), (0, 10), (0, 0, 10)), + (&m06a_29, &m06b_15, 341, (48, 5), (11, 16), (0, 11, 16)), // M06 leap year to M06 common year + (&m06a_29, &m07b_20, 375, (53, 4), (12, 20), (1, 0, 20)), // M06 leap year to M07 common year + (&m07a_10, &m06b_15, 331, (47, 2), (11, 5), (0, 11, 5)), // M07 leap year to M06 common year + (&m07a_10, &m07b_20, 365, (52, 1), (12, 10), (1, 0, 10)), // M07 leap year to M06 common year + (&m06b_15, &m07b_20, 34, (4, 6), (1, 5), (0, 1, 5)), + ]; + + for (d0, d1, exp0, exp1, exp2, exp3) in cases { + check(d0, d1, exp0, exp1, exp2, exp3); + } +} + +#[test] +fn test_tricky_leap_months() { + let mut add_options = DateAddOptions::default(); + add_options.overflow = Some(Overflow::Constrain); + let mut until_options = DateDifferenceOptions::default(); + until_options.largest_unit = Some(DateDurationUnit::Years); + + fn hebrew_date(year: i32, month: &str, day: u8) -> Date { + Date::try_new_from_codes(None, year, MonthCode(month.parse().unwrap()), day, Hebrew) + .unwrap() + } + + // M06 + 1yr = M06 (common to leap) + let date0 = hebrew_date(5783, "M06", 20); + let duration0 = DateDuration::for_years(1); + let date1 = date0 + .try_added_with_options(duration0, add_options) + .unwrap(); + assert_eq!(date1, hebrew_date(5784, "M06", 20)); + let duration0_actual = date0.try_until_with_options(&date1, until_options).unwrap(); + assert_eq!(duration0_actual, duration0); + + // M06 - 1mo = M05L (leap to leap) + let duration1 = DateDuration::for_months(-1); + let date2 = date1 + .try_added_with_options(duration1, add_options) + .unwrap(); + assert_eq!(date2, hebrew_date(5784, "M05L", 20)); + let duration1_actual = date1.try_until_with_options(&date2, until_options).unwrap(); + assert_eq!(duration1_actual, duration1); + + // M05L + 1yr1mo = M07 (leap to common) + let duration2 = DateDuration { + years: 1, + months: 1, + ..Default::default() + }; + let date3 = date2 + .try_added_with_options(duration2, add_options) + .unwrap(); + assert_eq!(date3, hebrew_date(5785, "M07", 20)); + let duration2_actual = date2.try_until_with_options(&date3, until_options).unwrap(); + assert_eq!(duration2_actual, duration2); + + // M06 + 1yr1mo = M07 (leap to common) + let date4 = date1 + .try_added_with_options(duration2, add_options) + .unwrap(); + assert_eq!(date4, hebrew_date(5785, "M07", 20)); + let duration2_actual = date1.try_until_with_options(&date4, until_options).unwrap(); + assert_eq!(duration2_actual, duration2); +} diff --git a/deps/crates/vendor/icu_calendar/tests/exhaustive.rs b/deps/crates/vendor/icu_calendar/tests/exhaustive.rs new file mode 100644 index 00000000000000..7552900a92fb2b --- /dev/null +++ b/deps/crates/vendor/icu_calendar/tests/exhaustive.rs @@ -0,0 +1,201 @@ +// 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_calendar::*; + +const MAGNITUDE: i32 = 1_000_000; + +// Check rd -> date -> iso -> date -> rd for whole range +#[test] +#[ignore] // takes about 200 seconds in release-with-assertions +fn check_round_trip() { + fn test(cal: C) { + let cal = Ref(&cal); + let low = Date::try_new_iso(-MAGNITUDE, 1, 1).unwrap().to_rata_die(); + let high = Date::try_new_iso(MAGNITUDE, 12, 31).unwrap().to_rata_die(); + let mut prev = Date::from_rata_die(low, cal); + let mut curr = low + 1; + while curr <= high { + let date = Date::from_rata_die(curr, cal); + assert!(prev < date); + + let rd = date.to_rata_die(); + assert_eq!(rd, curr, "{}", cal.as_calendar().debug_name()); + + let date2 = Date::new_from_iso(date.to_iso(), cal); + assert_eq!(date, date2, "{:?}", cal.as_calendar().debug_name()); + + prev = date; + curr += 1; + } + } + + for_each_calendar!(test); +} + +#[test] +#[ignore] // takes about 90 seconds in release-with-assertions +fn check_from_fields() { + fn test(cal: C) { + let cal = Ref(&cal); + + let codes = (1..19) + .flat_map(|i| { + [ + types::MonthCode::new_normal(i).unwrap(), + types::MonthCode::new_leap(i).unwrap(), + ] + .into_iter() + }) + .collect::>(); + for year in -MAGNITUDE..=MAGNITUDE { + if year % 50000 == 0 { + println!("{} {year:?}", cal.as_calendar().debug_name()); + } + for overflow in [options::Overflow::Constrain, options::Overflow::Reject] { + let mut options = options::DateFromFieldsOptions::default(); + options.overflow = Some(overflow); + for mut fields in codes + .iter() + .map(|m| { + let mut fields = types::DateFields::default(); + fields.month_code = Some(m.0.as_bytes()); + fields + }) + .chain((1..20).map(|m| { + let mut fields = types::DateFields::default(); + fields.ordinal_month = Some(m); + fields + })) + { + for day in 1..50 { + fields.extended_year = Some(year); + fields.day = Some(day); + let _ = Date::try_from_fields(fields, options, Ref(&cal)); + } + } + } + } + } + for_each_calendar!(test); +} + +macro_rules! for_each_calendar { + ($f:ident) => { + [ + || { + $f(cal::Buddhist); + println!("Buddhist done"); + }, + || { + $f(cal::east_asian_traditional::EastAsianTraditional( + EastAsianTraditionalYears::new(cal::east_asian_traditional::China::default()), + )); + println!("Chinese done"); + }, + || { + $f(cal::Coptic); + println!("Coptic done"); + }, + || { + $f(cal::east_asian_traditional::EastAsianTraditional( + EastAsianTraditionalYears::new(cal::east_asian_traditional::Korea::default()), + )); + println!("Korean done"); + }, + || { + $f(cal::Ethiopian::new()); + println!("Ethiopian done"); + }, + || { + $f(cal::Ethiopian::new_with_era_style( + cal::EthiopianEraStyle::AmeteAlem, + )); + println!("Ethiopian (Amete Alem) done"); + }, + || { + $f(cal::Gregorian); + println!("Gregorian done"); + }, + || { + $f(cal::Hebrew::new()); + println!("Hebrew done"); + }, + || { + $f(cal::Hijri::new_tabular( + cal::hijri::TabularAlgorithmLeapYears::TypeII, + cal::hijri::TabularAlgorithmEpoch::Friday, + )); + println!("Hijri (tabular) done"); + }, + || { + $f(cal::Hijri::new_tabular( + cal::hijri::TabularAlgorithmLeapYears::TypeII, + cal::hijri::TabularAlgorithmEpoch::Thursday, + )); + println!("Hijri (astronomical) done"); + }, + || { + $f(cal::Hijri::new_umm_al_qura()); + println!("Hijri (UAQ) done"); + }, + || { + $f(cal::Indian::new()); + println!("Indian done"); + }, + || { + $f(cal::Iso::new()); + println!("Iso done"); + }, + || { + $f(cal::Julian::new()); + println!("Julian done"); + }, + || { + $f(cal::Japanese::new()); + println!("Japanese done"); + }, + || { + $f(cal::JapaneseExtended::new()); + println!("JapaneseExtended done"); + }, + || { + $f(cal::Persian::new()); + println!("Persian done"); + }, + || { + $f(cal::Roc); + println!("Roc done"); + }, + ] + .map(std::thread::spawn) + .into_iter() + .for_each(|h| h.join().unwrap()); + }; +} +use for_each_calendar; + +// Precalculates Chinese years, significant performance improvement +#[derive(Debug, Clone)] +struct EastAsianTraditionalYears(Vec); + +impl EastAsianTraditionalYears { + fn new(r: R) -> Self { + Self( + ((-MAGNITUDE - 1)..=MAGNITUDE) + .map(|i| r.year_data(i)) + .collect(), + ) + } +} + +impl cal::scaffold::UnstableSealed for EastAsianTraditionalYears {} +impl cal::east_asian_traditional::Rules for EastAsianTraditionalYears { + fn year_data( + &self, + related_iso: i32, + ) -> cal::east_asian_traditional::EastAsianTraditionalYearData { + self.0[(related_iso + MAGNITUDE + 1) as usize] + } +} diff --git a/deps/crates/vendor/icu_calendar/tests/extended_year.rs b/deps/crates/vendor/icu_calendar/tests/extended_year.rs new file mode 100644 index 00000000000000..262dec5c24c913 --- /dev/null +++ b/deps/crates/vendor/icu_calendar/tests/extended_year.rs @@ -0,0 +1,85 @@ +// 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_calendar::types::MonthCode; +use icu_calendar::AnyCalendar; +use icu_calendar::AnyCalendarKind; +use icu_calendar::Date; + +#[cfg(test)] +use std::rc::Rc; + +/// Reference: +static EXTENDED_EPOCHS: &[(AnyCalendarKind, i32)] = &[ + (AnyCalendarKind::Buddhist, -543), + (AnyCalendarKind::Chinese, 0), + (AnyCalendarKind::Coptic, 283), + (AnyCalendarKind::Dangi, 0), + (AnyCalendarKind::Ethiopian, 7), + (AnyCalendarKind::EthiopianAmeteAlem, -5493), + (AnyCalendarKind::Gregorian, 0), + (AnyCalendarKind::Hebrew, -3761), + (AnyCalendarKind::Indian, 78), + (AnyCalendarKind::HijriTabularTypeIIFriday, 621), + (AnyCalendarKind::HijriSimulatedMecca, 621), + (AnyCalendarKind::HijriTabularTypeIIThursday, 621), + (AnyCalendarKind::HijriUmmAlQura, 621), + (AnyCalendarKind::Iso, 0), + (AnyCalendarKind::Japanese, 0), + (AnyCalendarKind::JapaneseExtended, 0), + (AnyCalendarKind::Persian, 621), + (AnyCalendarKind::Roc, 1911), +]; + +#[test] +fn test_extended_year() { + let iso = icu_calendar::cal::Iso; + let m_01 = MonthCode::new_normal(1).unwrap(); + for (kind, extended_epoch) in EXTENDED_EPOCHS.iter() { + let calendar = Rc::new(AnyCalendar::new(*kind)); + + // Create the first date in the epoch year (extended_year = 0) + let date_in_epoch_year = + Date::try_new_from_codes(None, 0, m_01, 1, calendar.clone()).unwrap(); + let iso_date_in_epoch_year = date_in_epoch_year.to_calendar(iso); + assert_eq!( + iso_date_in_epoch_year.extended_year(), + *extended_epoch, + "Extended year for {date_in_epoch_year:?} should be {extended_epoch}" + ); + + // Test that for all calendars except Japanese, the *current* era is + // the same as that used for the extended year + // This date can be anything as long as it is vaguely modern. + // + // Note that this property is not *required* by the specification, new + // calendars may have epochs that do not follow this property. This + // property is strongly suggested by the specification as a rule of thumb + // to follow where possible. + let iso_date_in_2025 = Date::try_new_iso(2025, 1, 1).unwrap(); + let date_in_2025 = iso_date_in_2025.to_calendar(calendar.clone()); + + // The extended year should align with the year in the modern era or related ISO. + // There is a special case for Japanese since it has a modern era but uses ISO for the extended year. + if matches!( + kind, + AnyCalendarKind::Japanese | AnyCalendarKind::JapaneseExtended + ) { + assert_eq!( + date_in_2025.extended_year(), + 2025, + "Extended year for {date_in_2025:?} should be 2025" + ); + } else { + // Note: This code only works because 2025 is in the modern era for all calendars. + // These two function calls are not equivalent in general. + let expected = date_in_2025.year().era_year_or_related_iso(); + assert_eq!( + date_in_2025.extended_year(), + expected, + "Extended year for {date_in_2025:?} should be {expected}" + ); + } + } +} diff --git a/deps/crates/vendor/icu_calendar/tests/reference_year.rs b/deps/crates/vendor/icu_calendar/tests/reference_year.rs new file mode 100644 index 00000000000000..35293569a68a9c --- /dev/null +++ b/deps/crates/vendor/icu_calendar/tests/reference_year.rs @@ -0,0 +1,323 @@ +// 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 std::{collections::HashSet, fmt::Debug}; + +use icu_calendar::{ + cal::*, + error::DateFromFieldsError, + options::{DateFromFieldsOptions, MissingFieldsStrategy, Overflow}, + types::{DateFields, MonthCode}, + Calendar, Date, Ref, +}; + +/// Test that a given calendar produces valid monthdays +/// +/// `valid_md_condition`, given (month_number, is_leap, day_number), should return whether or not +/// that combination is ever possible in that calendar +fn test_reference_year_impl(cal: C, valid_md_condition: impl Fn(u8, bool, u8) -> bool) +where + C: Calendar + Debug, +{ + // Test that all dates in a certain range behave according to Temporal + let mut month_days_seen = HashSet::new(); + let mut rd = Date::try_new_iso(1972, 12, 31).unwrap().to_rata_die(); + for _ in 1..2000 { + let date = Date::from_rata_die(rd, Ref(&cal)); + let month_day = (date.month().standard_code, date.day_of_month().0); + let mut fields = DateFields::default(); + fields.month_code = Some(month_day.0 .0.as_bytes()); + fields.day = Some(month_day.1); + let mut options = DateFromFieldsOptions::default(); + options.missing_fields_strategy = Some(MissingFieldsStrategy::Ecma); + let reference_date = Date::try_from_fields(fields, options, Ref(&cal)).unwrap(); + if month_days_seen.contains(&month_day) { + assert_ne!(date, reference_date, "{cal:?}"); + } else { + assert_eq!(date, reference_date, "{cal:?}"); + month_days_seen.insert(month_day); + } + rd -= 1; + } + // Test that all MonthDay values round-trip + for month_number in 1..=14 { + for is_leap in [false, true] { + let mut valid_day_number = 1; + let is_valid_month = valid_md_condition(month_number, is_leap, valid_day_number); + for day_number in 1..=32 { + if valid_md_condition(month_number, is_leap, day_number) { + valid_day_number = day_number; + } + let mut fields = DateFields::default(); + let mc = match is_leap { + false => MonthCode::new_normal(month_number), + true => MonthCode::new_leap(month_number), + }; + fields.month_code = mc.as_ref().map(|m| m.0.as_bytes()); + fields.day = Some(day_number); + let mut options = DateFromFieldsOptions::default(); + options.overflow = Some(Overflow::Constrain); + options.missing_fields_strategy = Some(MissingFieldsStrategy::Ecma); + let reference_date = match Date::try_from_fields(fields, options, Ref(&cal)) { + Ok(d) => { + assert!( + is_valid_month, + "try_from_fields passed but should have failed: {fields:?} => {d:?}" + ); + d + } + Err(DateFromFieldsError::MonthCodeNotInCalendar) => { + assert!( + !is_valid_month, + "try_from_fields failed but should have passed: {fields:?}" + ); + continue; + } + Err(e) => { + panic!("Unexpected error in month day from fields: {e}"); + } + }; + + // Test round-trip (to valid day number) + assert_eq!( + fields.month_code.unwrap(), + reference_date.month().standard_code.0.as_bytes(), + "{fields:?} {cal:?}" + ); + assert_eq!( + valid_day_number, + reference_date.day_of_month().0, + "{fields:?} {cal:?}" + ); + + // Test Overflow::Reject + options.overflow = Some(Overflow::Reject); + let reject_result = Date::try_from_fields(fields, options, Ref(&cal)); + if valid_day_number == day_number { + assert_eq!(reject_result, Ok(reference_date)); + } else { + assert!(matches!( + reject_result, + Err(DateFromFieldsError::Range { .. }) + )) + } + + // Test that ordinal months cause it to fail (even if the month code is still set) + fields.ordinal_month = Some(month_number); + let ordinal_result = Date::try_from_fields(fields, options, Ref(&cal)); + assert!(matches!( + ordinal_result, + Err(DateFromFieldsError::NotEnoughFields) + )); + } + } + } +} + +fn gregorian_md_condition(month_number: u8, is_leap: bool, day_number: u8) -> bool { + // No leap months + if is_leap { + return false; + } + + match month_number { + 1 | 3 | 5 | 7 | 8 | 10 | 12 => day_number <= 31, + 2 => day_number <= 29, + 4 | 6 | 9 | 11 => day_number <= 30, + _ => { + assert!(month_number > 12); + // No other months + false + } + } +} + +fn chinese_md_condition(month_number: u8, _is_leap: bool, day_number: u8) -> bool { + month_number <= 12 && day_number <= 30 +} + +fn coptic_md_condition(month_number: u8, is_leap: bool, day_number: u8) -> bool { + // No leap months + if is_leap { + return false; + } + match month_number { + 1..=12 => day_number <= 30, + 13 => day_number <= 6, + _ => false, + } +} + +fn hijri_md_condition(month_number: u8, is_leap: bool, day_number: u8) -> bool { + // No leap months + if is_leap { + return false; + } + month_number <= 12 && day_number <= 30 +} + +fn hijri_tabular_md_condition(month_number: u8, is_leap: bool, day_number: u8) -> bool { + // No leap months + if is_leap { + return false; + } + + if month_number > 12 { + return false; + } + + // Odd months have 30 days, even months have 29, except for M12 in a leap year + if month_number % 2 == 0 { + if month_number == 12 { + day_number <= 30 + } else { + day_number <= 29 + } + } else { + day_number <= 30 + } +} + +fn hebrew_md_condition(month_number: u8, is_leap: bool, day_number: u8) -> bool { + if is_leap { + return month_number == 5 && day_number <= 30; + } + match month_number { + 1 | 2 | 3 | 5 | 7 | 9 | 11 => day_number <= 30, + // Tevet, Adar, Iyar, Tammuz, Elul + 4 | 6 | 8 | 10 | 12 => day_number <= 29, + _ => { + assert!(month_number > 12); + // No other months + false + } + } +} + +#[test] +fn test_reference_year_buddhist() { + test_reference_year_impl(Buddhist, gregorian_md_condition) +} + +#[test] +fn test_reference_year_chinese() { + test_reference_year_impl(ChineseTraditional::new(), chinese_md_condition) +} + +#[test] +fn test_reference_year_coptic() { + test_reference_year_impl(Coptic, coptic_md_condition) +} + +#[test] +fn test_reference_year_korean() { + test_reference_year_impl(KoreanTraditional::new(), chinese_md_condition) +} + +#[test] +fn test_reference_year_ethiopian() { + test_reference_year_impl(Ethiopian::new(), coptic_md_condition) +} + +#[test] +fn test_reference_year_ethiopian_amete_alem() { + test_reference_year_impl( + Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteAlem), + coptic_md_condition, + ) +} + +#[test] +fn test_reference_year_gregorian() { + test_reference_year_impl(Gregorian, gregorian_md_condition) +} + +#[test] +fn test_reference_year_julian() { + test_reference_year_impl(Julian, gregorian_md_condition) +} + +#[test] +fn test_reference_year_hebrew() { + test_reference_year_impl(Hebrew, hebrew_md_condition) +} + +#[test] +fn test_reference_year_indian() { + test_reference_year_impl(Indian, |month_number, is_leap, day_number| { + if is_leap { + // No leap months + return false; + } + // First half of the year has long months, second half short + if month_number <= 6 { + day_number <= 31 + } else if month_number <= 12 { + day_number <= 30 + } else { + // No larger months + false + } + }) +} + +#[test] +fn test_reference_year_hijri_tabular_type_ii_friday() { + test_reference_year_impl( + Hijri::new_tabular(HijriTabularLeapYears::TypeII, HijriTabularEpoch::Friday), + hijri_tabular_md_condition, + ) +} + +#[test] +fn test_reference_year_hijri_tabular_type_ii_thursday() { + test_reference_year_impl( + Hijri::new_tabular(HijriTabularLeapYears::TypeII, HijriTabularEpoch::Thursday), + hijri_tabular_md_condition, + ) +} + +#[test] +fn test_reference_year_hijri_umm_al_qura() { + test_reference_year_impl(Hijri::new_umm_al_qura(), hijri_md_condition) +} + +#[test] +fn test_reference_year_iso() { + test_reference_year_impl(Iso, gregorian_md_condition) +} + +#[test] +fn test_reference_year_japanese() { + test_reference_year_impl(Japanese::new(), gregorian_md_condition) +} + +#[test] +fn test_reference_year_japanese_extended() { + test_reference_year_impl(JapaneseExtended::new(), gregorian_md_condition) +} + +#[test] +fn test_reference_year_persian() { + test_reference_year_impl(Persian, |month_number, is_leap, day_number| { + if is_leap { + // No leap months + return false; + } + // First half of the year has long months, second half short + if month_number <= 6 { + day_number <= 31 + } else if month_number <= 12 { + day_number <= 30 + } else { + // No larger months + false + } + }) +} + +#[test] +fn test_reference_year_roc() { + test_reference_year_impl(Roc, gregorian_md_condition) +} diff --git a/deps/crates/vendor/icu_calendar_data/.cargo-checksum.json b/deps/crates/vendor/icu_calendar_data/.cargo-checksum.json index 1f89ad9e1d30ab..5581eabccf52bd 100644 --- a/deps/crates/vendor/icu_calendar_data/.cargo-checksum.json +++ b/deps/crates/vendor/icu_calendar_data/.cargo-checksum.json @@ -1 +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 +{"files":{".cargo_vcs_info.json":"5ddfa3bbe4563249b2050508901cbefb05bd351ea39f5f4add8bc520346ce932","Cargo.lock":"af8b0f1887466167d9776494d3fd9cd8d63b742147ef69538987e7ec190da413","Cargo.toml":"ecdae7056aa05f5e981175be5c1ba744f819438cef7db31d3f9873fbbfe22575","Cargo.toml.orig":"31d1f8d246401f127cd0738522290375cd6124a8ef9232a650aded78f8071ded","LICENSE":"f367c1b8e1aa262435251e442901da4607b4650e0e63a026f5044473ecfb90f2","README.md":"089095cfdb8ce866d7ca71b51433144fb4878dc4ca9b5590b2327b11fdb64b1b","build.rs":"c2d446772e3d766a804963dbf36e51729f910920f91f4b68c0c199fe6ca0853e","data/calendar_japanese_extended_v1.rs.data":"079e4f46ffd69977a95364c12df5455342cd8dc03593b44d2fb73fe06c7145ef","data/calendar_japanese_modern_v1.rs.data":"3b836a21d5e537e06e3b767d44aee023222113415bcc3dbf87248fa89de70928","data/calendar_week_v1.rs.data":"c59edb26ec8b391b52ffa6ad9088d8a51b8353cffc04268701a824e0e9b76c21","data/mod.rs":"ad146e2fac0e7858fea7a10082a8bd63ae0a014b6ff885b041c66c7cc2579bbd","src/lib.rs":"bfc8989a13fe15781d30b59aa152d1806d99a77dbf326d118c5e196a534ccef0"},"package":"527f04223b17edfe0bd43baf14a0cb1b017830db65f3950dc00224860a9a446d"} \ No newline at end of file diff --git a/deps/crates/vendor/icu_calendar_data/.cargo_vcs_info.json b/deps/crates/vendor/icu_calendar_data/.cargo_vcs_info.json new file mode 100644 index 00000000000000..266c749a288779 --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "38a49da495248dd1ded84cf306e4ca42e64d5bb3" + }, + "path_in_vcs": "provider/data/calendar" +} \ No newline at end of file diff --git a/deps/crates/vendor/icu_calendar_data/Cargo.lock b/deps/crates/vendor/icu_calendar_data/Cargo.lock new file mode 100644 index 00000000000000..5b794b991b85ba --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "icu_calendar_data" +version = "2.1.1" diff --git a/deps/crates/vendor/icu_calendar_data/Cargo.toml b/deps/crates/vendor/icu_calendar_data/Cargo.toml index 48da7be47196bc..0f20ba005c23ec 100644 --- a/deps/crates/vendor/icu_calendar_data/Cargo.toml +++ b/deps/crates/vendor/icu_calendar_data/Cargo.toml @@ -11,9 +11,9 @@ [package] edition = "2021" -rust-version = "1.82" +rust-version = "1.83" name = "icu_calendar_data" -version = "2.0.0" +version = "2.1.1" authors = ["The ICU4X Project Developers"] build = "build.rs" include = [ @@ -40,10 +40,10 @@ license = "Unicode-3.0" repository = "https://github.com/unicode-org/icu4x" [package.metadata.sources.cldr] -tagged = "47.0.0" +tagged = "48.0.0" [package.metadata.sources.icuexport] -tagged = "icu4x/2025-05-01/77.x" +tagged = "release-78.1rc" [package.metadata.sources.segmenter_lstm] tagged = "v0.1.0" diff --git a/deps/crates/vendor/icu_calendar_data/Cargo.toml.orig b/deps/crates/vendor/icu_calendar_data/Cargo.toml.orig new file mode 100644 index 00000000000000..238a48230dabce --- /dev/null +++ b/deps/crates/vendor/icu_calendar_data/Cargo.toml.orig @@ -0,0 +1,27 @@ +# 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 ). + +[package] +name = "icu_calendar_data" +description = "Data for the icu_calendar crate" +license = "Unicode-3.0" +version.workspace = true + +authors.workspace = true +categories.workspace = true +edition.workspace = true +homepage.workspace = true +include.workspace = true +repository.workspace = true +rust-version.workspace = true + +[package.metadata.sources] +cldr = { tagged = "48.0.0" } +icuexport = { tagged = "release-78.1rc" } +segmenter_lstm = { tagged = "v0.1.0" } + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(icu4x_custom_data)'] } + +[dependencies] diff --git a/deps/crates/vendor/icu_calendar_data/README.md b/deps/crates/vendor/icu_calendar_data/README.md index 19c1f48292c481..b90473a6571cc5 100644 --- a/deps/crates/vendor/icu_calendar_data/README.md +++ b/deps/crates/vendor/icu_calendar_data/README.md @@ -4,7 +4,7 @@ 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 +This data was generated with CLDR version 48.0.0, ICU version release-78.1rc, and LSTM segmenter version v0.1.0. 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 deleted file mode 100644 index 944a49c45490c8..00000000000000 --- a/deps/crates/vendor/icu_calendar_data/data/calendar_chinese_v1.rs.data +++ /dev/null @@ -1,75 +0,0 @@ -// @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 deleted file mode 100644 index 30045896317596..00000000000000 --- a/deps/crates/vendor/icu_calendar_data/data/calendar_dangi_v1.rs.data +++ /dev/null @@ -1,75 +0,0 @@ -// @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 deleted file mode 100644 index 4803503a2a71f8..00000000000000 --- a/deps/crates/vendor/icu_calendar_data/data/calendar_hijri_simulated_mecca_v1.rs.data +++ /dev/null @@ -1,75 +0,0 @@ -// @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 index 338b69e5c61508..96a1dd8fd31809 100644 --- 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 @@ -7,18 +7,23 @@ /// * 5238B[^1] for the singleton data struct /// /// [^1]: these numbers can be smaller in practice due to linker deduplication +/// +/// This macro requires the following crates: +/// * `icu` +/// * `icu_provider` +/// * `zerovec` #[doc(hidden)] #[macro_export] macro_rules! __impl_calendar_japanese_extended_v1 { ($ provider : ty) => { - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] 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"] + #[clippy::msrv = "1.83"] impl icu_provider::DataProvider for $provider { fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { if req.id.locale.is_unknown() { @@ -31,7 +36,7 @@ macro_rules! __impl_calendar_japanese_extended_v1 { }; ($ provider : ty , ITER) => { __impl_calendar_japanese_extended_v1!($provider); - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] impl icu_provider::IterableDataProvider for $provider { fn iter_ids(&self) -> Result>, icu_provider::DataError> { Ok([Default::default()].into_iter().collect()) @@ -40,7 +45,7 @@ macro_rules! __impl_calendar_japanese_extended_v1 { }; ($ provider : ty , DRY) => { __impl_calendar_japanese_extended_v1!($provider); - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] impl icu_provider::DryDataProvider for $provider { fn dry_load(&self, req: icu_provider::DataRequest) -> Result { if req.id.locale.is_unknown() { @@ -53,7 +58,7 @@ macro_rules! __impl_calendar_japanese_extended_v1 { }; ($ provider : ty , DRY , ITER) => { __impl_calendar_japanese_extended_v1!($provider); - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] impl icu_provider::DryDataProvider for $provider { fn dry_load(&self, req: icu_provider::DataRequest) -> Result { if req.id.locale.is_unknown() { @@ -63,7 +68,7 @@ macro_rules! __impl_calendar_japanese_extended_v1 { } } } - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] impl icu_provider::IterableDataProvider for $provider { fn iter_ids(&self) -> Result>, icu_provider::DataError> { Ok([Default::default()].into_iter().collect()) 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 index b86298cbcec181..31c7a3de95d2b8 100644 --- 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 @@ -7,18 +7,23 @@ /// * 134B[^1] for the singleton data struct /// /// [^1]: these numbers can be smaller in practice due to linker deduplication +/// +/// This macro requires the following crates: +/// * `icu` +/// * `icu_provider` +/// * `zerovec` #[doc(hidden)] #[macro_export] macro_rules! __impl_calendar_japanese_modern_v1 { ($ provider : ty) => { - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] 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"] + #[clippy::msrv = "1.83"] impl icu_provider::DataProvider for $provider { fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { if req.id.locale.is_unknown() { @@ -31,7 +36,7 @@ macro_rules! __impl_calendar_japanese_modern_v1 { }; ($ provider : ty , ITER) => { __impl_calendar_japanese_modern_v1!($provider); - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] impl icu_provider::IterableDataProvider for $provider { fn iter_ids(&self) -> Result>, icu_provider::DataError> { Ok([Default::default()].into_iter().collect()) @@ -40,7 +45,7 @@ macro_rules! __impl_calendar_japanese_modern_v1 { }; ($ provider : ty , DRY) => { __impl_calendar_japanese_modern_v1!($provider); - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] impl icu_provider::DryDataProvider for $provider { fn dry_load(&self, req: icu_provider::DataRequest) -> Result { if req.id.locale.is_unknown() { @@ -53,7 +58,7 @@ macro_rules! __impl_calendar_japanese_modern_v1 { }; ($ provider : ty , DRY , ITER) => { __impl_calendar_japanese_modern_v1!($provider); - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] impl icu_provider::DryDataProvider for $provider { fn dry_load(&self, req: icu_provider::DataRequest) -> Result { if req.id.locale.is_unknown() { @@ -63,7 +68,7 @@ macro_rules! __impl_calendar_japanese_modern_v1 { } } } - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] impl icu_provider::IterableDataProvider for $provider { fn iter_ids(&self) -> Result>, icu_provider::DataError> { Ok([Default::default()].into_iter().collect()) 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 index 6a1c737066c3f0..d28cb3677c509d 100644 --- 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 @@ -4,25 +4,30 @@ /// `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) +/// * 295B for the lookup data structure (73 data identifiers) /// * 20B[^1] for the actual data (10 unique structs) /// /// [^1]: these numbers can be smaller in practice due to linker deduplication +/// +/// This macro requires the following crates: +/// * `icu` +/// * `icu_provider` +/// * `icu_provider/baked` #[doc(hidden)] #[macro_export] macro_rules! __impl_calendar_week_v1 { ($ provider : ty) => { - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] 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 = 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"] + #[clippy::msrv = "1.83"] impl icu_provider::DataProvider for $provider { fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { let mut metadata = icu_provider::DataResponseMetadata::default(); @@ -48,7 +53,7 @@ macro_rules! __impl_calendar_week_v1 { }; ($ provider : ty , ITER) => { __impl_calendar_week_v1!($provider); - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] 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()) diff --git a/deps/crates/vendor/icu_calendar_data/data/mod.rs b/deps/crates/vendor/icu_calendar_data/data/mod.rs index 84e6f6c55ee844..1ad69179b4969a 100644 --- a/deps/crates/vendor/icu_calendar_data/data/mod.rs +++ b/deps/crates/vendor/icu_calendar_data/data/mod.rs @@ -2,9 +2,6 @@ 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. /// @@ -20,7 +17,7 @@ include!("calendar_chinese_v1.rs.data"); #[macro_export] macro_rules! __make_provider { ($ name : ty) => { - #[clippy::msrv = "1.82"] + #[clippy::msrv = "1.83"] impl $name { #[allow(dead_code)] pub(crate) const MUST_USE_MAKE_PROVIDER_MACRO: () = (); @@ -30,6 +27,11 @@ macro_rules! __make_provider { } #[doc(inline)] pub use __make_provider as make_provider; +/// This macro requires the following crates: +/// * `icu` +/// * `icu_provider` +/// * `icu_provider/baked` +/// * `zerovec` #[allow(unused_macros)] macro_rules! impl_data_provider { ($ provider : ty) => { @@ -37,8 +39,5 @@ macro_rules! impl_data_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 index 2a3674bc16bb94..02ec18a35cc963 100644 --- a/deps/crates/vendor/icu_calendar_data/src/lib.rs +++ b/deps/crates/vendor/icu_calendar_data/src/lib.rs @@ -4,7 +4,7 @@ //! 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 +//! This data was generated with CLDR version 48.0.0, ICU version release-78.1rc, and //! LSTM segmenter version v0.1.0. #![no_std] diff --git a/deps/crates/vendor/icu_collections/.cargo-checksum.json b/deps/crates/vendor/icu_collections/.cargo-checksum.json index 87873bb53d1812..c83ec60da50d71 100644 --- a/deps/crates/vendor/icu_collections/.cargo-checksum.json +++ b/deps/crates/vendor/icu_collections/.cargo-checksum.json @@ -1 +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 +{"files":{".cargo_vcs_info.json":"f5ad06d6d816d1d211ec86d639b4fd2b6551db6e9bdcd37c3c7ccc47f1873618","Cargo.lock":"281b1642001f508afaf929a328b2d2801baa78b91f7e98e9aee6f39f7bd467a9","Cargo.toml":"8f7a2c13e5f27b3edcadac862f50ff5fd16689ec83bcca9a5a6bb0670918263d","Cargo.toml.orig":"963d26428f923ead6ef52219b65549eabcba96bef3e3dcb67279e6fa9c4cef3d","LICENSE":"f367c1b8e1aa262435251e442901da4607b4650e0e63a026f5044473ecfb90f2","README.md":"b1a0b37b61d42026996dda3b7d524d42888181f3e7eaf940c9b2e5f561c449e3","benches/codepointtrie.rs":"4052e9e3a3a744955a5ab3f7089cafaf2920ad5c7566fc8b3b77ee1d39376c20","benches/iai_cpt.rs":"a8ed4e67866d415e6ed0c8c95a9b1887b4198ea409d4cd9efafb50b8c13b3ecc","benches/inv_list.rs":"39e0386fd0e908d6e18b16e021345ba8c88fa70e06e26a29913dfa218a68b03d","benches/tries/gc_fast.rs":"4761a339f9b266813f4fa7ffa229b3464ced2ed106ce712ae6a96c0e49e5224e","benches/tries/gc_small.rs":"a1a75d2325dbce031e0127de8d84e900ca7c73ec81da1679965ab0127a99c205","benches/tries/mod.rs":"82cfdd1c5870d343613098fdff5a7961cfe5645a33480c6a252efae9a074e022","src/char16trie/mod.rs":"5950a1b427743e956b459956cadd72ff7531fe46bfb871d8e3a848b1e4ab0657","src/char16trie/trie.rs":"20ac75a0e2f3bcb74c619e98f44b3cc1f41bea2787ceef186d54cf997a1d9264","src/codepointinvlist/builder.rs":"bb0796333ca76d7714ee8425201a5957ab6b26b55dc049c34b3fb1839afc1581","src/codepointinvlist/conversions.rs":"8ac096ae63fa508ee2d7b2805aca864971110accaa358c178855540074e2ad21","src/codepointinvlist/cpinvlist.rs":"f9b47dd0432379637e194c2adf5acfcb91372a7f896cfab378928ffe65969532","src/codepointinvlist/mod.rs":"d48bc8ff1d103c4e37c4729181bc90b5e5e0db7701a49bd53c4d8c67e9089eb0","src/codepointinvlist/utils.rs":"6d6b4f5884beb830c16b6e5df07688f8cd70e2293a96d03037be690896d514e1","src/codepointinvliststringlist/mod.rs":"1fdb0b404f0b9a44218157ae1b58712d3ff7fe5b1d23521514a5eb36587d68df","src/codepointtrie/cptrie.rs":"dc7133751f32c74f3a87b1eb60e705aa0766a622ce48845aaa466f055267f6f2","src/codepointtrie/error.rs":"028dd55421b0bebf1634ad99752dbe349b40ab10ca565aa6bb134c5885ffd87b","src/codepointtrie/impl_const.rs":"ff25fa0d54e174c289b25a6060f50e03c8aa41bad922c9386de3148f8ad95109","src/codepointtrie/mod.rs":"d77de5edc258bbe79e0b6a37fedd315478fea6f9fd46c6923c564d045ac053d6","src/codepointtrie/planes.rs":"8a063b1efce889e46e69c7000ce48eeb420bb861f4ceafa839faaa944715c7bb","src/codepointtrie/serde.rs":"103bf57194a4d2111ed064d9bf2796b4ff7b5c2b1a1222a7378bad8143aa453f","src/codepointtrie/toml.rs":"6185421c1384e6a9a69b57153e1dcd793665ceb385dff2b61a2c1b0508609ec3","src/iterator_utils.rs":"2a5dfab19a752ae495617d68c07d11d1c0fbded233221dc43e9dd8f959001cd9","src/lib.rs":"a15ba283ccb32fc9a1cbe67166fa8eac5cd9225e4de022d09b057be4ff8eb688","tests/char16trie.rs":"f8018b90187f3b99a6a835c1c41bced18d98a28c41822abf3536cd1f0f08c44f","tests/cpt.rs":"3a151ba56273a29777f0a7656e533f4a603281569dd5349e15f837d2b9ec65e8","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":"4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"} \ No newline at end of file diff --git a/deps/crates/vendor/icu_collections/.cargo_vcs_info.json b/deps/crates/vendor/icu_collections/.cargo_vcs_info.json new file mode 100644 index 00000000000000..4364a1d8632a00 --- /dev/null +++ b/deps/crates/vendor/icu_collections/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "38a49da495248dd1ded84cf306e4ca42e64d5bb3" + }, + "path_in_vcs": "components/collections" +} \ No newline at end of file diff --git a/deps/crates/vendor/icu_collections/Cargo.lock b/deps/crates/vendor/icu_collections/Cargo.lock index 2cf19f6502f5e8..ae29068d4b0956 100644 --- a/deps/crates/vendor/icu_collections/Cargo.lock +++ b/deps/crates/vendor/icu_collections/Cargo.lock @@ -19,21 +19,21 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "cast" @@ -43,9 +43,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "ciborium" @@ -101,9 +101,12 @@ checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "cobs" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror", +] [[package]] name = "criterion" @@ -168,9 +171,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "databake" @@ -242,15 +245,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.3" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" [[package]] name = "hermit-abi" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "iai" @@ -260,7 +263,7 @@ checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678" [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" dependencies = [ "criterion", "databake", @@ -278,9 +281,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", "hashbrown", @@ -288,9 +291,9 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", @@ -314,9 +317,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" dependencies = [ "once_cell", "wasm-bindgen", @@ -324,21 +327,21 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.172" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "num-traits" @@ -391,9 +394,9 @@ dependencies = [ [[package]] name = "postcard" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" dependencies = [ "cobs", "embedded-io 0.4.0", @@ -403,28 +406,28 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ - "serde", + "serde_core", "zerovec", ] [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" dependencies = [ "proc-macro2", ] @@ -451,9 +454,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.1" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -463,9 +466,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -474,15 +477,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -501,18 +504,28 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +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 = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -521,36 +534,37 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "syn" -version = "2.0.101" +version = "2.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" dependencies = [ "proc-macro2", "quote", @@ -568,6 +582,26 @@ dependencies = [ "syn", ] +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -580,9 +614,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", @@ -592,18 +626,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.26" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", @@ -614,9 +648,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" [[package]] name = "walkdir" @@ -630,21 +664,22 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" dependencies = [ "bumpalo", "log", @@ -656,9 +691,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -666,9 +701,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" dependencies = [ "proc-macro2", "quote", @@ -679,18 +714,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" dependencies = [ "js-sys", "wasm-bindgen", @@ -698,100 +733,42 @@ dependencies = [ [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ "windows-sys", ] [[package]] -name = "windows-sys" -version = "0.59.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-targets" -version = "0.52.6" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" 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", + "windows-link", ] -[[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" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -800,9 +777,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", @@ -833,9 +810,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "databake", "serde", @@ -846,9 +823,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", diff --git a/deps/crates/vendor/icu_collections/Cargo.toml b/deps/crates/vendor/icu_collections/Cargo.toml index 5fd8b60b4ee492..abb0a93530006f 100644 --- a/deps/crates/vendor/icu_collections/Cargo.toml +++ b/deps/crates/vendor/icu_collections/Cargo.toml @@ -11,9 +11,9 @@ [package] edition = "2021" -rust-version = "1.82" +rust-version = "1.83" name = "icu_collections" -version = "2.0.0" +version = "2.1.1" authors = ["The ICU4X Project Developers"] build = false include = [ @@ -43,7 +43,10 @@ repository = "https://github.com/unicode-org/icu4x" all-features = true [features] -alloc = ["zerovec/alloc"] +alloc = [ + "serde?/alloc", + "zerovec/alloc", +] databake = [ "dep:databake", "zerovec/databake", @@ -60,10 +63,6 @@ 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" @@ -98,16 +97,13 @@ version = "0.2.3" default-features = false [dependencies.potential_utf] -version = "0.1.1" +version = "0.1.3" features = ["zerovec"] default-features = false [dependencies.serde] -version = "1.0.110" -features = [ - "derive", - "alloc", -] +version = "1.0.220" +features = ["derive"] optional = true default-features = false @@ -122,7 +118,7 @@ features = ["derive"] default-features = false [dependencies.zerovec] -version = "0.11.1" +version = "0.11.3" features = [ "derive", "yoke", @@ -138,7 +134,7 @@ features = ["alloc"] default-features = false [dev-dependencies.serde] -version = "1.0.110" +version = "1.0.220" features = ["derive"] default-features = false diff --git a/deps/crates/vendor/icu_collections/Cargo.toml.orig b/deps/crates/vendor/icu_collections/Cargo.toml.orig new file mode 100644 index 00000000000000..5e93a0cd333c53 --- /dev/null +++ b/deps/crates/vendor/icu_collections/Cargo.toml.orig @@ -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 ). + +[package] +name = "icu_collections" +description = "Collection of API for use in ICU libraries." + +authors.workspace = true +categories.workspace = true +edition.workspace = true +homepage.workspace = true +include.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true +version.workspace = true + +[package.metadata.docs.rs] +all-features = true + +[dependencies] +displaydoc = { workspace = true } +yoke = { workspace = true, features = ["derive"] } +zerofrom = { workspace = true, features = ["derive"] } +zerovec = { workspace = true, features = ["derive", "yoke"] } +potential_utf = { workspace = true, features = ["zerovec"] } + +serde = { workspace = true, features = ["derive"], optional = true } +databake = { workspace = true, features = ["derive"], optional = true } + +[dev-dependencies] +iai = { workspace = true } +icu = { path = "../../components/icu", default-features = false } +icu_properties = { path = "../../components/properties" } +postcard = { workspace = true, features = ["alloc"] } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } + +toml = { workspace = true } + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +criterion = { workspace = true } + +[features] +serde = ["dep:serde", "zerovec/serde", "potential_utf/serde", "alloc"] +databake = ["dep:databake", "zerovec/databake"] +alloc = ["serde?/alloc", "zerovec/alloc"] + +[lib] +bench = false # This option is required for Benchmark CI + +[[bench]] +name = "codepointtrie" +harness = false +path = "benches/codepointtrie.rs" + +[[bench]] +name = "iai_cpt" +harness = false +path = "benches/iai_cpt.rs" + +[[bench]] +name = "inv_list" +harness = false +path = "benches/inv_list.rs" diff --git a/deps/crates/vendor/icu_collections/benches/inv_list.rs b/deps/crates/vendor/icu_collections/benches/inv_list.rs index 41a23568046090..743c855af8c745 100644 --- a/deps/crates/vendor/icu_collections/benches/inv_list.rs +++ b/deps/crates/vendor/icu_collections/benches/inv_list.rs @@ -14,7 +14,7 @@ fn uniset_bench(c: &mut Criterion) { CodePointInversionList::try_from_u32_inversion_list_slice(&worst_ex).unwrap(); c.bench_function("uniset/overview", |b| { - #[allow(clippy::suspicious_map)] + #[expect(clippy::suspicious_map)] b.iter(|| { best_sample .iter_chars() 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 deleted file mode 100644 index c29f1d25000564..00000000000000 --- a/deps/crates/vendor/icu_collections/examples/unicode_bmp_blocks_selector.rs +++ /dev/null @@ -1,71 +0,0 @@ -// 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/trie.rs b/deps/crates/vendor/icu_collections/src/char16trie/trie.rs index 1d48307957c3ce..5aedccabe5e1c4 100644 --- a/deps/crates/vendor/icu_collections/src/char16trie/trie.rs +++ b/deps/crates/vendor/icu_collections/src/char16trie/trie.rs @@ -88,12 +88,14 @@ pub struct Char16Trie<'data> { impl<'data> Char16Trie<'data> { /// Returns a new [`Char16Trie`] with ownership of the provided data. + #[inline] 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 { + #[inline] + pub fn iter(&self) -> Char16TrieIterator<'_> { Char16TrieIterator::new(&self.data) } } @@ -164,6 +166,7 @@ macro_rules! trie_unwrap { impl<'a> Char16TrieIterator<'a> { /// Returns a new [`Char16TrieIterator`] backed by borrowed data for the `trie` array + #[inline] pub fn new(trie: &'a ZeroSlice) -> Self { Self { trie, diff --git a/deps/crates/vendor/icu_collections/src/codepointinvlist/builder.rs b/deps/crates/vendor/icu_collections/src/codepointinvlist/builder.rs index f5b019dd58ff08..d12cba38626269 100644 --- a/deps/crates/vendor/icu_collections/src/codepointinvlist/builder.rs +++ b/deps/crates/vendor/icu_collections/src/codepointinvlist/builder.rs @@ -32,7 +32,7 @@ impl CodePointInversionListBuilder { .into_iter() .map(PotentialCodePoint::from_u24) .collect(); - #[allow(clippy::unwrap_used)] // by invariant + #[expect(clippy::unwrap_used)] // by invariant CodePointInversionList::try_from_inversion_list(inv_list).unwrap() } @@ -51,7 +51,7 @@ impl CodePointInversionListBuilder { 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 + #[expect(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 { @@ -182,7 +182,7 @@ impl CodePointInversionListBuilder { /// ``` #[allow(unused_assignments)] pub fn add_set(&mut self, set: &CodePointInversionList) { - #[allow(clippy::indexing_slicing)] // chunks + #[expect(clippy::indexing_slicing)] // chunks set.as_inversion_list() .as_ule_slice() .chunks(2) @@ -203,7 +203,7 @@ impl CodePointInversionListBuilder { return; } if let Some(&last) = self.intervals.last() { - #[allow(clippy::indexing_slicing)] + #[expect(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(); @@ -267,7 +267,7 @@ impl CodePointInversionListBuilder { /// builder.remove_set(&set); // removes 'A'..='E' /// let check = builder.build(); /// assert_eq!(check.iter_chars().next(), Some('F')); - #[allow(clippy::indexing_slicing)] // chunks + #[expect(clippy::indexing_slicing)] // chunks pub fn remove_set(&mut self, set: &CodePointInversionList) { set.as_inversion_list() .as_ule_slice() @@ -350,7 +350,7 @@ impl CodePointInversionListBuilder { /// assert!(check.contains('A')); /// assert!(!check.contains('G')); /// ``` - #[allow(clippy::indexing_slicing)] // chunks + #[expect(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) { @@ -424,7 +424,7 @@ impl CodePointInversionListBuilder { /// ``` pub fn complement(&mut self) { if !self.intervals.is_empty() { - #[allow(clippy::indexing_slicing)] // by invariant + #[expect(clippy::indexing_slicing)] // by invariant if self.intervals[0] == 0 { self.intervals.drain(0..1); } else { diff --git a/deps/crates/vendor/icu_collections/src/codepointinvlist/conversions.rs b/deps/crates/vendor/icu_collections/src/codepointinvlist/conversions.rs index 9e4cb380c7b41f..7488654a8f32b2 100644 --- a/deps/crates/vendor/icu_collections/src/codepointinvlist/conversions.rs +++ b/deps/crates/vendor/icu_collections/src/codepointinvlist/conversions.rs @@ -25,7 +25,7 @@ fn try_from_range<'data>( PotentialCodePoint::from_u24(till), ]; let inv_list: ZeroVec = ZeroVec::alloc_from_slice(&set); - #[allow(clippy::unwrap_used)] // valid + #[expect(clippy::unwrap_used)] // valid Ok(CodePointInversionList::try_from_inversion_list(inv_list).unwrap()) } else { Err(RangeError(from, till)) diff --git a/deps/crates/vendor/icu_collections/src/codepointinvlist/cpinvlist.rs b/deps/crates/vendor/icu_collections/src/codepointinvlist/cpinvlist.rs index 3b63ff365d3a79..02f624cdd16a73 100644 --- a/deps/crates/vendor/icu_collections/src/codepointinvlist/cpinvlist.rs +++ b/deps/crates/vendor/icu_collections/src/codepointinvlist/cpinvlist.rs @@ -120,7 +120,7 @@ impl UnicodeCodePoint { if cp <= char::MAX as u32 { Ok(Self(cp)) } else { - Err(format!("Not a Unicode code point {}", cp)) + Err(format!("Not a Unicode code point {cp}")) } } @@ -221,7 +221,7 @@ impl<'data> CodePointInversionList<'data> { pub fn try_from_inversion_list( inv_list: ZeroVec<'data, PotentialCodePoint>, ) -> Result { - #[allow(clippy::indexing_slicing)] // chunks + #[expect(clippy::indexing_slicing)] // chunks if is_valid_zv(&inv_list) { let size = inv_list .as_ule_slice() @@ -255,6 +255,8 @@ impl<'data> CodePointInversionList<'data> { /// 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. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -290,6 +292,8 @@ impl<'data> CodePointInversionList<'data> { } /// Attempts to convert this list into a fully-owned one. No-op if already fully owned + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] pub fn into_owned(self) -> CodePointInversionList<'static> { CodePointInversionList { @@ -299,6 +303,8 @@ impl<'data> CodePointInversionList<'data> { } /// Returns an owned inversion list representing the current [`CodePointInversionList`] + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] pub fn get_inversion_list_vec(&self) -> Vec { self.as_inversion_list().iter().map(u32::from).collect() @@ -362,7 +368,7 @@ impl<'data> CodePointInversionList<'data> { /// /// Public only to the crate, not exposed to public #[cfg(feature = "alloc")] - pub(crate) fn as_inversion_list(&self) -> &ZeroVec { + pub(crate) fn as_inversion_list(&self) -> &ZeroVec<'_, PotentialCodePoint> { &self.inv_list } @@ -385,7 +391,7 @@ impl<'data> CodePointInversionList<'data> { /// assert_eq!(None, ex_iter_chars.next()); /// ``` pub fn iter_chars(&self) -> impl Iterator + '_ { - #[allow(clippy::indexing_slicing)] // chunks + #[expect(clippy::indexing_slicing)] // chunks self.inv_list .as_ule_slice() .chunks(2) @@ -418,7 +424,7 @@ impl<'data> CodePointInversionList<'data> { /// assert_eq!(None, example_iter_ranges.next()); /// ``` pub fn iter_ranges(&self) -> impl ExactSizeIterator> + '_ { - #[allow(clippy::indexing_slicing)] // chunks + #[expect(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])); @@ -471,7 +477,7 @@ impl<'data> CodePointInversionList<'data> { } else { None }; - #[allow(clippy::indexing_slicing)] // chunks + #[expect(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])); diff --git a/deps/crates/vendor/icu_collections/src/codepointinvlist/mod.rs b/deps/crates/vendor/icu_collections/src/codepointinvlist/mod.rs index be4986a301d3c2..34b99b3b8cfd5c 100644 --- a/deps/crates/vendor/icu_collections/src/codepointinvlist/mod.rs +++ b/deps/crates/vendor/icu_collections/src/codepointinvlist/mod.rs @@ -53,8 +53,6 @@ #![warn(missing_docs)] -extern crate alloc; - #[cfg(feature = "alloc")] #[macro_use] mod builder; diff --git a/deps/crates/vendor/icu_collections/src/codepointinvlist/utils.rs b/deps/crates/vendor/icu_collections/src/codepointinvlist/utils.rs index 525b02ffd116f1..ef04d3b18b9a27 100644 --- a/deps/crates/vendor/icu_collections/src/codepointinvlist/utils.rs +++ b/deps/crates/vendor/icu_collections/src/codepointinvlist/utils.rs @@ -12,8 +12,8 @@ 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 +#[expect(clippy::indexing_slicing)] // windows +#[expect(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 @@ -48,7 +48,7 @@ mod tests { use core::char; use zerovec::ZeroVec; - fn make_zv(slice: &[u32]) -> ZeroVec { + fn make_zv(slice: &[u32]) -> ZeroVec<'_, PotentialCodePoint> { slice .iter() .copied() diff --git a/deps/crates/vendor/icu_collections/src/codepointinvliststringlist/mod.rs b/deps/crates/vendor/icu_collections/src/codepointinvliststringlist/mod.rs index 2562cc5bc69512..136f5ef2c21984 100644 --- a/deps/crates/vendor/icu_collections/src/codepointinvliststringlist/mod.rs +++ b/deps/crates/vendor/icu_collections/src/codepointinvliststringlist/mod.rs @@ -231,6 +231,7 @@ impl<'data> CodePointInversionListAndStringList<'data> { } #[cfg(feature = "alloc")] +/// ✨ *Enabled with the `alloc` Cargo feature.* impl<'a> FromIterator<&'a str> for CodePointInversionListAndStringList<'_> { fn from_iter(it: I) -> Self where diff --git a/deps/crates/vendor/icu_collections/src/codepointtrie/cptrie.rs b/deps/crates/vendor/icu_collections/src/codepointtrie/cptrie.rs index 8a79032afbecfd..5b184a46f894f5 100644 --- a/deps/crates/vendor/icu_collections/src/codepointtrie/cptrie.rs +++ b/deps/crates/vendor/icu_collections/src/codepointtrie/cptrie.rs @@ -17,8 +17,10 @@ use core::num::TryFromIntError; use core::ops::RangeInclusive; use yoke::Yokeable; use zerofrom::ZeroFrom; +use zerovec::ule::AsULE; #[cfg(feature = "alloc")] use zerovec::ule::UleError; +use zerovec::ZeroSlice; use zerovec::ZeroVec; /// The type of trie represents whether the trie has an optimization that @@ -129,8 +131,28 @@ fn maybe_filter_value(value: T, trie_null_value: T, null_value: T) // serde impls in crate::serde #[derive(Debug, Eq, PartialEq, Yokeable, ZeroFrom)] pub struct CodePointTrie<'trie, T: TrieValue> { + /// # Safety Invariant + /// + /// The value of `header.trie_type` must not change after construction. pub(crate) header: CodePointTrieHeader, + /// # Safety Invariant + /// + /// If `header.trie_type == TrieType::Fast`, `index.len()` must be greater + /// than `FAST_TYPE_FAST_INDEXING_MAX`. Otherwise, `index.len()` + /// must be greater than `SMALL_TYPE_FAST_INDEXING_MAX`. Furthermore, + /// this field must not change after construction. (Strictly: It must + /// not become shorter than the length requirement stated above and the + /// values within the prefix up to the length requirement must not change.) pub(crate) index: ZeroVec<'trie, u16>, + /// # Safety Invariant + /// + /// If `header.trie_type == TrieType::Fast`, `data.len()` must be greater + /// than `FAST_TYPE_DATA_MASK` plus the largest value in + /// `index[0..FAST_TYPE_FAST_INDEXING_MAX + 1]`. Otherwise, `data.len()` + /// must be greater than `FAST_TYPE_DATA_MASK` plus the largest value in + /// `index[0..SMALL_TYPE_FAST_INDEXING_MAX + 1]`. Furthermore, this field + /// must not change after construction. (Strictly: The stated length + /// requirement must continue to hold.) pub(crate) data: ZeroVec<'trie, T>, // serde impl skips this field #[zerofrom(clone)] // TrieValue is Copy, this allows us to avoid @@ -139,6 +161,13 @@ pub struct CodePointTrie<'trie, T: TrieValue> { } /// This struct contains the fixed-length header fields of a [`CodePointTrie`]. +/// +/// # Safety Invariant +/// +/// The `trie_type` field must not change after construction. +/// +/// (In practice, all the fields here remain unchanged during the lifetime +/// of the trie.) #[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))] @@ -173,6 +202,10 @@ pub struct CodePointTrieHeader { 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). + /// + /// # Safety Invariant + /// + /// Must not change after construction. pub trie_type: TrieType, } @@ -232,12 +265,21 @@ macro_rules! w( impl<'trie, T: TrieValue> CodePointTrie<'trie, T> { #[doc(hidden)] // databake internal - pub const fn from_parts( + /// # Safety + /// + /// `header.trie_type`, `index`, and `data` must + /// satisfy the invariants for the fields of the + /// same names on `CodePointTrie`. + pub const unsafe fn from_parts_unstable_unchecked_v1( header: CodePointTrieHeader, index: ZeroVec<'trie, u16>, data: ZeroVec<'trie, T>, error_value: T, ) -> Self { + // Field invariants upheld: The caller is responsible. + // In practice, this means that datagen in the databake + // mode upholds these invariants when constructing the + // `CodePointTrie` that is then baked. Self { header, index, @@ -253,19 +295,8 @@ impl<'trie, T: TrieValue> CodePointTrie<'trie, T> { 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 error_value = Self::validate_fields(&header, &index, &data)?; + // Field invariants upheld: Checked by `validate_fields` above. let trie: CodePointTrie<'trie, T> = CodePointTrie { header, index, @@ -275,9 +306,122 @@ impl<'trie, T: TrieValue> CodePointTrie<'trie, T> { Ok(trie) } + /// Checks the invariant on the fields that fast-path access relies on for + /// safety in order to omit slice bound checks and upon success returns the + /// `error_value` for the trie. + /// + /// # Safety Usable Invariant + /// + /// Iff this function returns `Ok(T)`, the arguments satisfy the invariants + /// for corresponding fields of `CodePointTrie`. (Other than proving that + /// nothing else changes the fields subsequently.) + pub(crate) fn validate_fields( + header: &CodePointTrieHeader, + index: &ZeroSlice, + data: &ZeroSlice, + ) -> Result { + let error_value = data.last().ok_or(Error::EmptyDataVector)?; + + // `CodePointTrie` lookup has two stages: fast and small (the trie types + // are also fast and small; they affect where the boundary between fast + // and small lookups is). + // + // The length requirements for `index` and `data` are checked here only + // for the fast lookup case so that the fast lookup can omit bound checks + // at the time of access. In the small lookup case, bounds are checked at + // the time of access. + // + // The fast lookup happens on the prefixes of `index` and `data` with + // more items for the small lookup case afterwards. The check here + // only looks at the prefixes relevant to the fast case. + // + // In the fast lookup case, the bits of the of the code point are + // partitioned into a bit prefix and a bit suffix. First, a value + // is read from `index` by indexing into it using the bit prefix. + // Then `data` is accessed by the value just read from `index` plus + // the bit suffix. + // + // Therefore, the length of `index` needs to accommodate access + // by the maximum possible bit prefix, and the length of `data` + // needs to accommodate access by the largest value stored in the part + // of `data` reachable by the bit prefix plus the maximum possible bit + // suffix. + // + // The maximum possible bit prefix depends on the trie type. + + // The maximum code point that can be used for fast-path access: + let fast_max = match header.trie_type { + TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX, + TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX, + }; + // Keep only the prefix bits: + let max_bit_prefix = fast_max >> FAST_TYPE_SHIFT; + // Attempt slice the part of `index` that the fast path can index into. + // Since `max_bit_prefix` is the largest possible value used for + // indexing (inclusive bound), we need to add one to get the exclusive + // bound, which is what `get_subslice` wants. + let fast_index = index + .get_subslice(0..(max_bit_prefix as usize) + 1) + .ok_or(Error::IndexTooShortForFastAccess)?; + // Invariant upheld for `index`: If we got this far, the length of `index` + // satisfies its length invariant on the assumption that `header.trie_type` + // will not change subsequently. + + // Now find the largest offset in the part of `index` reachable by the + // bit prefix. `max` can never actually return `None`, since we already + // know the slice isn't empty. Hence, reusing the error kind instead of + // minting a new one for this check. + let max_offset = fast_index + .iter() + .max() + .ok_or(Error::IndexTooShortForFastAccess)?; + // `FAST_TYPE_DATA_MASK` is the maximum possible bit suffix, since the + // maximum is when all the bits in the suffix are set, and the mask + // has that many bits set. + if (max_offset) as usize + (FAST_TYPE_DATA_MASK as usize) >= data.len() { + return Err(Error::DataTooShortForFastAccess); + } + + // Invariant upheld for `data`: If we got this far, the length of `data` + // satisfies `data`'s length invariant on the assumption that the contents + // of `fast_index` subslice of `index` and `header.trie_type` will not + // change subsequently. + + Ok(error_value) + } + + /// Turns this trie into a version whose trie type is encoded in the Rust type. + #[inline] + pub fn to_typed(self) -> Typed, SmallCodePointTrie<'trie, T>> { + match self.header.trie_type { + TrieType::Fast => Typed::Fast(FastCodePointTrie { inner: self }), + TrieType::Small => Typed::Small(SmallCodePointTrie { inner: self }), + } + } + + /// Obtains a reference to this trie as a Rust type that encodes the trie type in the Rust type. + #[inline] + pub fn as_typed_ref( + &self, + ) -> Typed<&FastCodePointTrie<'trie, T>, &SmallCodePointTrie<'trie, T>> { + // SAFETY: `FastCodePointTrie` and `SmallCodePointTrie` are `repr(transparent)` + // with `CodePointTrie`, so transmuting between the references is OK when the + // actual trie type agrees with the semantics of the typed wrapper. + match self.header.trie_type { + TrieType::Fast => Typed::Fast(unsafe { + core::mem::transmute::<&CodePointTrie<'trie, T>, &FastCodePointTrie<'trie, T>>(self) + }), + TrieType::Small => Typed::Small(unsafe { + core::mem::transmute::<&CodePointTrie<'trie, T>, &SmallCodePointTrie<'trie, T>>( + self, + ) + }), + } + } + /// Returns the position in the data array containing the trie's stored /// error value. - #[inline(always)] // `always` based on normalizer benchmarking + #[inline(always)] // `always` was based on previous 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 @@ -375,7 +519,6 @@ impl<'trie, T: TrieValue> CodePointTrie<'trie, T> { /// 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 = @@ -390,6 +533,105 @@ impl<'trie, T: TrieValue> CodePointTrie<'trie, T> { fast_index_val } + /// Returns the value that is associated with `code_point` in this [`CodePointTrie`] + /// if `code_point` uses fast-path lookup or `None` if `code_point` + /// should use small-path lookup or is above the supported range. + #[inline(always)] // "always" to make the `Option` collapse away + fn get32_by_fast_index(&self, code_point: u32) -> Option { + let fast_max = match self.header.trie_type { + TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX, + TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX, + }; + if code_point <= fast_max { + // SAFETY: We just checked the invariant of + // `get32_assuming_fast_index`, + // which is + // "If `self.header.trie_type == TrieType::Small`, `code_point` must be at most + // `SMALL_TYPE_FAST_INDEXING_MAX`. If `self.header.trie_type == + // TrieType::Fast`, `code_point` must be at most `FAST_TYPE_FAST_INDEXING_MAX`." + Some(unsafe { self.get32_assuming_fast_index(code_point) }) + } else { + // The caller needs to call `get32_by_small_index` or determine + // that the argument is above the permitted range. + None + } + } + + /// Performs the actual fast-mode lookup + /// + /// # Safety + /// + /// If `self.header.trie_type == TrieType::Small`, `code_point` must be at most + /// `SMALL_TYPE_FAST_INDEXING_MAX`. If `self.header.trie_type == + /// TrieType::Fast`, `code_point` must be at most `FAST_TYPE_FAST_INDEXING_MAX`. + #[inline(always)] + unsafe fn get32_assuming_fast_index(&self, code_point: u32) -> T { + // Check the safety invariant of this method. + debug_assert!( + code_point + <= match self.header.trie_type { + TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX, + TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX, + } + ); + + let bit_prefix = (code_point as usize) >> FAST_TYPE_SHIFT; + debug_assert!(bit_prefix < self.index.len()); + // SAFETY: Relying on the length invariant of `self.index` having + // been checked and on the unchangedness invariant of `self.index` + // and `self.header.trie_type` after construction. + let base_offset_to_data: usize = usize::from(u16::from_unaligned(*unsafe { + self.index.as_ule_slice().get_unchecked(bit_prefix) + })); + let bit_suffix = (code_point & FAST_TYPE_DATA_MASK) as usize; + // SAFETY: Cannot overflow with supported (32-bit and 64-bit) `usize` + // sizes, since `base_offset_to_data` was extended from `u16` and + // `bit_suffix` is at most `FAST_TYPE_DATA_MASK`, which is well + // under what it takes to reach the 32-bit (or 64-bit) max with + // additon from the max of `u16`. + let offset_to_data = w!(base_offset_to_data + bit_suffix); + debug_assert!(offset_to_data < self.data.len()); + // SAFETY: Relying on the length invariant of `self.data` having + // been checked and on the unchangedness invariant of `self.data`, + // `self.index`, and `self.header.trie_type` after construction. + T::from_unaligned(*unsafe { self.data.as_ule_slice().get_unchecked(offset_to_data) }) + } + + /// Coldness wrapper for `get32_by_small_index` to also allow + /// calls without the effects of `#[cold]`. + #[cold] + #[inline(always)] + fn get32_by_small_index_cold(&self, code_point: u32) -> T { + self.get32_by_small_index(code_point) + } + + /// Returns the value that is associated with `code_point` in this [`CodePointTrie`] + /// assuming that the small index path should be used. + /// + /// # Intended Precondition + /// + /// `code_point` must be at most `CODE_POINT_MAX` AND greter than + /// `FAST_TYPE_FAST_INDEXING_MAX` if the trie type is fast or greater + /// than `SMALL_TYPE_FAST_INDEXING_MAX` if the trie type is small. + /// This is checked when debug assertions are enabled. If this + /// precondition is violated, the behavior of this method is + /// memory-safe, but the returned value may be bogus (not + /// necessarily the designated error value). + #[inline(never)] + fn get32_by_small_index(&self, code_point: u32) -> T { + debug_assert!(code_point <= CODE_POINT_MAX); + debug_assert!( + code_point + > match self.header.trie_type { + TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX, + TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX, + } + ); + self.data + .get(self.small_index(code_point) as usize) + .unwrap_or(self.error_value) + } + /// Returns the value that is associated with `code_point` in this [`CodePointTrie`]. /// /// # Examples @@ -404,11 +646,13 @@ impl<'trie, T: TrieValue> CodePointTrie<'trie, T> { /// ``` #[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) + if let Some(v) = self.get32_by_fast_index(code_point) { + v + } else if code_point <= CODE_POINT_MAX { + self.get32_by_small_index_cold(code_point) + } else { + self.error_value + } } /// Returns the value that is associated with `char` in this [`CodePointTrie`]. @@ -425,7 +669,41 @@ impl<'trie, T: TrieValue> CodePointTrie<'trie, T> { /// ``` #[inline(always)] pub fn get(&self, c: char) -> T { - self.get32(u32::from(c)) + // LLVM's optimizations have been observed not to be 100% + // reliable around collapsing away unnecessary parts of + // `get32`, so not just calling `get32` here. + let code_point = u32::from(c); + if let Some(v) = self.get32_by_fast_index(code_point) { + v + } else { + self.get32_by_small_index_cold(code_point) + } + } + + /// Returns the value that is associated with `bmp` in this [`CodePointTrie`]. + #[inline(always)] + pub fn get16(&self, bmp: u16) -> T { + // LLVM's optimizations have been observed not to be 100% + // reliable around collapsing away unnecessary parts of + // `get32`, so not just calling `get32` here. + let code_point = u32::from(bmp); + if let Some(v) = self.get32_by_fast_index(code_point) { + v + } else { + self.get32_by_small_index_cold(code_point) + } + } + + /// Lookup trie value by non-Basic Multilingual Plane Scalar Value. + /// + /// The return value may be bogus (not necessarily `error_value`) is the argument is actually in + /// the Basic Multilingual Plane or above the Unicode Scalar Value + /// range (panics instead with debug assertions enabled). + #[inline(always)] + pub fn get32_supplementary(&self, supplementary: u32) -> T { + debug_assert!(supplementary > 0xFFFF); + debug_assert!(supplementary <= CODE_POINT_MAX); + self.get32_by_small_index(supplementary) } /// Returns a reference to the ULE of the value that is associated with `code_point` in this [`CodePointTrie`]. @@ -440,7 +718,7 @@ impl<'trie, T: TrieValue> CodePointTrie<'trie, T> { /// 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 + #[inline(always)] // `always` was based on previous 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 @@ -475,6 +753,8 @@ impl<'trie, T: TrieValue> CodePointTrie<'trie, T> { /// 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. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ```no_run @@ -497,7 +777,7 @@ impl<'trie, T: TrieValue> CodePointTrie<'trie, T> { 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 + #[expect(clippy::expect_used)] // we know this cannot fail Ok(CodePointTrie { header: self.header, index: self.index, @@ -515,6 +795,8 @@ impl<'trie, T: TrieValue> CodePointTrie<'trie, T> { /// If the old and new types are the same size, use the more efficient /// [`CodePointTrie::try_into_converted`]. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -930,7 +1212,7 @@ impl<'trie, T: TrieValue> CodePointTrie<'trie, T> { /// assert_eq!(ranges.next(), None); /// assert_eq!(ranges.next(), None); /// ``` - pub fn iter_ranges(&self) -> CodePointMapRangeIterator { + pub fn iter_ranges(&self) -> CodePointMapRangeIterator<'_, T> { let init_range = Some(CodePointMapRange { range: u32::MAX..=u32::MAX, value: self.error_value(), @@ -1007,6 +1289,8 @@ impl<'trie, T: TrieValue> CodePointTrie<'trie, T> { /// Returns a [`CodePointInversionList`] for the code points that have the given /// [`TrieValue`] in the trie. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -1045,7 +1329,7 @@ impl databake::Bake for CodePointTrie<'_, T> { 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) } + databake::quote! { unsafe { icu_collections::codepointtrie::CodePointTrie::from_parts_unstable_unchecked_v1(#header, #index, #data, #error_value) } } } } @@ -1138,6 +1422,255 @@ impl Iterator for CodePointMapRangeIterator<'_, T> { } } +/// For sealing `TypedCodePointTrie` +/// +/// # Safety Usable Invariant +/// +/// All implementations of `TypedCodePointTrie` are reviewable in this module. +trait Seal {} + +/// Trait for writing trait bounds for monomorphizing over either +/// `FastCodePointTrie` or `SmallCodePointTrie`. +#[allow(private_bounds)] // Permit sealing +pub trait TypedCodePointTrie<'trie, T: TrieValue>: Seal { + /// The `TrieType` associated with this `TypedCodePointTrie` + /// + /// # Safety Usable Invariant + /// + /// This constant matches `self.as_untyped_ref().header.trie_type`. + const TRIE_TYPE: TrieType; + + /// Lookup trie value as `u32` by Unicode Scalar Value without branching on trie type. + #[inline(always)] + fn get32_u32(&self, code_point: u32) -> u32 { + self.get32(code_point).to_u32() + } + + /// Lookup trie value by Basic Multilingual Plane Code Point without branching on trie type. + #[inline(always)] + fn get16(&self, bmp: u16) -> T { + // LLVM's optimizations have been observed not to be 100% + // reliable around collapsing away unnecessary parts of + // `get32`, so not just calling `get32` here. + let code_point = u32::from(bmp); + if let Some(v) = self.get32_by_fast_index(code_point) { + v + } else { + self.as_untyped_ref().get32_by_small_index_cold(code_point) + } + } + + /// Lookup trie value by non-Basic Multilingual Plane Scalar Value without branching on trie type. + #[inline(always)] + fn get32_supplementary(&self, supplementary: u32) -> T { + self.as_untyped_ref().get32_supplementary(supplementary) + } + + /// Lookup trie value by Unicode Scalar Value without branching on trie type. + #[inline(always)] + fn get(&self, c: char) -> T { + // LLVM's optimizations have been observed not to be 100% + // reliable around collapsing away unnecessary parts of + // `get32`, so not just calling `get32` here. + let code_point = u32::from(c); + if let Some(v) = self.get32_by_fast_index(code_point) { + v + } else { + self.as_untyped_ref().get32_by_small_index_cold(code_point) + } + } + + /// Lookup trie value by Unicode Code Point without branching on trie type. + #[inline(always)] + fn get32(&self, code_point: u32) -> T { + if let Some(v) = self.get32_by_fast_index(code_point) { + v + } else if code_point <= CODE_POINT_MAX { + self.as_untyped_ref().get32_by_small_index_cold(code_point) + } else { + self.as_untyped_ref().error_value + } + } + + /// Returns the value that is associated with `code_point` in this [`CodePointTrie`] + /// if `code_point` uses fast-path lookup or `None` if `code_point` + /// should use small-path lookup or is above the supported range. + #[inline(always)] // "always" to make the `Option` collapse away + fn get32_by_fast_index(&self, code_point: u32) -> Option { + debug_assert_eq!(Self::TRIE_TYPE, self.as_untyped_ref().header.trie_type); + let fast_max = match Self::TRIE_TYPE { + TrieType::Fast => FAST_TYPE_FAST_INDEXING_MAX, + TrieType::Small => SMALL_TYPE_FAST_INDEXING_MAX, + }; + if code_point <= fast_max { + // SAFETY: We just checked the invariant of + // `get32_assuming_fast_index`, + // which is + // "If `self.header.trie_type == TrieType::Small`, `code_point` must be at most + // `SMALL_TYPE_FAST_INDEXING_MAX`. If `self.header.trie_type == + // TrieType::Fast`, `code_point` must be at most `FAST_TYPE_FAST_INDEXING_MAX`." + // ... assuming that `Self::TRIE_TYPE` always matches + // `self.as_untyped_ref().header.trie_type`, i.e. we're relying on + // `CodePointTrie::to_typed` and `CodePointTrie::as_typed_ref` being correct + // and the exclusive ways of obtaining `Self`. + Some(unsafe { self.as_untyped_ref().get32_assuming_fast_index(code_point) }) + } else { + // The caller needs to call `get32_by_small_index` or determine + // that the argument is above the permitted range. + None + } + } + + /// Returns a reference to the wrapped `CodePointTrie`. + fn as_untyped_ref(&self) -> &CodePointTrie<'trie, T>; + + /// Extracts the wrapped `CodePointTrie`. + fn to_untyped(self) -> CodePointTrie<'trie, T>; +} + +/// Type-safe wrapper for a fast trie guaranteeing +/// the the getters don't branch on the trie type +/// and for guarenteeing that `get16` is branchless +/// in release builds. +#[derive(Debug)] +#[repr(transparent)] +pub struct FastCodePointTrie<'trie, T: TrieValue> { + inner: CodePointTrie<'trie, T>, +} + +impl<'trie, T: TrieValue> TypedCodePointTrie<'trie, T> for FastCodePointTrie<'trie, T> { + const TRIE_TYPE: TrieType = TrieType::Fast; + + /// Returns a reference to the wrapped `CodePointTrie`. + #[inline(always)] + fn as_untyped_ref(&self) -> &CodePointTrie<'trie, T> { + &self.inner + } + + /// Extracts the wrapped `CodePointTrie`. + #[inline(always)] + fn to_untyped(self) -> CodePointTrie<'trie, T> { + self.inner + } + + /// Lookup trie value by Basic Multilingual Plane Code Point without branching on trie type. + #[inline(always)] + fn get16(&self, bmp: u16) -> T { + debug_assert!(u32::from(u16::MAX) <= FAST_TYPE_FAST_INDEXING_MAX); + debug_assert_eq!(Self::TRIE_TYPE, TrieType::Fast); + debug_assert_eq!(self.as_untyped_ref().header.trie_type, TrieType::Fast); + let code_point = u32::from(bmp); + // SAFETY: With `TrieType::Fast`, the `u16` range satisfies + // the invariant of `get32_assuming_fast_index`, which is + // "If `self.header.trie_type == TrieType::Small`, `code_point` must be at most + // `SMALL_TYPE_FAST_INDEXING_MAX`. If `self.header.trie_type == + // TrieType::Fast`, `code_point` must be at most `FAST_TYPE_FAST_INDEXING_MAX`." + // + // We're relying on `CodePointTrie::to_typed` and `CodePointTrie::as_typed_ref` + // being correct and the exclusive ways of obtaining `Self`. + unsafe { self.as_untyped_ref().get32_assuming_fast_index(code_point) } + } +} + +impl<'trie, T: TrieValue> Seal for FastCodePointTrie<'trie, T> {} + +impl<'trie, T: TrieValue> TryFrom<&'trie CodePointTrie<'trie, T>> + for &'trie FastCodePointTrie<'trie, T> +{ + type Error = TypedCodePointTrieError; + + fn try_from( + reference: &'trie CodePointTrie<'trie, T>, + ) -> Result<&'trie FastCodePointTrie<'trie, T>, TypedCodePointTrieError> { + match reference.as_typed_ref() { + Typed::Fast(trie) => Ok(trie), + Typed::Small(_) => Err(TypedCodePointTrieError), + } + } +} + +impl<'trie, T: TrieValue> TryFrom> for FastCodePointTrie<'trie, T> { + type Error = TypedCodePointTrieError; + + fn try_from( + value: CodePointTrie<'trie, T>, + ) -> Result, TypedCodePointTrieError> { + match value.to_typed() { + Typed::Fast(trie) => Ok(trie), + Typed::Small(_) => Err(TypedCodePointTrieError), + } + } +} + +/// Type-safe wrapper for a small trie guaranteeing +/// the the getters don't branch on the trie type. +#[derive(Debug)] +#[repr(transparent)] +pub struct SmallCodePointTrie<'trie, T: TrieValue> { + inner: CodePointTrie<'trie, T>, +} + +impl<'trie, T: TrieValue> TypedCodePointTrie<'trie, T> for SmallCodePointTrie<'trie, T> { + const TRIE_TYPE: TrieType = TrieType::Small; + + /// Returns a reference to the wrapped `CodePointTrie`. + #[inline(always)] + fn as_untyped_ref(&self) -> &CodePointTrie<'trie, T> { + &self.inner + } + + /// Extracts the wrapped `CodePointTrie`. + #[inline(always)] + fn to_untyped(self) -> CodePointTrie<'trie, T> { + self.inner + } +} + +impl<'trie, T: TrieValue> Seal for SmallCodePointTrie<'trie, T> {} + +impl<'trie, T: TrieValue> TryFrom<&'trie CodePointTrie<'trie, T>> + for &'trie SmallCodePointTrie<'trie, T> +{ + type Error = TypedCodePointTrieError; + + fn try_from( + reference: &'trie CodePointTrie<'trie, T>, + ) -> Result<&'trie SmallCodePointTrie<'trie, T>, TypedCodePointTrieError> { + match reference.as_typed_ref() { + Typed::Fast(_) => Err(TypedCodePointTrieError), + Typed::Small(trie) => Ok(trie), + } + } +} + +impl<'trie, T: TrieValue> TryFrom> for SmallCodePointTrie<'trie, T> { + type Error = TypedCodePointTrieError; + + fn try_from( + value: CodePointTrie<'trie, T>, + ) -> Result, TypedCodePointTrieError> { + match value.to_typed() { + Typed::Fast(_) => Err(TypedCodePointTrieError), + Typed::Small(trie) => Ok(trie), + } + } +} + +/// Error indicating that the `TrieType` of an untyped trie +/// does not match the requested typed trie type. +#[derive(Debug)] +#[non_exhaustive] +pub struct TypedCodePointTrieError; + +/// Holder for either fast or small trie with the trie +/// type encoded into the Rust type. +pub enum Typed { + /// The trie type is fast. + Fast(F), + /// The trie type is small. + Small(S), +} + #[cfg(test)] mod tests { use super::*; @@ -1279,6 +1812,17 @@ mod tests { Ok(()) } + #[test] + fn test_typed() { + let untyped = planes::get_planes_trie(); + assert_eq!(untyped.get('\u{10000}'), 1); + let small_ref = <&SmallCodePointTrie<_>>::try_from(&untyped).unwrap(); + assert_eq!(small_ref.get('\u{10000}'), 1); + let _ = <&FastCodePointTrie<_>>::try_from(&untyped).is_err(); + let small = >::try_from(untyped).unwrap(); + assert_eq!(small.get('\u{10000}'), 1); + } + #[test] fn test_get_range() { let planes_trie = planes::get_planes_trie(); @@ -1321,23 +1865,26 @@ mod tests { } #[test] + #[allow(unused_unsafe)] // `unsafe` below is both necessary and unnecessary 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, - ), + unsafe { + crate::codepointtrie::CodePointTrie::from_parts_unstable_unchecked_v1( + 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 index 4cd157fc3f2762..383949d9561142 100644 --- a/deps/crates/vendor/icu_collections/src/codepointtrie/error.rs +++ b/deps/crates/vendor/icu_collections/src/codepointtrie/error.rs @@ -19,6 +19,12 @@ pub enum Error { /// [`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, + /// [`CodePointTrie`](super::CodePointTrie) must be constructed from index vector long enough to accommodate fast-path access + #[displaydoc("CodePointTrie must be constructed from index vector long enough to accommodate fast-path access")] + IndexTooShortForFastAccess, + /// [`CodePointTrie`](super::CodePointTrie) must be constructed from data vector long enough to accommodate fast-path access + #[displaydoc("CodePointTrie must be constructed from data vector long enough to accommodate fast-path access")] + DataTooShortForFastAccess, } impl core::error::Error for Error {} diff --git a/deps/crates/vendor/icu_collections/src/codepointtrie/mod.rs b/deps/crates/vendor/icu_collections/src/codepointtrie/mod.rs index 970eab4fbfd570..dfc5a29ffc21a6 100644 --- a/deps/crates/vendor/icu_collections/src/codepointtrie/mod.rs +++ b/deps/crates/vendor/icu_collections/src/codepointtrie/mod.rs @@ -29,8 +29,6 @@ //! //! [`ICU4X`]: ../icu/index.html -extern crate alloc; - mod cptrie; mod error; mod impl_const; @@ -46,6 +44,10 @@ pub use cptrie::CodePointMapRange; pub use cptrie::CodePointMapRangeIterator; pub use cptrie::CodePointTrie; pub use cptrie::CodePointTrieHeader; +pub use cptrie::FastCodePointTrie; +pub use cptrie::SmallCodePointTrie; pub use cptrie::TrieType; pub use cptrie::TrieValue; +pub use cptrie::Typed; +pub use cptrie::TypedCodePointTrie; 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 index 70ab1629d8b731..a806632992fe55 100644 --- a/deps/crates/vendor/icu_collections/src/codepointtrie/planes.rs +++ b/deps/crates/vendor/icu_collections/src/codepointtrie/planes.rs @@ -172,9 +172,9 @@ pub fn get_planes_trie() -> CodePointTrie<'static, u8> { 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 + #[expect(clippy::unwrap_used)] // valid bytes let index: ZeroVec = ZeroVec::parse_bytes(index_array_as_bytes).unwrap(); - #[allow(clippy::unwrap_used)] // valid bytes + #[expect(clippy::unwrap_used)] // valid bytes let data: ZeroVec = ZeroVec::parse_bytes(data_8_array).unwrap(); let high_start = 0x100000; let shifted12_high_start = 0x100; @@ -192,7 +192,7 @@ pub fn get_planes_trie() -> CodePointTrie<'static, u8> { trie_type, }; - #[allow(clippy::unwrap_used)] // valid data + #[expect(clippy::unwrap_used)] // valid data CodePointTrie::try_new(trie_header, index, data).unwrap() } diff --git a/deps/crates/vendor/icu_collections/src/codepointtrie/serde.rs b/deps/crates/vendor/icu_collections/src/codepointtrie/serde.rs index 74b9e7bb3ed1b6..adfb2d8aa08e06 100644 --- a/deps/crates/vendor/icu_collections/src/codepointtrie/serde.rs +++ b/deps/crates/vendor/icu_collections/src/codepointtrie/serde.rs @@ -39,9 +39,31 @@ 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") - })?; + // SAFETY: + // `validate_fields` upholds the invariants for the fields that + // fast-path access without bound checks relies on. + let error_value = match CodePointTrie::validate_fields(&de.header, &de.index, &de.data) { + Ok(v) => v, + Err(e) => { + match e { + super::CodePointTrieError::FromDeserialized { reason } => { + // Not supposed to be returned by `validate_fields`. + debug_assert!(false); + return Err(D::Error::custom(reason)); + } + super::CodePointTrieError::EmptyDataVector => { + return Err(D::Error::custom("CodePointTrie must be constructed from data vector with at least one element")); + } + super::CodePointTrieError::IndexTooShortForFastAccess => { + return Err(D::Error::custom("CodePointTrie must be constructed from index vector long enough to accommodate fast-path access")); + } + super::CodePointTrieError::DataTooShortForFastAccess => { + return Err(D::Error::custom("CodePointTrie must be constructed from data vector long enough to accommodate fast-path access")); + } + } + } + }; + // Field invariants upheld: Checked by `validate_fields` above. Ok(CodePointTrie { header: de.header, index: de.index, diff --git a/deps/crates/vendor/icu_collections/src/codepointtrie/toml.rs b/deps/crates/vendor/icu_collections/src/codepointtrie/toml.rs index f8b0f7b4638e1e..af54098e1f21ad 100644 --- a/deps/crates/vendor/icu_collections/src/codepointtrie/toml.rs +++ b/deps/crates/vendor/icu_collections/src/codepointtrie/toml.rs @@ -18,7 +18,6 @@ use zerovec::ZeroVec; /// 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)] @@ -72,7 +71,7 @@ impl CodePointTrieToml { } /// Gets the `data` slice. - pub fn data_slice(&self) -> Result { + pub fn data_slice(&self) -> Result, Error> { if let Some(data_8) = &self.data_8 { Ok(CodePointDataSlice::U8(data_8.as_slice())) } else if let Some(data_16) = &self.data_16 { diff --git a/deps/crates/vendor/icu_collections/src/iterator_utils.rs b/deps/crates/vendor/icu_collections/src/iterator_utils.rs index 701a77eea31da8..0701f32ffd748e 100644 --- a/deps/crates/vendor/icu_collections/src/iterator_utils.rs +++ b/deps/crates/vendor/icu_collections/src/iterator_utils.rs @@ -39,7 +39,7 @@ where }; // Keep pulling ranges - #[allow(clippy::while_let_on_iterator)] + #[expect(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 { diff --git a/deps/crates/vendor/icu_collections/tests/cpt.rs b/deps/crates/vendor/icu_collections/tests/cpt.rs index 210277cf40f72c..f4b04d55963b09 100644 --- a/deps/crates/vendor/icu_collections/tests/cpt.rs +++ b/deps/crates/vendor/icu_collections/tests/cpt.rs @@ -255,7 +255,7 @@ pub fn check_trie>(trie: &CodePointTrie, check_range 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,); + assert_eq!(range_value, trie.get32(i).into(), "trie_get({i})",); i += 1; } } @@ -335,7 +335,6 @@ pub struct EnumPropCodePointMapData { 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"))] @@ -347,7 +346,6 @@ pub struct EnumPropSerializedCPT { // 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))] diff --git a/deps/crates/vendor/icu_locale/.cargo-checksum.json b/deps/crates/vendor/icu_locale/.cargo-checksum.json index 6a5d8438d2631c..6fb690bcbf0fb7 100644 --- a/deps/crates/vendor/icu_locale/.cargo-checksum.json +++ b/deps/crates/vendor/icu_locale/.cargo-checksum.json @@ -1 +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 +{"files":{".cargo_vcs_info.json":"75f8e5fb1d26d5b74f3aa5d09b4aced17b8ab9a9155ecf57bc5f528445916547","Cargo.lock":"b3f2f2eed3b6035323161be0b43ff6f66864420afe482c7f9d1c3689489ef790","Cargo.toml":"2f55d17536899327b3f4b59f44f20c8d932c84bc4c7016270c49992c081273a4","Cargo.toml.orig":"9cf2a1729c32b9736763644d8af2ab09a4971a6f0fc3d932dfb9d7e03b650594","LICENSE":"f367c1b8e1aa262435251e442901da4607b4650e0e63a026f5044473ecfb90f2","README.md":"3eabddc961d47b3205baacf44113fc4aa414d8429ae0b045a6a7e264af980747","benches/fixtures/locales.json":"9846601a29874baf140cac1252d4624fadc30182fec106d17f008ece886b9185","benches/fixtures/uncanonicalized-locales.json":"a866ed318b92f79d8853567e79b373c02984967023f5f39161140544e71b0c72","benches/locale_canonicalizer.rs":"3b6599352c88d2c039d083f91b5b7e222614946c55a77e3ccb1ae0b5fa2ae346","src/canonicalizer.rs":"88255bae6b4f2799ff9d3f644ec6de8dbd558b5a9f6634e5c5390caa7ec758f2","src/directionality.rs":"af2e0421cf36d08232c1cf6b6d7e08824132128559fc69b888974c2ae007e8f5","src/exemplar_chars.rs":"70f37cde5153f27a4f112b908354d584a00daa6047ef9901569ef64f1a1da5f6","src/expander.rs":"f74f35d1b58b3086cd1d992c35238831057c9063c6afc6bc4dd0ef702bf8cf4b","src/fallback/algorithms.rs":"93c0bdc427570dc2899ccdd2f82ad5e3237e5afe6890c3e7a09ef92dcf63661b","src/fallback/mod.rs":"fd51cb417d0918df4c9f02da3095430e236af7dd9ab87df7fa683fdf2e83b011","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":"dc00a426018d2c5ffec6077f962ce6da1f458ff2df14ba53f2cc390ab2fc622e"},"package":"532b11722e350ab6bf916ba6eb0efe3ee54b932666afec989465f9243fe6dd60"} \ No newline at end of file diff --git a/deps/crates/vendor/icu_locale/.cargo_vcs_info.json b/deps/crates/vendor/icu_locale/.cargo_vcs_info.json new file mode 100644 index 00000000000000..82f90aa2fb05c6 --- /dev/null +++ b/deps/crates/vendor/icu_locale/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "38a49da495248dd1ded84cf306e4ca42e64d5bb3" + }, + "path_in_vcs": "components/locale" +} \ No newline at end of file diff --git a/deps/crates/vendor/icu_locale/Cargo.lock b/deps/crates/vendor/icu_locale/Cargo.lock new file mode 100644 index 00000000000000..921a35c9b3426b --- /dev/null +++ b/deps/crates/vendor/icu_locale/Cargo.lock @@ -0,0 +1,845 @@ +# 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.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[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.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror", +] + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[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 = "erased-serde" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + +[[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 = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "databake", + "displaydoc", + "potential_utf", + "serde", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale" +version = "2.1.1" +dependencies = [ + "criterion", + "databake", + "icu_collections", + "icu_locale_core", + "icu_locale_data", + "icu_provider", + "potential_utf", + "serde", + "serde_json", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "databake", + "displaydoc", + "litemap", + "serde", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locale_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f03e2fcaefecdf05619f3d6f91740e79ab969b4dd54f77cbf546b1d0d28e3147" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "databake", + "displaydoc", + "erased-serde", + "icu_locale_core", + "postcard", + "serde", + "stable_deref_trait", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "is-terminal" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +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.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "serde", +] + +[[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.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +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.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[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.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 = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "syn" +version = "2.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +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 = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "databake", + "displaydoc", + "serde_core", + "zerovec", +] + +[[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 = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + +[[package]] +name = "unicode-ident" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" + +[[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.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[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 = [ + "databake", + "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", +] diff --git a/deps/crates/vendor/icu_locale/Cargo.toml b/deps/crates/vendor/icu_locale/Cargo.toml index 7c1c38bb74c4f5..270bc9bfc418a9 100644 --- a/deps/crates/vendor/icu_locale/Cargo.toml +++ b/deps/crates/vendor/icu_locale/Cargo.toml @@ -11,9 +11,9 @@ [package] edition = "2021" -rust-version = "1.82" +rust-version = "1.83" name = "icu_locale" -version = "2.0.0" +version = "2.1.1" authors = ["The ICU4X Project Developers"] build = false include = [ @@ -91,16 +91,12 @@ features = ["derive"] optional = true default-features = false -[dependencies.displaydoc] -version = "0.2.3" -default-features = false - [dependencies.icu_collections] -version = "~2.0.0" +version = "~2.1.1" default-features = false [dependencies.icu_locale_core] -version = "2.0.0" +version = "2.1.1" features = [ "alloc", "zerovec", @@ -108,16 +104,17 @@ features = [ default-features = false [dependencies.icu_locale_data] -version = "~2.0.0" +version = "~2.1.1" optional = true default-features = false [dependencies.icu_provider] -version = "2.0.0" +version = "2.1.1" +features = ["alloc"] default-features = false [dependencies.potential_utf] -version = "0.1.1" +version = "0.1.3" features = [ "alloc", "zerovec", @@ -125,7 +122,7 @@ features = [ default-features = false [dependencies.serde] -version = "1.0.110" +version = "1.0.220" features = [ "derive", "alloc", @@ -142,7 +139,7 @@ features = [ default-features = false [dependencies.zerovec] -version = "0.11.1" +version = "0.11.3" features = [ "alloc", "yoke", @@ -150,7 +147,7 @@ features = [ default-features = false [dev-dependencies.serde] -version = "1.0.110" +version = "1.0.220" features = ["derive"] default-features = false diff --git a/deps/crates/vendor/icu_locale/Cargo.toml.orig b/deps/crates/vendor/icu_locale/Cargo.toml.orig new file mode 100644 index 00000000000000..1d96b0151d25e3 --- /dev/null +++ b/deps/crates/vendor/icu_locale/Cargo.toml.orig @@ -0,0 +1,62 @@ +# 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 ). + +[package] +name = "icu_locale" +description = "API for Unicode Language and Locale Identifiers canonicalization" + +authors.workspace = true +categories.workspace = true +edition.workspace = true +homepage.workspace = true +include.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true +version.workspace = true + +[package.metadata.cargo-all-features] +skip_optional_dependencies = true + +[package.metadata.docs.rs] +all-features = true + +[dependencies] +databake = { workspace = true, optional = true, features = ["derive"] } +icu_locale_core = { workspace = true, features = ["alloc", "zerovec"] } +icu_provider = { workspace = true, features = ["alloc"] } +serde = { workspace = true, features = ["derive", "alloc"], optional = true } +tinystr = { workspace = true, features = ["alloc", "zerovec"] } +potential_utf = { workspace = true, features = ["alloc", "zerovec"] } +zerovec = { workspace = true, features = ["alloc", "yoke"] } + +icu_collections = { workspace = true } + +icu_locale_data = { workspace = true, optional = true } + +[dev-dependencies] +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +icu = { path = "../../components/icu", default-features = false } +writeable = { path = "../../utils/writeable" } + +[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] +criterion = { workspace = true } + +[lib] +bench = false # This option is required for Benchmark CI + +[features] +default = ["compiled_data"] +serde = ["dep:serde", "icu_locale_core/serde", "tinystr/serde", "zerovec/serde", "icu_provider/serde", "potential_utf/serde", "icu_collections/serde"] +datagen = ["serde", "dep:databake", "zerovec/databake", "icu_locale_core/databake", "tinystr/databake", "icu_collections/databake", "icu_provider/export"] +compiled_data = ["dep:icu_locale_data", "icu_provider/baked"] + +[[bench]] +name = "locale_canonicalizer" +harness = false + +[[test]] +name = "locale_canonicalizer" +required-features = ["serde"] diff --git a/deps/crates/vendor/icu_locale/src/canonicalizer.rs b/deps/crates/vendor/icu_locale/src/canonicalizer.rs index c8320cc1d447fe..ea6a14a3d4374e 100644 --- a/deps/crates/vendor/icu_locale/src/canonicalizer.rs +++ b/deps/crates/vendor/icu_locale/src/canonicalizer.rs @@ -450,7 +450,7 @@ impl> LocaleCanonicalizer { if modified.is_empty() { modified = locale.id.variants.to_vec(); } - #[allow(clippy::indexing_slicing)] + #[expect(clippy::indexing_slicing)] let _ = core::mem::replace(&mut modified[idx], updated); } } @@ -589,8 +589,7 @@ mod test { rule.variants.iter().map(Variant::as_str), ), result, - "{}", - source + "{source}" ); } } diff --git a/deps/crates/vendor/icu_locale/src/expander.rs b/deps/crates/vendor/icu_locale/src/expander.rs index 25291a6649013d..f1d6684dd4a6ac 100644 --- a/deps/crates/vendor/icu_locale/src/expander.rs +++ b/deps/crates/vendor/icu_locale/src/expander.rs @@ -310,7 +310,7 @@ impl LocaleExpander { }) } - fn as_borrowed(&self) -> LocaleExpanderBorrowed { + fn as_borrowed(&self) -> LocaleExpanderBorrowed<'_> { LocaleExpanderBorrowed { likely_subtags_l: self.likely_subtags_l.get(), likely_subtags_sr: self.likely_subtags_sr.get(), diff --git a/deps/crates/vendor/icu_locale/src/fallback/algorithms.rs b/deps/crates/vendor/icu_locale/src/fallback/algorithms.rs index 58f2352cc6e860..7e9e5f0419cf23 100644 --- a/deps/crates/vendor/icu_locale/src/fallback/algorithms.rs +++ b/deps/crates/vendor/icu_locale/src/fallback/algorithms.rs @@ -204,7 +204,6 @@ impl LocaleFallbackIteratorInner<'_> { locale.variant = self.backup_variant.take(); } // needed if more fallback is added at the end - #[allow(clippy::needless_return)] return; } else { // 3. Remove the language and apply the maximized script @@ -215,7 +214,6 @@ impl LocaleFallbackIteratorInner<'_> { locale.variant = self.backup_variant.take(); } // needed if more fallback is added at the end - #[allow(clippy::needless_return)] return; } } diff --git a/deps/crates/vendor/icu_locale/src/fallback/mod.rs b/deps/crates/vendor/icu_locale/src/fallback/mod.rs index d1266831f65401..8f13a620493ab3 100644 --- a/deps/crates/vendor/icu_locale/src/fallback/mod.rs +++ b/deps/crates/vendor/icu_locale/src/fallback/mod.rs @@ -104,8 +104,7 @@ impl LocaleFallbacker { /// /// [📚 Help choosing a constructor](icu_provider::constructors) #[cfg(feature = "compiled_data")] - #[allow(clippy::new_ret_no_self)] // keeping constructors together - #[allow(clippy::new_without_default)] // Deliberate choice, see #5554 + #[expect(clippy::new_ret_no_self)] // keeping constructors together pub const fn new<'a>() -> LocaleFallbackerBorrowed<'a> { // Safety: we're transmuting down from LocaleFallbackerBorrowed<'static> to LocaleFallbackerBorrowed<'a> // ZeroMaps use associated types in a way that confuse the compiler which gives up and marks them @@ -157,12 +156,12 @@ impl LocaleFallbacker { /// Associates a configuration with this fallbacker. #[inline] - pub fn for_config(&self, config: LocaleFallbackConfig) -> LocaleFallbackerWithConfig { + pub fn for_config(&self, config: LocaleFallbackConfig) -> LocaleFallbackerWithConfig<'_> { self.as_borrowed().for_config(config) } /// Creates a borrowed version of this fallbacker for performance. - pub fn as_borrowed(&self) -> LocaleFallbackerBorrowed { + pub fn as_borrowed(&self) -> LocaleFallbackerBorrowed<'_> { LocaleFallbackerBorrowed { likely_subtags: self.likely_subtags.get(), parents: self.parents.get(), @@ -189,7 +188,7 @@ impl LocaleFallbackerBorrowed<'static> { /// /// [📚 Help choosing a constructor](icu_provider::constructors) #[cfg(feature = "compiled_data")] - #[allow(clippy::new_without_default)] + #[expect(clippy::new_without_default)] pub const fn new() -> Self { Self { likely_subtags: crate::provider::Baked::SINGLETON_LOCALE_LIKELY_SUBTAGS_LANGUAGE_V1, diff --git a/deps/crates/vendor/icu_locale/tests/locale_canonicalizer.rs b/deps/crates/vendor/icu_locale/tests/locale_canonicalizer.rs index aa91070fcf3a89..b5dceed85568dd 100644 --- a/deps/crates/vendor/icu_locale/tests/locale_canonicalizer.rs +++ b/deps/crates/vendor/icu_locale/tests/locale_canonicalizer.rs @@ -25,9 +25,9 @@ fn test_maximize() { let result = lc.maximize(&mut locale.id); assert_writeable_eq!(locale, case.output, "{:?}", case); if result == TransformResult::Modified { - assert_ne!(locale, unmodified, "{:?}", case); + assert_ne!(locale, unmodified, "{case:?}"); } else { - assert_eq!(locale, unmodified, "{:?}", case); + assert_eq!(locale, unmodified, "{case:?}"); } } } @@ -49,9 +49,9 @@ fn test_minimize() { let result = lc.minimize(&mut locale.id); assert_writeable_eq!(locale, case.output, "{:?}", case); if result == TransformResult::Modified { - assert_ne!(locale, unmodified, "{:?}", case); + assert_ne!(locale, unmodified, "{case:?}"); } else { - assert_eq!(locale, unmodified, "{:?}", case); + assert_eq!(locale, unmodified, "{case:?}"); } } } @@ -73,9 +73,9 @@ fn test_canonicalize() { let result = lc.canonicalize(&mut locale); assert_writeable_eq!(locale, case.output, "{:?}", case); if result == TransformResult::Modified { - assert_ne!(locale, unmodified, "{:?}", case); + assert_ne!(locale, unmodified, "{case:?}"); } else { - assert_eq!(locale, unmodified, "{:?}", case); + assert_eq!(locale, unmodified, "{case:?}"); } } } diff --git a/deps/crates/vendor/icu_locale_core/.cargo-checksum.json b/deps/crates/vendor/icu_locale_core/.cargo-checksum.json index 93787cc80f4487..c60bf2a096b473 100644 --- a/deps/crates/vendor/icu_locale_core/.cargo-checksum.json +++ b/deps/crates/vendor/icu_locale_core/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"1410e3b8b7992dc36ace635a935718887ee70908121633151e9ae31fff773e81","LICENSE":"f367c1b8e1aa262435251e442901da4607b4650e0e63a026f5044473ecfb90f2","README.md":"3e30d773b84c9682a0f03fbfae067edca276b16a2ed0f0ab99c31f6a53aa68b2","benches/fixtures/langid.json":"373c11527653c63c685c9e229a8de5ae2b557c25b686a9d891c59e1f603232d8","benches/fixtures/locale.json":"669b19db933094290a45bf856559920f4e92401072e364ac82c482119dc9233a","benches/fixtures/mod.rs":"d59ae0ebb4d42c5b9a89376bb20d400145eeb8edcd4e93dcd07adfd55f1db8c0","benches/fixtures/subtags.json":"28be3a639e452d713e807d5779b6819e06277e2dbbf67801ef34964fb9b074b6","benches/helpers/macros.rs":"b9bf068a08156f8421ea39ca2a5b83351f9f9b63336b207706b75d1acb7697ac","benches/helpers/mod.rs":"9118aceb41badd98a6d3e07f79bf6328f3da1f93ae82ef99e6ca7e7229aa4c42","benches/iai_langid.rs":"256aa84228af9fd730a90ffc81b2adafaec131b338d786142b770fa45fc221f1","benches/langid.rs":"0203769d2c5ae9d5269344216b93d43c6cb9f58bf4e3b182247afe00f5bb0287","benches/locale.rs":"172d82598b2924515de72c731837d702ce2ff75fdc3655069288c9015ff30c56","benches/subtags.rs":"6ff85047f04896749dff12ed00060afc882ac2ff27f86a57c3afdcbba13f797a","src/data.rs":"bb36f7ed75cdabbfc54c7e108057d85583c712aaf1783b713ef71b5008493032","src/databake.rs":"b0cb3175eb2a919fe9d48d6c85635676a99d2474fc34b2b2ba503fd6d67fec3e","src/extensions/mod.rs":"b5982c55e099b4596371c2d7faed4086009c33d9fc6e10b475f5655bde6727fc","src/extensions/other/mod.rs":"5dc66dcde0263c1b9562f8ef90edcd616c49b118a40059458e314d45a672a337","src/extensions/private/mod.rs":"0a5271741722dbe0495713946c19d257e63dde3b4ab80d7c81c51c251557979d","src/extensions/private/other.rs":"050fba0eeb47b45c539ebda561cabe8f2d6b1cd6ab272bd8d25eb34b33466c96","src/extensions/transform/fields.rs":"88b968c260de0e7ee92efd044bb85392846db22acc19be3b9acfbad410ab1e5f","src/extensions/transform/key.rs":"7b44e1ccd95f3fcc0892a018effa054cd74d64a3667535eed2270d41baef1393","src/extensions/transform/mod.rs":"9072ebdb61afb5427d60855289a686dbf8debbee36feecdc034bdbac8593e97c","src/extensions/transform/value.rs":"5aa653c37cd7c2ae0aec9b37f102986095ec904bdac797c374cabad9059bd9a7","src/extensions/unicode/attribute.rs":"c2a6cfc920532c58023c40a9bd10632a73aedd4670a1562fa7caa15a500018e1","src/extensions/unicode/attributes.rs":"c644d7dcf310e4e24376351e45ec88db08c3d86f1c53d3d163ecc08cfcdda212","src/extensions/unicode/key.rs":"ad3c8844b6b55529d70a7d91889bf53703f92994b316d5c9052fe68b5350e530","src/extensions/unicode/keywords.rs":"73f563d887412ff4bc37947c1df9f361df6e34d1e82f2a4c906cf115844d7dd5","src/extensions/unicode/mod.rs":"a51ce421f1375d8c8108d09094951ccd44eb6488100c1ed57dbd2d2432f0da0f","src/extensions/unicode/subdivision.rs":"a1523c051f55833c94995d95920579a2c30cea98cba9e68cd1f90bc21ce2c9ea","src/extensions/unicode/value.rs":"ac158d119ef833a0b457405ffb792cc4eda7edf2e14906cfc1be737d5f69e444","src/helpers.rs":"20a7de315db2c0b48e343e81a9b45dc5548025facfe880ae81e00f59530259fc","src/langid.rs":"21bc904b0098c42817a271398afd2822b2cd5f87936f8cb676e5c91e05197bac","src/lib.rs":"8128cdc5057eed807e057d241f545b59e76b64e106938c4fc87aa558afcc72b6","src/locale.rs":"0ad643efa17d23ca68f6ce7edc4aee60e42486e5ac7448640d61f9488d162740","src/macros.rs":"ed064e4a5bec77706d3022d73e24a6d410b2e7cd395447b6bcb5822c4714bd1c","src/parser/errors.rs":"9959d6e1f00f89ce739d18d489cf7733865cb95a26e4a33b9651eda2e310d89d","src/parser/langid.rs":"f60fb31f7dea4d6090a411da15773135283b6ea8564f4f51be702ce3d40bacf6","src/parser/locale.rs":"81068dfdcc1e765d759df7eb964c8441a3e6e17be881b059be49af2cf802b4d4","src/parser/mod.rs":"7202edc3c6cea056d9172c0a18c1fa84ad2b9a1409809974da93ae9ab80080ae","src/preferences/extensions/mod.rs":"8055be6df84eac91b2bb96603e022025ff80b8f6594b5a82c2b0fb95f0367043","src/preferences/extensions/unicode/errors.rs":"9f6e2edfaecd1b8679aa011c1d35250be8d0aac9ea5558b1e0fa58f5f9527ead","src/preferences/extensions/unicode/keywords/calendar.rs":"472defc4a3574b56496c8d2542ef98584cc1f2f33c3b0903131983158e19f768","src/preferences/extensions/unicode/keywords/collation.rs":"9c60a1156c8e20f4a0fdfa6a544f047ca0710fc116a9e8bdcbaa8d8fdc743f87","src/preferences/extensions/unicode/keywords/currency.rs":"92335724649b7ce1f840fe8f0b02f1896a7dab495d36fc45e7858bfa645420bd","src/preferences/extensions/unicode/keywords/currency_format.rs":"03c94e5dd3253c4cb1c8a4d5a2708be3d77cae9c334985649213440b8bac42c0","src/preferences/extensions/unicode/keywords/dictionary_break.rs":"a13ad0985a98dbf7cea96e2c50db1b6f9513d099a5b15f8bd55edc1e922699cc","src/preferences/extensions/unicode/keywords/emoji.rs":"0c79aa3b90cc228580204807d82809587e00204bc3d09783e4dfc2c302bec984","src/preferences/extensions/unicode/keywords/first_day.rs":"16471ad310624f059f1c280f3aa518f379d746feb892b6a8533631557d5ce690","src/preferences/extensions/unicode/keywords/hour_cycle.rs":"531e959c95a8289c56050e8b5e6ae899277c49b4c8a7f04f99cebf436db25fd6","src/preferences/extensions/unicode/keywords/line_break.rs":"5380f187ea22ea24576c15507a1b1275c947f374c9ec05ac4ba6576ba26122e2","src/preferences/extensions/unicode/keywords/line_break_word.rs":"7aae1d07ffaa6c2a44617b99c8bc1ba19df048cc3ec7aac10ccff89a6d84304b","src/preferences/extensions/unicode/keywords/measurement_system.rs":"b41bb9ce40c310e7370b11f211ca22cb07b08e8c7a8f0aab2dc99a766ff2b22e","src/preferences/extensions/unicode/keywords/measurement_unit_override.rs":"6670167cd9942cfc1c6c1b45d954ae3acc8c69f0609eefe1e33532fb02cdb8fd","src/preferences/extensions/unicode/keywords/mod.rs":"1ca967da8529fe3f7d1943da6e853d753ba2dd94ac5a86f496c80b3ff22b7df7","src/preferences/extensions/unicode/keywords/numbering_system.rs":"47105a6613fca0f9306f1db3f0ce9b5b29416218144af5596ed392ab552521f1","src/preferences/extensions/unicode/keywords/region_override.rs":"65590219d58dcf466f48f07f94d6fc0ce1433182e5acd8e926ad01f6a7d245be","src/preferences/extensions/unicode/keywords/regional_subdivision.rs":"0e54659cfc99c416fc108580c34c4710fbf32b9183422635b6c766d6a47e0d05","src/preferences/extensions/unicode/keywords/sentence_supression.rs":"31942a4bedc3e247bbd73740baf32e3b95bb4c91522dbc55f97c3374eee8669e","src/preferences/extensions/unicode/keywords/timezone.rs":"1d7f7ba02728919d57e793fe1d695e7d47bd5c173d72e518b7e35f0e724c77d9","src/preferences/extensions/unicode/keywords/variant.rs":"3d96c4da532d59965d81761fdf7aa78ec3bbd316bf72ec23e7d19d292850bc76","src/preferences/extensions/unicode/macros/enum_keyword.rs":"70c3185eacd51a1698c14ff98f68a49a788729893f6975b83cf6ccc8aae8d0e0","src/preferences/extensions/unicode/macros/mod.rs":"7a62888e12399959469a39c7f353e7b5d00988302f78b44df5e3b7fd22e442c7","src/preferences/extensions/unicode/macros/struct_keyword.rs":"dba324f98c3e108b7add972cbf2a9586486e560350d736a4e7034834177472d6","src/preferences/extensions/unicode/mod.rs":"9ce8a095b63724f124798a0f7e4b7dcc60bd0e7bfb2523d0f9e11883a81f904d","src/preferences/locale.rs":"67ae458b6c8cbaa9fbec2f602fe3b33f6a82f9b5a3968c0b45a80ee9aae4a812","src/preferences/mod.rs":"36940ac6a6476276fff513fef174bc45eda3487507e14adeab2bc1794f763376","src/serde.rs":"0a9c35d10714376621bf15e1f12d00bf05fc30f20c1e53be17d67bc64c03d63a","src/shortvec/litemap.rs":"e3970c8984ff951d613a951bc372a67ec4410bb49e209979181e8aedb2eaebee","src/shortvec/mod.rs":"be860b8574ca081a14e4dcf63344c259f0e31b2f11c4ddd75c7fb21c81b4e7c3","src/subtags/language.rs":"94757472cfb54f2f583c79ea6ad7c7662240868a2bc04e4b938998e32a8de394","src/subtags/mod.rs":"29e68217c2a47aa70db941467631eee7343bec96d823cf79eb70fcb8975abfd9","src/subtags/region.rs":"1157ea7f2defb86233ee86f4522e494d6dfe4776a2b5f853008c75cbbcc312f0","src/subtags/script.rs":"f562cc5607b5acec4ba5fc14dddf5d7eff1d19129535f3a309fd0fb31607b714","src/subtags/variant.rs":"6230b1bb252b0782c9cb015be8f583e8b2d8ab7ffff79789bb6df600e2b0eb5c","src/subtags/variants.rs":"c8caa29a442f527f657bee41fb2179c3eb01f30fde9bf80198bc54bc273732ed","src/zerovec.rs":"89442aa13615cfd3d92d9079249f8432e33b7739401dda3266b4c2a9d4a5ff7b","tests/fixtures/canonicalize.json":"5414bd4972eb80ba46c727b407a8ed48a6e12e3639db034033586813c872f59c","tests/fixtures/invalid-extensions.json":"36eb5966085a1c9e966689af504cfbf8ea9b78b741675fe033ec9b6153e63ea6","tests/fixtures/invalid.json":"109169258632bd23d06827dfae6509f02a8127ffec25f48281ed61d795c67765","tests/fixtures/langid.json":"960fd01722217ef1ea9077e2e0821d7089fe318a241bd7fb7918f50bf8f3f5c3","tests/fixtures/locale.json":"df1b195b18780758a6b1c0264206b9cd9ac8c4741c5d6b0cc2b92f8e17991c17","tests/fixtures/mod.rs":"12e5815ba46229304aa8234eb537faa568f10576815739beaa3f815134d7e7ac","tests/langid.rs":"d79f33c1f536bec7a0eb1c466842afd61e15098f5039ea6a8085cdf31128199c","tests/locale.rs":"a7ffc4e9d1ebc70e9d915994033b3853285764953c6f0416f07e30520852b17f"},"package":"93cca704c2d63cf8a91f5c2c5f88e027940dede132319b85a52939db9758f7e5"} \ No newline at end of file +{"files":{".cargo_vcs_info.json":"87472294cb1b942324597b25d40baa022967be22454f8c2172de6089d9ff8d32","Cargo.lock":"060041080fd4db117c6f5604ac650c14f88eedbc28b5169a30f3337d40b4313f","Cargo.toml":"4dd1fdf5dcd1517c4f6339872f8589f2074090ede054ba1f38259ad7d6abb7af","Cargo.toml.orig":"1953cfdf680ff8b4f33d2602aee3a0e8c5dc11c8936325953fb254bf2c3b4840","LICENSE":"f367c1b8e1aa262435251e442901da4607b4650e0e63a026f5044473ecfb90f2","README.md":"3e30d773b84c9682a0f03fbfae067edca276b16a2ed0f0ab99c31f6a53aa68b2","benches/fixtures/langid.json":"373c11527653c63c685c9e229a8de5ae2b557c25b686a9d891c59e1f603232d8","benches/fixtures/locale.json":"669b19db933094290a45bf856559920f4e92401072e364ac82c482119dc9233a","benches/fixtures/mod.rs":"d59ae0ebb4d42c5b9a89376bb20d400145eeb8edcd4e93dcd07adfd55f1db8c0","benches/fixtures/subtags.json":"28be3a639e452d713e807d5779b6819e06277e2dbbf67801ef34964fb9b074b6","benches/helpers/macros.rs":"b9bf068a08156f8421ea39ca2a5b83351f9f9b63336b207706b75d1acb7697ac","benches/helpers/mod.rs":"9118aceb41badd98a6d3e07f79bf6328f3da1f93ae82ef99e6ca7e7229aa4c42","benches/iai_langid.rs":"256aa84228af9fd730a90ffc81b2adafaec131b338d786142b770fa45fc221f1","benches/langid.rs":"0203769d2c5ae9d5269344216b93d43c6cb9f58bf4e3b182247afe00f5bb0287","benches/locale.rs":"172d82598b2924515de72c731837d702ce2ff75fdc3655069288c9015ff30c56","benches/subtags.rs":"6ff85047f04896749dff12ed00060afc882ac2ff27f86a57c3afdcbba13f797a","src/data.rs":"29274b5276adeb92d91a2da4a37cc9216e131e1d8f7984d50d6899f5e71e9d20","src/databake.rs":"b0cb3175eb2a919fe9d48d6c85635676a99d2474fc34b2b2ba503fd6d67fec3e","src/extensions/mod.rs":"93c2d618750068e4f724fc3389330115daae93fdff54f13d3c6d81852127a417","src/extensions/other/mod.rs":"7548cca590f16f04db3245e322b0ba3596eff26c129f89bb554fc2c7d3e97c16","src/extensions/private/mod.rs":"0063cd169fa42285c331a8c4d9c3a24a60a79d9217bebb4b105523fde678faba","src/extensions/private/other.rs":"050fba0eeb47b45c539ebda561cabe8f2d6b1cd6ab272bd8d25eb34b33466c96","src/extensions/transform/fields.rs":"06ba3c3baec94b76f8120bdb8e76ceeb5cdab4e9dba6852f10965e8af8e76dd3","src/extensions/transform/key.rs":"7b44e1ccd95f3fcc0892a018effa054cd74d64a3667535eed2270d41baef1393","src/extensions/transform/mod.rs":"1a24f18770f870985501069d760b0ab26a071c4fb32738fb5a81e309eacd16eb","src/extensions/transform/value.rs":"6ee1205b7576d7d49d9d2b983e7bea7e8b92db9f2a70cd940c1f61bf94e14eef","src/extensions/unicode/attribute.rs":"c2a6cfc920532c58023c40a9bd10632a73aedd4670a1562fa7caa15a500018e1","src/extensions/unicode/attributes.rs":"5fe26de18edf670e93aeff51a1d95f29a2117d4f965796126c6c99baf2640683","src/extensions/unicode/key.rs":"ad3c8844b6b55529d70a7d91889bf53703f92994b316d5c9052fe68b5350e530","src/extensions/unicode/keywords.rs":"25028c190011c26ff98c1f41d756b832c5077d47bc3cda16619080c0ea9256f5","src/extensions/unicode/mod.rs":"c3d96faca4cfbb2097ee163adf7d2284f3bdf809a74aa5465f96af9f8a3b2d1d","src/extensions/unicode/subdivision.rs":"ee1c7d0e4b0e4fe3124dafaafef24356f661077201a6a16269b0315374f0bf7a","src/extensions/unicode/value.rs":"d30a4708c7cc0867bd863ad40b49419116786cc39eedd06205088af1b60a10ee","src/helpers.rs":"b157f722e09e3da2bc1920cb964638940207173c5bcfcc271c3086a8a70cfb77","src/langid.rs":"d37dc4aaf8d07bf2dc21a028ea117295f37f46afefe98845e65740692bdf317c","src/lib.rs":"0f38bc043dd3f9ee84c0934f91aa32a739f0b5f839e32869180f94270c284bc6","src/locale.rs":"c595ec154ea306359c92a4b5bc7e6f42fc0b8cbc1bb3a1d145ce9ba36fe63c4e","src/macros.rs":"c2d9fa8a671561d7e9b8082439d56450a1d87039fa5040742a95bd3ab85e9288","src/parser/errors.rs":"9959d6e1f00f89ce739d18d489cf7733865cb95a26e4a33b9651eda2e310d89d","src/parser/langid.rs":"32b4950254793f77d0d5873cba17d6e134b0c3772cbddf559c9e52f4af80d57f","src/parser/locale.rs":"3ba0374f8af82c3751974c4007cd167753153dc3bca9f0cd70d0b0cd17b36fe0","src/parser/mod.rs":"56430a72c3c407f9661e9b6062b7bb13627c508838330482a1a6630de3169d94","src/preferences/extensions/mod.rs":"8055be6df84eac91b2bb96603e022025ff80b8f6594b5a82c2b0fb95f0367043","src/preferences/extensions/unicode/errors.rs":"9f6e2edfaecd1b8679aa011c1d35250be8d0aac9ea5558b1e0fa58f5f9527ead","src/preferences/extensions/unicode/keywords/calendar.rs":"e78abd46c4488776e720e6e4fbef4cf7d2c0e7a5a73a5897b5a0a43c497c0609","src/preferences/extensions/unicode/keywords/collation.rs":"2fbdf8d32967afa80ae35eb33555fb390d96c8690efcfd0d61e30d09f945781c","src/preferences/extensions/unicode/keywords/currency.rs":"92335724649b7ce1f840fe8f0b02f1896a7dab495d36fc45e7858bfa645420bd","src/preferences/extensions/unicode/keywords/currency_format.rs":"69ca7166d19a3d90953bd898e00ad76db89570b7973f251d930d5b5f090ef3ef","src/preferences/extensions/unicode/keywords/dictionary_break.rs":"2489abf09a017c419de5e443ac4bf014476c27c6d31b84a2b55cf6fa53740826","src/preferences/extensions/unicode/keywords/emoji.rs":"0b34acbba058050452d7b4d0b538cd784d5bb76b54cac7b2acd1f946b3ae04c5","src/preferences/extensions/unicode/keywords/first_day.rs":"65e7be67e62b0f5de16508001d2a9d902361eb630df1be5ef4d0ea4f24713e0e","src/preferences/extensions/unicode/keywords/hour_cycle.rs":"01d36e9066b4c6a8db0bf224f0877fa9f4414217484267fff183779b492a11e5","src/preferences/extensions/unicode/keywords/line_break.rs":"0292b4e9c6dadf9759f7371e1a4b6db0b917211026b7dde1983a1726e1d89206","src/preferences/extensions/unicode/keywords/line_break_word.rs":"6fef4aef3dc44541bb1cbeefc0a8cdb9b97f0a26ad9c4f9be057cb4fb3f1c45b","src/preferences/extensions/unicode/keywords/measurement_system.rs":"ddcadb5c654f6dd253ea70a095534978588788979f03796fa128354d349bf909","src/preferences/extensions/unicode/keywords/measurement_unit_override.rs":"ee3a9417050f6b7d6e5c987ece779218e006a19136fea705485bf080c0865dde","src/preferences/extensions/unicode/keywords/mod.rs":"18c6384f19567e7865b48963eb43f34cb53e4eb52dfa9e6592e3af64a4b4b687","src/preferences/extensions/unicode/keywords/numbering_system.rs":"47105a6613fca0f9306f1db3f0ce9b5b29416218144af5596ed392ab552521f1","src/preferences/extensions/unicode/keywords/region_override.rs":"65590219d58dcf466f48f07f94d6fc0ce1433182e5acd8e926ad01f6a7d245be","src/preferences/extensions/unicode/keywords/regional_subdivision.rs":"77866d9824b3b4569b63c4bfeac26f2d2025d1eab3d2ea147961f6773ee270e9","src/preferences/extensions/unicode/keywords/sentence_supression.rs":"8e991966dd9e4a6de441fdd03f8075a70c544741c76e8e076923159a107b6689","src/preferences/extensions/unicode/keywords/timezone.rs":"1d7f7ba02728919d57e793fe1d695e7d47bd5c173d72e518b7e35f0e724c77d9","src/preferences/extensions/unicode/keywords/variant.rs":"8598a4dd392c32ad08db700a3500a218b5c0674444675a4ca84da8be81b2bcb7","src/preferences/extensions/unicode/macros/enum_keyword.rs":"45cd0ace21a363b813a1bbb571a2b22f93839549ba1a96f776dc442b08b2bdd9","src/preferences/extensions/unicode/macros/mod.rs":"fc4212e6a62a402eebbaba29cec5e0f91109d3aa1d962039e50dd633a7ecc70d","src/preferences/extensions/unicode/macros/struct_keyword.rs":"dba324f98c3e108b7add972cbf2a9586486e560350d736a4e7034834177472d6","src/preferences/extensions/unicode/mod.rs":"9ce8a095b63724f124798a0f7e4b7dcc60bd0e7bfb2523d0f9e11883a81f904d","src/preferences/locale.rs":"759466d81773a853d87f2f8288d096a001fa208a2b6752ee767ec63c4f80e605","src/preferences/mod.rs":"e563ebc4594e54da8f60bcd6a3aefc77677163c7b847db67f576a1680da979e9","src/serde.rs":"a1a3439a0cc2e9ff754784d355ac8daf885cc5f3f210460b6781ff6d0ae2e7a3","src/shortvec/litemap.rs":"51af8e84fa010492ec44938eb65fbef23486267bb4d6c6a03154497b38ba35b1","src/shortvec/mod.rs":"e4ff29488b509354d80f8d75f6468cf68eda4a1de1cfaa54e8f1c9f9dc0b9f6a","src/subtags/language.rs":"94757472cfb54f2f583c79ea6ad7c7662240868a2bc04e4b938998e32a8de394","src/subtags/mod.rs":"f998571e80229552aa0aedcae35d0918a9aff261a58e488cfcc6d67d1f696b8d","src/subtags/region.rs":"1157ea7f2defb86233ee86f4522e494d6dfe4776a2b5f853008c75cbbcc312f0","src/subtags/script.rs":"f562cc5607b5acec4ba5fc14dddf5d7eff1d19129535f3a309fd0fb31607b714","src/subtags/variant.rs":"6230b1bb252b0782c9cb015be8f583e8b2d8ab7ffff79789bb6df600e2b0eb5c","src/subtags/variants.rs":"c3af767be128fa4bcab6efd65188f428e3a6b66ac3c69cb3e6489938cbb7094d","src/zerovec.rs":"a63c99e0ef6d38f4b4903b42b1e800aa821c7cbfd817b07d313dcdf4d377823d","tests/fixtures/canonicalize.json":"5414bd4972eb80ba46c727b407a8ed48a6e12e3639db034033586813c872f59c","tests/fixtures/invalid-extensions.json":"36eb5966085a1c9e966689af504cfbf8ea9b78b741675fe033ec9b6153e63ea6","tests/fixtures/invalid.json":"109169258632bd23d06827dfae6509f02a8127ffec25f48281ed61d795c67765","tests/fixtures/langid.json":"960fd01722217ef1ea9077e2e0821d7089fe318a241bd7fb7918f50bf8f3f5c3","tests/fixtures/locale.json":"df1b195b18780758a6b1c0264206b9cd9ac8c4741c5d6b0cc2b92f8e17991c17","tests/fixtures/mod.rs":"448fcf033391285b2f7ed2d73195a80a1342007083708b0786dc7d822df5831c","tests/langid.rs":"d79f33c1f536bec7a0eb1c466842afd61e15098f5039ea6a8085cdf31128199c","tests/locale.rs":"a7ffc4e9d1ebc70e9d915994033b3853285764953c6f0416f07e30520852b17f"},"package":"edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"} \ No newline at end of file diff --git a/deps/crates/vendor/icu_locale_core/.cargo_vcs_info.json b/deps/crates/vendor/icu_locale_core/.cargo_vcs_info.json new file mode 100644 index 00000000000000..c1582af2bc43cc --- /dev/null +++ b/deps/crates/vendor/icu_locale_core/.cargo_vcs_info.json @@ -0,0 +1,7 @@ +{ + "git": { + "sha1": "38a49da495248dd1ded84cf306e4ca42e64d5bb3", + "dirty": true + }, + "path_in_vcs": "components/locale_core" +} \ No newline at end of file diff --git a/deps/crates/vendor/icu_locale_core/Cargo.lock b/deps/crates/vendor/icu_locale_core/Cargo.lock new file mode 100644 index 00000000000000..77a22263621536 --- /dev/null +++ b/deps/crates/vendor/icu_locale_core/Cargo.lock @@ -0,0 +1,165 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[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 = "icu_locale_core" +version = "2.1.1" +dependencies = [ + "databake", + "displaydoc", + "litemap", + "serde", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[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.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[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 = "syn" +version = "2.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +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 = "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.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "serde", + "zerofrom", +] diff --git a/deps/crates/vendor/icu_locale_core/Cargo.toml b/deps/crates/vendor/icu_locale_core/Cargo.toml index 924ab0d1863b42..99eb6b9dd720ae 100644 --- a/deps/crates/vendor/icu_locale_core/Cargo.toml +++ b/deps/crates/vendor/icu_locale_core/Cargo.toml @@ -11,9 +11,9 @@ [package] edition = "2021" -rust-version = "1.82" +rust-version = "1.83" name = "icu_locale_core" -version = "2.0.1" +version = "2.1.1" authors = ["The ICU4X Project Developers"] build = false include = [ @@ -43,7 +43,12 @@ repository = "https://github.com/unicode-org/icu4x" all-features = true [features] -alloc = [] +alloc = [ + "litemap/alloc", + "tinystr/alloc", + "writeable/alloc", + "serde?/alloc", +] databake = [ "dep:databake", "alloc", @@ -51,7 +56,6 @@ databake = [ serde = [ "dep:serde", "tinystr/serde", - "alloc", ] zerovec = [ "dep:zerovec", @@ -103,57 +107,22 @@ default-features = false [dependencies.litemap] version = "0.8.0" -features = ["alloc"] default-features = false [dependencies.serde] -version = "1.0.110" -features = [ - "alloc", - "derive", -] +version = "1.0.220" optional = true default-features = false [dependencies.tinystr] version = "0.8.0" -features = ["alloc"] default-features = false [dependencies.writeable] version = "0.6.0" -features = ["alloc"] default-features = false [dependencies.zerovec] -version = "0.11.1" +version = "0.11.3" optional = true default-features = false - -[dev-dependencies.iai] -version = "0.1.1" - -[dev-dependencies.litemap] -version = "0.8.0" -features = ["testing"] -default-features = false - -[dev-dependencies.postcard] -version = "1.0.3" -features = ["use-std"] -default-features = false - -[dev-dependencies.potential_utf] -version = "0.1.1" -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_core/Cargo.toml.orig b/deps/crates/vendor/icu_locale_core/Cargo.toml.orig new file mode 100644 index 00000000000000..94d03fa7a7354a --- /dev/null +++ b/deps/crates/vendor/icu_locale_core/Cargo.toml.orig @@ -0,0 +1,55 @@ +# 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 ). + +[package] +name = "icu_locale_core" +description = "API for managing Unicode Language and Locale Identifiers" + +authors.workspace = true +categories.workspace = true +edition.workspace = true +homepage.workspace = true +include.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true +version.workspace = true + +[package.metadata.docs.rs] +all-features = true + +[dependencies] +displaydoc = { workspace = true } +litemap = { workspace = true } +tinystr = { workspace = true } +writeable = { workspace = true } + +databake = { workspace = true, features = ["derive"], optional = true } +serde = { workspace = true, optional = true } +zerovec = { workspace = true, optional = true } + +[features] +databake = ["dep:databake", "alloc"] +serde = ["dep:serde", "tinystr/serde"] +zerovec = ["dep:zerovec", "tinystr/zerovec"] +alloc = ["litemap/alloc", "tinystr/alloc", "writeable/alloc", "serde?/alloc"] + +[lib] +bench = false # This option is required for Benchmark CI + +[[bench]] +name = "subtags" +harness = false + +[[bench]] +name = "langid" +harness = false + +[[bench]] +name = "locale" +harness = false + +[[bench]] +name = "iai_langid" +harness = false diff --git a/deps/crates/vendor/icu_locale_core/src/data.rs b/deps/crates/vendor/icu_locale_core/src/data.rs index 5bf0e971bb3d7a..5143bf23b1fa25 100644 --- a/deps/crates/vendor/icu_locale_core/src/data.rs +++ b/deps/crates/vendor/icu_locale_core/src/data.rs @@ -101,7 +101,7 @@ impl fmt::Debug for DataLocale { } } -impl_writeable_for_each_subtag_str_no_test!(DataLocale, selff, selff.script.is_none() && selff.region.is_none() && selff.variant.is_none() && selff.subdivision.is_none() => selff.language.write_to_string()); +impl_writeable_for_each_subtag_str_no_test!(DataLocale, selff, selff.script.is_none() && selff.region.is_none() && selff.variant.is_none() && selff.subdivision.is_none() => Some(selff.language.as_str())); impl From for DataLocale { fn from(langid: LanguageIdentifier) -> Self { @@ -141,6 +141,7 @@ impl From<&Locale> for DataLocale { } } +/// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] impl FromStr for DataLocale { type Err = ParseError; @@ -153,12 +154,16 @@ impl FromStr for DataLocale { impl DataLocale { #[inline] /// Parses a [`DataLocale`]. + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] pub fn try_from_str(s: &str) -> Result { Self::try_from_utf8(s.as_bytes()) } /// Parses a [`DataLocale`] from a UTF-8 byte slice. + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] pub fn try_from_utf8(code_units: &[u8]) -> Result { let locale = Locale::try_from_utf8(code_units)?; diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/mod.rs b/deps/crates/vendor/icu_locale_core/src/extensions/mod.rs index 1893ad7349e02c..134921a3b96134 100644 --- a/deps/crates/vendor/icu_locale_core/src/extensions/mod.rs +++ b/deps/crates/vendor/icu_locale_core/src/extensions/mod.rs @@ -194,7 +194,7 @@ impl Extensions { && self.other.is_empty() } - #[allow(clippy::type_complexity)] + #[expect(clippy::type_complexity)] pub(crate) fn as_tuple( &self, ) -> ( @@ -231,6 +231,8 @@ impl Extensions { /// Retains the specified extension types, clearing all others. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -252,6 +254,7 @@ impl Extensions { /// }); /// assert_eq!(only_t_z, "und-t-mul-z-zzz".parse().unwrap()); /// ``` + #[cfg(feature = "alloc")] pub fn retain_by_type(&mut self, mut predicate: F) where F: FnMut(ExtensionType) -> bool, @@ -360,7 +363,6 @@ impl Extensions { } } -#[cfg(feature = "alloc")] impl_writeable_for_each_subtag_str_no_test!(Extensions); #[test] diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/other/mod.rs b/deps/crates/vendor/icu_locale_core/src/extensions/other/mod.rs index 050b379c6da0d3..8934c4dff76fa7 100644 --- a/deps/crates/vendor/icu_locale_core/src/extensions/other/mod.rs +++ b/deps/crates/vendor/icu_locale_core/src/extensions/other/mod.rs @@ -64,6 +64,8 @@ pub struct Other { impl Other { /// A constructor which takes a str slice, parses it and /// produces a well-formed [`Other`]. + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[inline] #[cfg(feature = "alloc")] pub fn try_from_str(s: &str) -> Result { @@ -71,6 +73,8 @@ impl Other { } /// See [`Self::try_from_str`] + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] pub fn try_from_utf8(code_units: &[u8]) -> Result { let mut iter = SubtagIterator::new(code_units); @@ -85,6 +89,8 @@ impl Other { /// A constructor which takes a pre-sorted list of [`Subtag`]. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Panics /// /// Panics if `ext` is not ASCII alphabetic. @@ -200,6 +206,7 @@ impl Other { } } +/// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] impl FromStr for Other { type Err = ParseError; @@ -210,7 +217,7 @@ impl FromStr for Other { } } -writeable::impl_display_with_writeable!(Other); +writeable::impl_display_with_writeable!(Other, #[cfg(feature = "alloc")]); impl writeable::Writeable for Other { fn write_to(&self, sink: &mut W) -> core::fmt::Result { @@ -236,17 +243,6 @@ impl writeable::Writeable for Other { } result } - - #[cfg(feature = "alloc")] - fn write_to_string(&self) -> alloc::borrow::Cow { - if self.keys.is_empty() { - return alloc::borrow::Cow::Borrowed(""); - } - let mut string = - alloc::string::String::with_capacity(self.writeable_length_hint().capacity()); - let _ = self.write_to(&mut string); - alloc::borrow::Cow::Owned(string) - } } #[cfg(test)] diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/private/mod.rs b/deps/crates/vendor/icu_locale_core/src/extensions/private/mod.rs index ee9852921af51d..458259c26e15fa 100644 --- a/deps/crates/vendor/icu_locale_core/src/extensions/private/mod.rs +++ b/deps/crates/vendor/icu_locale_core/src/extensions/private/mod.rs @@ -89,6 +89,8 @@ impl Private { /// A constructor which takes a str slice, parses it and /// produces a well-formed [`Private`]. + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[inline] #[cfg(feature = "alloc")] pub fn try_from_str(s: &str) -> Result { @@ -96,6 +98,8 @@ impl Private { } /// See [`Self::try_from_str`] + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] pub fn try_from_utf8(code_units: &[u8]) -> Result { let mut iter = SubtagIterator::new(code_units); @@ -110,6 +114,8 @@ impl Private { /// A constructor which takes a pre-sorted list of [`Subtag`]. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -190,6 +196,7 @@ impl Private { } } +/// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] impl FromStr for Private { type Err = ParseError; @@ -200,7 +207,7 @@ impl FromStr for Private { } } -writeable::impl_display_with_writeable!(Private); +writeable::impl_display_with_writeable!(Private, #[cfg(feature = "alloc")]); impl writeable::Writeable for Private { fn write_to(&self, sink: &mut W) -> core::fmt::Result { diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/transform/fields.rs b/deps/crates/vendor/icu_locale_core/src/extensions/transform/fields.rs index d5d9cf72484124..d7a027d9210093 100644 --- a/deps/crates/vendor/icu_locale_core/src/extensions/transform/fields.rs +++ b/deps/crates/vendor/icu_locale_core/src/extensions/transform/fields.rs @@ -3,7 +3,6 @@ // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use core::borrow::Borrow; -use core::iter::FromIterator; use litemap::LiteMap; use super::Key; @@ -32,7 +31,12 @@ use super::Value; /// assert_eq!(&fields.to_string(), "h0-hybrid"); /// ``` #[derive(Clone, PartialEq, Eq, Debug, Default, Hash, PartialOrd, Ord)] -pub struct Fields(LiteMap); +pub struct Fields(Inner); + +#[cfg(feature = "alloc")] +type Inner = LiteMap; +#[cfg(not(feature = "alloc"))] +type Inner = LiteMap; impl Fields { /// Returns a new empty list of key-value pairs. Same as [`default()`](Default::default()), but is `const`. @@ -137,6 +141,8 @@ impl Fields { /// Sets the specified keyword, returning the old value if it already existed. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -154,12 +160,15 @@ impl Fields { /// assert_eq!(old_value, Some(casefold)); /// assert_eq!(loc, "en-t-hi-d0-lower".parse().unwrap()); /// ``` + #[cfg(feature = "alloc")] pub fn set(&mut self, key: Key, value: Value) -> Option { self.0.insert(key, value) } /// Retains a subset of fields as specified by the predicate function. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -180,6 +189,7 @@ impl Fields { /// .retain_by_key(|&k| k == key!("d0")); /// assert_eq!(loc, Locale::UNKNOWN); /// ``` + #[cfg(feature = "alloc")] pub fn retain_by_key(&mut self, mut predicate: F) where F: FnMut(&Key) -> bool, @@ -205,13 +215,17 @@ impl Fields { } } +/// ✨ *Enabled with the `alloc` Cargo feature.* +#[cfg(feature = "alloc")] impl From> for Fields { fn from(map: LiteMap) -> Self { Self(map) } } -impl FromIterator<(Key, Value)> for Fields { +/// ✨ *Enabled with the `alloc` Cargo feature.* +#[cfg(feature = "alloc")] +impl core::iter::FromIterator<(Key, Value)> for Fields { fn from_iter>(iter: I) -> Self { LiteMap::from_iter(iter).into() } diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/transform/mod.rs b/deps/crates/vendor/icu_locale_core/src/extensions/transform/mod.rs index 8f3094f1bf2145..712009954f127f 100644 --- a/deps/crates/vendor/icu_locale_core/src/extensions/transform/mod.rs +++ b/deps/crates/vendor/icu_locale_core/src/extensions/transform/mod.rs @@ -117,6 +117,8 @@ impl Transform { /// A constructor which takes a str slice, parses it and /// produces a well-formed [`Transform`]. + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[inline] #[cfg(feature = "alloc")] pub fn try_from_str(s: &str) -> Result { @@ -124,6 +126,8 @@ impl Transform { } /// See [`Self::try_from_str`] + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] pub fn try_from_utf8(code_units: &[u8]) -> Result { let mut iter = SubtagIterator::new(code_units); @@ -167,7 +171,7 @@ impl Transform { self.fields.clear(); } - #[allow(clippy::type_complexity)] + #[expect(clippy::type_complexity)] pub(crate) fn as_tuple( &self, ) -> ( @@ -270,6 +274,7 @@ impl Transform { } } +/// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] impl FromStr for Transform { type Err = ParseError; @@ -280,7 +285,7 @@ impl FromStr for Transform { } } -writeable::impl_display_with_writeable!(Transform); +writeable::impl_display_with_writeable!(Transform, #[cfg(feature = "alloc")]); impl writeable::Writeable for Transform { fn write_to(&self, sink: &mut W) -> core::fmt::Result { diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/transform/value.rs b/deps/crates/vendor/icu_locale_core/src/extensions/transform/value.rs index 3a54f739dd1b92..2d59476ec37ed5 100644 --- a/deps/crates/vendor/icu_locale_core/src/extensions/transform/value.rs +++ b/deps/crates/vendor/icu_locale_core/src/extensions/transform/value.rs @@ -40,6 +40,8 @@ impl Value { /// A constructor which takes a str slice, parses it and /// produces a well-formed [`Value`]. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -54,6 +56,8 @@ impl Value { } /// See [`Self::try_from_str`] + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] pub fn try_from_utf8(code_units: &[u8]) -> Result { let mut v = ShortBoxSlice::default(); @@ -115,6 +119,7 @@ impl Value { } } +/// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] impl FromStr for Value { type Err = ParseError; @@ -125,7 +130,7 @@ impl FromStr for Value { } } -impl_writeable_for_each_subtag_str_no_test!(Value, selff, selff.0.is_empty() => alloc::borrow::Cow::Borrowed("true")); +impl_writeable_for_each_subtag_str_no_test!(Value, selff, selff.0.is_empty() => Some("true")); #[test] fn test_writeable() { diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/attributes.rs b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/attributes.rs index 7ca0fecfcfc212..fe0b1ef14c8522 100644 --- a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/attributes.rs +++ b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/attributes.rs @@ -57,6 +57,8 @@ impl Attributes { /// A constructor which takes a str slice, parses it and /// produces a well-formed [`Attributes`]. + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[inline] #[cfg(feature = "alloc")] pub fn try_from_str(s: &str) -> Result { @@ -64,6 +66,8 @@ impl Attributes { } /// See [`Self::try_from_str`] + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] pub fn try_from_utf8(code_units: &[u8]) -> Result { let mut iter = SubtagIterator::new(code_units); @@ -72,6 +76,7 @@ impl Attributes { /// A constructor which takes a pre-sorted list of [`Attribute`] elements. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* /// /// # Examples /// @@ -143,8 +148,32 @@ impl Attributes { { self.deref().iter().map(|t| t.as_str()).try_for_each(f) } + + /// Extends the `Attributes` with values from another `Attributes`. + /// + /// # Example + /// + /// ``` + /// use icu::locale::extensions::unicode::Attributes; + /// + /// let mut attrs: Attributes = "foobar-foobaz".parse().unwrap(); + /// let attrs2: Attributes = "foobar-fooqux".parse().unwrap(); + /// + /// attrs.extend_from_attributes(attrs2); + /// + /// assert_eq!(attrs, "foobar-foobaz-fooqux".parse().unwrap()); + /// ``` + #[cfg(feature = "alloc")] + pub fn extend_from_attributes(&mut self, other: Attributes) { + for attr in other.0 { + if let Err(idx) = self.binary_search(&attr) { + self.0.insert(idx, attr); + } + } + } } +/// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] impl FromStr for Attributes { type Err = ParseError; diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/keywords.rs b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/keywords.rs index 726b5490efc52b..c7287fc66c7979 100644 --- a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/keywords.rs +++ b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/keywords.rs @@ -96,6 +96,8 @@ impl Keywords { /// A constructor which takes a str slice, parses it and /// produces a well-formed [`Keywords`]. + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[inline] #[cfg(feature = "alloc")] pub fn try_from_str(s: &str) -> Result { @@ -103,6 +105,8 @@ impl Keywords { } /// See [`Self::try_from_str`] + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] pub fn try_from_utf8(code_units: &[u8]) -> Result { let mut iter = SubtagIterator::new(code_units); @@ -175,6 +179,8 @@ impl Keywords { /// /// Returns `None` if the key doesn't exist or if the key has no value. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -200,6 +206,8 @@ impl Keywords { /// Sets the specified keyword, returning the old value if it already existed. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -225,6 +233,8 @@ impl Keywords { /// Removes the specified keyword, returning the old value if it existed. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -261,6 +271,8 @@ impl Keywords { /// Retains a subset of keywords as specified by the predicate function. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -374,6 +386,27 @@ impl Keywords { Ok(()) } + /// Extends the `Keywords` with values from another `Keywords`. + /// + /// # Example + /// + /// ``` + /// use icu::locale::extensions::unicode::Keywords; + /// + /// let mut kw: Keywords = "ab-cd-ca-buddhist".parse().unwrap(); + /// let kw2: Keywords = "ca-gregory-hc-h12".parse().unwrap(); + /// + /// kw.extend_from_keywords(kw2); + /// + /// assert_eq!(kw, "ab-cd-ca-gregory-hc-h12".parse().unwrap()); + /// ``` + #[cfg(feature = "alloc")] + pub fn extend_from_keywords(&mut self, other: Keywords) { + for (key, value) in other.0 { + self.0.insert(key, value); + } + } + /// This needs to be its own method to help with type inference in helpers.rs #[cfg(test)] pub(crate) fn from_tuple_vec(v: Vec<(Key, Value)>) -> Self { @@ -387,6 +420,7 @@ impl From>> for Keywords { } } +/// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] impl FromIterator<(Key, Value)> for Keywords { fn from_iter>(iter: I) -> Self { @@ -394,6 +428,7 @@ impl FromIterator<(Key, Value)> for Keywords { } } +/// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] impl FromStr for Keywords { type Err = ParseError; diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/mod.rs b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/mod.rs index f51593548ba3b5..1a2d984312f787 100644 --- a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/mod.rs +++ b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/mod.rs @@ -115,6 +115,8 @@ impl Unicode { /// A constructor which takes a str slice, parses it and /// produces a well-formed [`Unicode`]. + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[inline] #[cfg(feature = "alloc")] pub fn try_from_str(s: &str) -> Result { @@ -122,6 +124,8 @@ impl Unicode { } /// See [`Self::try_from_str`] + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] pub fn try_from_utf8(code_units: &[u8]) -> Result { let mut iter = SubtagIterator::new(code_units); @@ -210,8 +214,29 @@ impl Unicode { } Ok(()) } + + /// Extends the `Unicode` with values from another `Unicode`. + /// + /// # Example + /// + /// ``` + /// use icu::locale::extensions::unicode::Unicode; + /// + /// let mut ue: Unicode = "u-foobar-ca-buddhist".parse().unwrap(); + /// let ue2: Unicode = "u-ca-gregory-hc-h12".parse().unwrap(); + /// + /// ue.extend(ue2); + /// + /// assert_eq!(ue, "u-foobar-ca-gregory-hc-h12".parse().unwrap()); + /// ``` + #[cfg(feature = "alloc")] + pub fn extend(&mut self, other: Unicode) { + self.keywords.extend_from_keywords(other.keywords); + self.attributes.extend_from_attributes(other.attributes); + } } +/// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] impl FromStr for Unicode { type Err = ParseError; @@ -222,7 +247,7 @@ impl FromStr for Unicode { } } -writeable::impl_display_with_writeable!(Unicode); +writeable::impl_display_with_writeable!(Unicode, #[cfg(feature = "alloc")]); impl writeable::Writeable for Unicode { fn write_to(&self, sink: &mut W) -> core::fmt::Result { diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/subdivision.rs b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/subdivision.rs index 5855fed7fc09d4..26e0436e3b0795 100644 --- a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/subdivision.rs +++ b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/subdivision.rs @@ -151,7 +151,7 @@ impl writeable::Writeable for SubdivisionId { } } -writeable::impl_display_with_writeable!(SubdivisionId); +writeable::impl_display_with_writeable!(SubdivisionId, #[cfg(feature = "alloc")]); impl FromStr for SubdivisionId { type Err = ParseError; @@ -175,7 +175,7 @@ mod tests { for sample in ["", "gb", "o"] { let oe: Result = sample.parse(); - assert!(oe.is_err(), "Should fail: {}", sample); + assert!(oe.is_err(), "Should fail: {sample}"); } } } diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/value.rs b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/value.rs index c2f3381078da5a..41beb43915bea3 100644 --- a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/value.rs +++ b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/value.rs @@ -3,7 +3,6 @@ // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use crate::parser::ParseError; -#[cfg(feature = "alloc")] use crate::parser::SubtagIterator; use crate::shortvec::{ShortBoxSlice, ShortBoxSliceIntoIter}; use crate::subtags::{subtag, Subtag}; @@ -51,14 +50,18 @@ impl Value { /// /// Value::try_from_str("buddhist").expect("Parsing failed."); /// ``` + /// + /// # `alloc` Cargo feature + /// + /// Without the `alloc` Cargo feature, this only supports parsing + /// up to two (non-`true`) subtags, and will return an error for + /// longer strings. #[inline] - #[cfg(feature = "alloc")] pub fn try_from_str(s: &str) -> Result { Self::try_from_utf8(s.as_bytes()) } /// See [`Self::try_from_str`] - #[cfg(feature = "alloc")] pub fn try_from_utf8(code_units: &[u8]) -> Result { let mut v = ShortBoxSlice::new(); @@ -66,7 +69,16 @@ impl Value { for chunk in SubtagIterator::new(code_units) { let subtag = Subtag::try_from_utf8(chunk)?; if subtag != TRUE_VALUE { + #[cfg(feature = "alloc")] v.push(subtag); + #[cfg(not(feature = "alloc"))] + if v.is_empty() { + v = ShortBoxSlice::new_single(subtag); + } else if let &[prev] = &*v { + v = ShortBoxSlice::new_double(prev, subtag); + } else { + return Err(ParseError::InvalidSubtag); + } } } } @@ -118,6 +130,8 @@ impl Value { /// Appends a subtag to the back of a [`Value`]. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -170,7 +184,7 @@ impl Value { /// use icu::locale::{extensions::unicode::Value, subtags::subtag}; /// /// let mut v = Value::default(); - /// assert_eq!(v.is_empty(), true); + /// assert!(v.is_empty()); /// ``` pub fn is_empty(&self) -> bool { self.0.is_empty() @@ -226,8 +240,14 @@ impl Value { } } + #[doc(hidden)] + pub fn from_two_subtags(f: Subtag, s: Subtag) -> Self { + Self(ShortBoxSlice::new_double(f, s)) + } + /// A constructor which takes a pre-sorted list of [`Value`] elements. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* /// /// # Examples /// @@ -283,6 +303,7 @@ impl IntoIterator for Value { } } +/// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] impl FromIterator for Value { fn from_iter>(iter: T) -> Self { @@ -290,6 +311,7 @@ impl FromIterator for Value { } } +/// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] impl Extend for Value { fn extend>(&mut self, iter: T) { @@ -299,6 +321,7 @@ impl Extend for Value { } } +/// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] impl FromStr for Value { type Err = ParseError; diff --git a/deps/crates/vendor/icu_locale_core/src/helpers.rs b/deps/crates/vendor/icu_locale_core/src/helpers.rs index 48522f4bb1277a..c4ad9c78620c33 100644 --- a/deps/crates/vendor/icu_locale_core/src/helpers.rs +++ b/deps/crates/vendor/icu_locale_core/src/helpers.rs @@ -19,7 +19,6 @@ macro_rules! impl_tinystr_subtag { [$bad_example:literal $(, $more_bad_examples:literal)*], ) => { #[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord, Copy)] - #[cfg_attr(feature = "serde", derive(serde::Serialize))] #[repr(transparent)] $(#[$doc])* pub struct $name(tinystr::TinyAsciiStr<$len_end>); @@ -45,7 +44,6 @@ macro_rules! impl_tinystr_subtag { pub const fn try_from_utf8( code_units: &[u8], ) -> Result { - #[allow(clippy::double_comparisons)] // if code_units.len() === 0 if code_units.len() < $len_start || code_units.len() > $len_end { return Err(crate::parser::errors::ParseError::$error); } @@ -157,14 +155,12 @@ macro_rules! impl_tinystr_subtag { fn writeable_length_hint(&self) -> writeable::LengthHint { writeable::LengthHint::exact(self.0.len()) } - #[inline] - #[cfg(feature = "alloc")] - fn write_to_string(&self) -> alloc::borrow::Cow { - alloc::borrow::Cow::Borrowed(self.0.as_str()) + fn writeable_borrow(&self) -> Option<&str> { + Some(self.0.as_str()) } } - writeable::impl_display_with_writeable!($name); + writeable::impl_display_with_writeable!($name, #[cfg(feature = "alloc")]); #[doc = concat!("A macro allowing for compile-time construction of valid [`", stringify!($name), "`] subtags.")] /// @@ -191,7 +187,6 @@ macro_rules! impl_tinystr_subtag { use $crate::$($path ::)+ $name; match $name::try_from_utf8($string.as_bytes()) { Ok(r) => r, - #[allow(clippy::panic)] // const context _ => panic!(concat!("Invalid ", $(stringify!($path), "::",)+ stringify!($name), ": ", $string)), } }}; @@ -241,6 +236,16 @@ macro_rules! impl_tinystr_subtag { )* } + #[cfg(feature = "serde")] + impl serde::Serialize for $name { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.0.serialize(serializer) + } + } + #[cfg(feature = "serde")] impl<'de> serde::Deserialize<'de> for $name { fn deserialize(deserializer: D) -> Result @@ -317,6 +322,7 @@ macro_rules! impl_tinystr_subtag { } #[cfg(feature = "zerovec")] + #[cfg(feature = "alloc")] impl<'a> zerovec::maps::ZeroMapKV<'a> for $name { type Container = zerovec::ZeroVec<'a, $name>; type Slice = zerovec::ZeroSlice<$name>; @@ -361,28 +367,24 @@ macro_rules! impl_writeable_for_each_subtag_str_no_test { } $( - #[cfg(feature = "alloc")] - fn write_to_string(&self) -> alloc::borrow::Cow { - #[allow(clippy::unwrap_used)] // impl_writeable_for_subtag_list's $borrow uses unwrap + fn writeable_borrow(&self) -> Option<&str> { let $self = self; if $borrow_cond { $borrow } else { - let mut output = alloc::string::String::with_capacity(self.writeable_length_hint().capacity()); - let _ = self.write_to(&mut output); - alloc::borrow::Cow::Owned(output) + None } } )? } - writeable::impl_display_with_writeable!($type); + writeable::impl_display_with_writeable!($type, #[cfg(feature = "alloc")]); }; } macro_rules! impl_writeable_for_subtag_list { ($type:tt, $sample1:literal, $sample2:literal) => { - impl_writeable_for_each_subtag_str_no_test!($type, selff, selff.0.len() == 1 => alloc::borrow::Cow::Borrowed(selff.0.get(0).unwrap().as_str())); + impl_writeable_for_each_subtag_str_no_test!($type, selff, selff.0.len() == 1 => #[allow(clippy::unwrap_used)] { Some(selff.0.get(0).unwrap().as_str()) } ); #[test] fn test_writeable() { diff --git a/deps/crates/vendor/icu_locale_core/src/langid.rs b/deps/crates/vendor/icu_locale_core/src/langid.rs index 82ef5e0d44bb7f..0f8001c0126bb7 100644 --- a/deps/crates/vendor/icu_locale_core/src/langid.rs +++ b/deps/crates/vendor/icu_locale_core/src/langid.rs @@ -40,6 +40,14 @@ use alloc::borrow::Cow; /// This operation normalizes syntax to be well-formed. No legacy subtag replacements is performed. /// For validation and canonicalization, see `LocaleCanonicalizer`. /// +/// # Serde +/// +/// This type implements `serde::Serialize` and `serde::Deserialize` if the +/// `"serde"` Cargo feature is enabled on the crate. +/// +/// The value will be serialized as a string and parsed when deserialized. +/// For tips on efficient storage and retrieval of locales, see [`crate::zerovec`]. +/// /// # Examples /// /// Simple example: @@ -71,7 +79,7 @@ use alloc::borrow::Cow; /// assert_eq!(li.language, language!("en")); /// assert_eq!(li.script, Some(script!("Latn"))); /// assert_eq!(li.region, Some(region!("US"))); -/// assert_eq!(li.variants.get(0), Some(&variant!("valencia"))); +/// assert_eq!(li.variants.first(), Some(&variant!("valencia"))); /// ``` /// /// [`Unicode BCP47 Language Identifier`]: https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier @@ -95,6 +103,8 @@ impl LanguageIdentifier { /// A constructor which takes a utf8 slice, parses it and /// produces a well-formed [`LanguageIdentifier`]. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -109,13 +119,15 @@ impl LanguageIdentifier { } /// See [`Self::try_from_str`] + /// + /// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] pub fn try_from_utf8(code_units: &[u8]) -> Result { crate::parser::parse_language_identifier(code_units, parser::ParserMode::LanguageIdentifier) } #[doc(hidden)] // macro use - #[allow(clippy::type_complexity)] + #[expect(clippy::type_complexity)] // The return type should be `Result` once the `const_precise_live_drops` // is stabilized ([rust-lang#73255](https://github.com/rust-lang/rust/issues/73255)). pub const fn try_from_utf8_with_single_variant( @@ -138,6 +150,8 @@ impl LanguageIdentifier { /// A constructor which takes a utf8 slice which may contain extension keys, /// parses it and produces a well-formed [`LanguageIdentifier`]. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -168,6 +182,8 @@ impl LanguageIdentifier { /// /// This operation will normalize casing and the separator. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -179,7 +195,7 @@ impl LanguageIdentifier { /// ); /// ``` #[cfg(feature = "alloc")] - pub fn normalize_utf8(input: &[u8]) -> Result, ParseError> { + pub fn normalize_utf8(input: &[u8]) -> Result, ParseError> { let lang_id = Self::try_from_utf8(input)?; Ok(writeable::to_string_or_borrow(&lang_id, input)) } @@ -188,6 +204,8 @@ impl LanguageIdentifier { /// /// This operation will normalize casing and the separator. /// + /// ✨ *Enabled with the `alloc` Cargo feature.* + /// /// # Examples /// /// ``` @@ -199,7 +217,7 @@ impl LanguageIdentifier { /// ); /// ``` #[cfg(feature = "alloc")] - pub fn normalize(input: &str) -> Result, ParseError> { + pub fn normalize(input: &str) -> Result, ParseError> { Self::normalize_utf8(input.as_bytes()) } @@ -495,6 +513,7 @@ impl core::fmt::Debug for LanguageIdentifier { } } +/// ✨ *Enabled with the `alloc` Cargo feature.* #[cfg(feature = "alloc")] impl FromStr for LanguageIdentifier { type Err = ParseError; @@ -505,7 +524,7 @@ impl FromStr for LanguageIdentifier { } } -impl_writeable_for_each_subtag_str_no_test!(LanguageIdentifier, selff, selff.script.is_none() && selff.region.is_none() && selff.variants.is_empty() => selff.language.write_to_string()); +impl_writeable_for_each_subtag_str_no_test!(LanguageIdentifier, selff, selff.script.is_none() && selff.region.is_none() && selff.variants.is_empty() => Some(selff.language.as_str())); #[test] fn test_writeable() { diff --git a/deps/crates/vendor/icu_locale_core/src/lib.rs b/deps/crates/vendor/icu_locale_core/src/lib.rs index 8e8a130411c1a5..b465710e9525f4 100644 --- a/deps/crates/vendor/icu_locale_core/src/lib.rs +++ b/deps/crates/vendor/icu_locale_core/src/lib.rs @@ -89,7 +89,7 @@ pub mod subtags; pub mod preferences; pub mod zerovec; -#[cfg(feature = "serde")] +#[cfg(all(feature = "alloc", feature = "serde"))] mod serde; #[cfg(feature = "databake")] diff --git a/deps/crates/vendor/icu_locale_core/src/locale.rs b/deps/crates/vendor/icu_locale_core/src/locale.rs index a3435f215f9b28..31af244c243ad6 100644 --- a/deps/crates/vendor/icu_locale_core/src/locale.rs +++ b/deps/crates/vendor/icu_locale_core/src/locale.rs @@ -46,6 +46,14 @@ use core::str::FromStr; /// ICU4X's Locale parsing does not allow for non-BCP-47-compatible locales [allowed by UTS 35 for backwards compatability][tr35-bcp]. /// Furthermore, it currently does not allow for language tags to have more than three characters. /// +/// # Serde +/// +/// This type implements `serde::Serialize` and `serde::Deserialize` if the +/// `"serde"` Cargo feature is enabled on the crate. +/// +/// The value will be serialized as a string and parsed when deserialized. +/// For tips on efficient storage and retrieval of locales, see [`crate::zerovec`]. +/// /// # Examples /// /// Simple example: @@ -82,7 +90,7 @@ use core::str::FromStr; /// assert_eq!(loc.id.script, "Latn".parse:: + + diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index d88b42c22e72ba..32d186340386ab 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -76,7 +76,7 @@ "path": "url" }, "urlpattern": { - "commit": "23aac9278460a73394585ff5a15b6a04dfcd5ec8", + "commit": "11a459a2b1d411506d9230edf9f2ef32babfeb0b", "path": "urlpattern" }, "user-timing": { diff --git a/test/fuzzers/fuzz_env.cc b/test/fuzzers/fuzz_env.cc index 326d82ae20e03d..e2169296550da6 100644 --- a/test/fuzzers/fuzz_env.cc +++ b/test/fuzzers/fuzz_env.cc @@ -35,9 +35,8 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { node::InitializeNodeWithArgs(&node_argv, &exec_argv, &errors); - tracing_agent = std::make_unique(); - node::tracing::TraceEventHelper::SetAgent(tracing_agent.get()); - node::tracing::TracingController* tracing_controller = + tracing_agent = node::tracing::Agent::CreateDefault(); + v8::TracingController* tracing_controller = tracing_agent->GetTracingController(); CHECK_EQ(0, uv_loop_init(¤t_loop)); static constexpr int kV8ThreadPoolSize = 4; diff --git a/test/fuzzers/fuzz_strings.cc b/test/fuzzers/fuzz_strings.cc index 2226a471f3bef9..92b386d2ecd4a7 100644 --- a/test/fuzzers/fuzz_strings.cc +++ b/test/fuzzers/fuzz_strings.cc @@ -42,9 +42,8 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { node::InitializeNodeWithArgs(&node_argv, &exec_argv, &errors); - tracing_agent = std::make_unique(); - node::tracing::TraceEventHelper::SetAgent(tracing_agent.get()); - node::tracing::TracingController* tracing_controller = + tracing_agent = node::tracing::Agent::CreateDefault(); + v8::TracingController* tracing_controller = tracing_agent->GetTracingController(); CHECK_EQ(0, uv_loop_init(¤t_loop)); static constexpr int kV8ThreadPoolSize = 4; diff --git a/test/parallel/test-blob.js b/test/parallel/test-blob.js index dd74b244420f2a..9ec2a3c04079a7 100644 --- a/test/parallel/test-blob.js +++ b/test/parallel/test-blob.js @@ -3,7 +3,7 @@ const common = require('../common'); const assert = require('assert'); -const { Blob } = require('buffer'); +const { Blob, File } = require('buffer'); const { inspect } = require('util'); const { EOL } = require('os'); const { kState } = require('internal/webstreams/util'); @@ -354,8 +354,10 @@ assert.throws(() => new Blob({}), { assert(!done); setTimeout(common.mustCall(() => { // The blob stream is now a byte stream hence after the first read, - // it should pull in the next 'hello' which is 5 bytes hence -5. - assert.strictEqual(stream[kState].controller.desiredSize, 0); + // it may have pulled in the next 'hello' which is 5 bytes hence -5. + // The ordering of this timer and the stream's setImmediate() pull + // continuation can vary across platforms. + assert([0, -5].includes(stream[kState].controller.desiredSize)); }), 0); })().then(common.mustCall()); @@ -524,3 +526,22 @@ assert.throws(() => new Blob({}), { Blob.prototype.arrayBuffer = arrayBuffer; } })().then(common.mustCall()); + +{ + assert.strictEqual(typeof Blob.prototype.textStream, 'function'); + assert.strictEqual(typeof File.prototype.textStream, 'function'); + assert.strictEqual(File.prototype.textStream, Blob.prototype.textStream); +} + +(async () => { + const smiley = Buffer.from('😀', 'utf8'); + const blob = new Blob(['hello ', smiley.subarray(0, 2), smiley.subarray(2)]); + const stream = blob.textStream(); + assert.ok(stream instanceof ReadableStream); + let result = ''; + for await (const chunk of stream) { + assert.strictEqual(typeof chunk, 'string'); + result += chunk; + } + assert.strictEqual(result, 'hello 😀'); +})().then(common.mustCall()); diff --git a/test/parallel/test-buffer-isutf8-isascii-fast.js b/test/parallel/test-buffer-isutf8-isascii-fast.js new file mode 100644 index 00000000000000..fb2b57025c5272 --- /dev/null +++ b/test/parallel/test-buffer-isutf8-isascii-fast.js @@ -0,0 +1,34 @@ +// Flags: --expose-internals --no-warnings --allow-natives-syntax +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { Buffer, isAscii, isUtf8 } = require('buffer'); + +const ascii = Buffer.from('hello'); +const utf8 = Buffer.from('hello \xc4\x9f'); + +function testFastIsAscii() { + assert.strictEqual(isAscii(ascii), true); +} + +function testFastIsUtf8() { + assert.strictEqual(isUtf8(utf8), true); +} + +eval('%PrepareFunctionForOptimization(isAscii)'); +testFastIsAscii(); +eval('%OptimizeFunctionOnNextCall(isAscii)'); +testFastIsAscii(); + +eval('%PrepareFunctionForOptimization(isUtf8)'); +testFastIsUtf8(); +eval('%OptimizeFunctionOnNextCall(isUtf8)'); +testFastIsUtf8(); + +if (common.isDebug) { + const { internalBinding } = require('internal/test/binding'); + const { getV8FastApiCallCount } = internalBinding('debug'); + assert.strictEqual(getV8FastApiCallCount('buffer.isAscii'), 1); + assert.strictEqual(getV8FastApiCallCount('buffer.isUtf8'), 1); +} diff --git a/test/parallel/test-dgram-custom-lookup.js b/test/parallel/test-dgram-custom-lookup.js index 4f80451c526625..7a2bf92187bda8 100644 --- a/test/parallel/test-dgram-custom-lookup.js +++ b/test/parallel/test-dgram-custom-lookup.js @@ -4,10 +4,12 @@ const assert = require('assert'); const dgram = require('dgram'); const dns = require('dns'); +const originalLookup = dns.lookup; + { // Verify that the provided lookup function is called. const lookup = common.mustCall((host, family, callback) => { - dns.lookup(host, family, callback); + originalLookup(host, family, callback); }); const socket = dgram.createSocket({ type: 'udp4', lookup }); @@ -18,17 +20,17 @@ const dns = require('dns'); } { - // Verify that lookup defaults to dns.lookup(). - const originalLookup = dns.lookup; - + // Verify that the default lookup forwards host names to dns.lookup(). dns.lookup = common.mustCall((host, family, callback) => { dns.lookup = originalLookup; - originalLookup(host, family, callback); + assert.strictEqual(host, 'example.invalid'); + assert.strictEqual(family, 4); + callback(null, '127.0.0.1', 4); }); const socket = dgram.createSocket({ type: 'udp4' }); - socket.bind(common.mustCall(() => { + socket.bind(0, 'example.invalid', common.mustCall(() => { socket.close(); })); } diff --git a/test/parallel/test-dgram-default-lookup-ip.js b/test/parallel/test-dgram-default-lookup-ip.js new file mode 100644 index 00000000000000..826ac7582aac1b --- /dev/null +++ b/test/parallel/test-dgram-default-lookup-ip.js @@ -0,0 +1,80 @@ +'use strict'; + +// The default dgram lookup resolves a literal IP address of the socket's own +// family to itself, without calling dns.lookup(). Each case below stubs the +// process-global dns.lookup(), so they run sequentially to keep one case from +// observing another's stub. + +const common = require('../common'); +const assert = require('assert'); +const dgram = require('dgram'); +const dns = require('dns'); + +const originalLookup = dns.lookup; + +function ipv4SendSkipsLookup(next) { + dns.lookup = common.mustNotCall('dns.lookup() ran for an IPv4 literal'); + + const receiver = dgram.createSocket('udp4'); + const sender = dgram.createSocket('udp4'); + + receiver.on('message', common.mustCall((msg) => { + assert.strictEqual(msg.toString(), 'payload'); + dns.lookup = originalLookup; + receiver.close(); + sender.close(); + next(); + })); + + receiver.bind(0, '127.0.0.1', common.mustCall(() => { + sender.send('payload', receiver.address().port, '127.0.0.1', common.mustCall()); + })); +} + +function ipv6BindSkipsLookup(next) { + if (!common.hasIPv6) { + next(); + return; + } + + dns.lookup = common.mustNotCall('dns.lookup() ran for an IPv6 literal'); + + const socket = dgram.createSocket('udp6'); + + socket.bind(0, '::1', common.mustCall(() => { + dns.lookup = originalLookup; + socket.close(); + next(); + })); +} + +function mismatchedFamilyFallsThrough(next) { + // '::1' is not an IPv4 literal, so a udp4 socket still resolves it via + // dns.lookup() rather than short-circuiting. + dns.lookup = common.mustCall((host, family, callback) => { + dns.lookup = originalLookup; + assert.strictEqual(host, '::1'); + assert.strictEqual(family, 4); + callback(null, '127.0.0.1', 4); + }); + + const socket = dgram.createSocket('udp4'); + + socket.bind(0, '::1', common.mustCall(() => { + socket.close(); + next(); + })); +} + +const cases = [ + ipv4SendSkipsLookup, + ipv6BindSkipsLookup, + mismatchedFamilyFallsThrough, +]; + +(function runNext() { + const testCase = cases.shift(); + if (testCase !== undefined) { + testCase(runNext); + } +})(); diff --git a/test/parallel/test-diagnostics-channel-tracing-channel-promise-spoofed-constructor.js b/test/parallel/test-diagnostics-channel-tracing-channel-promise-spoofed-constructor.js new file mode 100644 index 00000000000000..973a50b87e19d2 --- /dev/null +++ b/test/parallel/test-diagnostics-channel-tracing-channel-promise-spoofed-constructor.js @@ -0,0 +1,52 @@ +'use strict'; + +const common = require('../common'); +const dc = require('diagnostics_channel'); +const assert = require('assert'); + +class SpoofedPromise extends Promise { + customMethod() { + return 'works'; + } +} + +const channel = dc.tracingChannel('test'); + +const expectedResult = { foo: 'bar' }; +const input = { foo: 'bar' }; +const thisArg = { baz: 'buz' }; + +function check(found) { + assert.strictEqual(found, input); +} + +function checkAsync(found) { + check(found); + assert.strictEqual(found.error, undefined); + assert.deepStrictEqual(found.result, expectedResult); +} + +const handlers = { + start: common.mustCall(check), + end: common.mustCall(check), + asyncStart: common.mustCall(checkAsync), + asyncEnd: common.mustCall(checkAsync), + error: common.mustNotCall() +}; + +channel.subscribe(handlers); + +let innerPromise; + +const result = channel.tracePromise(common.mustCall(function() { + innerPromise = SpoofedPromise.resolve(expectedResult); + // Spoof the constructor to try to trick the brand check + innerPromise.constructor = Promise; + return innerPromise; +}), input, thisArg); + +// Despite the spoofed constructor, the original subclass instance should be +// returned directly so that custom methods remain accessible. +assert(result instanceof SpoofedPromise); +assert.strictEqual(result, innerPromise); +assert.strictEqual(result.customMethod(), 'works'); diff --git a/test/parallel/test-diagnostics-channel-tracing-channel-promise-thenable.js b/test/parallel/test-diagnostics-channel-tracing-channel-promise-thenable.js index b93be1dd304c7d..18b38cec9f9949 100644 --- a/test/parallel/test-diagnostics-channel-tracing-channel-promise-thenable.js +++ b/test/parallel/test-diagnostics-channel-tracing-channel-promise-thenable.js @@ -12,6 +12,9 @@ class ResolvedThenable { then(resolve) { return new ResolvedThenable(resolve(this.#result)); } + customMethod() { + return this.#result; + } } const channel = dc.tracingChannel('test'); @@ -49,7 +52,10 @@ const result = channel.tracePromise(common.mustCall(function(value) { }), input, thisArg, expectedResult); assert(result instanceof ResolvedThenable); -assert.notStrictEqual(result, innerThenable); +// With branching then, the original thenable is returned directly so that +// extra methods defined on it remain accessible to the caller. +assert.strictEqual(result, innerThenable); +assert.deepStrictEqual(result.customMethod(), expectedResult); result.then(common.mustCall((value) => { assert.deepStrictEqual(value, expectedResult); })); diff --git a/test/parallel/test-http-connect-default-host-header.js b/test/parallel/test-http-connect-default-host-header.js new file mode 100644 index 00000000000000..9522f028f5165b --- /dev/null +++ b/test/parallel/test-http-connect-default-host-header.js @@ -0,0 +1,37 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); +const net = require('net'); + +const target = 'target.example.com:443'; + +const server = net.createServer(common.mustCall((socket) => { + socket.once('data', common.mustCall((data) => { + const rawRequest = data.toString(); + const requestLines = rawRequest.split('\r\n'); + + assert.strictEqual(requestLines[0], `CONNECT ${target} HTTP/1.1`); + assert(requestLines.includes(`Host: ${target}`)); + + socket.end('HTTP/1.1 200 Connection established\r\n\r\n'); + })); +})); + +server.listen(0, common.localhostIPv4, common.mustCall(() => { + const req = http.request({ + host: common.localhostIPv4, + port: server.address().port, + method: 'CONNECT', + path: target, + }, common.mustNotCall()); + + req.on('connect', common.mustCall((res, socket) => { + assert.strictEqual(res.statusCode, 200); + socket.destroy(); + server.close(); + })); + + req.end(); +})); diff --git a/test/parallel/test-http-response-drain-cork.js b/test/parallel/test-http-response-drain-cork.js new file mode 100644 index 00000000000000..18678748b9c2a4 --- /dev/null +++ b/test/parallel/test-http-response-drain-cork.js @@ -0,0 +1,64 @@ +'use strict'; +const common = require('../common'); +const http = require('http'); +const assert = require('assert'); + +// Test that drain event is emitted correctly when using cork/uncork +// with ServerResponse and the write buffer is full + +const server = http.createServer(common.mustCall(async (req, res) => { + res.cork(); + + // Write small amount - won't need drain + assert.strictEqual(res.write('1'.repeat(10)), true); + + // Write enough to exceed highWaterMark (set in 'connection' listener) + assert.strictEqual(res.write('2'.repeat(1000)), false); + + // Verify writableNeedDrain is set + assert.strictEqual(res.writableNeedDrain, true); + + // Wait for drain event after uncorking + const drainPromise = new Promise((resolve) => { + res.once('drain', common.mustCall(() => { + // After drain, writableNeedDrain should be false + assert.strictEqual(res.writableNeedDrain, false); + resolve(); + })); + }); + + // Uncork should trigger drain + res.uncork(); + await drainPromise; + + res.end(); +})); + +server.on('connection', common.mustCall((socket) => { + // Set high water mark large enough to cover HTTP overhead + first + // small content batch, but not enough to cover second batch. + socket._writableState.highWaterMark = 1000; +})); + +server.listen(0, common.localhostIPv4, common.mustCall(() => { + http.get({ + host: common.localhostIPv4, + port: server.address().port, + }, common.mustCall((res) => { + let data = ''; + res.setEncoding('utf8'); + + res.on('data', (chunk) => { + data += chunk; + }); + + res.on('end', common.mustCall(() => { + // Verify we got all the data + assert.strictEqual(data.length, 10 + 1000); + assert.strictEqual(data.substring(0, 10), '1'.repeat(10)); + assert.strictEqual(data.substring(10), '2'.repeat(1000)); + + server.close(common.mustCall()); + })); + })); +})); diff --git a/test/parallel/test-http-server-consumed-timeout.js b/test/parallel/test-http-server-consumed-timeout.js index d335ef4b21ffbd..b1781913b56866 100644 --- a/test/parallel/test-http-server-consumed-timeout.js +++ b/test/parallel/test-http-server-consumed-timeout.js @@ -58,7 +58,8 @@ function runTest(timeoutDuration) { server.listen(0, common.mustCall(() => { const req = http.request({ port: server.address().port, - method: 'POST' + method: 'POST', + agent: false, }, () => { let lastIntervalTimestamp = Date.now(); const interval = setInterval(() => { diff --git a/test/parallel/test-internal-validators-validateport.js b/test/parallel/test-internal-validators-validateport.js index a4c92b8dbca929..b125d0a93f71ab 100644 --- a/test/parallel/test-internal-validators-validateport.js +++ b/test/parallel/test-internal-validators-validateport.js @@ -21,3 +21,17 @@ for (let n = 0; n <= 0xFFFF; n++) { ].forEach((i) => assert.throws(() => validatePort(i), { code: 'ERR_SOCKET_BAD_PORT' })); + +// When allowZero is false, every form of zero must be rejected, including +// the string forms that coerce to 0. Refs: the zero check must coerce the +// value the same way the rest of the validation does (`+port`). +[ + 0, '0', ' 0 ', '00', '0x0', '0o0', '0b0', +].forEach((i) => assert.throws(() => validatePort(i, 'Port', false), { + code: 'ERR_SOCKET_BAD_PORT' +})); + +// With allowZero left at its default (true), those same values are accepted. +[ + 0, '0', ' 0 ', '00', '0x0', '0o0', '0b0', +].forEach((i) => assert.strictEqual(validatePort(i), 0)); diff --git a/test/parallel/test-net-allow-half-open-async-iter.js b/test/parallel/test-net-allow-half-open-async-iter.js new file mode 100644 index 00000000000000..30d82fc4e5b327 --- /dev/null +++ b/test/parallel/test-net-allow-half-open-async-iter.js @@ -0,0 +1,80 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); + +(async function() { + let resolveServerSocket; + const serverSocketPromise = new Promise((resolve) => { + resolveServerSocket = resolve; + }); + + const server = net.createServer({ + allowHalfOpen: true, + }, common.mustCall((socket) => { + resolveServerSocket(socket); + })); + + server.on('error', common.mustNotCall()); + server.on('close', common.mustCall()); + + await new Promise((resolve) => { + server.listen(0, common.localhostIPv4, resolve); + }); + + const clientSocket = await new Promise((resolve) => { + const socket = net.createConnection({ + allowHalfOpen: true, + port: server.address().port, + host: server.address().address, + }, common.mustCall(() => { + resolve(socket); + })); + socket.on('error', common.mustNotCall()); + }); + + const serverSocket = await serverSocketPromise; + serverSocket.on('error', common.mustNotCall()); + + await new Promise((resolve, reject) => { + clientSocket.write('data written to client socket', (err) => { + if (err) reject(err); + else resolve(); + }); + }); + + await new Promise((resolve) => { + clientSocket.end(resolve); + }); + + let serverRead = ''; + for await (const chunk of serverSocket) { + serverRead += chunk; + } + + assert.strictEqual(serverRead, 'data written to client socket'); + assert.strictEqual(serverSocket.destroyed, false); + + await new Promise((resolve, reject) => { + serverSocket.write('data written to server socket', (err) => { + if (err) reject(err); + else resolve(); + }); + }); + + await new Promise((resolve) => { + serverSocket.end(resolve); + }); + + let clientRead = ''; + for await (const chunk of clientSocket) { + clientRead += chunk; + } + + assert.strictEqual(clientRead, 'data written to server socket'); + + await new Promise((resolve) => { + server.close(resolve); + }); +})().then(common.mustCall()); diff --git a/test/parallel/test-node-run.js b/test/parallel/test-node-run.js index 26295256849702..e24117f6b1658b 100644 --- a/test/parallel/test-node-run.js +++ b/test/parallel/test-node-run.js @@ -143,15 +143,15 @@ describe('node --run [command]', () => { it('appends positional arguments', async () => { const child = await common.spawnPromisified( process.execPath, - [ '--run', `positional-args${envSuffix}`, '--', '--help "hello world test"', 'A', 'B', 'C'], + [ '--run', `positional-args${envSuffix}`, '--', '--help "hello world test"', 'A', 'B', 'C', 'I think therefore I\'m'], { cwd: fixtures.path('run-script') }, ); if (common.isWindows) { - assert.match(child.stdout, /Arguments: '--help ""hello world test"" A B C'/); + assert.match(child.stdout, /Arguments: '--help ""hello world test"" A B C I think therefore I'm'/); } else { - assert.match(child.stdout, /Arguments: '--help "hello world test" A B C'/); + assert.match(child.stdout, /Arguments: '--help "hello world test" A B C I think therefore I'm'/); } - assert.match(child.stdout, /The total number of arguments are: 4/); + assert.match(child.stdout, /The total number of arguments is: 5/); assert.strictEqual(child.stderr, ''); assert.strictEqual(child.code, 0); }); diff --git a/test/parallel/test-perf-hooks-monitor-event-loop-delay-fast-calls.js b/test/parallel/test-perf-hooks-monitor-event-loop-delay-fast-calls.js new file mode 100644 index 00000000000000..1954f52e441557 --- /dev/null +++ b/test/parallel/test-perf-hooks-monitor-event-loop-delay-fast-calls.js @@ -0,0 +1,26 @@ +// Flags: --allow-natives-syntax --expose-internals --no-warnings +'use strict'; + +const common = require('../common'); +const assert = require('assert'); + +const { internalBinding } = require('internal/test/binding'); +const { createELDHistogram } = internalBinding('performance'); + +const histogram = createELDHistogram(1, true); + +function testFastMethods() { + histogram.start(true); + histogram.stop(); +} + +eval('%PrepareFunctionForOptimization(testFastMethods)'); +testFastMethods(); +eval('%OptimizeFunctionOnNextCall(testFastMethods)'); +testFastMethods(); + +if (common.isDebug) { + const { getV8FastApiCallCount } = internalBinding('debug'); + assert.strictEqual(getV8FastApiCallCount('histogram.eventLoopDelay.start'), 1); + assert.strictEqual(getV8FastApiCallCount('histogram.eventLoopDelay.stop'), 1); +} diff --git a/test/parallel/test-performance-gc-minor-ms.js b/test/parallel/test-performance-gc-minor-ms.js new file mode 100644 index 00000000000000..322d22c6b00201 --- /dev/null +++ b/test/parallel/test-performance-gc-minor-ms.js @@ -0,0 +1,36 @@ +// Flags: --expose-gc --no-warnings --minor-ms +'use strict'; + +// When V8's Minor Mark-Sweep collector is enabled (--minor-ms), minor garbage +// collections are reported with kind NODE_PERFORMANCE_GC_MINOR_MARK_SWEEP +// rather than NODE_PERFORMANCE_GC_MINOR. + +const common = require('../common'); +const assert = require('assert'); +const { gcUntil } = require('../common/gc'); +const { + PerformanceObserver, + constants +} = require('perf_hooks'); + +const { + NODE_PERFORMANCE_GC_MINOR_MARK_SWEEP +} = constants; + +let observed = false; +const obs = new PerformanceObserver(common.mustCallAtLeast((list) => { + for (const entry of list.getEntries()) { + // Other GC kinds (e.g. a scheduled or incremental GC) may be observed in + // between; only the minor mark-sweep entry is relevant here. + if (entry.detail.kind === NODE_PERFORMANCE_GC_MINOR_MARK_SWEEP) { + assert.strictEqual(entry.name, 'gc'); + assert.strictEqual(entry.entryType, 'gc'); + observed = true; + obs.disconnect(); + return; + } + } +})); +obs.observe({ entryTypes: ['gc'] }); + +gcUntil('minor gc event', () => observed, 10, { type: 'minor' }); diff --git a/test/parallel/test-performance-gc.js b/test/parallel/test-performance-gc.js index 4fad8b5b9ff349..0c2ea201fc630a 100644 --- a/test/parallel/test-performance-gc.js +++ b/test/parallel/test-performance-gc.js @@ -11,6 +11,7 @@ const { const { NODE_PERFORMANCE_GC_MAJOR, NODE_PERFORMANCE_GC_MINOR, + NODE_PERFORMANCE_GC_MINOR_MARK_SWEEP, NODE_PERFORMANCE_GC_INCREMENTAL, NODE_PERFORMANCE_GC_WEAKCB, NODE_PERFORMANCE_GC_FLAGS_FORCED @@ -19,6 +20,7 @@ const { const kinds = [ NODE_PERFORMANCE_GC_MAJOR, NODE_PERFORMANCE_GC_MINOR, + NODE_PERFORMANCE_GC_MINOR_MARK_SWEEP, NODE_PERFORMANCE_GC_INCREMENTAL, NODE_PERFORMANCE_GC_WEAKCB, ]; diff --git a/test/parallel/test-permission-child-process-inherit-flags-substring.js b/test/parallel/test-permission-child-process-inherit-flags-substring.js new file mode 100644 index 00000000000000..f992a1f3dc8f3b --- /dev/null +++ b/test/parallel/test-permission-child-process-inherit-flags-substring.js @@ -0,0 +1,96 @@ +// Flags: --permission --allow-child-process --allow-fs-read=* --allow-worker +// Tests that NODE_OPTIONS values containing '--permission' as a substring +// in unrelated option values (e.g., --title=--permission) do NOT suppress +// Permission Model flag propagation to child processes. +'use strict'; + +const common = require('../common'); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} +if (process.config.variables.node_without_node_options) { + common.skip('missing NODE_OPTIONS support'); +} + +const assert = require('assert'); +const childProcess = require('child_process'); + +// Verify that the parent has Permission Model enabled +assert.ok(process.permission.has('child')); +assert.strictEqual(process.env.NODE_OPTIONS, undefined); + +// Test cases: NODE_OPTIONS values that contain '--permission' as a substring +// but are NOT actual permission flags. These should NOT suppress propagation. +const testCases = [ + { name: 'title', nodeOptions: '--title=--permission' }, + { name: 'conditions', nodeOptions: '--conditions=--permission' }, + { name: 'trace-event-categories', nodeOptions: '--trace-event-categories=--permission' }, + { name: 'title-audit', nodeOptions: '--title=--permission-audit' }, +]; + +for (const { name, nodeOptions } of testCases) { + // Spawn a child with the problematic NODE_OPTIONS value. + // Without the fix, the substring check causes propagation to be skipped, + // and the child will not have process.permission. + const { status, stdout } = childProcess.spawnSync( + process.execPath, + [ + '-e', + ` + console.log(typeof process.permission); + console.log(process.permission && process.permission.has("child")); + console.log(process.env.NODE_OPTIONS); + `, + ], + { + env: { + ...process.env, + 'NODE_OPTIONS': nodeOptions, + } + } + ); + + assert.strictEqual(status, 0, `child process for ${name} exited with status ${status}`); + + const [permType, hasChild] = stdout.toString().split('\n'); + + // Verify the child has Permission Model enabled (the bug caused it to be absent) + assert.strictEqual(permType, 'object', `child ${name} should have process.permission object`); + + // Verify the child inherited child permission + assert.strictEqual(hasChild, 'true', `child ${name} should have child permission`); +} + +// Also verify that a child with a real --permission flag in NODE_OPTIONS +// still gets its own flags honored (regression test for existing behavior). +{ + const { status, stdout } = childProcess.spawnSync( + process.execPath, + [ + '-e', + ` + console.log(process.permission.has("fs.write")); + console.log(process.permission.has("fs.read")); + console.log(process.permission.has("child")); + `, + ], + { + env: { + ...process.env, + 'NODE_OPTIONS': '--permission --allow-fs-write=*', + } + } + ); + + assert.strictEqual(status, 0); + const [fsWrite, fsRead, child] = stdout.toString().split('\n'); + assert.strictEqual(fsWrite, 'true'); + assert.strictEqual(fsRead, 'false'); + assert.strictEqual(child, 'false'); +} + +{ + assert.strictEqual(process.env.NODE_OPTIONS, undefined); +} diff --git a/test/parallel/test-permission-drop-addons.js b/test/parallel/test-permission-drop-addons.js new file mode 100644 index 00000000000000..baf87c3b95b858 --- /dev/null +++ b/test/parallel/test-permission-drop-addons.js @@ -0,0 +1,38 @@ +// Flags: --permission --allow-addons --allow-fs-read=* +'use strict'; + +const common = require('../common'); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} + +const assert = require('assert'); + +let bindingPath; +try { + bindingPath = require.resolve( + `../addons/hello-world/build/${common.buildType}/binding`); +} catch (err) { + if (err.code !== 'MODULE_NOT_FOUND') { + throw err; + } + common.skip('addon not found'); +} + +function openAddon() { + process.dlopen({ exports: {} }, bindingPath); +} + +assert.ok(process.permission.has('addon')); +openAddon(); + +process.permission.drop('addon'); +assert.ok(!process.permission.has('addon')); +assert.throws(() => { + openAddon(); +}, common.expectsError({ + code: 'ERR_ACCESS_DENIED', + permission: 'Addon', +})); diff --git a/test/parallel/test-process-finalization.mjs b/test/parallel/test-process-finalization.mjs index 5d3222aaca67d4..dddd0b8fae19d7 100644 --- a/test/parallel/test-process-finalization.mjs +++ b/test/parallel/test-process-finalization.mjs @@ -9,6 +9,7 @@ import assert from 'assert'; const files = [ 'close.mjs', 'before-exit.mjs', + 'finalization-cleanup.mjs', 'gc-not-close.mjs', 'unregister.mjs', 'different-registry-per-thread.mjs', diff --git a/test/parallel/test-quic-version-negotiation-oversized-cid.mjs b/test/parallel/test-quic-version-negotiation-oversized-cid.mjs new file mode 100644 index 00000000000000..55b5f6e0f669f8 --- /dev/null +++ b/test/parallel/test-quic-version-negotiation-oversized-cid.mjs @@ -0,0 +1,89 @@ +// Flags: --experimental-quic --no-warnings + +// Regression test for an unauthenticated remote crash in the QUIC Version +// Negotiation path. +// +// ngtcp2_pkt_decode_version_cid() does not clamp the connection ID lengths +// to NGTCP2_MAX_CIDLEN (20) when the packet's version is unsupported -- it +// returns the raw single-byte length fields from the wire, which can be up +// to 255. Endpoint::Receive() used to build CID objects (each backed by a +// fixed 20-byte buffer) directly from those lengths before any bound check, +// so a single crafted UDP datagram with an oversized DCID/SCID length would +// overflow the buffer and abort the process before the handshake. +// +// This test sends such a datagram directly with node:dgram and asserts the +// endpoint drops it without crashing, while a well-formed unsupported-version +// datagram still produces exactly one Version Negotiation response. + +import { hasQuic, skip, mustNotCall } from '../common/index.mjs'; +import assert from 'node:assert'; + +const { strictEqual } = assert; + +if (!hasQuic) { + skip('QUIC is not enabled'); +} + +const { createSocket } = await import('node:dgram'); +const { listen } = await import('../common/quic.mjs'); + +// A long-header QUIC packet must be at least NGTCP2_MAX_UDP_PAYLOAD_SIZE +// (1200) bytes for an unsupported version to decode as a VN trigger. +const PACKET_SIZE = 1200; + +// Build a QUIC long-header packet with an unsupported version and the given +// DCID/SCID lengths. Lengths greater than 20 are only expressible because the +// on-wire length field is a single byte (0-255). +function buildLongHeaderPacket(dcidLen, scidLen) { + const packet = Buffer.alloc(PACKET_SIZE); + // Header form bit (0x80) + fixed bit (0x40). + packet[0] = 0xc0; + // Version 0x0a0a0a0a: nonzero (so it is not a real VN packet) and not a + // version Node supports, which forces the NGTCP2_ERR_VERSION_NEGOTIATION + // decode path. + packet.writeUInt32BE(0x0a0a0a0a, 1); + packet[5] = dcidLen; // DCID length byte + // DCID bytes occupy [6, 6 + dcidLen); SCID length byte follows them. + packet[6 + dcidLen] = scidLen; + // Remaining bytes stay zero-filled as padding to reach PACKET_SIZE. + return packet; +} + +// No handshake ever completes: the test only sends raw datagrams, so the +// session callback must never fire. +const serverEndpoint = await listen(mustNotCall()); +const { address, port } = serverEndpoint.address; + +const socket = createSocket('udp4'); + +function send(packet) { + return new Promise((resolve, reject) => { + socket.send(packet, port, address, (err) => { + if (err) reject(err); + else resolve(); + }); + }); +} + +// 1. Oversized DCID (21 > NGTCP2_MAX_CIDLEN). Before the fix this aborted the +// process. After the fix it must be dropped silently. +await send(buildLongHeaderPacket(21, 0)); + +// 2. A well-formed unsupported-version packet with valid (<= 20 byte) CIDs. +// This must still elicit exactly one Version Negotiation response, proving +// the fix did not break legitimate version negotiation. +await send(buildLongHeaderPacket(8, 8)); + +// Poll until the valid packet has been processed into a VN response. +const deadline = Date.now() + 2000; +while (serverEndpoint.stats.versionNegotiationCount === 0n) { + if (Date.now() > deadline) break; + await new Promise((resolve) => setTimeout(resolve, 25)); +} + +// Exactly one VN response: the oversized packet was dropped (not crashed, not +// negotiated), the valid packet was negotiated. +strictEqual(serverEndpoint.stats.versionNegotiationCount, 1n); + +socket.close(); +await serverEndpoint.close(); diff --git a/test/parallel/test-runner-coverage.js b/test/parallel/test-runner-coverage.js index 5a8f3d743538cb..542078c93d5e45 100644 --- a/test/parallel/test-runner-coverage.js +++ b/test/parallel/test-runner-coverage.js @@ -77,6 +77,22 @@ function getSpecCoverageFixtureReport() { return report; } +function formatSpawnSyncResult(result) { + return [ + `status: ${result.status}`, + `signal: ${result.signal}`, + `stdout:\n${result.stdout}`, + `stderr:\n${result.stderr}`, + ].join('\n'); +} + +function assertIncludesReport(result, report) { + assert( + result.stdout.toString().includes(report), + formatSpawnSyncResult(result), + ); +} + test('test coverage report', async (t) => { await t.test('handles the inspector not being available', (t) => { if (process.features.inspector) { @@ -111,7 +127,7 @@ test('test tap coverage reporter', skipIfNoInspector, async (t) => { const options = { env: { ...process.env, NODE_V8_COVERAGE: tmpdir.path } }; const result = spawnSync(process.execPath, args, options); const report = getTapCoverageFixtureReport(); - assert(result.stdout.toString().includes(report)); + assertIncludesReport(result, report); assert.strictEqual(result.stderr.toString(), ''); assert.strictEqual(result.status, 0); assert(findCoverageFileForPid(result.pid)); @@ -129,7 +145,7 @@ test('test tap coverage reporter', skipIfNoInspector, async (t) => { const result = spawnSync(process.execPath, args); const report = getTapCoverageFixtureReport(); - assert(result.stdout.toString().includes(report)); + assertIncludesReport(result, report); assert.strictEqual(result.stderr.toString(), ''); assert.strictEqual(result.status, 0); assert(!findCoverageFileForPid(result.pid)); @@ -149,7 +165,7 @@ test('test spec coverage reporter', skipIfNoInspector, async (t) => { const result = spawnSync(process.execPath, args, options); const report = getSpecCoverageFixtureReport(); - assert(result.stdout.toString().includes(report)); + assertIncludesReport(result, report); assert.strictEqual(result.stderr.toString(), ''); assert.strictEqual(result.status, 0); assert(findCoverageFileForPid(result.pid)); @@ -166,7 +182,7 @@ test('test spec coverage reporter', skipIfNoInspector, async (t) => { const result = spawnSync(process.execPath, args); const report = getSpecCoverageFixtureReport(); - assert(result.stdout.toString().includes(report)); + assertIncludesReport(result, report); assert.strictEqual(result.stderr.toString(), ''); assert.strictEqual(result.status, 0); assert(!findCoverageFileForPid(result.pid)); @@ -187,7 +203,7 @@ test('single process coverage is the same with --test', skipIfNoInspector, () => const report = getTapCoverageFixtureReport(); assert.strictEqual(result.stderr.toString(), ''); - assert(result.stdout.toString().includes(report)); + assertIncludesReport(result, report); assert.strictEqual(result.status, 0); assert(!findCoverageFileForPid(result.pid)); }); @@ -226,7 +242,7 @@ test('coverage is combined for multiple processes', skipIfNoInspector, () => { }); assert.strictEqual(result.stderr.toString(), ''); - assert(result.stdout.toString().includes(report)); + assertIncludesReport(result, report); assert.strictEqual(result.status, 0); }); @@ -268,7 +284,7 @@ test.skip('coverage works with isolation=none', skipIfNoInspector, common.mustCa }); assert.strictEqual(result.stderr.toString(), ''); - assert(result.stdout.toString().includes(report)); + assertIncludesReport(result, report); assert.strictEqual(result.status, 0); }, 0)); @@ -285,6 +301,7 @@ test('coverage reports on lines, functions, and branches', skipIfNoInspector, as ]); assert.strictEqual(child.stderr.toString(), ''); const stdout = child.stdout.toString(); + assert.notStrictEqual(stdout, '', formatSpawnSyncResult(child)); const coverage = JSON.parse(stdout); await t.test('does not include node_modules', () => { @@ -366,7 +383,7 @@ test('coverage with ESM hook - source irrelevant', skipIfNoInspector, () => { const result = spawnSync(process.execPath, args, { cwd: fixture }); assert.strictEqual(result.stderr.toString(), ''); - assert(result.stdout.toString().includes(report)); + assertIncludesReport(result, report); assert.strictEqual(result.status, 0); }); @@ -401,7 +418,7 @@ test('coverage with ESM hook - source transpiled', skipIfNoInspector, () => { const result = spawnSync(process.execPath, args, { cwd: fixture }); assert.strictEqual(result.stderr.toString(), ''); - assert(result.stdout.toString().includes(report)); + assertIncludesReport(result, report); assert.strictEqual(result.status, 0); }); @@ -435,7 +452,7 @@ test('coverage with excluded files', skipIfNoInspector, () => { return report.replaceAll('/', '\\'); } - assert(result.stdout.toString().includes(report)); + assertIncludesReport(result, report); assert.strictEqual(result.status, 0); assert(!findCoverageFileForPid(result.pid)); }); @@ -472,7 +489,7 @@ test('coverage with included files', skipIfNoInspector, () => { return report.replaceAll('/', '\\'); } - assert(result.stdout.toString().includes(report)); + assertIncludesReport(result, report); assert.strictEqual(result.status, 0); assert(!findCoverageFileForPid(result.pid)); }); @@ -506,7 +523,7 @@ test('coverage with included and excluded files', skipIfNoInspector, () => { return report.replaceAll('/', '\\'); } - assert(result.stdout.toString().includes(report)); + assertIncludesReport(result, report); assert.strictEqual(result.status, 0); assert(!findCoverageFileForPid(result.pid)); }); @@ -547,7 +564,7 @@ test('correctly prints the coverage report of files contained in parent director }); assert.strictEqual(result.stderr.toString(), ''); - assert(result.stdout.toString().includes(report)); + assertIncludesReport(result, report); assert.strictEqual(result.status, 0); }); @@ -564,5 +581,5 @@ test('coverage with directory and file named "file"', skipIfNoInspector, () => { assert.strictEqual(result.stderr.toString(), ''); assert.strictEqual(result.status, 0); - assert(result.stdout.toString().includes('start of coverage report')); + assertIncludesReport(result, 'start of coverage report'); }); diff --git a/test/parallel/test-runner-reporters.js b/test/parallel/test-runner-reporters.js index 50a47578a1da7e..7fed79d45b48fd 100644 --- a/test/parallel/test-runner-reporters.js +++ b/test/parallel/test-runner-reporters.js @@ -200,6 +200,12 @@ describe('node:test reporters', { concurrency: true }, () => { assert.strictEqual(child.stdout.toString(), ''); const fileContents = fs.readFileSync(file, 'utf8'); assert.match(fileContents, //); + // The exact timestamp format is intentionally not pinned here (still under + // discussion); assert only that the value is present and a real date. + const { 1: timestamp } = fileContents.match(/]*timestamp="([^"]+)"/) ?? []; + assert.ok(timestamp, 'testsuite should have a timestamp attribute'); + assert.match(timestamp, /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/); + assert.ok(!Number.isNaN(Date.parse(timestamp)), `expected a valid date, got ${timestamp}`); assert.match(fileContents, /\s*/); assert.match(fileContents, //); assert.match(fileContents, //); diff --git a/test/parallel/test-runner-run-coverage.mjs b/test/parallel/test-runner-run-coverage.mjs index 89a9da2a179e44..5a70644a89d93c 100644 --- a/test/parallel/test-runner-run-coverage.mjs +++ b/test/parallel/test-runner-run-coverage.mjs @@ -154,10 +154,13 @@ describe('require(\'node:test\').run coverage settings', { concurrency: true }, for await (const _ of stream); }); - await it('should run with coverage and fail when below line threshold', async () => { + await it('should run with coverage and fail when below line threshold', async (t) => { const thresholdErrors = []; const originalExitCode = process.exitCode; - assert.notStrictEqual(originalExitCode, 1); + t.after(() => { + process.exitCode = originalExitCode; + }); + process.exitCode = undefined; const stream = run({ files, coverage: true, @@ -178,7 +181,6 @@ describe('require(\'node:test\').run coverage settings', { concurrency: true }, for await (const _ of stream); assert.deepStrictEqual(thresholdErrors.sort(), ['branch', 'function', 'line']); assert.strictEqual(process.exitCode, 1); - process.exitCode = originalExitCode; }); }); }); diff --git a/test/parallel/test-stream-iter-broadcast-basic.js b/test/parallel/test-stream-iter-broadcast-basic.js index 39a2e2348ecb2e..bdecd7d5beb9b1 100644 --- a/test/parallel/test-stream-iter-broadcast-basic.js +++ b/test/parallel/test-stream-iter-broadcast-basic.js @@ -174,6 +174,19 @@ async function testPendingNextSettlesAfterReturn() { assert.strictEqual(result.value, undefined); } +async function testPushAbortSignalRejectsPendingNext() { + const ac = new AbortController(); + const reason = new Error('push aborted'); + const { broadcast: bc } = broadcast(); + const iter = bc.push({ signal: ac.signal })[Symbol.asyncIterator](); + + const pendingNext = iter.next(); + const rejected = assert.rejects(pendingNext, (error) => error === reason); + ac.abort(reason); + + await rejected; +} + // ============================================================================= // Writer fail detaches consumers // ============================================================================= @@ -300,6 +313,7 @@ Promise.all([ testCancelWithReason(), testCancelWithFalsyReason(), testPendingNextSettlesAfterReturn(), + testPushAbortSignalRejectsPendingNext(), testFailDetachesConsumers(), testWriterFailIdempotent(), testLateJoinerSeesBufferedData(), diff --git a/test/parallel/test-stream-iter-broadcast-from.js b/test/parallel/test-stream-iter-broadcast-from.js index 0203252f26229a..39d92c2aef49b3 100644 --- a/test/parallel/test-stream-iter-broadcast-from.js +++ b/test/parallel/test-stream-iter-broadcast-from.js @@ -43,6 +43,28 @@ async function testBroadcastFromStringChunks() { assert.strictEqual(data, 'foobar'); } +async function testBroadcastFromStringInput() { + const { broadcast: bc } = Broadcast.from('abc'); + const consumer = bc.push(); + const data = await text(consumer); + assert.strictEqual(data, 'abc'); +} + +async function testBroadcastFromUint8ArrayInput() { + const { broadcast: bc } = Broadcast.from(new Uint8Array([97])); + const consumer = bc.push(); + const data = await text(consumer); + assert.strictEqual(data, 'a'); +} + +async function testBroadcastFromDataViewInput() { + const view = new DataView(new Uint8Array([104, 105]).buffer); + const { broadcast: bc } = Broadcast.from(view); + const consumer = bc.push(); + const data = await text(consumer); + assert.strictEqual(data, 'hi'); +} + async function testBroadcastFromMultipleConsumers() { const source = from('shared-data'); const { broadcast: bc } = Broadcast.from(source); @@ -180,6 +202,9 @@ Promise.all([ testBroadcastFromAsyncIterable(), testBroadcastFromNonArrayChunks(), testBroadcastFromStringChunks(), + testBroadcastFromStringInput(), + testBroadcastFromUint8ArrayInput(), + testBroadcastFromDataViewInput(), testBroadcastFromMultipleConsumers(), testAbortSignal(), testAlreadyAbortedSignal(), diff --git a/test/parallel/test-stream-iter-consumers-bytes.js b/test/parallel/test-stream-iter-consumers-bytes.js index e45ee991d587fd..53d0a3858f87ec 100644 --- a/test/parallel/test-stream-iter-consumers-bytes.js +++ b/test/parallel/test-stream-iter-consumers-bytes.js @@ -14,6 +14,7 @@ const { arrayBufferSync, array, arraySync, + toAsyncStreamable, } = require('stream/iter'); // ============================================================================= @@ -51,6 +52,55 @@ async function testBytesAsyncAbort() { ); } +async function testAsyncConsumersAbortPendingNext() { + const consumers = [ + ['bytes', bytes], + ['text', text], + ['arrayBuffer', arrayBuffer], + ['array', array], + ]; + + for (const [name, consumer] of consumers) { + const ac = new AbortController(); + const reason = new Error(`${name} boom`); + + async function* never() { + await new Promise(() => {}); + yield []; + } + + const promise = consumer(never(), { __proto__: null, signal: ac.signal }); + ac.abort(reason); + + await assert.rejects(promise, reason); + } +} + +async function testAsyncConsumersAbortPendingNormalization() { + const consumers = [ + ['bytes', bytes], + ['text', text], + ['arrayBuffer', arrayBuffer], + ['array', array], + ]; + + for (const [name, consumer] of consumers) { + const ac = new AbortController(); + const reason = new Error(`${name} normalization boom`); + const source = { + __proto__: null, + [toAsyncStreamable]() { + return new Promise(() => {}); + }, + }; + + const promise = consumer(source, { __proto__: null, signal: ac.signal }); + ac.abort(reason); + + await assert.rejects(promise, reason); + } +} + async function testBytesEmpty() { const data = await bytes(from([])); assert.ok(data instanceof Uint8Array); @@ -203,6 +253,8 @@ Promise.all([ testBytesAsync(), testBytesAsyncLimit(), testBytesAsyncAbort(), + testAsyncConsumersAbortPendingNext(), + testAsyncConsumersAbortPendingNormalization(), testBytesEmpty(), testArrayBufferSyncBasic(), testArrayBufferAsync(), diff --git a/test/parallel/test-stream-iter-consumers-merge.js b/test/parallel/test-stream-iter-consumers-merge.js index 97cc8b9ac89477..b551599f731462 100644 --- a/test/parallel/test-stream-iter-consumers-merge.js +++ b/test/parallel/test-stream-iter-consumers-merge.js @@ -151,6 +151,25 @@ async function testMergeSignalMidIteration() { await assert.rejects(() => iter.next(), { name: 'AbortError' }); } +async function testMergeSignalDuringPendingMultiSourceRead() { + const ac = new AbortController(); + + async function* pending() { + await new Promise(() => {}); + yield []; + } + + const iter = merge(pending(), pending(), { + __proto__: null, + signal: ac.signal, + })[Symbol.asyncIterator](); + + const next = iter.next(); + ac.abort(); + + await assert.rejects(next, { name: 'AbortError' }); +} + // merge() accepts string sources (normalized via from()) async function testMergeStringSources() { const batches = []; @@ -286,6 +305,7 @@ Promise.all([ testMergeSourceError(), testMergeConsumerBreak(), testMergeSignalMidIteration(), + testMergeSignalDuringPendingMultiSourceRead(), testMergeStringSources(), testMergeObjectLikeSources(), testMergeCleanupErrorOnly(), diff --git a/test/parallel/test-stream-iter-pipeto-signal.js b/test/parallel/test-stream-iter-pipeto-signal.js index 153ee1a80e6176..ec1324a4e04bdc 100644 --- a/test/parallel/test-stream-iter-pipeto-signal.js +++ b/test/parallel/test-stream-iter-pipeto-signal.js @@ -6,6 +6,7 @@ const common = require('../common'); const assert = require('assert'); +const { setTimeout } = require('timers/promises'); const { pipeTo, from } = require('stream/iter'); // pipeTo with live signal, no transforms — abort mid-stream @@ -30,6 +31,38 @@ async function testPipeToLiveSignalNoTransforms() { assert.ok(written.length >= 1); } +// pipeTo with live signal, no transforms — abort while waiting for next chunk +async function testPipeToLiveSignalNoTransformsPendingNext() { + const ac = new AbortController(); + const reason = new Error('abort reason'); + const writer = { + write: common.mustNotCall(), + }; + const source = { + [Symbol.asyncIterator]() { + return { + next() { + return new Promise(() => {}); + }, + }; + }, + }; + + setTimeout(10) + .then(() => ac.abort(reason)) + .then(common.mustCall()); + + const result = await Promise.race([ + assert.rejects( + () => pipeTo(source, writer, { signal: ac.signal }), + reason, + ).then(() => 'aborted'), + setTimeout(1000, 'timed out'), + ]); + + assert.strictEqual(result, 'aborted'); +} + // pipeTo with live signal + transforms — abort mid-stream async function testPipeToLiveSignalWithTransforms() { const ac = new AbortController(); @@ -84,6 +117,7 @@ async function testPipeToLiveSignalWithTransformsCompletes() { Promise.all([ testPipeToLiveSignalNoTransforms(), + testPipeToLiveSignalNoTransformsPendingNext(), testPipeToLiveSignalWithTransforms(), testPipeToLiveSignalCompletes(), testPipeToLiveSignalWithTransformsCompletes(), diff --git a/test/parallel/test-stream-iter-share-async.js b/test/parallel/test-stream-iter-share-async.js index 7e1c06b6328f19..ad382c97e03cf7 100644 --- a/test/parallel/test-stream-iter-share-async.js +++ b/test/parallel/test-stream-iter-share-async.js @@ -196,6 +196,25 @@ async function testShareAbortSignalWhileSourcePullPending() { await Promise.all([rejected1, rejected2]); } +async function testSharePullAbortSignalRejectsPendingNext() { + const ac = new AbortController(); + const reason = new Error('pull aborted'); + const shared = share( + // eslint-disable-next-line require-yield + (async function* never() { + await new Promise(() => {}); + })(), + ); + const iter = shared.pull({ signal: ac.signal })[Symbol.asyncIterator](); + + const pendingNext = iter.next(); + const rejected = assert.rejects(pendingNext, (error) => error === reason); + ac.abort(reason); + + await rejected; + shared.cancel(); +} + async function testShareAlreadyAborted() { const shared = share(from('data'), { signal: AbortSignal.abort() }); const consumer = shared.pull(); @@ -340,6 +359,7 @@ Promise.all([ testShareCancelWithReason(), testShareAbortSignal(), testShareAbortSignalWhileSourcePullPending(), + testSharePullAbortSignalRejectsPendingNext(), testShareAlreadyAborted(), testShareSourceError(), testShareLateJoiningConsumer(), diff --git a/test/parallel/test-stream-iter-validation.js b/test/parallel/test-stream-iter-validation.js index 19cde169d6f496..ecefaeb171ec41 100644 --- a/test/parallel/test-stream-iter-validation.js +++ b/test/parallel/test-stream-iter-validation.js @@ -157,9 +157,8 @@ assert.throws(() => broadcast({ backpressure: 'bad' }), { code: 'ERR_INVALID_ARG writer.endSync(); } -// Broadcast.from rejects non-iterable input +// Broadcast.from rejects non-streamable input assert.throws(() => Broadcast.from(42), { code: 'ERR_INVALID_ARG_TYPE' }); -assert.throws(() => Broadcast.from('bad'), { code: 'ERR_INVALID_ARG_TYPE' }); // ============================================================================= // share() / shareSync() validation diff --git a/test/parallel/test-stream-readable-async-iter-half-open-duplex.js b/test/parallel/test-stream-readable-async-iter-half-open-duplex.js new file mode 100644 index 00000000000000..13e0d4b2f3dffc --- /dev/null +++ b/test/parallel/test-stream-readable-async-iter-half-open-duplex.js @@ -0,0 +1,41 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { + Duplex, +} = require('stream'); + +{ + let written = ''; + + const duplex = new Duplex({ + allowHalfOpen: true, + read() { + this.push('hello'); + this.push(null); + }, + write(chunk, encoding, callback) { + written += chunk; + callback(); + }, + }); + + duplex.on('error', common.mustNotCall()); + duplex.on('close', common.mustCall()); + + (async () => { + let read = ''; + for await (const chunk of duplex) { + read += chunk; + } + + assert.strictEqual(read, 'hello'); + assert.strictEqual(duplex.destroyed, false); + + duplex.write('world', common.mustSucceed(() => { + assert.strictEqual(written, 'world'); + duplex.end(); + })); + })().then(common.mustCall()); +} diff --git a/test/parallel/test-stream2-readable-wrap-proxy-methods.js b/test/parallel/test-stream2-readable-wrap-proxy-methods.js new file mode 100644 index 00000000000000..6ed7072c7881e9 --- /dev/null +++ b/test/parallel/test-stream2-readable-wrap-proxy-methods.js @@ -0,0 +1,40 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { Readable } = require('stream'); + +// Readable.prototype.wrap() proxies the methods of the wrapped old-style +// stream onto the new Readable. Regression test for an off-by-one that made +// the proxy loop start at index 1, silently skipping the first own-enumerable +// key returned by Object.keys() — so a method happening to sit at that first +// position was never proxied. + +// A minimal old-style stream whose *first* own-enumerable key is a method. +// `Object.keys()` preserves insertion order for string keys, so `firstMethod` +// is `streamKeys[0]` — exactly the slot the bug skipped. +const source = { + firstMethod() { return `first:${this === source}`; }, + secondMethod() { return `second:${this === source}`; }, + on() { return this; }, + pause() {}, + resume() {}, +}; + +assert.strictEqual(Object.keys(source)[0], 'firstMethod'); + +const wrapped = new Readable().wrap(source); + +// The method at the first key must be proxied (was `undefined` before the fix). +assert.strictEqual(typeof wrapped.firstMethod, 'function'); +assert.strictEqual(typeof wrapped.secondMethod, 'function'); + +// Proxied methods stay bound to the original stream. +assert.strictEqual(wrapped.firstMethod(), 'first:true'); +assert.strictEqual(wrapped.secondMethod(), 'second:true'); + +// Existing Readable methods must not be clobbered by the proxying. +assert.strictEqual(wrapped.pause, Readable.prototype.pause); +assert.strictEqual(wrapped.resume, Readable.prototype.resume); + +wrapped.on('end', common.mustNotCall()); +wrapped.destroy(); diff --git a/test/parallel/test-tls-client-getephemeralkeyinfo.js b/test/parallel/test-tls-client-getephemeralkeyinfo.js index 2107d024012c4d..ea6dec7bdc4629 100644 --- a/test/parallel/test-tls-client-getephemeralkeyinfo.js +++ b/test/parallel/test-tls-client-getephemeralkeyinfo.js @@ -18,9 +18,6 @@ const tls = require('tls'); const key = fixtures.readKey('agent2-key.pem'); const cert = fixtures.readKey('agent2-cert.pem'); -// TODO(@sam-github) test works with TLS1.3, rework test to add -// 'ECDH' with 'TLS_AES_128_GCM_SHA256', - function loadDHParam(n) { return fixtures.readKey(`dh${n}.pem`); } @@ -89,3 +86,57 @@ test(256, 'ECDH', 'prime256v1', 'ECDHE-RSA-AES256-GCM-SHA384'); test(521, 'ECDH', 'secp521r1', 'ECDHE-RSA-AES256-GCM-SHA384'); test(253, 'ECDH', 'X25519', 'ECDHE-RSA-AES256-GCM-SHA384'); test(448, 'ECDH', 'X448', 'ECDHE-RSA-AES256-GCM-SHA384'); + +function testTLS13Group(size, type, name) { + const options = { + key, + cert, + ecdhCurve: name, + minVersion: 'TLSv1.3', + maxVersion: 'TLSv1.3', + }; + + const server = tls.createServer(options, common.mustCall((conn) => { + assert.strictEqual(conn.getEphemeralKeyInfo(), null); + conn.end(); + })); + + server.on('close', common.mustSucceed()); + + server.listen(0, common.mustCall(() => { + const client = tls.connect({ + port: server.address().port, + rejectUnauthorized: false, + ecdhCurve: name, + minVersion: 'TLSv1.3', + maxVersion: 'TLSv1.3', + }, common.mustCall(() => { + const ekeyinfo = client.getEphemeralKeyInfo(); + assert.strictEqual(ekeyinfo.type, type); + assert.strictEqual(ekeyinfo.size, size); + assert.strictEqual(ekeyinfo.name, name); + server.close(); + })); + client.on('secureConnect', common.mustCall()); + })); +} + +testTLS13Group(253, 'ECDH', 'X25519'); + +if (hasOpenSSL(3, 5)) { + const tls13Groups = [ + 'MLKEM512', + 'MLKEM768', + 'MLKEM1024', + 'SecP256r1MLKEM768', + 'X25519MLKEM768', + 'SecP384r1MLKEM1024', + ]; + + if (hasOpenSSL(4, 0)) { + tls13Groups.push('curveSM2'); + tls13Groups.push('curveSM2MLKEM768'); + } + + tls13Groups.forEach((name) => testTLS13Group(undefined, 'TLSGroup', name)); +} diff --git a/test/parallel/test-tls-over-http-tunnel.js b/test/parallel/test-tls-over-http-tunnel.js index baef7a56f6884a..e16400d06aece9 100644 --- a/test/parallel/test-tls-over-http-tunnel.js +++ b/test/parallel/test-tls-over-http-tunnel.js @@ -61,7 +61,7 @@ const proxy = net.createServer(common.mustCall((clientSocket) => { `CONNECT localhost:${server.address().port} ` + 'HTTP/1.1\r\n' + 'Proxy-Connections: keep-alive\r\n' + - `Host: localhost:${proxy.address().port}\r\n` + + `Host: localhost:${server.address().port}\r\n` + 'Connection: keep-alive\r\n\r\n'); console.log('PROXY: got CONNECT request'); diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index c41c89c7efa113..6a1da6d4129fbd 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -3418,6 +3418,21 @@ assert.strictEqual( ); } +{ + // A node_modules segment that is the last path component (no trailing + // separator after the module name) must not send markNodeModules into an + // infinite loop that exhausts the heap. + // https://github.com/nodejs/node/issues/64011 + const err = new Error('boom'); + err.stack = 'Error: boom\n at /app/node_modules/foo.js:1:1'; + const out = util.inspect(err, { colors: true }); + assert.strictEqual( + out, + 'Error: boom\n' + + ' at /app/node_modules/\x1B[4mfoo.js:1:1\x1B[24m', + ); +} + { // Cross platform checks. const err = new Error('foo'); diff --git a/test/parallel/test-vfs-fd.js b/test/parallel/test-vfs-fd.js index ec9145189da299..f9f6b25f51ce57 100644 --- a/test/parallel/test-vfs-fd.js +++ b/test/parallel/test-vfs-fd.js @@ -80,6 +80,26 @@ const vfs = require('node:vfs'); myVfs.closeSync(fd); } +// Test readSync with Node's current-position sentinel +{ + const myVfs = vfs.create(); + myVfs.writeFileSync('/file.txt', 'hello world'); + + const fd = myVfs.openSync('/file.txt'); + const buffer1 = Buffer.alloc(5); + const buffer2 = Buffer.alloc(6); + + let bytesRead = myVfs.readSync(fd, buffer1, 0, 5, -1); + assert.strictEqual(bytesRead, 5); + assert.strictEqual(buffer1.toString(), 'hello'); + + bytesRead = myVfs.readSync(fd, buffer2, 0, 6, -1); + assert.strictEqual(bytesRead, 6); + assert.strictEqual(buffer2.toString(), ' world'); + + myVfs.closeSync(fd); +} + // Test readSync with explicit position { const myVfs = vfs.create(); diff --git a/test/parallel/test-vfs-file-handle.js b/test/parallel/test-vfs-file-handle.js index 6c653593ce7ea2..d9d919446b8ea6 100644 --- a/test/parallel/test-vfs-file-handle.js +++ b/test/parallel/test-vfs-file-handle.js @@ -82,6 +82,12 @@ myVfs.writeFileSync('/file.txt', 'hello world'); myVfs.writeSync(fd, buf, 0, 3, 0); myVfs.closeSync(fd); + const fd3 = myVfs.openSync('/sync-current.txt', 'w'); + myVfs.writeSync(fd3, Buffer.from('abc'), 0, 3, -1); + myVfs.writeSync(fd3, Buffer.from('def'), 0, 3, -1); + myVfs.closeSync(fd3); + assert.strictEqual(myVfs.readFileSync('/sync-current.txt', 'utf8'), 'abcdef'); + const fd2 = myVfs.openSync('/sync.txt', 'r'); const out = Buffer.alloc(3); myVfs.readSync(fd2, out, 0, 3, 0); diff --git a/test/parallel/test-vfs-fs-openSync.js b/test/parallel/test-vfs-fs-openSync.js index f2c73f0d634469..28fa17d28b3cf6 100644 --- a/test/parallel/test-vfs-fs-openSync.js +++ b/test/parallel/test-vfs-fs-openSync.js @@ -30,6 +30,19 @@ myVfs.mount(mountPoint); fs.closeSync(fd); } +// readSync with position null uses and advances the current file position +{ + const fd = fs.openSync(path.join(mountPoint, 'src/hello.txt'), 'r'); + const b1 = Buffer.alloc(5); + const b2 = Buffer.alloc(6); + + assert.strictEqual(fs.readSync(fd, b1, 0, 5, null), 5); + assert.strictEqual(fs.readSync(fd, b2, 0, 6, null), 6); + assert.strictEqual(b1.toString(), 'hello'); + assert.strictEqual(b2.toString(), ' world'); + fs.closeSync(fd); +} + // openSync + writeSync (buffer) + closeSync { const fd = fs.openSync(path.join(mountPoint, 'src/wfd.txt'), 'w'); diff --git a/test/parallel/test-vfs-fs-readFileSync.js b/test/parallel/test-vfs-fs-readFileSync.js index 96e39892e66a9f..1ca906b2a0577c 100644 --- a/test/parallel/test-vfs-fs-readFileSync.js +++ b/test/parallel/test-vfs-fs-readFileSync.js @@ -43,3 +43,32 @@ assert.strictEqual( } myVfs.unmount(); + +// readFileSync via a RealFSProvider fd remains usable after the backing path +// is renamed. +{ + const root = path.join('/tmp', 'vfs-real-readFileSync-' + process.pid); + const realMountPoint = path.join('/tmp', 'vfs-real-readFileSync-mount-' + process.pid); + fs.rmSync(root, { recursive: true, force: true }); + fs.rmSync(realMountPoint, { recursive: true, force: true }); + fs.mkdirSync(root, { recursive: true }); + fs.mkdirSync(realMountPoint, { recursive: true }); + + const realVfs = vfs + .create(new vfs.RealFSProvider(root), { emitExperimentalWarning: false }) + .mount(realMountPoint); + try { + fs.writeFileSync(path.join(root, 'a.txt'), 'still readable'); + const fd = fs.openSync(path.join(realMountPoint, 'a.txt'), 'r'); + try { + fs.renameSync(path.join(root, 'a.txt'), path.join(root, 'b.txt')); + assert.strictEqual(fs.readFileSync(fd, 'utf8'), 'still readable'); + } finally { + fs.closeSync(fd); + } + } finally { + realVfs.unmount(); + fs.rmSync(root, { recursive: true, force: true }); + fs.rmSync(realMountPoint, { recursive: true, force: true }); + } +} diff --git a/test/parallel/test-vfs-fs-writeFileSync.js b/test/parallel/test-vfs-fs-writeFileSync.js index 7469127bb1fde3..eeed2a685f08e3 100644 --- a/test/parallel/test-vfs-fs-writeFileSync.js +++ b/test/parallel/test-vfs-fs-writeFileSync.js @@ -26,4 +26,63 @@ assert.strictEqual(fs.readFileSync(target, 'utf8'), 'fresh more'); fs.writeFileSync(target, Buffer.from('binary')); assert.strictEqual(fs.readFileSync(target, 'utf8'), 'binary'); +// writeFileSync via a VFS fd writes through the open descriptor. +{ + const fdTarget = path.join(mountPoint, 'src/fd.txt'); + const fd = fs.openSync(fdTarget, 'w+'); + try { + fs.writeFileSync(fd, 'hello'); + fs.writeFileSync(fd, new Uint8Array(Buffer.from(' world'))); + assert.strictEqual(fs.readFileSync(fdTarget, 'utf8'), 'hello world'); + } finally { + fs.closeSync(fd); + } +} + +// appendFileSync via a VFS fd follows normal fd write semantics. +{ + const fdTarget = path.join(mountPoint, 'src/append-fd.txt'); + fs.writeFileSync(fdTarget, 'start'); + const fd = fs.openSync(fdTarget, 'a'); + try { + fs.appendFileSync(fd, ' end'); + assert.strictEqual(fs.readFileSync(fdTarget, 'utf8'), 'start end'); + } finally { + fs.closeSync(fd); + } +} + myVfs.unmount(); + +// writeFileSync via a RealFSProvider fd remains tied to the open descriptor +// after the backing path is renamed. +{ + const root = path.join('/tmp', 'vfs-real-writeFileSync-' + process.pid); + const realMountPoint = path.join('/tmp', 'vfs-real-writeFileSync-mount-' + process.pid); + fs.rmSync(root, { recursive: true, force: true }); + fs.rmSync(realMountPoint, { recursive: true, force: true }); + fs.mkdirSync(root, { recursive: true }); + fs.mkdirSync(realMountPoint, { recursive: true }); + + const realVfs = vfs + .create(new vfs.RealFSProvider(root), { emitExperimentalWarning: false }) + .mount(realMountPoint); + try { + const mountedFile = path.join(realMountPoint, 'a.txt'); + fs.writeFileSync(path.join(root, 'a.txt'), 'old'); + const fd = fs.openSync(mountedFile, 'r+'); + try { + fs.renameSync(path.join(root, 'a.txt'), path.join(root, 'b.txt')); + fs.writeFileSync(path.join(root, 'a.txt'), 'new'); + fs.writeFileSync(fd, 'updated'); + assert.strictEqual(fs.readFileSync(path.join(root, 'b.txt'), 'utf8'), 'updated'); + assert.strictEqual(fs.readFileSync(path.join(root, 'a.txt'), 'utf8'), 'new'); + } finally { + fs.closeSync(fd); + } + } finally { + realVfs.unmount(); + fs.rmSync(root, { recursive: true, force: true }); + fs.rmSync(realMountPoint, { recursive: true, force: true }); + } +} diff --git a/test/parallel/test-vfs-readdir-symlink-recursive.js b/test/parallel/test-vfs-readdir-symlink-recursive.js index 1f9661947c7444..33b52bb5d4a416 100644 --- a/test/parallel/test-vfs-readdir-symlink-recursive.js +++ b/test/parallel/test-vfs-readdir-symlink-recursive.js @@ -3,7 +3,7 @@ // Recursive readdir must follow symlinks to directories. -require('../common'); +const common = require('../common'); const assert = require('assert'); const vfs = require('node:vfs'); @@ -21,6 +21,59 @@ assert.ok( `Expected 'symdir/nested.txt' in entries: ${entries}`, ); +// Recursive readdir avoids following symlink cycles indefinitely. +{ + const v = vfs.create(); + v.mkdirSync('/dir'); + v.writeFileSync('/dir/nested.txt', 'nested'); + v.symlinkSync('/dir', '/dir/loop'); + + assert.deepStrictEqual(v.readdirSync('/', { recursive: true }).sort(), [ + 'dir', + 'dir/loop', + 'dir/nested.txt', + ]); + + const dirents = v.readdirSync('/', { recursive: true, withFileTypes: true }); + assert.strictEqual(dirents.length, 3); + assert.ok(dirents.some((dirent) => + dirent.name === 'loop' && + dirent.parentPath === '/dir' && + dirent.isSymbolicLink())); +} + +// Recursive readdir avoids cycles through multiple symlinks. +{ + const v = vfs.create(); + v.mkdirSync('/a'); + v.mkdirSync('/b'); + v.symlinkSync('/b', '/a/link_to_b'); + v.symlinkSync('/a', '/b/link_to_a'); + + assert.deepStrictEqual(v.readdirSync('/', { recursive: true }).sort(), [ + 'a', + 'a/link_to_b', + 'a/link_to_b/link_to_a', + 'b', + 'b/link_to_a', + 'b/link_to_a/link_to_b', + ]); +} + +(async () => { + const v = vfs.create(); + v.mkdirSync('/dir'); + v.writeFileSync('/dir/nested.txt', 'nested'); + v.symlinkSync('/dir', '/dir/loop'); + + const entries = await v.promises.readdir('/', { recursive: true }); + assert.deepStrictEqual(entries.sort(), [ + 'dir', + 'dir/loop', + 'dir/nested.txt', + ]); +})().then(common.mustCall()); + // Recursive readdir with withFileTypes:true returns Dirent objects whose // parentPath reflects the actual location of the entry (not the entry's // stringified relative path). diff --git a/test/parallel/test-vfs-real-provider-handle.js b/test/parallel/test-vfs-real-provider-handle.js index 5246e28e3206c5..50d31470b8644f 100644 --- a/test/parallel/test-vfs-real-provider-handle.js +++ b/test/parallel/test-vfs-real-provider-handle.js @@ -75,6 +75,55 @@ const myVfs = vfs.create(new vfs.RealFSProvider(root)); await handle.close(); } + // ===== readFile through an open real fd survives backing path rename ===== + { + fs.writeFileSync(path.join(root, 'rename-read.txt'), 'still readable'); + const syncHandle = await myVfs.provider.open('/rename-read.txt', 'r'); + const asyncHandle = await myVfs.provider.open('/rename-read.txt', 'r'); + fs.renameSync(path.join(root, 'rename-read.txt'), + path.join(root, 'rename-read-renamed.txt')); + try { + assert.strictEqual(syncHandle.readFileSync('utf8'), 'still readable'); + assert.strictEqual(await asyncHandle.readFile('utf8'), 'still readable'); + } finally { + await syncHandle.close(); + await asyncHandle.close(); + fs.unlinkSync(path.join(root, 'rename-read-renamed.txt')); + } + } + + // ===== readFile reads past the fallback chunk when fstat reports size 0 ===== + { + const content = 'a'.repeat(8192) + 'trailing data'; + fs.writeFileSync(path.join(root, 'zero-stat.txt'), content); + const syncHandle = await myVfs.provider.open('/zero-stat.txt', 'r'); + const asyncHandle = await myVfs.provider.open('/zero-stat.txt', 'r'); + const originalFstatSync = fs.fstatSync; + const originalFstat = fs.fstat; + + fs.fstatSync = common.mustCall(function fstatSync(...args) { + const stats = originalFstatSync.apply(this, args); + stats.size = 0; + return stats; + }); + fs.fstat = common.mustCall(function fstat(fd, options, callback) { + return originalFstat.call(this, fd, options, (err, stats) => { + if (stats) stats.size = 0; + callback(err, stats); + }); + }); + + try { + assert.strictEqual(syncHandle.readFileSync('utf8'), content); + assert.strictEqual(await asyncHandle.readFile('utf8'), content); + } finally { + fs.fstatSync = originalFstatSync; + fs.fstat = originalFstat; + await syncHandle.close(); + await asyncHandle.close(); + } + } + // ===== EBADF after close ===== { await myVfs.promises.writeFile('/h.txt', 'hello'); diff --git a/test/parallel/test-vfs-rename.js b/test/parallel/test-vfs-rename.js index 26506f01dd7338..69daba43c11ddf 100644 --- a/test/parallel/test-vfs-rename.js +++ b/test/parallel/test-vfs-rename.js @@ -44,3 +44,17 @@ const vfs = require('node:vfs'); assert.strictEqual(myVfs.existsSync('/d/a.txt'), false); assert.strictEqual(myVfs.existsSync('/d/b.txt'), true); } + +// Renaming a directory into its own descendant throws EINVAL +{ + const myVfs = vfs.create(); + myVfs.mkdirSync('/a/b', { recursive: true }); + myVfs.writeFileSync('/a/file.txt', 'data'); + + assert.throws(() => myVfs.renameSync('/a', '/a/b/c'), { code: 'EINVAL' }); + assert.deepStrictEqual(myVfs.readdirSync('/'), ['a']); + assert.strictEqual(myVfs.existsSync('/a'), true); + assert.strictEqual(myVfs.existsSync('/a/b'), true); + assert.strictEqual(myVfs.existsSync('/a/b/c'), false); + assert.strictEqual(myVfs.readFileSync('/a/file.txt', 'utf8'), 'data'); +} diff --git a/test/parallel/test-vm-property-definer-partial-update.js b/test/parallel/test-vm-property-definer-partial-update.js new file mode 100644 index 00000000000000..b2291b00a2ba73 --- /dev/null +++ b/test/parallel/test-vm-property-definer-partial-update.js @@ -0,0 +1,56 @@ +'use strict'; + +require('../common'); +const vm = require('vm'); +const assert = require('assert'); + +// Object.defineProperty should only modify specified attributes and preserve +// unspecified ones. Regression test for https://github.com/nodejs/node/issues/64008 +{ + const context = {}; + vm.createContext(context); + + // Changing enumerable should preserve value. + vm.runInContext(` + globalThis.a1 = 1; + Object.defineProperty(globalThis, 'a1', { enumerable: false }); + Object.defineProperty(globalThis, 'a2', { + value: 2, enumerable: false, configurable: true, + }); + Object.defineProperty(globalThis, 'a2', { enumerable: true }); + `, context); + assert.strictEqual(context.a1, 1); + assert.strictEqual( + Object.getOwnPropertyDescriptor(context, 'a1').enumerable, false); + assert.strictEqual(context.a2, 2); + assert.strictEqual( + Object.getOwnPropertyDescriptor(context, 'a2').enumerable, true); + + // Changing writable should preserve value. + vm.runInContext(` + globalThis.b1 = 1; + Object.defineProperty(globalThis, 'b1', { writable: false }); + Object.defineProperty(globalThis, 'b2', { + value: 2, writable: false, configurable: true, + }); + Object.defineProperty(globalThis, 'b2', { writable: true }); + `, context); + assert.strictEqual(context.b1, 1); + assert.strictEqual(context.b2, 2); + + // Changing value should preserve enumerable. + vm.runInContext(` + globalThis.c1 = 1; + Object.defineProperty(globalThis, 'c1', { value: 2 }); + Object.defineProperty(globalThis, 'c2', { + value: 1, enumerable: false, configurable: true, + }); + Object.defineProperty(globalThis, 'c2', { value: 2 }); + `, context); + assert.strictEqual(context.c1, 2); + assert.strictEqual( + Object.getOwnPropertyDescriptor(context, 'c1').enumerable, true); + assert.strictEqual(context.c2, 2); + assert.strictEqual( + Object.getOwnPropertyDescriptor(context, 'c2').enumerable, false); +} diff --git a/test/parallel/test-webcrypto-sign-verify-eddsa.js b/test/parallel/test-webcrypto-sign-verify-eddsa.js index 1dfd3ddd76a6a0..3c40139754bea9 100644 --- a/test/parallel/test-webcrypto-sign-verify-eddsa.js +++ b/test/parallel/test-webcrypto-sign-verify-eddsa.js @@ -15,6 +15,44 @@ const vectors = require('../fixtures/crypto/eddsa')(); const supportsContext = hasOpenSSL(3, 2); +const smallOrderVerifyVectors = [ + { + name: 'Ed25519', + publicKey: Buffer.from( + 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa', + 'hex'), + signature: Buffer.from( + 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a' + + '0000000000000000000000000000000000000000000000000000000000000000', + 'hex'), + data: Buffer.from( + '8c93255d71dcab10e8f379c26200f3c7bd5f09d9bc3068d3ef4edeb4853022b6', + 'hex'), + }, +]; + +if (!process.features.openssl_is_boringssl) { + smallOrderVerifyVectors.push({ + name: 'Ed448', + publicKey: Buffer.concat([Buffer.from([1]), Buffer.alloc(56)]), + signature: Buffer.concat([Buffer.from([1]), Buffer.alloc(113)]), + data: Buffer.from([1, 2, 3]), + }); +} + +async function testSmallOrderVerify({ name, publicKey, signature, data }) { + const key = await subtle.importKey( + 'raw', + publicKey, + { name }, + false, + ['verify']); + + assert.strictEqual( + await subtle.verify({ name }, key, signature, data), + false); +} + async function testVerify({ name, context, publicKeyBuffer, @@ -260,6 +298,9 @@ async function testSign({ name, variations.push(testVerify(vector)); variations.push(testSign(vector)); }); + smallOrderVerifyVectors.forEach((vector) => { + variations.push(testSmallOrderVerify(vector)); + }); await Promise.all(variations); })().then(common.mustCall()); diff --git a/test/parallel/test-whatwg-readablestream.js b/test/parallel/test-whatwg-readablestream.js index 2fd99d33929023..d1001d51b4e8d1 100644 --- a/test/parallel/test-whatwg-readablestream.js +++ b/test/parallel/test-whatwg-readablestream.js @@ -15,6 +15,7 @@ const { ByteLengthQueuingStrategy, CountQueuingStrategy, ReadableStream, + ReadableStreamTee, ReadableStreamDefaultReader, ReadableStreamDefaultController, ReadableByteStreamController, @@ -1527,6 +1528,28 @@ class Source { }).then(common.mustCall()); } +{ + // Test public ReadableStreamTee() cloneForBranch2 argument + assert.strictEqual(typeof ReadableStreamTee, 'function'); + const chunk = new Uint8Array([65]); + const readable = new ReadableStream({ + start(controller) { + controller.enqueue(chunk); + controller.close(); + }, + }); + const [r1, r2] = ReadableStreamTee(readable, true); + + (async () => { + const { value: value1 } = await r1.getReader().read(); + assert.strictEqual(value1[0], 65); + value1[0] = 66; + + const { value: value2 } = await r2.getReader().read(); + assert.strictEqual(value2[0], 65); + })().then(common.mustCall()); +} + { // Test tee() cloneForBranch2 argument const readable = new ReadableStream({ diff --git a/test/parallel/test-zlib-brotli-flush-invalid-kind.js b/test/parallel/test-zlib-brotli-flush-invalid-kind.js new file mode 100644 index 00000000000000..af8a2c67d1d9a4 --- /dev/null +++ b/test/parallel/test-zlib-brotli-flush-invalid-kind.js @@ -0,0 +1,92 @@ +'use strict'; +// Regression test for https://github.com/nodejs/node/issues/63701. +// Invalid Brotli flush kinds used to spin in native code. flush(kind) should +// reject invalid kinds before writing the fake flush chunk. + +require('../common'); +const assert = require('assert'); +const zlib = require('zlib'); + +const { + BROTLI_OPERATION_PROCESS, + BROTLI_OPERATION_FLUSH, + BROTLI_OPERATION_FINISH, + BROTLI_OPERATION_EMIT_METADATA, + Z_NO_FLUSH, + Z_BLOCK, + Z_FINISH, + ZSTD_e_continue, + ZSTD_e_flush, + ZSTD_e_end, +} = zlib.constants; + +const noop = () => {}; + +const flushKindTestCases = [ + { + factories: [zlib.createGzip], + validKinds: [Z_NO_FLUSH, Z_FINISH, Z_BLOCK], + invalidKinds: [-1, 6, 100], + }, + { + factories: [zlib.createBrotliCompress, zlib.createBrotliDecompress], + validKinds: [ + BROTLI_OPERATION_PROCESS, + BROTLI_OPERATION_FLUSH, + BROTLI_OPERATION_FINISH, + BROTLI_OPERATION_EMIT_METADATA, + ], + invalidKinds: [-1, Z_FINISH, Z_BLOCK, 6, 100], + }, + { + factories: [zlib.createZstdCompress, zlib.createZstdDecompress], + validKinds: [ZSTD_e_continue, ZSTD_e_flush, ZSTD_e_end], + invalidKinds: [-1, 3, Z_FINISH, Z_BLOCK, 100], + }, +]; + +for (const { factories, validKinds } of flushKindTestCases) { + for (const factory of factories) { + for (const kind of validKinds) { + const stream = factory(); + stream.on('error', noop); + stream.flush(kind); + } + } +} + +for (const { factories, invalidKinds } of flushKindTestCases) { + for (const factory of factories) { + for (const kind of invalidKinds) { + assert.throws( + () => factory().flush(kind), + { code: 'ERR_OUT_OF_RANGE', name: 'RangeError' }, + ); + } + } +} + +for (const { factories } of flushKindTestCases) { + for (const factory of factories) { + for (const kind of ['foobar', null, {}]) { + assert.throws( + () => factory().flush(kind), + { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError' }, + ); + } + } +} + +for (const { factories } of flushKindTestCases) { + for (const factory of factories) { + for (const kind of [undefined, NaN]) { + const stream = factory(); + stream.on('error', noop); + stream.flush(kind); + } + + const stream = factory(); + stream.on('error', noop); + stream.flush(noop); + } +} diff --git a/test/parallel/test-zlib-reject-garbage-after-end.js b/test/parallel/test-zlib-reject-garbage-after-end.js new file mode 100644 index 00000000000000..8039865f5f1193 --- /dev/null +++ b/test/parallel/test-zlib-reject-garbage-after-end.js @@ -0,0 +1,144 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const test = require('node:test'); +const { finished } = require('stream/promises'); +const zlib = require('zlib'); + +const trailingJunkError = { + code: 'ERR_TRAILING_JUNK_AFTER_STREAM_END', + name: 'TypeError', +}; + +function callAsync(fn, input, options) { + return new Promise((resolve, reject) => { + fn(input, options, (err, result) => { + if (err) { + reject(err); + } else { + resolve(result); + } + }); + }); +} + +async function collect(stream, input) { + const chunks = []; + stream.on('data', (chunk) => chunks.push(chunk)); + stream.end(input); + await finished(stream); + return Buffer.concat(chunks); +} + +const cases = [ + { + label: 'inflate', + compress: zlib.deflateSync, + decompress: zlib.inflate, + decompressSync: zlib.inflateSync, + createDecompress: zlib.createInflate, + defaultOutput: 'a', + }, + { + label: 'inflateRaw', + compress: zlib.deflateRawSync, + decompress: zlib.inflateRaw, + decompressSync: zlib.inflateRawSync, + createDecompress: zlib.createInflateRaw, + defaultOutput: 'a', + }, + { + label: 'gunzip', + compress: zlib.gzipSync, + decompress: zlib.gunzip, + decompressSync: zlib.gunzipSync, + createDecompress: zlib.createGunzip, + defaultOutput: 'aa', + }, + { + label: 'unzip', + compress: zlib.gzipSync, + decompress: zlib.unzip, + decompressSync: zlib.unzipSync, + createDecompress: zlib.createUnzip, + defaultOutput: 'aa', + }, + { + label: 'brotli', + compress: zlib.brotliCompressSync, + decompress: zlib.brotliDecompress, + decompressSync: zlib.brotliDecompressSync, + createDecompress: zlib.createBrotliDecompress, + defaultOutput: 'a', + }, + { + label: 'zstd', + compress: zlib.zstdCompressSync, + decompress: zlib.zstdDecompress, + decompressSync: zlib.zstdDecompressSync, + createDecompress: zlib.createZstdDecompress, + defaultOutput: 'a', + }, +]; + +for (const { + label, + compress, + decompress, + decompressSync, + createDecompress, + defaultOutput, +} of cases) { + test(`rejectGarbageAfterEnd rejects trailing input for ${label}`, async () => { + const compressed = compress(Buffer.from('a')); + const withTrailingInput = Buffer.concat([compressed, compressed]); + + assert.strictEqual(decompressSync(withTrailingInput).toString(), defaultOutput); + assert.strictEqual( + (await callAsync(decompress, withTrailingInput)).toString(), + defaultOutput, + ); + assert.strictEqual( + (await collect(createDecompress(), withTrailingInput)).toString(), + defaultOutput, + ); + + assert.throws( + () => decompressSync(withTrailingInput, { rejectGarbageAfterEnd: true }), + trailingJunkError, + ); + await assert.rejects( + callAsync(decompress, withTrailingInput, { rejectGarbageAfterEnd: true }), + trailingJunkError, + ); + await assert.rejects( + collect( + createDecompress({ rejectGarbageAfterEnd: true }), + withTrailingInput, + ), + trailingJunkError, + ); + }); +} + +test('rejectGarbageAfterEnd must be a boolean', () => { + const compressed = zlib.deflateSync(Buffer.from('a')); + + for (const value of [1, 'true', null]) { + assert.throws( + () => zlib.inflateSync(compressed, { rejectGarbageAfterEnd: value }), + { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + }, + ); + assert.throws( + () => zlib.createInflate({ rejectGarbageAfterEnd: value }), + { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + }, + ); + } +}); diff --git a/test/parallel/test-zlib-type-error.js b/test/parallel/test-zlib-type-error.js index 912b59fd9ca923..ab2bdfb1b777a3 100644 --- a/test/parallel/test-zlib-type-error.js +++ b/test/parallel/test-zlib-type-error.js @@ -2,36 +2,67 @@ require('../common'); const assert = require('assert'); const test = require('node:test'); +const zlib = require('zlib'); const { DecompressionStream } = require('stream/web'); -test('DecompressStream deflat emits error on trailing data', async () => { +async function assertDecompressionStreamRejects(format, chunks) { + await assert.rejects( + Array.fromAsync( + new Blob(chunks).stream().pipeThrough(new DecompressionStream(format)) + ), + { name: 'TypeError' }, + ); +} + +test('DecompressionStream deflate emits TypeError on trailing data', async () => { const valid = new Uint8Array([120, 156, 75, 4, 0, 0, 98, 0, 98]); // deflate('a') const empty = new Uint8Array(1); const invalid = new Uint8Array([...valid, ...empty]); const double = new Uint8Array([...valid, ...valid]); - for (const chunk of [[invalid], [valid, empty], [valid, valid], [valid, double]]) { - await assert.rejects( - Array.fromAsync( - new Blob([chunk]).stream().pipeThrough(new DecompressionStream('deflate')) - ), - { name: 'TypeError' }, - ); + for (const chunks of [[invalid], [valid, empty], [valid, valid], [double]]) { + await assertDecompressionStreamRejects('deflate', chunks); } }); -test('DecompressStream gzip emits error on trailing data', async () => { +test('DecompressionStream gzip emits TypeError on trailing data', async () => { const valid = new Uint8Array([31, 139, 8, 0, 0, 0, 0, 0, 0, 19, 75, 4, 0, 67, 190, 183, 232, 1, 0, 0, 0]); // gzip('a') const empty = new Uint8Array(1); const invalid = new Uint8Array([...valid, ...empty]); const double = new Uint8Array([...valid, ...valid]); - for (const chunk of [[invalid], [valid, empty], [valid, valid], [double]]) { - await assert.rejects( - Array.fromAsync( - new Blob([chunk]).stream().pipeThrough(new DecompressionStream('gzip')) - ), - { name: 'TypeError' }, - ); + for (const chunks of [[invalid], [valid, empty], [valid, valid], [double]]) { + await assertDecompressionStreamRejects('gzip', chunks); + } +}); + +test('DecompressionStream brotli emits TypeError on trailing data', async () => { + const valid = zlib.brotliCompressSync(Buffer.from('a')); + const empty = new Uint8Array(1); + const invalid = new Uint8Array([...valid, ...empty]); + const double = new Uint8Array([...valid, ...valid]); + for (const chunks of [[invalid], [valid, empty], [valid, valid], [double]]) { + await assertDecompressionStreamRejects('brotli', chunks); } }); + +test('zlib sync decompression honors rejectGarbageAfterEnd', () => { + const valid = new Uint8Array([31, 139, 8, 0, 0, 0, 0, 0, 0, 19, 75, 4, + 0, 67, 190, 183, 232, 1, 0, 0, 0]); // gzip('a') + const double = new Uint8Array([...valid, ...valid]); + + assert.deepStrictEqual(zlib.gunzipSync(double), Buffer.from('aa')); + assert.throws( + () => zlib.gunzipSync(double, { rejectGarbageAfterEnd: true }), + { code: 'ERR_TRAILING_JUNK_AFTER_STREAM_END', name: 'TypeError' }, + ); + + const brotli = zlib.brotliCompressSync(Buffer.from('a')); + const brotliDouble = Buffer.concat([brotli, brotli]); + + assert.deepStrictEqual(zlib.brotliDecompressSync(brotliDouble), Buffer.from('a')); + assert.throws( + () => zlib.brotliDecompressSync(brotliDouble, { rejectGarbageAfterEnd: true }), + { code: 'ERR_TRAILING_JUNK_AFTER_STREAM_END', name: 'TypeError' }, + ); +}); diff --git a/test/sequential/test-dgram-implicit-bind-failure.js b/test/sequential/test-dgram-implicit-bind-failure.js index 89da00d5766fb3..ec00022c693730 100644 --- a/test/sequential/test-dgram-implicit-bind-failure.js +++ b/test/sequential/test-dgram-implicit-bind-failure.js @@ -4,19 +4,20 @@ const common = require('../common'); const assert = require('assert'); const EventEmitter = require('events'); const dgram = require('dgram'); -const dns = require('dns'); const { kStateSymbol } = require('internal/dgram'); const mockError = new Error('fake DNS'); -// Monkey patch dns.lookup() so that it always fails. -dns.lookup = function(address, family, callback) { +const socket = dgram.createSocket('udp4'); + +// Fail the implicit bind by making the handle's address resolution fail. A +// literal bind address is not passed to dns.lookup(), so patching dns.lookup() +// would not be observed here. +socket[kStateSymbol].handle.lookup = function(address, callback) { process.nextTick(() => { callback(mockError); }); }; -const socket = dgram.createSocket('udp4'); - socket.on(EventEmitter.errorMonitor, common.mustCall((err) => { - // The DNS lookup should fail since it is monkey patched. At that point in + // The bind should fail since the lookup is monkey patched. At that point in // time, the send queue should be populated with the send() operation. assert.strictEqual(err, mockError); assert(Array.isArray(socket[kStateSymbol].queue)); diff --git a/test/sequential/test-performance-eventloopdelay.js b/test/sequential/test-performance-eventloopdelay.js index 66493318f5651d..ddd33372ec5e8e 100644 --- a/test/sequential/test-performance-eventloopdelay.js +++ b/test/sequential/test-performance-eventloopdelay.js @@ -49,6 +49,16 @@ const { sleep } = require('internal/util'); } ); }); + + [null, 'a', 1, {}, []].forEach((i) => { + assert.throws( + () => monitorEventLoopDelay({ samplePerIteration: i }), + { + name: 'TypeError', + code: 'ERR_INVALID_ARG_TYPE', + } + ); + }); } { @@ -114,6 +124,101 @@ const { sleep } = require('internal/util'); spinAWhile(); } +{ + const histogram = monitorEventLoopDelay({ samplePerIteration: true }); + histogram.enable(); + setTimeout(common.mustCall(() => { + histogram.disable(); + assert(histogram.count > 0, + `Expected samples to be recorded, got count=${histogram.count}`); + assert(histogram.min > 0); + assert(histogram.max > 0); + assert(histogram.mean > 0); + assert(histogram.percentiles.size > 0); + for (let n = 1; n < 100; n = n + 10) { + assert(histogram.percentile(n) >= 0); + } + // reset() should restore the histogram to its initial state + histogram.reset(); + assert.strictEqual(histogram.count, 0); + assert.strictEqual(histogram.max, 0); + assert.strictEqual(histogram.min, 9223372036854776000); + assert(Number.isNaN(histogram.mean)); + assert(Number.isNaN(histogram.stddev)); + assert.strictEqual(histogram.percentiles.size, 1); + }), common.platformTimeout(20)); +} + +{ + // enable()/disable() return values for ELDHistogram (samplePerIteration: true) + const histogram = monitorEventLoopDelay({ samplePerIteration: true }); + assert.strictEqual(histogram.enable(), true); + assert.strictEqual(histogram.enable(), false); // Already enabled, no-op + assert.strictEqual(histogram.disable(), true); + assert.strictEqual(histogram.disable(), false); // Already disabled, no-op + // Re-enabling after disable should work + assert.strictEqual(histogram.enable(), true); + setTimeout(common.mustCall(() => { + histogram.disable(); + assert(histogram.count > 0, + `Expected samples after re-enable, got count=${histogram.count}`); + }), common.platformTimeout(20)); +} + +{ + // Verify that samplePerIteration records exactly one sample per event loop iteration. + const N = 10; + const histogram = monitorEventLoopDelay({ samplePerIteration: true }); + histogram.enable(); + + let iterations = 0; + const verify = common.mustCall(() => { + histogram.disable(); + assert( + histogram.count >= N - 1, + `Expected at least ${N - 1} samples for ${N} iterations, got ${histogram.count}` + ); + }); + + function tick() { + if (++iterations < N) { + setImmediate(tick); + } else { + verify(); + } + } + setImmediate(tick); +} + +{ + // samplePerIteration should sample per event loop iteration, independent of + // the timer resolution used by the legacy monitorEventLoopDelay path. + const N = 10; + const histogram = monitorEventLoopDelay({ + samplePerIteration: true, + resolution: 60 * 1000, + }); + histogram.enable(); + + let iterations = 0; + const verify = common.mustCall(() => { + histogram.disable(); + assert( + histogram.count >= N - 1, + `Expected samples despite large resolution, got count=${histogram.count}` + ); + }); + + function tick() { + if (++iterations < N) { + setImmediate(tick); + } else { + verify(); + } + } + setImmediate(tick); +} + // Make sure that the histogram instances can be garbage-collected without // and not just implicitly destroyed when the Environment is torn down. process.on('exit', global.gc); diff --git a/test/wpt/status/WebCryptoAPI.cjs b/test/wpt/status/WebCryptoAPI.cjs index 20b8f1ed8f650a..60111e61edf95d 100644 --- a/test/wpt/status/WebCryptoAPI.cjs +++ b/test/wpt/status/WebCryptoAPI.cjs @@ -1,11 +1,7 @@ 'use strict'; -const os = require('node:os'); - const { hasOpenSSL } = require('../../common/crypto.js'); -const s390x = os.arch() === 's390x'; - const conditionalFileSkips = {}; const conditionalSubtestSkips = {}; @@ -115,19 +111,4 @@ module.exports = { 'historical.any.js': { 'skip': 'Not relevant in Node.js context', }, - 'sign_verify/eddsa_small_order_points.https.any.js': { - 'fail': { - 'note': 'see https://github.com/nodejs/node/issues/54572', - 'expected': [ - 'Ed25519 Verification checks with small-order key of order - Test 1', - 'Ed25519 Verification checks with small-order key of order - Test 2', - 'Ed25519 Verification checks with small-order key of order - Test 12', - 'Ed25519 Verification checks with small-order key of order - Test 13', - ...(s390x ? [] : [ - 'Ed25519 Verification checks with small-order key of order - Test 0', - 'Ed25519 Verification checks with small-order key of order - Test 11', - ]), - ], - }, - }, }; diff --git a/test/wpt/status/hr-time.cjs b/test/wpt/status/hr-time.cjs new file mode 100644 index 00000000000000..c426eeeb8e9274 --- /dev/null +++ b/test/wpt/status/hr-time.cjs @@ -0,0 +1,37 @@ +'use strict'; + +const os = require('node:os'); + +const isMacOS15X64 = + os.platform() === 'darwin' && + process.arch === 'x64' && + os.release().startsWith('24.'); + +module.exports = { + ...(isMacOS15X64 ? { + 'basic.any.js': { + fail: { + note: 'Flaky on macos15-x64: Date.now() can shift relative to monotonic performance.now()', + flaky: [ + 'High resolution time has approximately the right relative magnitude', + ], + }, + }, + } : {}), + + 'idlharness.any.js': { + fail: { + expected: [ + 'Window interface: attribute performance', + ], + }, + }, + + 'idlharness-shadowrealm.window.js': { + skip: 'ShadowRealm support is not enabled', + }, + + 'window-worker-timeOrigin.window.js': { + skip: 'depends on URL.createObjectURL(blob)', + }, +}; diff --git a/test/wpt/status/hr-time.json b/test/wpt/status/hr-time.json deleted file mode 100644 index b787bcb7862cb6..00000000000000 --- a/test/wpt/status/hr-time.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "idlharness.any.js": { - "fail": { - "expected": [ - "Window interface: attribute performance" - ] - } - }, - "idlharness-shadowrealm.window.js": { - "skip": "ShadowRealm support is not enabled" - }, - "window-worker-timeOrigin.window.js": { - "skip": "depends on URL.createObjectURL(blob)" - } -} diff --git a/tools/dep_updaters/c-ares.kbx b/tools/dep_updaters/c-ares.kbx new file mode 100644 index 00000000000000..720f1df36917d7 Binary files /dev/null and b/tools/dep_updaters/c-ares.kbx differ diff --git a/tools/dep_updaters/update-c-ares.sh b/tools/dep_updaters/update-c-ares.sh index f990430d9f6aee..ca77ee52183d64 100755 --- a/tools/dep_updaters/update-c-ares.sh +++ b/tools/dep_updaters/update-c-ares.sh @@ -1,5 +1,5 @@ #!/bin/sh -set -e +set -ex # Shell script to update c-ares in the source tree to a specific version BASE_DIR=$(cd "$(dirname "$0")/../.." && pwd) @@ -22,11 +22,11 @@ if (!res.ok) throw new Error(`FetchError: ${res.status} ${res.statusText}`, { ca const { tag_name, assets } = await res.json(); const { browser_download_url, name } = assets.find(({ name }) => name.endsWith('.tar.gz')); if(!browser_download_url || !name) throw new Error('No tarball found'); -console.log(`${tag_name} ${browser_download_url} ${name}`); +console.log(`${tag_name.replace(/^v/, '')} ${browser_download_url}`); EOF )" -IFS=' ' read -r NEW_VERSION NEW_VERSION_URL ARES_TARBALL < /dev/null || mktemp -d -t 'tmp') +ARES_TARBALL="$WORKSPACE/c-ares.tgz" cleanup () { EXIT_CODE=$? @@ -47,29 +48,29 @@ cleanup () { trap cleanup INT TERM EXIT -cd "$WORKSPACE" - echo "Fetching c-ares source archive" curl -sL -o "$ARES_TARBALL" "$NEW_VERSION_URL" -log_and_verify_sha256sum "c-ares" "$ARES_TARBALL" -gzip -dc "$ARES_TARBALL" | tar xf - -rm -- "$ARES_TARBALL" -FOLDER=$(ls -d -- */) +echo "Verifying PGP signature" +curl -sL -o "$ARES_TARBALL.asc" "$NEW_VERSION_URL.asc" +gpgv --keyring "$BASE_DIR/tools/dep_updaters/c-ares.kbx" "${ARES_TARBALL}.asc" "${ARES_TARBALL}" + +log_and_verify_sha256sum "c-ares" "$ARES_TARBALL" +tar -C "$WORKSPACE" -xzf "$ARES_TARBALL" -mv -- "$FOLDER" cares +ARES_FOLDER=$(find "$WORKSPACE" -mindepth 1 -maxdepth 1 -type d -print -quit) echo "Removing tests" -rm -rf "$WORKSPACE/cares/test" +rm -rf "$ARES_FOLDER/test" echo "Copying existing .gitignore, config, gyp and gn files" -cp -R "$DEPS_DIR/cares/config" "$WORKSPACE/cares" -cp "$DEPS_DIR/cares/.gitignore" "$WORKSPACE/cares" -cp "$DEPS_DIR/cares/cares.gyp" "$WORKSPACE/cares" -cp "$DEPS_DIR/cares/"*.gn "$DEPS_DIR/cares/"*.gni "$WORKSPACE/cares" +cp -R "$DEPS_DIR/cares/config" "$ARES_FOLDER" +cp "$DEPS_DIR/cares/.gitignore" "$ARES_FOLDER" +cp "$DEPS_DIR/cares/cares.gyp" "$ARES_FOLDER" +cp "$DEPS_DIR/cares/"*.gn "$DEPS_DIR/cares/"*.gni "$ARES_FOLDER" echo "Replacing existing c-ares" -replace_dir "$DEPS_DIR/cares" "$WORKSPACE/cares" +replace_dir "$DEPS_DIR/cares" "$ARES_FOLDER" echo "Updating cares.gyp" "$NODE" "$ROOT/tools/dep_updaters/update-c-ares.mjs" diff --git a/tools/dep_updaters/update-libffi.sh b/tools/dep_updaters/update-libffi.sh index ba12a10cfb2480..dc96c9c3244909 100755 --- a/tools/dep_updaters/update-libffi.sh +++ b/tools/dep_updaters/update-libffi.sh @@ -1,5 +1,5 @@ #!/bin/sh -set -e +set -ex # Shell script to update libffi in the source tree to a specific version BASE_DIR=$(cd "$(dirname "$0")/../.." && pwd) @@ -26,13 +26,13 @@ const tarball = assets.find(({ name }) => name === tarballName); if (!tarball?.browser_download_url) throw new Error(`No release tarball found for ${tag_name}`); console.log(`${version} ${tarball.browser_download_url} ${tarballName}`); EOF -)" +)" # " IFS=' ' read -r NEW_VERSION NEW_VERSION_URL LIBFFI_TARBALL < fileURLToPath(new URL(path, root)); + +export default { + target: ['man-page'], + + global: { + input: [fromRoot('doc/api/cli.md')], + output: fromRoot('tools/doc/.manpagecheck'), + + // Point every loadable URL at its local file so no network request is made. + changelog: fromRoot('CHANGELOG.md'), + index: fromRoot('doc/api/index.md'), + }, +}; diff --git a/tools/doc/package-lock.json b/tools/doc/package-lock.json index 9ee8c0128d17b3..a63b70a7d3c3f3 100644 --- a/tools/doc/package-lock.json +++ b/tools/doc/package-lock.json @@ -6,13 +6,13 @@ "": { "name": "doc", "dependencies": { - "@node-core/doc-kit": "1.3.9" + "@node-core/doc-kit": "1.4.1" } }, "node_modules/@actions/core": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-3.0.0.tgz", - "integrity": "sha512-zYt6cz+ivnTmiT/ksRVriMBOiuoUpDCJJlZ5KPl2/FRdvwU3f7MPh9qftvbkXJThragzUZieit2nyHUyw53Seg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-3.0.1.tgz", + "integrity": "sha512-a6d/Nwahm9fliVGRhdhofo40HjHQasUPusmc7vBfyky+7Z+P2A1J68zyFVaNcEclc/Se+eO595oAr5nwEIoIUA==", "license": "MIT", "dependencies": { "@actions/exec": "^3.0.0", @@ -29,9 +29,9 @@ } }, "node_modules/@actions/http-client": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-4.0.0.tgz", - "integrity": "sha512-QuwPsgVMsD6qaPD57GLZi9sqzAZCtiJT8kVBCDpLtxhL5MydQ4gS+DrejtZZPdIYyB1e95uCK9Luyds7ybHI3g==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-4.0.1.tgz", + "integrity": "sha512-+Nvd1ImaOZBSoPbsUtEhv+1z99H12xzncCkz0a3RuehINE81FZSe2QTj3uvAPTcJX/SCzUQHQ0D1GrPMbrPitg==", "license": "MIT", "dependencies": { "tunnel": "^0.0.6", @@ -44,18 +44,6 @@ "integrity": "sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==", "license": "MIT" }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@emnapi/core": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", @@ -134,51 +122,6 @@ "react": ">= 16 || ^19.0.0-rc" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/@minify-html/wasm": { "version": "0.18.1", "resolved": "https://registry.npmjs.org/@minify-html/wasm/-/wasm-0.18.1.tgz", @@ -321,6 +264,9 @@ "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -337,6 +283,9 @@ "cpu": [ "arm64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -353,6 +302,9 @@ "cpu": [ "ppc64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -369,6 +321,9 @@ "cpu": [ "riscv64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -385,6 +340,9 @@ "cpu": [ "s390x" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -401,6 +359,9 @@ "cpu": [ "x64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -417,6 +378,9 @@ "cpu": [ "x64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -491,13 +455,13 @@ } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", - "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", + "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==", "license": "MIT", "optional": true, "dependencies": { - "@tybys/wasm-util": "^0.10.1" + "@tybys/wasm-util": "^0.10.3" }, "funding": { "type": "github", @@ -513,6 +477,7 @@ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", "license": "MIT", + "peer": true, "engines": { "node": "^14.21.3 || >=16" }, @@ -521,19 +486,19 @@ } }, "node_modules/@node-core/doc-kit": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/@node-core/doc-kit/-/doc-kit-1.3.9.tgz", - "integrity": "sha512-DVRaycj3humM/GJ4jFk5+kKrnzHEEKAqiNcUWsb/b0BCQePrqVl6sJ8L4E82HP2qTBq6EkNkwdEI5uf+w45tkA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@node-core/doc-kit/-/doc-kit-1.4.1.tgz", + "integrity": "sha512-4S9cIGW6+3U3wWsCHRABJg5rjkTLU90Mdyb9v53ljf622A9u8sGQgSzVH9FgQHcKw5z3ofK25h12E/eDGi5SVA==", "dependencies": { "@actions/core": "^3.0.0", "@heroicons/react": "^2.2.0", "@minify-html/wasm": "^0.18.1", "@node-core/rehype-shiki": "^1.4.1", - "@node-core/ui-components": "^1.6.3", + "@node-core/ui-components": "^1.7.0", "@orama/orama": "^3.1.18", "@orama/ui": "^1.5.4", "@rollup/plugin-virtual": "^3.0.2", - "@swc/html-wasm": "^1.15.32", + "@swc/html-wasm": "^1.15.40", "acorn": "^8.16.0", "commander": "^14.0.3", "dedent": "^1.7.2", @@ -545,21 +510,22 @@ "hastscript": "^9.0.1", "lightningcss-wasm": "^1.32.0", "mdast-util-slice-markdown": "^2.0.1", - "piscina": "^5.1.4", - "preact": "^10.29.0", - "preact-render-to-string": "^6.6.7", + "piscina": "^5.2.0", + "preact": "^10.29.2", + "preact-render-to-string": "^6.7.0", "reading-time": "^1.5.0", "recma-jsx": "^1.0.1", "rehype-raw": "^7.0.0", "rehype-recma": "^1.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", + "remark-mdx": "^3.1.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-stringify": "^11.0.0", - "rolldown": "1.0.0-rc.17", + "rolldown": "1.0.2", "semver": "^7.8.0", - "shiki": "^4.0.2", + "shiki": "^4.1.0", "tinyglobby": "^0.2.15", "unified": "^11.0.5", "unist-builder": "^4.0.0", @@ -574,30 +540,18 @@ "doc-kit": "bin/cli.mjs" } }, - "node_modules/@node-core/doc-kit/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/@node-core/rehype-shiki": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@node-core/rehype-shiki/-/rehype-shiki-1.4.1.tgz", - "integrity": "sha512-Ku63bR4wOq6MuZPRSNwj5NcVEU1zmQ+YtXRmwjIMm/Fdp8sZQVAhzyVJLjeYXDKTeYLRPYhtWu8jEu2+G9tumg==", - "dependencies": { - "@shikijs/core": "^3.22.0", - "@shikijs/engine-javascript": "^3.22.0", - "@shikijs/engine-oniguruma": "^3.22.0", - "@shikijs/twoslash": "^3.22.0", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@node-core/rehype-shiki/-/rehype-shiki-1.4.2.tgz", + "integrity": "sha512-H2T4bi9EZg0s0HLlcdANXzozrxeCfXzhZvbqUEygkggrv5pzJX9MVFU5K0/zGJfiqhzUu6TXMrNgpLqX1pylyw==", + "dependencies": { + "@shikijs/core": "^4.0.2", + "@shikijs/engine-javascript": "^4.0.2", + "@shikijs/engine-oniguruma": "^4.0.2", + "@shikijs/twoslash": "^4.0.2", "classnames": "~2.5.1", "hast-util-to-string": "^3.0.1", - "shiki": "~3.22.0", + "shiki": "~4.0.2", "typescript": "5.9.3", "unist-util-visit": "^5.1.0" }, @@ -606,89 +560,125 @@ } }, "node_modules/@node-core/rehype-shiki/node_modules/@shikijs/core": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.22.0.tgz", - "integrity": "sha512-iAlTtSDDbJiRpvgL5ugKEATDtHdUVkqgHDm/gbD2ZS9c88mx7G1zSYjjOxp5Qa0eaW0MAQosFRmJSk354PRoQA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.0.2.tgz", + "integrity": "sha512-hxT0YF4ExEqB8G/qFdtJvpmHXBYJ2lWW7qTHDarVkIudPFE6iCIrqdgWxGn5s+ppkGXI0aEGlibI0PAyzP3zlw==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.22.0", + "@shikijs/primitive": "4.0.2", + "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" + }, + "engines": { + "node": ">=20" } }, "node_modules/@node-core/rehype-shiki/node_modules/@shikijs/engine-javascript": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.22.0.tgz", - "integrity": "sha512-jdKhfgW9CRtj3Tor0L7+yPwdG3CgP7W+ZEqSsojrMzCjD1e0IxIbwUMDDpYlVBlC08TACg4puwFGkZfLS+56Tw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.0.2.tgz", + "integrity": "sha512-7PW0Nm49DcoUIQEXlJhNNBHyoGMjalRETTCcjMqEaMoJRLljy1Bi/EGV3/qLBgLKQejdspiiYuHGQW6dX94Nag==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.22.0", + "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" + }, + "engines": { + "node": ">=20" } }, "node_modules/@node-core/rehype-shiki/node_modules/@shikijs/engine-oniguruma": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.22.0.tgz", - "integrity": "sha512-DyXsOG0vGtNtl7ygvabHd7Mt5EY8gCNqR9Y7Lpbbd/PbJvgWrqaKzH1JW6H6qFkuUa8aCxoiYVv8/YfFljiQxA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.0.2.tgz", + "integrity": "sha512-UpCB9Y2sUKlS9z8juFSKz7ZtysmeXCgnRF0dlhXBkmQnek7lAToPte8DkxmEYGNTMii72zU/lyXiCB6StuZeJg==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.22.0", + "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2" + }, + "engines": { + "node": ">=20" } }, "node_modules/@node-core/rehype-shiki/node_modules/@shikijs/langs": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.22.0.tgz", - "integrity": "sha512-x/42TfhWmp6H00T6uwVrdTJGKgNdFbrEdhaDwSR5fd5zhQ1Q46bHq9EO61SCEWJR0HY7z2HNDMaBZp8JRmKiIA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.0.2.tgz", + "integrity": "sha512-KaXby5dvoeuZzN0rYQiPMjFoUrz4hgwIE+D6Du9owcHcl6/g16/yT5BQxSW5cGt2MZBz6Hl0YuRqf12omRfUUg==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.0.2" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@node-core/rehype-shiki/node_modules/@shikijs/primitive": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.0.2.tgz", + "integrity": "sha512-M6UMPrSa3fN5ayeJwFVl9qWofl273wtK1VG8ySDZ1mQBfhCpdd8nEx7nPZ/tk7k+TYcpqBZzj/AnwxT9lO+HJw==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.22.0" + "@shikijs/types": "4.0.2", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" } }, "node_modules/@node-core/rehype-shiki/node_modules/@shikijs/themes": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.22.0.tgz", - "integrity": "sha512-o+tlOKqsr6FE4+mYJG08tfCFDS+3CG20HbldXeVoyP+cYSUxDhrFf3GPjE60U55iOkkjbpY2uC3It/eeja35/g==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.0.2.tgz", + "integrity": "sha512-mjCafwt8lJJaVSsQvNVrJumbnnj1RI8jbUKrPKgE6E3OvQKxnuRoBaYC51H4IGHePsGN/QtALglWBU7DoKDFnA==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.22.0" + "@shikijs/types": "4.0.2" + }, + "engines": { + "node": ">=20" } }, "node_modules/@node-core/rehype-shiki/node_modules/@shikijs/types": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.22.0.tgz", - "integrity": "sha512-491iAekgKDBFE67z70Ok5a8KBMsQ2IJwOWw3us/7ffQkIBCyOQfm/aNwVMBUriP02QshIfgHCBSIYAl3u2eWjg==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.0.2.tgz", + "integrity": "sha512-qzbeRooUTPnLE+sHD/Z8DStmaDgnbbc/pMrU203950aRqjX/6AFHeDYT+j00y2lPdz0ywJKx7o/7qnqTivtlXg==", "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" } }, "node_modules/@node-core/rehype-shiki/node_modules/shiki": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.22.0.tgz", - "integrity": "sha512-LBnhsoYEe0Eou4e1VgJACes+O6S6QC0w71fCSp5Oya79inkwkm15gQ1UF6VtQ8j/taMDh79hAB49WUk8ALQW3g==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.0.2.tgz", + "integrity": "sha512-eAVKTMedR5ckPo4xne/PjYQYrU3qx78gtJZ+sHlXEg5IHhhoQhMfZVzetTYuaJS0L2Ef3AcCRzCHV8T0WI6nIQ==", "license": "MIT", "dependencies": { - "@shikijs/core": "3.22.0", - "@shikijs/engine-javascript": "3.22.0", - "@shikijs/engine-oniguruma": "3.22.0", - "@shikijs/langs": "3.22.0", - "@shikijs/themes": "3.22.0", - "@shikijs/types": "3.22.0", + "@shikijs/core": "4.0.2", + "@shikijs/engine-javascript": "4.0.2", + "@shikijs/engine-oniguruma": "4.0.2", + "@shikijs/langs": "4.0.2", + "@shikijs/themes": "4.0.2", + "@shikijs/types": "4.0.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" } }, "node_modules/@node-core/ui-components": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@node-core/ui-components/-/ui-components-1.6.3.tgz", - "integrity": "sha512-Oy/bI4mZC6V/i8CdIX8q62r81zR6bAEARZE0jwTpv7w49SNomB2WAVb5fnFBSumyigOCgQKgR/OJtwh8XQJnkw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@node-core/ui-components/-/ui-components-1.7.1.tgz", + "integrity": "sha512-i1un8y0yth6WdT0OXpAQeL8XIkohcZ2P8khSC0oQstWG8H7PCRqX+mdZlJAuVUKq3MaQnC2fO34Q3j7L4TenXg==", "dependencies": { "@heroicons/react": "^2.2.0", - "@orama/core": "^1.2.19", + "@orama/orama": "^3.1.18", "@orama/ui": "^1.5.4", "@radix-ui/react-avatar": "^1.1.11", "@radix-ui/react-dialog": "^1.1.15", @@ -698,15 +688,9 @@ "@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-tabs": "^1.1.13", "@radix-ui/react-tooltip": "^1.2.8", - "@tailwindcss/postcss": "~4.2.1", - "@types/react": "^19.2.13", "@vcarl/remark-headings": "~0.1.0", "classnames": "~2.5.1", - "postcss-calc": "10.1.1", - "postcss-cli": "11.0.1", - "react": "^19.2.4", - "tailwindcss": "~4.1.17", - "typescript": "5.9.3" + "react": "^19.2.6" }, "engines": { "node": ">=20" @@ -717,6 +701,7 @@ "resolved": "https://registry.npmjs.org/@orama/core/-/core-1.2.19.tgz", "integrity": "sha512-AVEI0eG/a1RUQK+tBloRMppQf46Ky4kIYKEVjo0V0VfIGZHdLOE2PJR4v949kFwiTnfSJCUaxgwM74FCA1uHUA==", "license": "AGPL-3.0", + "peer": true, "dependencies": { "@orama/cuid2": "2.2.3", "@orama/oramacore-events-parser": "0.0.5" @@ -727,6 +712,7 @@ "resolved": "https://registry.npmjs.org/@orama/cuid2/-/cuid2-2.2.3.tgz", "integrity": "sha512-Lcak3chblMejdlSHgYU2lS2cdOhDpU6vkfIJH4m+YKvqQyLqs1bB8+w6NT1MG5bO12NUK2GFc34Mn2xshMIQ1g==", "license": "MIT", + "peer": true, "dependencies": { "@noble/hashes": "^1.1.5" } @@ -744,7 +730,8 @@ "version": "0.0.5", "resolved": "https://registry.npmjs.org/@orama/oramacore-events-parser/-/oramacore-events-parser-0.0.5.tgz", "integrity": "sha512-yAuSwog+HQBAXgZ60TNKEwu04y81/09mpbYBCmz1RCxnr4ObNY2JnPZI7HmALbjAhLJ8t5p+wc2JHRK93ubO4w==", - "license": "AGPL-3.0" + "license": "AGPL-3.0", + "peer": true }, "node_modules/@orama/stopwords": { "version": "3.1.18", @@ -772,33 +759,33 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.127.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.127.0.tgz", - "integrity": "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==", + "version": "0.132.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.132.0.tgz", + "integrity": "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" } }, "node_modules/@radix-ui/number": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", - "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.2.tgz", + "integrity": "sha512-ceTwaxc4I5IOi97DgCotl3pqiyRGvffcc0oOsE2dQYaJOFIDsDt4VWG6xEbg1QePv9QWausCEIppud/tJ1wNig==", "license": "MIT" }, "node_modules/@radix-ui/primitive": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", - "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.4.tgz", + "integrity": "sha512-7AdCK9PQyiljKoBDbN8OuctCbd/esdwZPQ8RtOE3SsyQtUpiPb+ND75q0jEhC1m1ecBI0MFNeLJvwIh9iKHRcQ==", "license": "MIT" }, "node_modules/@radix-ui/react-arrow": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", - "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.11.tgz", + "integrity": "sha512-Kdil9BB1rIFC/khmf4hC35bn8701AJcizTU7G7cUbEbk5XqqbjDuHW60uUfKqO5WojjZcbAW51Q7P0hRmMLw8A==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.3" + "@radix-ui/react-primitive": "2.1.7" }, "peerDependencies": { "@types/react": "*", @@ -815,13 +802,17 @@ } } }, - "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "node_modules/@radix-ui/react-avatar": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.2.1.tgz", + "integrity": "sha512-+8PWoLLZv3AVb5m0pvoiOca/bQGzc9vPVb+982HB2x3Un0DpYEPM3zLMl4oqRpBsocJuNqLkiv/HXTnTrlwr4g==", "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.2.3" + "@radix-ui/react-context": "1.1.4", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-is-hydrated": "0.1.1", + "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", @@ -838,17 +829,16 @@ } } }, - "node_modules/@radix-ui/react-avatar": { + "node_modules/@radix-ui/react-collection": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.11.tgz", - "integrity": "sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.11.tgz", + "integrity": "sha512-djW9+zeg137KQdlPtmE8xnaD+K2rcXXMWFrSg0hsmYZ6HRbdTA7tDHFgpaW9+huWVEu0RCabL+985T4TA0BE7g==", "license": "MIT", "dependencies": { - "@radix-ui/react-context": "1.1.3", - "@radix-ui/react-primitive": "2.1.4", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-is-hydrated": "0.1.0", - "@radix-ui/react-use-layout-effect": "1.1.1" + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.1.4", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-slot": "1.3.0" }, "peerDependencies": { "@types/react": "*", @@ -865,36 +855,25 @@ } } }, - "node_modules/@radix-ui/react-collection": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", - "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.3.tgz", + "integrity": "sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA==", "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3" - }, "peerDependencies": { "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - }, - "@types/react-dom": { - "optional": true } } }, - "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "node_modules/@radix-ui/react-context": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.4.tgz", + "integrity": "sha512-QwH4PO5urrbO+FaGd5Aglg+YJgWTyyuZ3g/6mKvsqraLkglDdckw9JafgL5McL5VEJ6EPNduPaT3ZE9BttDAqg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -906,13 +885,26 @@ } } }, - "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.3" + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.18.tgz", + "integrity": "sha512-apa28mldjMgORmE6g/w3sCcA0Y9UAVeeDVoozN4i7kOw12mLl9RBchfzK3Nn6qxOWjrZhK1Lfy7f07kyzxtnBw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.4", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.1.4", + "@radix-ui/react-dismissable-layer": "1.1.14", + "@radix-ui/react-focus-guards": "1.1.4", + "@radix-ui/react-focus-scope": "1.1.11", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-portal": "1.1.13", + "@radix-ui/react-presence": "1.1.6", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-slot": "1.3.0", + "@radix-ui/react-use-controllable-state": "1.2.3", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", @@ -929,10 +921,10 @@ } } }, - "node_modules/@radix-ui/react-compose-refs": { + "node_modules/@radix-ui/react-direction": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.2.tgz", + "integrity": "sha512-C3vFhbyi4SW3PmbAi6Awpu4OzJtd0MxGurvSsYtr7p7nM8RNB3VAF3CUmnp2j50knpkrRcB7+ycVXzgLgF6yNA==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -944,41 +936,46 @@ } } }, - "node_modules/@radix-ui/react-context": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz", - "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==", + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.14.tgz", + "integrity": "sha512-4lUhWTWAjbDIqFrAPWJ3WqBOpO5YchVZ88X3nh6H9Lu5AFi5nCUeTPj3D8FSDmabmFeRe9ME0BDA4MwKTha5GQ==", "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.4", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-effect-event": "0.0.3" + }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true + }, + "@types/react-dom": { + "optional": true } } }, - "node_modules/@radix-ui/react-dialog": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", - "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-focus-guards": "1.1.3", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.19.tgz", + "integrity": "sha512-HZccBkbK0LOi8nYKIp5jll/zIRW0cCOmG6WWyqsSpmXCU+ZlcBbTqIwlBvPCu886C5RVu6c/kHV7xSP8IgYNHw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.4", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.1.4", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-menu": "2.1.19", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -995,10 +992,10 @@ } } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.4.tgz", + "integrity": "sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -1010,13 +1007,15 @@ } } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.11.tgz", + "integrity": "sha512-Mn88Vg2whaRocGJNOH+DKFqYm6ySFPQaiwHNxZPyjn99B52KAEJWWY9NP83+nWdk2HM3rdov+STu9AG471Rt9w==", "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.2.3" + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2" }, "peerDependencies": { "@types/react": "*", @@ -1033,11 +1032,14 @@ } } }, - "node_modules/@radix-ui/react-direction": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", - "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "node_modules/@radix-ui/react-id": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.2.tgz", + "integrity": "sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA==", "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.2" + }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -1048,17 +1050,13 @@ } } }, - "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", - "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "node_modules/@radix-ui/react-label": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.11.tgz", + "integrity": "sha512-3PKvDDxOn62k0oV1n4QtNtD2vpu+zYjXR7ojLBPaO6SPvhy53yg0vAmgNeBQeJW5rV3dffoRG+HYfLBZuzw0CQ==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-escape-keydown": "1.1.1" + "@radix-ui/react-primitive": "2.1.7" }, "peerDependencies": { "@types/react": "*", @@ -1075,13 +1073,30 @@ } } }, - "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.3" + "node_modules/@radix-ui/react-menu": { + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.19.tgz", + "integrity": "sha512-Mht9BVd1AIsNFVQr4KG3bIK7XQn5IXF0TL/2ObsrzOdc1loaly/+kBDL5roSCYn8j8XZkvpOD0WYLz2FQtH1Eg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.4", + "@radix-ui/react-collection": "1.1.11", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.1.4", + "@radix-ui/react-direction": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.14", + "@radix-ui/react-focus-guards": "1.1.4", + "@radix-ui/react-focus-scope": "1.1.11", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-popper": "1.3.2", + "@radix-ui/react-portal": "1.1.13", + "@radix-ui/react-presence": "1.1.6", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-roving-focus": "1.1.14", + "@radix-ui/react-slot": "1.3.0", + "@radix-ui/react-use-callback-ref": "1.1.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", @@ -1098,19 +1113,22 @@ } } }, - "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", - "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", + "node_modules/@radix-ui/react-popper": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.3.2.tgz", + "integrity": "sha512-3QXNeMkdshed1MR3LNoiCirBywRFPkD8ETJa/HlPuLwSajaQixf2ro+isoDNJlGABg9ug41XuZpINZJIle4XWg==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-menu": "2.1.16", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2" + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.11", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.1.4", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.2", + "@radix-ui/react-use-rect": "1.1.2", + "@radix-ui/react-use-size": "1.1.2", + "@radix-ui/rect": "1.1.2" }, "peerDependencies": { "@types/react": "*", @@ -1127,28 +1145,37 @@ } } }, - "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "node_modules/@radix-ui/react-portal": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.13.tgz", + "integrity": "sha512-z3oXfmaHLJTF1wktbjgD6cn9jiEbq3WSondB10LIuIt2m2Ym4iJlrW04/euMwENDdWDdE7z+OuY7Qyp1YpRSwA==", "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-layout-effect": "1.1.2" + }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true + }, + "@types/react-dom": { + "optional": true } } }, - "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "node_modules/@radix-ui/react-presence": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.6.tgz", + "integrity": "sha512-zdTk4PlUO0E18HnZ3wYbW0KkJJxWCdiNYp6g6X1PtONFhxVkg01vliTJAmwIszU6mHiyBOoW9P0rAugl5/hULQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.2.3" + "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", @@ -1165,30 +1192,44 @@ } } }, - "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", - "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.7.tgz", + "integrity": "sha512-bC3NiwsprbxKjuon9l7X6BUTw7FPVzEYaL92MPEY5SCd/9hUTPXVFtVwRix7778wtRsVao+zE062gL79FZleeQ==", "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.3.0" + }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true + }, + "@types/react-dom": { + "optional": true } } }, - "node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", - "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.14.tgz", + "integrity": "sha512-8Qcnx9447tx/aCBgw6Jenfqg4Skq+vqab9mCBmuGNipIS5YXvL275wbKEu7+ICYHIlAPgCduUMJH1XOYewKF6Q==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1" + "@radix-ui/primitive": "1.1.4", + "@radix-ui/react-collection": "1.1.11", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.1.4", + "@radix-ui/react-direction": "1.1.2", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -1205,13 +1246,57 @@ } } }, - "node_modules/@radix-ui/react-focus-scope/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "node_modules/@radix-ui/react-select": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.3.2.tgz", + "integrity": "sha512-brXD6C/V0fVK0DDbscLVw6LsXrjQ+ay8jdOBaN+tLb4vsHsAMm6Gt6eT77wHX1Eq8GPtD5rJ+RxFtfDozsb4+Q==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.2", + "@radix-ui/primitive": "1.1.4", + "@radix-ui/react-collection": "1.1.11", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.1.4", + "@radix-ui/react-direction": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.14", + "@radix-ui/react-focus-guards": "1.1.4", + "@radix-ui/react-focus-scope": "1.1.11", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-popper": "1.3.2", + "@radix-ui/react-portal": "1.1.13", + "@radix-ui/react-presence": "1.1.6", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-slot": "1.3.0", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-controllable-state": "1.2.3", + "@radix-ui/react-use-layout-effect": "1.1.2", + "@radix-ui/react-use-previous": "1.1.2", + "@radix-ui/react-visually-hidden": "1.2.7", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.11.tgz", + "integrity": "sha512-jRhe86+8PF7VZ1u14eOWVOuh2BuAhALg/FT1VcMC4OHedMTRUazDnDlKTt+yxo5cRNKHMfmvZ4sSQtWDeMV4CQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.2.3" + "@radix-ui/react-primitive": "2.1.7" }, "peerDependencies": { "@types/react": "*", @@ -1228,13 +1313,13 @@ } } }, - "node_modules/@radix-ui/react-id": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", - "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "node_modules/@radix-ui/react-slot": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.3.0.tgz", + "integrity": "sha512-MojKku4U/miO8Av4Dkb+ctMAQx7JmY96LmtDQlAarCRtd7rN52QCSzBF+XAvr5S6coSVj9HEPBgHAHKEJVk/WA==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" + "@radix-ui/react-compose-refs": "1.1.3" }, "peerDependencies": { "@types/react": "*", @@ -1246,13 +1331,20 @@ } } }, - "node_modules/@radix-ui/react-label": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz", - "integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==", + "node_modules/@radix-ui/react-tabs": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.16.tgz", + "integrity": "sha512-v3Ab2l7z6U7tRB4xA0IyKdq0OsqaO1o9ZjsIEoKKnSZ/l96mZz8aCTX0NCXw+YVHJXr8Km4d+Mn6/Q8YjXa+gw==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.4" + "@radix-ui/primitive": "1.1.4", + "@radix-ui/react-context": "1.1.4", + "@radix-ui/react-direction": "1.1.2", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-presence": "1.1.6", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-roving-focus": "1.1.14", + "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -1269,30 +1361,24 @@ } } }, - "node_modules/@radix-ui/react-menu": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", - "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-focus-guards": "1.1.3", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-popper": "1.2.8", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-roving-focus": "1.1.11", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" + "node_modules/@radix-ui/react-tooltip": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.11.tgz", + "integrity": "sha512-8XZ6Py3y3W2nEzAUGCN5cfVKaUi+CVApcz1d6lrNVVf2hvYEixMRkq8k9ggPKnQUpRRuOV5avt8uvxViH2jLwA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.4", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.1.4", + "@radix-ui/react-dismissable-layer": "1.1.14", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-popper": "1.3.2", + "@radix-ui/react-portal": "1.1.13", + "@radix-ui/react-presence": "1.1.6", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-slot": "1.3.0", + "@radix-ui/react-use-controllable-state": "1.2.3", + "@radix-ui/react-visually-hidden": "1.2.7" }, "peerDependencies": { "@types/react": "*", @@ -1309,10 +1395,10 @@ } } }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-context": { + "node_modules/@radix-ui/react-use-callback-ref": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.2.tgz", + "integrity": "sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -1324,65 +1410,47 @@ } } }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.3.tgz", + "integrity": "sha512-PLzC90MS+ReootmjC597dvopoelpZ8Q61HJkDXZSExitIq7PL55vHNnesAHwguHK0aPfBnpdNzQtv1uliaqQrA==", "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.2.3" + "@radix-ui/react-use-effect-event": "0.0.3", + "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - }, - "@types/react-dom": { - "optional": true } } }, - "node_modules/@radix-ui/react-popper": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", - "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.3.tgz", + "integrity": "sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA==", "license": "MIT", "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-layout-effect": "1.1.1", - "@radix-ui/react-use-rect": "1.1.1", - "@radix-ui/react-use-size": "1.1.1", - "@radix-ui/rect": "1.1.1" + "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - }, - "@types/react-dom": { - "optional": true } } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "node_modules/@radix-ui/react-use-is-hydrated": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.1.tgz", + "integrity": "sha512-qwOiz4Tjo8CNnrOLAYUMXeZwDzXgXpvK4TKQPmWLECM9XoWvA6+0Z2/7Ag3A4ivjS4ovbLJPbskkxioFyBhr8A==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -1394,107 +1462,79 @@ } } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.2.tgz", + "integrity": "sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA==", "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.3" - }, "peerDependencies": { "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - }, - "@types/react-dom": { - "optional": true } } }, - "node_modules/@radix-ui/react-portal": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", - "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.2.tgz", + "integrity": "sha512-IGBQPtRFdhN6MQ8dbegVmBq1LVZluya3F1jWY+puIcQC3MHctRwTDSBWCkL/3ZcnMJLTMJ++Z+ktmvg0F89iCw==", "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, "peerDependencies": { "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - }, - "@types/react-dom": { - "optional": true } } }, - "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.2.tgz", + "integrity": "sha512-d8a+bBY/FxikNPlgJJoaBHZX+zKVbWHYJGTLnLvveQgFSTntkGdEKv3JDtHrMS0DNYpllz2nRsTLGLKYttbpmw==", "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.2.3" + "@radix-ui/rect": "1.1.2" }, "peerDependencies": { "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - }, - "@types/react-dom": { - "optional": true } } }, - "node_modules/@radix-ui/react-presence": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", - "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.2.tgz", + "integrity": "sha512-giWQp+4mxjBPt4KZ0MmyuykFNWfbDxKt4x+fPkRYmgRFJSbCZFzUglvMb/Kjn38tm10YP4ufiQZDx3zna4LU6w==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-use-layout-effect": "1.1.1" + "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - }, - "@types/react-dom": { - "optional": true } } }, - "node_modules/@radix-ui/react-primitive": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", - "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.7.tgz", + "integrity": "sha512-1wNZBggTDK3GRuuQ6nP4k2yi7a6l7I5qbMPbZcRsrGsGVead/f/d5FhEzUvqFs0bcrDLx7n1zKQ3JvLR6whaaw==", "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.2.4" + "@radix-ui/react-primitive": "2.1.7" }, "peerDependencies": { "@types/react": "*", @@ -1511,728 +1551,140 @@ } } }, - "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", - "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "node_modules/@radix-ui/rect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.2.tgz", + "integrity": "sha512-xnXE7wG13PI+cxieVssYXlQJuYVRhH9NBoxt3KNwzghDIA69GMm7d4wXRouHIYjE+KvS6U/MsMO73NdS2MH9ZA==", + "license": "MIT" + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.2.tgz", + "integrity": "sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", - "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.2.tgz", + "integrity": "sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.2.tgz", + "integrity": "sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA==", + "cpu": [ + "x64" + ], "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.2.tgz", + "integrity": "sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@radix-ui/react-select": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", - "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/number": "1.1.1", - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-focus-guards": "1.1.3", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-popper": "1.2.8", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-layout-effect": "1.1.1", - "@radix-ui/react-use-previous": "1.1.1", - "@radix-ui/react-visually-hidden": "1.2.3", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.2.tgz", + "integrity": "sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.2.tgz", + "integrity": "sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.2.tgz", + "integrity": "sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@radix-ui/react-separator": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz", - "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tabs": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", - "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-roving-focus": "1.1.11", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tooltip": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz", - "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-popper": "1.2.8", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-visually-hidden": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", - "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", - "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-effect-event": "0.0.2", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-effect-event": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", - "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", - "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-is-hydrated": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz", - "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==", - "license": "MIT", - "dependencies": { - "use-sync-external-store": "^1.5.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-previous": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", - "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", - "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", - "license": "MIT", - "dependencies": { - "@radix-ui/rect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", - "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", - "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/rect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", - "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", - "license": "MIT" - }, - "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.17.tgz", - "integrity": "sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.17.tgz", - "integrity": "sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.17.tgz", - "integrity": "sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.17.tgz", - "integrity": "sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.17.tgz", - "integrity": "sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.17.tgz", - "integrity": "sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.17.tgz", - "integrity": "sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.17.tgz", - "integrity": "sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.17.tgz", - "integrity": "sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.17.tgz", - "integrity": "sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.17.tgz", - "integrity": "sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==", - "cpu": [ - "x64" - ], + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.2.tgz", + "integrity": "sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2242,350 +1694,15 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.17.tgz", - "integrity": "sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.17.tgz", - "integrity": "sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==", - "cpu": [ - "wasm32" - ], - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "1.10.0", - "@emnapi/runtime": "1.10.0", - "@napi-rs/wasm-runtime": "^1.1.4" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.17.tgz", - "integrity": "sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.17.tgz", - "integrity": "sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.17.tgz", - "integrity": "sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==", - "license": "MIT" - }, - "node_modules/@rollup/plugin-virtual": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-3.0.2.tgz", - "integrity": "sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@shikijs/core": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.23.0.tgz", - "integrity": "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.23.0", - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4", - "hast-util-to-html": "^9.0.5" - } - }, - "node_modules/@shikijs/langs": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.0.2.tgz", - "integrity": "sha512-KaXby5dvoeuZzN0rYQiPMjFoUrz4hgwIE+D6Du9owcHcl6/g16/yT5BQxSW5cGt2MZBz6Hl0YuRqf12omRfUUg==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "4.0.2" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/@shikijs/langs/node_modules/@shikijs/types": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.0.2.tgz", - "integrity": "sha512-qzbeRooUTPnLE+sHD/Z8DStmaDgnbbc/pMrU203950aRqjX/6AFHeDYT+j00y2lPdz0ywJKx7o/7qnqTivtlXg==", - "license": "MIT", - "dependencies": { - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/@shikijs/primitive": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.0.2.tgz", - "integrity": "sha512-M6UMPrSa3fN5ayeJwFVl9qWofl273wtK1VG8ySDZ1mQBfhCpdd8nEx7nPZ/tk7k+TYcpqBZzj/AnwxT9lO+HJw==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "4.0.2", - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/@shikijs/primitive/node_modules/@shikijs/types": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.0.2.tgz", - "integrity": "sha512-qzbeRooUTPnLE+sHD/Z8DStmaDgnbbc/pMrU203950aRqjX/6AFHeDYT+j00y2lPdz0ywJKx7o/7qnqTivtlXg==", - "license": "MIT", - "dependencies": { - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/@shikijs/themes": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.0.2.tgz", - "integrity": "sha512-mjCafwt8lJJaVSsQvNVrJumbnnj1RI8jbUKrPKgE6E3OvQKxnuRoBaYC51H4IGHePsGN/QtALglWBU7DoKDFnA==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "4.0.2" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/@shikijs/themes/node_modules/@shikijs/types": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.0.2.tgz", - "integrity": "sha512-qzbeRooUTPnLE+sHD/Z8DStmaDgnbbc/pMrU203950aRqjX/6AFHeDYT+j00y2lPdz0ywJKx7o/7qnqTivtlXg==", - "license": "MIT", - "dependencies": { - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/@shikijs/twoslash": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@shikijs/twoslash/-/twoslash-3.23.0.tgz", - "integrity": "sha512-pNaLJWMA3LU7PhT8tm9OQBZ1epy0jmdgeJzntBtr1EVXLbHxGzTj3mnf9vOdcl84l96qnlJXkJ/NGXZYBpXl5g==", - "license": "MIT", - "dependencies": { - "@shikijs/core": "3.23.0", - "@shikijs/types": "3.23.0", - "twoslash": "^0.3.6" - }, - "peerDependencies": { - "typescript": ">=5.5.0" - } - }, - "node_modules/@shikijs/types": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.23.0.tgz", - "integrity": "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==", - "license": "MIT", - "dependencies": { - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" - } - }, - "node_modules/@shikijs/vscode-textmate": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", - "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", - "license": "MIT" - }, - "node_modules/@swc/html-wasm": { - "version": "1.15.40", - "resolved": "https://registry.npmjs.org/@swc/html-wasm/-/html-wasm-1.15.40.tgz", - "integrity": "sha512-WbRp7vSPK9bAGwpP1U8+RDE/xw1yj6P8ZYVqzA/64nlnFuB4MrW92EdkHiKvTPdlFDUZUno8yJKRKcRkE/UK6Q==", - "license": "Apache-2.0" - }, - "node_modules/@tailwindcss/node": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.2.tgz", - "integrity": "sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==", - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.5", - "enhanced-resolve": "^5.19.0", - "jiti": "^2.6.1", - "lightningcss": "1.32.0", - "magic-string": "^0.30.21", - "source-map-js": "^1.2.1", - "tailwindcss": "4.2.2" - } - }, - "node_modules/@tailwindcss/node/node_modules/tailwindcss": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.2.tgz", - "integrity": "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==", - "license": "MIT" - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.2.tgz", - "integrity": "sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==", - "license": "MIT", - "engines": { - "node": ">= 20" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.2.2", - "@tailwindcss/oxide-darwin-arm64": "4.2.2", - "@tailwindcss/oxide-darwin-x64": "4.2.2", - "@tailwindcss/oxide-freebsd-x64": "4.2.2", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.2", - "@tailwindcss/oxide-linux-arm64-gnu": "4.2.2", - "@tailwindcss/oxide-linux-arm64-musl": "4.2.2", - "@tailwindcss/oxide-linux-x64-gnu": "4.2.2", - "@tailwindcss/oxide-linux-x64-musl": "4.2.2", - "@tailwindcss/oxide-wasm32-wasi": "4.2.2", - "@tailwindcss/oxide-win32-arm64-msvc": "4.2.2", - "@tailwindcss/oxide-win32-x64-msvc": "4.2.2" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.2.tgz", - "integrity": "sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.2.tgz", - "integrity": "sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.2.tgz", - "integrity": "sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.2.tgz", - "integrity": "sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.2.tgz", - "integrity": "sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.2.tgz", - "integrity": "sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==", + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.2.tgz", + "integrity": "sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ==", "cpu": [ - "arm64" + "s390x" + ], + "libc": [ + "glibc" ], "license": "MIT", "optional": true, @@ -2593,15 +1710,18 @@ "linux" ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.2.tgz", - "integrity": "sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.2.tgz", + "integrity": "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ==", "cpu": [ - "arm64" + "x64" + ], + "libc": [ + "glibc" ], "license": "MIT", "optional": true, @@ -2609,74 +1729,66 @@ "linux" ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.2.tgz", - "integrity": "sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.2.tgz", + "integrity": "sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw==", "cpu": [ "x64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.2.tgz", - "integrity": "sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.2.tgz", + "integrity": "sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w==", "cpu": [ - "x64" + "arm64" ], "license": "MIT", "optional": true, "os": [ - "linux" + "openharmony" ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.2.tgz", - "integrity": "sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.2.tgz", + "integrity": "sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ==", "cpu": [ "wasm32" ], "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.8.1", - "@emnapi/runtime": "^1.8.1", - "@emnapi/wasi-threads": "^1.1.0", - "@napi-rs/wasm-runtime": "^1.1.1", - "@tybys/wasm-util": "^0.10.1", - "tslib": "^2.8.1" + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" }, "engines": { - "node": ">=14.0.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.2.tgz", - "integrity": "sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==", + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.2.tgz", + "integrity": "sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A==", "cpu": [ "arm64" ], @@ -2686,13 +1798,13 @@ "win32" ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.2.tgz", - "integrity": "sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.2.tgz", + "integrity": "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ==", "cpu": [ "x64" ], @@ -2702,32 +1814,159 @@ "win32" ], "engines": { - "node": ">= 20" + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "license": "MIT" + }, + "node_modules/@rollup/plugin-virtual": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-3.0.2.tgz", + "integrity": "sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@shikijs/core": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.3.1.tgz", + "integrity": "sha512-ANMDxuaPsNMdDC1m4vfvhlDmJweMwkE5XitTwrq2rWHx5jM+dlm4MmHt2PP6t0uejfR77SuhrhJ0zEijIF/uhA==", + "license": "MIT", + "dependencies": { + "@shikijs/primitive": "4.3.1", + "@shikijs/types": "4.3.1", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.5" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.3.1.tgz", + "integrity": "sha512-JBItcnPuYq7jVJdZo/vMj94r+szT7XEjHFX+mvFDGSEIbVAXAGyHAHzhbWzpGOwYidCZrErJLLgn2PVeiokHnQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.3.1", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.6" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.3.1.tgz", + "integrity": "sha512-OXyNMzg0pews+msMj4cHeqT4xiYKKvbnn6VbdAXxfoFl3SSx4fJTc8FadECuc5/H9p3BzhNAoAUXKwAu9rWYhg==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.3.1", + "@shikijs/vscode-textmate": "^10.0.2" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/langs": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.3.1.tgz", + "integrity": "sha512-m0l9nsDqgBHvbZbk7A0/kXz/impK3uB/c6rAn6Gpg/uPtdZRQ+alsN/17MU5thb68XTj/4DxkZAotrM0GGSpDQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.3.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/primitive": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.3.1.tgz", + "integrity": "sha512-CXQRQOYy1leqQ8ceTeJdmXv/bsUY++6QyLpXJ94LZAAYj5X2SKRdc5ipguv4NPyGVKItB2PPwUpRNe0Sjh5S1A==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.3.1", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/themes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.3.1.tgz", + "integrity": "sha512-dgpoJ4WqNi2yTmizQHBJ5zcX6j2lE6icN/0yt4l1kkf16jrY/pwPLoTb1ETsWMz0OBLf9ZNvwmxft+cH+N9qSA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.3.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/twoslash": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/twoslash/-/twoslash-4.3.1.tgz", + "integrity": "sha512-xK8inH/gK++1V4rTxrwCwjvaNwkkJ7oDjOIpdqONVxIpAFnVC3gzqjH5KiXGTelUcxpUJ3PtOKWct1YQ0kAloA==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "4.3.1", + "@shikijs/types": "4.3.1", + "twoslash": "^0.3.9" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "typescript": ">=5.5.0" } }, - "node_modules/@tailwindcss/postcss": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.2.2.tgz", - "integrity": "sha512-n4goKQbW8RVXIbNKRB/45LzyUqN451deQK0nzIeauVEqjlI49slUlgKYJM2QyUzap/PcpnS7kzSUmPb1sCRvYQ==", + "node_modules/@shikijs/types": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.3.1.tgz", + "integrity": "sha512-CHFxE0jztBIZRHH6gxXE7DXUCFXjReEGxZ/j0rfSLGKZuwp2xBYycEP14875DSa9KLL/6700oxIq6oO6ef9K2g==", "license": "MIT", "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.2.2", - "@tailwindcss/oxide": "4.2.2", - "postcss": "^8.5.6", - "tailwindcss": "4.2.2" + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" } }, - "node_modules/@tailwindcss/postcss/node_modules/tailwindcss": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.2.tgz", - "integrity": "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==", + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", "license": "MIT" }, + "node_modules/@swc/html-wasm": { + "version": "1.15.43", + "resolved": "https://registry.npmjs.org/@swc/html-wasm/-/html-wasm-1.15.43.tgz", + "integrity": "sha512-tw1DpLmh54BDNPDBY/tHLDFcLnxzji242Fu/8Y8nrbSBdDndO0Lv56g869mRgrsmZBvsoS31JqgDkf6YYtvi3g==", + "license": "Apache-2.0" + }, "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", "license": "MIT", "optional": true, "dependencies": { @@ -2735,18 +1974,18 @@ } }, "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", "license": "MIT", "dependencies": { "@types/ms": "*" } }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "license": "MIT" }, "node_modules/@types/estree-jsx": { @@ -2783,10 +2022,11 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -2810,9 +2050,9 @@ } }, "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.2.tgz", + "integrity": "sha512-5jsZFwgR5rTdKwidH9Qmat75RKwqfpKlWWB1frDkljN127mwqBu8K0PYo7/hFpF03IEJpfVPpCQDY/eDx3iHvA==", "license": "ISC" }, "node_modules/@vcarl/remark-headings": { @@ -2874,9 +2114,9 @@ } }, "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -2894,43 +2134,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/aria-hidden": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", @@ -2962,36 +2165,12 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "license": "ISC" }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ccount": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", @@ -3042,68 +2221,12 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, "node_modules/classnames": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", "license": "MIT" }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -3139,23 +2262,12 @@ ], "license": "MIT" }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/debug": { "version": "4.4.3", @@ -3201,15 +2313,6 @@ } } }, - "node_modules/dependency-graph": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-1.0.0.tgz", - "integrity": "sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -3219,15 +2322,6 @@ "node": ">=6" } }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, "node_modules/detect-node-es": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", @@ -3247,25 +2341,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/enhanced-resolve": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz", - "integrity": "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/entities": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", @@ -3310,15 +2385,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/escape-string-regexp": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", @@ -3385,57 +2451,25 @@ }, "node_modules/extend": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs-extra": { - "version": "11.3.4", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", - "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, "node_modules/get-nonce": { @@ -3454,23 +2488,17 @@ "license": "ISC" }, "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, "node_modules/hast-util-from-parse5": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", @@ -3719,18 +2747,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/is-decimal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", @@ -3750,15 +2766,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -3781,15 +2788,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -3802,292 +2800,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jiti": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", - "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" - } - }, - "node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", - "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", - "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", - "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", - "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", - "cpu": [ - "arm" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", - "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", - "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/lightningcss-wasm": { "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-wasm/-/lightningcss-wasm-1.32.0.tgz", - "integrity": "sha512-SteAkCtRuSCDYPGHKhLV/dDs5Bk+7I4QUxWxfk4xwsTI1rQk8MQyYtpGcd3NECsUGzK0q2/KqoVS+YHCqKHUTQ==", - "bundleDependencies": [ - "napi-wasm" - ], - "license": "MPL-2.0", - "dependencies": { - "napi-wasm": "^1.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-wasm/node_modules/napi-wasm": { - "version": "1.1.3", - "inBundle": true, - "license": "MIT" - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", - "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", - "cpu": [ - "x64" + "resolved": "https://registry.npmjs.org/lightningcss-wasm/-/lightningcss-wasm-1.32.0.tgz", + "integrity": "sha512-SteAkCtRuSCDYPGHKhLV/dDs5Bk+7I4QUxWxfk4xwsTI1rQk8MQyYtpGcd3NECsUGzK0q2/KqoVS+YHCqKHUTQ==", + "bundleDependencies": [ + "napi-wasm" ], "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "napi-wasm": "^1.0.1" + }, "engines": { "node": ">= 12.0.0" }, @@ -4096,17 +2819,10 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } + "node_modules/lightningcss-wasm/node_modules/napi-wasm": { + "version": "1.1.3", + "inBundle": true, + "license": "MIT" }, "node_modules/longest-streak": { "version": "3.1.0", @@ -4118,15 +2834,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, "node_modules/markdown-table": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", @@ -4291,6 +2998,23 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-mdx-expression": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", @@ -4644,6 +3368,108 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", + "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", + "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "license": "MIT", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/micromark-factory-destination": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", @@ -4687,6 +3513,33 @@ "micromark-util-types": "^2.0.0" } }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", + "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, "node_modules/micromark-factory-space": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", @@ -4888,6 +3741,31 @@ ], "license": "MIT" }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", + "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, "node_modules/micromark-util-html-tag-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", @@ -5023,33 +3901,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -5063,18 +3914,18 @@ } }, "node_modules/oniguruma-parser": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", - "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz", + "integrity": "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==", "license": "MIT" }, "node_modules/oniguruma-to-es": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.5.tgz", - "integrity": "sha512-Zjygswjpsewa0NLTsiizVuMQZbp0MDyM6lIt66OxsF21npUDlzpHi1Mgb/qhQdkb+dWFTzJmFbEWdvZgRho8eQ==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.6.tgz", + "integrity": "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==", "license": "MIT", "dependencies": { - "oniguruma-parser": "^0.12.1", + "oniguruma-parser": "^0.12.2", "regex": "^6.1.0", "regex-recursion": "^6.0.2" } @@ -5102,219 +3953,48 @@ "version": "2.0.11", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "license": "MIT" - }, - "node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "license": "MIT", - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/piscina": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.2.0.tgz", - "integrity": "sha512-DszUCKeVN/5G5QKo6jAVHL8fmKnkJvQ0ACiVgY7YGCq3TUB2oznAOayvZPIAdEThvhczkXR+qm3IHsNXpFCYfA==", - "license": "MIT", - "engines": { - "node": ">=20.x" - }, - "optionalDependencies": { - "@napi-rs/nice": "^1.0.4" - } - }, - "node_modules/postcss": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz", - "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-calc": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-10.1.1.tgz", - "integrity": "sha512-NYEsLHh8DgG/PRH2+G9BTuUdtf9ViS+vdoQ0YA5OQdGsfN4ztiwtDWNtBl9EKeqNMFnIu8IKZ0cLxEQ5r5KVMw==", - "license": "MIT", - "dependencies": { - "postcss-selector-parser": "^7.0.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12 || ^20.9 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.38" - } - }, - "node_modules/postcss-cli": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.1.tgz", - "integrity": "sha512-0UnkNPSayHKRe/tc2YGW6XnSqqOA9eqpiRMgRlV1S6HdGi16vwJBx7lviARzbV1HpQHqLLRH3o8vTcB0cLc+5g==", - "license": "MIT", - "dependencies": { - "chokidar": "^3.3.0", - "dependency-graph": "^1.0.0", - "fs-extra": "^11.0.0", - "picocolors": "^1.0.0", - "postcss-load-config": "^5.0.0", - "postcss-reporter": "^7.0.0", - "pretty-hrtime": "^1.0.3", - "read-cache": "^1.0.0", - "slash": "^5.0.0", - "tinyglobby": "^0.2.12", - "yargs": "^17.0.0" - }, - "bin": { - "postcss": "index.js" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } + "license": "MIT" }, - "node_modules/postcss-load-config": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-5.1.0.tgz", - "integrity": "sha512-G5AJ+IX0aD0dygOE0yFZQ/huFFMSNneyfp0e3/bT05a8OfPC5FUoZRPfGijUdGOJNMewJiwzcHJXFafFzeKFVA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", "license": "MIT", "dependencies": { - "lilconfig": "^3.1.1", - "yaml": "^2.4.2" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "jiti": ">=1.21.0", - "postcss": ">=8.0.9", - "tsx": "^4.8.1" + "entities": "^6.0.0" }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tsx": { - "optional": true - } + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/postcss-reporter": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.1.0.tgz", - "integrity": "sha512-/eoEylGWyy6/DOiMP5lmFRdmDKThqgn7D6hP2dXKJI/0rJSO1ADFNngZfDzxL0YAxFvws+Rtpuji1YIHj4mySA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "license": "MIT", - "dependencies": { - "picocolors": "^1.0.0", - "thenby": "^1.3.4" - }, "engines": { - "node": ">=10" + "node": ">=12" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/postcss-selector-parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", - "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "node_modules/piscina": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.2.0.tgz", + "integrity": "sha512-DszUCKeVN/5G5QKo6jAVHL8fmKnkJvQ0ACiVgY7YGCq3TUB2oznAOayvZPIAdEThvhczkXR+qm3IHsNXpFCYfA==", "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, "engines": { - "node": ">=4" + "node": ">=20.x" + }, + "optionalDependencies": { + "@napi-rs/nice": "^1.0.4" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "license": "MIT" - }, "node_modules/preact": { - "version": "10.29.1", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.1.tgz", - "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==", + "version": "10.29.4", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.4.tgz", + "integrity": "sha512-GMpwh9+NJ8tSmqwIaVyFRQkiKfBEzQ+k7r7tle4W+kaJ+7wJiB9hFz9BixAomMtenPPSBfM4bZhXozGxhf0uFQ==", "license": "MIT", "funding": { "type": "opencollective", @@ -5322,23 +4002,14 @@ } }, "node_modules/preact-render-to-string": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.6.7.tgz", - "integrity": "sha512-3XdbsX3+vn9dQW+jJI/FsI9rlkgl6dbeUpqLsChak6jp3j3auFqBCkno7VChbMFs5Q8ylBj6DrUkKRwtVN3nvw==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.7.0.tgz", + "integrity": "sha512-Z4WR8fmLMRpdYqJ9i7vrlXSsSrxVJydwrkEXHapexfARbWfGb7vGcnvNQnIzN0cXciMVOlz/XLoiMCi9gUsy9Q==", "license": "MIT", "peerDependencies": { "preact": ">=10 || >= 11.0.0-0" } }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/prism-react-renderer": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz", @@ -5349,9 +4020,9 @@ } }, "node_modules/property-information": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", - "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz", + "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", "license": "MIT", "funding": { "type": "github", @@ -5359,25 +4030,25 @@ } }, "node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", - "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", + "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", "license": "MIT", "peer": true, "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.4" + "react": "^19.2.7" } }, "node_modules/react-markdown": { @@ -5476,27 +4147,6 @@ } } }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "license": "MIT", - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, "node_modules/reading-time": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", @@ -5642,6 +4292,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", + "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-parse": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", @@ -5690,23 +4354,14 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/rolldown": { - "version": "1.0.0-rc.17", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.17.tgz", - "integrity": "sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.2.tgz", + "integrity": "sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g==", "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.127.0", - "@rolldown/pluginutils": "1.0.0-rc.17" + "@oxc-project/types": "=0.132.0", + "@rolldown/pluginutils": "^1.0.0" }, "bin": { "rolldown": "bin/cli.mjs" @@ -5715,21 +4370,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.0-rc.17", - "@rolldown/binding-darwin-arm64": "1.0.0-rc.17", - "@rolldown/binding-darwin-x64": "1.0.0-rc.17", - "@rolldown/binding-freebsd-x64": "1.0.0-rc.17", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.17", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.17", - "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.17", - "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.17", - "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.17", - "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.17", - "@rolldown/binding-linux-x64-musl": "1.0.0-rc.17", - "@rolldown/binding-openharmony-arm64": "1.0.0-rc.17", - "@rolldown/binding-wasm32-wasi": "1.0.0-rc.17", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.17", - "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.17" + "@rolldown/binding-android-arm64": "1.0.2", + "@rolldown/binding-darwin-arm64": "1.0.2", + "@rolldown/binding-darwin-x64": "1.0.2", + "@rolldown/binding-freebsd-x64": "1.0.2", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.2", + "@rolldown/binding-linux-arm64-gnu": "1.0.2", + "@rolldown/binding-linux-arm64-musl": "1.0.2", + "@rolldown/binding-linux-ppc64-gnu": "1.0.2", + "@rolldown/binding-linux-s390x-gnu": "1.0.2", + "@rolldown/binding-linux-x64-gnu": "1.0.2", + "@rolldown/binding-linux-x64-musl": "1.0.2", + "@rolldown/binding-openharmony-arm64": "1.0.2", + "@rolldown/binding-wasm32-wasi": "1.0.2", + "@rolldown/binding-win32-arm64-msvc": "1.0.2", + "@rolldown/binding-win32-x64-msvc": "1.0.2" } }, "node_modules/scheduler": { @@ -5740,9 +4395,9 @@ "peer": true }, "node_modules/semver": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", - "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -5752,73 +4407,17 @@ } }, "node_modules/shiki": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.0.2.tgz", - "integrity": "sha512-eAVKTMedR5ckPo4xne/PjYQYrU3qx78gtJZ+sHlXEg5IHhhoQhMfZVzetTYuaJS0L2Ef3AcCRzCHV8T0WI6nIQ==", - "license": "MIT", - "dependencies": { - "@shikijs/core": "4.0.2", - "@shikijs/engine-javascript": "4.0.2", - "@shikijs/engine-oniguruma": "4.0.2", - "@shikijs/langs": "4.0.2", - "@shikijs/themes": "4.0.2", - "@shikijs/types": "4.0.2", - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/shiki/node_modules/@shikijs/core": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.0.2.tgz", - "integrity": "sha512-hxT0YF4ExEqB8G/qFdtJvpmHXBYJ2lWW7qTHDarVkIudPFE6iCIrqdgWxGn5s+ppkGXI0aEGlibI0PAyzP3zlw==", - "license": "MIT", - "dependencies": { - "@shikijs/primitive": "4.0.2", - "@shikijs/types": "4.0.2", - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4", - "hast-util-to-html": "^9.0.5" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/shiki/node_modules/@shikijs/engine-javascript": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.0.2.tgz", - "integrity": "sha512-7PW0Nm49DcoUIQEXlJhNNBHyoGMjalRETTCcjMqEaMoJRLljy1Bi/EGV3/qLBgLKQejdspiiYuHGQW6dX94Nag==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "4.0.2", - "@shikijs/vscode-textmate": "^10.0.2", - "oniguruma-to-es": "^4.3.4" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/shiki/node_modules/@shikijs/engine-oniguruma": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.0.2.tgz", - "integrity": "sha512-UpCB9Y2sUKlS9z8juFSKz7ZtysmeXCgnRF0dlhXBkmQnek7lAToPte8DkxmEYGNTMii72zU/lyXiCB6StuZeJg==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "4.0.2", - "@shikijs/vscode-textmate": "^10.0.2" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/shiki/node_modules/@shikijs/types": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.0.2.tgz", - "integrity": "sha512-qzbeRooUTPnLE+sHD/Z8DStmaDgnbbc/pMrU203950aRqjX/6AFHeDYT+j00y2lPdz0ywJKx7o/7qnqTivtlXg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.3.1.tgz", + "integrity": "sha512-oR+qDVi2OjX1tmDpyv+3KviX01KzO6Af+0NNnKnsp9491UEGz2YpxTuJboS/6VhYpTdqzmuJBuiTlrAWWJAssw==", "license": "MIT", "dependencies": { + "@shikijs/core": "4.3.1", + "@shikijs/engine-javascript": "4.3.1", + "@shikijs/engine-oniguruma": "4.3.1", + "@shikijs/langs": "4.3.1", + "@shikijs/themes": "4.3.1", + "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" }, @@ -5826,18 +4425,6 @@ "node": ">=20" } }, - "node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/source-map": { "version": "0.7.6", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", @@ -5847,15 +4434,6 @@ "node": ">= 12" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/space-separated-tokens": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", @@ -5866,20 +4444,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/stringify-entities": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", @@ -5894,18 +4458,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/style-to-js": { "version": "1.1.21", "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", @@ -5924,31 +4476,6 @@ "inline-style-parser": "0.2.7" } }, - "node_modules/tailwindcss": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", - "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", - "license": "MIT" - }, - "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/thenby": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", - "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==", - "license": "Apache-2.0" - }, "node_modules/throttleit": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-2.1.0.tgz", @@ -5962,13 +4489,13 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "license": "MIT", "dependencies": { "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -5977,47 +4504,6 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -6054,22 +4540,22 @@ } }, "node_modules/twoslash": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/twoslash/-/twoslash-0.3.6.tgz", - "integrity": "sha512-VuI5OKl+MaUO9UIW3rXKoPgHI3X40ZgB/j12VY6h98Ae1mCBihjPvhOPeJWlxCYcmSbmeZt5ZKkK0dsVtp+6pA==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/twoslash/-/twoslash-0.3.9.tgz", + "integrity": "sha512-rDclk+OtzuTX+tnea7DYLCkqGQ3eP0IyfD+kzUJ7t46X/NzlaxwrhecmEBNuSCuEn3V+n1PhcjUUQQ7gUJzX5Q==", "license": "MIT", "dependencies": { - "@typescript/vfs": "^1.6.2", - "twoslash-protocol": "0.3.6" + "@typescript/vfs": "^1.6.4", + "twoslash-protocol": "0.3.9" }, "peerDependencies": { - "typescript": "^5.5.0" + "typescript": "^5.5.0 || ^6.0.0" } }, "node_modules/twoslash-protocol": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/twoslash-protocol/-/twoslash-protocol-0.3.6.tgz", - "integrity": "sha512-FHGsJ9Q+EsNr5bEbgG3hnbkvEBdW5STgPU824AHUjB4kw0Dn4p8tABT7Ncg1Ie6V0+mDg3Qpy41VafZXcQhWMA==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/twoslash-protocol/-/twoslash-protocol-0.3.9.tgz", + "integrity": "sha512-9/iwp+CXOnjFMPQuPL5PkuRbZnDoNpBvtJCLs9t8kDYkL3YHujbvnHfZA1i5fApDftVEdBw+T/4F+dH5kIzpYQ==", "license": "MIT" }, "node_modules/typescript": { @@ -6086,9 +4572,9 @@ } }, "node_modules/undici": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz", - "integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==", + "version": "6.27.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.27.0.tgz", + "integrity": "sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==", "license": "MIT", "engines": { "node": ">=18.17" @@ -6253,15 +4739,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/use-callback-ref": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", @@ -6305,21 +4782,6 @@ } } }, - "node_modules/use-sync-external-store": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", - "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT" - }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", @@ -6372,32 +4834,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/yaml": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", @@ -6413,33 +4849,6 @@ "url": "https://github.com/sponsors/eemeli" } }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/tools/doc/package.json b/tools/doc/package.json index 42e9916b908571..9d59db21ef0e1a 100644 --- a/tools/doc/package.json +++ b/tools/doc/package.json @@ -2,6 +2,6 @@ "name": "doc", "private": true, "dependencies": { - "@node-core/doc-kit": "1.3.9" + "@node-core/doc-kit": "1.4.1" } } diff --git a/tools/eslint/package-lock.json b/tools/eslint/package-lock.json index 47edf403673e5d..de8e6862cdb1b6 100644 --- a/tools/eslint/package-lock.json +++ b/tools/eslint/package-lock.json @@ -8,27 +8,27 @@ "name": "eslint-tools", "version": "0.0.0", "dependencies": { - "@babel/core": "^8.0.0-rc.6", - "@babel/eslint-parser": "^8.0.0-rc.6", - "@babel/plugin-syntax-import-defer": "^8.0.0-rc.6", - "@babel/plugin-syntax-import-source": "^8.0.0-rc.6", + "@babel/core": "^8.0.1", + "@babel/eslint-parser": "^8.0.1", + "@babel/plugin-syntax-import-defer": "^8.0.1", + "@babel/plugin-syntax-import-source": "^8.0.1", "@eslint/js": "^10.0.1", "@eslint/markdown": "^8.0.2", "@stylistic/eslint-plugin": "^5.10.0", - "eslint": "^10.4.0", + "eslint": "^10.5.0", "eslint-formatter-tap": "^9.0.1", - "eslint-plugin-jsdoc": "^63.0.0", - "eslint-plugin-regexp": "^3.1.0", - "globals": "^17.6.0" + "eslint-plugin-jsdoc": "^63.0.9", + "eslint-plugin-regexp": "^3.1.1", + "globals": "^17.7.0" } }, "node_modules/@babel/code-frame": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-8.0.0-rc.6.tgz", - "integrity": "sha512-Ru0EdYEptXbJGAGDMsenx+RcelHazuj8spqi7l0geXEPXv0X7qVisqWX+2pMaEZsWhS3Q6Um7oITwhnLe0cHJQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-8.0.0.tgz", + "integrity": "sha512-dYYg153EyN2Ekbqw2zAsbd6/JR+9N2SEoC7YV2GyyqMM7x9bLDTjBD6XBhSMLH0wtIVyJj03jWNriQhaN+eoCw==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^8.0.0-rc.6", + "@babel/helper-validator-identifier": "^8.0.0", "js-tokens": "^10.0.0" }, "engines": { @@ -36,31 +36,31 @@ } }, "node_modules/@babel/compat-data": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-8.0.0-rc.6.tgz", - "integrity": "sha512-9ikfbIp7PCtV/mo8NYrzag1TYInVJAKLwpSoA28+3Bl5z1KVYt5ZGvBZD57yJlf/0HsCntlTlHHodu+eMpUffQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-8.0.0.tgz", + "integrity": "sha512-DOjnob/cXOUgDOozCDeq/aK2p5y8dUIVdf6tNhEV1HQRd6I8aQ4f4fbtHRVEvb6lP3BGomrKHiS8ICAASSVQSw==", "license": "MIT", "engines": { "node": "^22.18.0 || >=24.11.0" } }, "node_modules/@babel/core": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-8.0.0-rc.6.tgz", - "integrity": "sha512-89SVbTu7p+M/W052SFC7R5QuQYgypfuO6HmBBbhA/Kzl6gME8Ly2QrVpIegvTxmcQKOzAPIxiEIfNk+Jxd26mw==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^8.0.0-rc.6", - "@babel/generator": "^8.0.0-rc.6", - "@babel/helper-compilation-targets": "^8.0.0-rc.6", - "@babel/helpers": "^8.0.0-rc.6", - "@babel/parser": "^8.0.0-rc.6", - "@babel/template": "^8.0.0-rc.6", - "@babel/traverse": "^8.0.0-rc.6", - "@babel/types": "^8.0.0-rc.6", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-8.0.1.tgz", + "integrity": "sha512-5FgxM4dLQpMJHSiVATk8foW263dVHQHBVpXYiimNECVWG01f4nFyEbQixeT6Mwvg7TayREJ2gpKl3o2RoMdnqw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^8.0.0", + "@babel/generator": "^8.0.0", + "@babel/helper-compilation-targets": "^8.0.0", + "@babel/helpers": "^8.0.0", + "@babel/parser": "^8.0.0", + "@babel/template": "^8.0.0", + "@babel/traverse": "^8.0.0", + "@babel/types": "^8.0.0", "@types/gensync": "^1.0.5", "convert-source-map": "^2.0.0", - "find-up-simple": "^1.0.1", + "empathic": "^2.0.1", "gensync": "^1.0.0-beta.2", "import-meta-resolve": "^4.2.0", "json5": "^2.2.3", @@ -76,9 +76,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-8.0.0-rc.6.tgz", - "integrity": "sha512-qVHD7K5PyUXj57bsJWbyT5V9JtOX/4dtX9QSQpqGfBG4xiVE/mrCYCT25Ih+wHvISR98Lctl9BtvEUtGyYsrvA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-8.0.1.tgz", + "integrity": "sha512-2javO8pAQv/ld6sS6OcxoLAlzZEZy+xm99bnoAfMhzKSumKhdF5wylpbZB7XTorWr3KLPtx5K95eduJPOy1mzA==", "license": "MIT", "dependencies": { "eslint-scope": "^9.1.0", @@ -89,18 +89,18 @@ "node": "^22.18.0 || >=24.11.0" }, "peerDependencies": { - "@babel/core": "^8.0.0-rc.6", + "@babel/core": "^8.0.0", "eslint": "^9.0.0 || ^10.0.0" } }, "node_modules/@babel/generator": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-8.0.0-rc.6.tgz", - "integrity": "sha512-6mIzgVK8DgEzvIapoQwhXTMnnkuE4STQmVv9H03i/tZ2ml8oev3TRvZJgTenK2Bsq0YWNtzOrFdTyNzCMFtjJQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-8.0.0.tgz", + "integrity": "sha512-NT9NrVwJsbSV6Y2FSstWa71EETOnzrjkL5/wX3D2mYHtKM+qvqB1DvR4D0Setb/gDBsHzRICifwEWMO8CnTF6g==", "license": "MIT", "dependencies": { - "@babel/parser": "^8.0.0-rc.6", - "@babel/types": "^8.0.0-rc.6", + "@babel/parser": "^8.0.0", + "@babel/types": "^8.0.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "@types/jsesc": "^2.5.0", @@ -111,15 +111,15 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-8.0.0-rc.6.tgz", - "integrity": "sha512-jqQD45/yUSy63U8zs9hE5FMXS8J1TLAI/NTMx76C6xWO021e13gJACQvuGmEF7syloC39LkkKwhqtAbMku1rwg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-8.0.0.tgz", + "integrity": "sha512-JwculLABZvyPvyLBpwU/E/IbH2uM3mnxNtIJpxnIfb24y1PrdVxK5Dqjle4DpgqpGRnwgC7G8IkzPdSXZrO1Ew==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^8.0.0-rc.6", - "@babel/helper-validator-option": "^8.0.0-rc.6", + "@babel/compat-data": "^8.0.0", + "@babel/helper-validator-option": "^8.0.0", "browserslist": "^4.24.0", - "lru-cache": "^7.14.1", + "lru-cache": "^11.0.0", "semver": "^7.7.3" }, "engines": { @@ -127,73 +127,73 @@ } }, "node_modules/@babel/helper-globals": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-8.0.0-rc.6.tgz", - "integrity": "sha512-ZF5FsxE4y7Eb6DiEbsLW3Gz3e73U/Uq3/ZotWf/moxv0DnZziXSMnW/tcXJF8b1mQE8XJnwPNSQOksKcKTz8kQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-8.0.0.tgz", + "integrity": "sha512-lLozHOM6sWWlxNo8CYqHy4MBZeTvHXNgVPBfPOGsjPKUzHC2Az9QwB6gxdQmpwHl6GlQtbGgS+lj5887guDiLw==", "license": "MIT", "engines": { "node": "^22.18.0 || >=24.11.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-8.0.0-rc.6.tgz", - "integrity": "sha512-sLAjvuIcjzUQJR+CoHwU0JA4i706o71bCJtF+W9sc4KuHK3LCIJCjbKRuzbVn1eubUc66uAEZdBNWSqhLpwp2g==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-8.0.1.tgz", + "integrity": "sha512-3PKFgjTyPlhFhorfP+SjKQxLViIL++zWjFOO4hGriYU+Bsm983DxEM1JmDRJVWXV0O9npu+xXRqz7Pbd3mh70g==", "license": "MIT", "engines": { "node": "^22.18.0 || >=24.11.0" }, "peerDependencies": { - "@babel/core": "^8.0.0-rc.6" + "@babel/core": "^8.0.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-8.0.0-rc.6.tgz", - "integrity": "sha512-BCkFy+zN6kXQed3YOT7aJl93NfDSzQc3pBfsvTVPs9gU9X3V0aefEF5kwBT0E+mDWH9QgKaZstYUQN9VdQZT4g==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-8.0.0.tgz", + "integrity": "sha512-6mJgmFFFIIO82vvoLt9XtRC7/TkzXfts1t/SpRX4IHSzMgqoPYCWesVu1udUPUWioAE/2fcG6WuI8zrkE1gwrg==", "license": "MIT", "engines": { "node": "^22.18.0 || >=24.11.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.0-rc.6.tgz", - "integrity": "sha512-nVJ+1JcCgntv8d78rRo++o2wuODT0Irknx2BF8Np4Ft2CRgjLqIs4qzSZ8b66yGbBdMWGmZBO9WEZv1hhNiSpg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.2.tgz", + "integrity": "sha512-9Fr9QeyCAyi1BR1jKZ6uYQ24EIhQUx5ReHfQU7drOE+TPOb+w11/dsqLkMOT2U29OdCT71XajrOT8xDc1C7orA==", "license": "MIT", "engines": { "node": "^22.18.0 || >=24.11.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-8.0.0-rc.6.tgz", - "integrity": "sha512-uonhzCIL2Vf0xA10g5C0zD5thR7a6XxOSwZAzYfyl8n2zEev5bAB9J4b2oZ7u5YkyqdONfkptl2DesvW2P56Kg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-8.0.0.tgz", + "integrity": "sha512-U4Dybxh4WESWHt5XhBeExi4DrY0/DNK1aHpQbsrQXCUbFHuMweT0TpLEWKvaraV2Y6fS+ZXunsZ8zIuZIgvF2Q==", "license": "MIT", "engines": { "node": "^22.18.0 || >=24.11.0" } }, "node_modules/@babel/helpers": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-8.0.0-rc.6.tgz", - "integrity": "sha512-kTTqnw+Ubp1/WGXiIpDcl+WYVGTUVGjrQKswGI9VOamk7eWVf5ZYOcCB+o1UxaaHjs/L+QK7IRPlyP7vg579OQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-8.0.0.tgz", + "integrity": "sha512-wfbi91pM3py96oIiJEz7qIpyXDytgr9zQC1HEWwlGNVRAEmItuU/0a41ZUKu1sJGyhhOIpc4t5vk4PYzt8wpsg==", "license": "MIT", "dependencies": { - "@babel/template": "^8.0.0-rc.6", - "@babel/types": "^8.0.0-rc.6" + "@babel/template": "^8.0.0", + "@babel/types": "^8.0.0" }, "engines": { "node": "^22.18.0 || >=24.11.0" } }, "node_modules/@babel/parser": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.0-rc.6.tgz", - "integrity": "sha512-rOS8IpdO7mQELkTPlCsTgPejO0bFuZdEDCGQJouYbYf9e1FLTym7Fei2pEjq8q7MWbX0ravcd7QQYKs1TxOuog==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.0.tgz", + "integrity": "sha512-aLxAE+imI9bCcyaPrUDjBv3uSkWieifjLe0kuFOZF0zli0L6GCsTmsePnTr55adbIAgYz2zhN1vnFimCBUYcRQ==", "license": "MIT", "dependencies": { - "@babel/types": "^8.0.0-rc.6" + "@babel/types": "^8.0.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -203,61 +203,61 @@ } }, "node_modules/@babel/plugin-syntax-import-defer": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-defer/-/plugin-syntax-import-defer-8.0.0-rc.6.tgz", - "integrity": "sha512-VUzalsGv2W89DJbKyXy8mP7uhsXFZoE4td5iDndOGART94WLXvnKuF72ndJFFYE8t4eRS0zX5PZFmMGBVGmIUw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-defer/-/plugin-syntax-import-defer-8.0.1.tgz", + "integrity": "sha512-fRveH6xm797m3R8dIP0JlW/pGVsWeBPArVoh0+QG3biW8o66oukSKtTkjGRVCwTTdfspra/XU0Jq482mECzB+g==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^8.0.0-rc.6" + "@babel/helper-plugin-utils": "^8.0.1" }, "engines": { "node": "^22.18.0 || >=24.11.0" }, "peerDependencies": { - "@babel/core": "^8.0.0-rc.6" + "@babel/core": "^8.0.0" } }, "node_modules/@babel/plugin-syntax-import-source": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-source/-/plugin-syntax-import-source-8.0.0-rc.6.tgz", - "integrity": "sha512-kvUkjNZhBdZleJjJ60gH5QGHD2ttZBzEZACPnqaAMraDdPz0bERCWNyptdiCZFTOBo6LRhD9QtMAzdZK3jvPZQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-source/-/plugin-syntax-import-source-8.0.1.tgz", + "integrity": "sha512-qtgn6T5XL3GxNq+7MPj/12D8lCnVHBJQVzRYqHbgZhu+Y5XEYeEM6h9FlMinGkrbS5SMH/b6oTX7ewXtfcMR8A==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^8.0.0-rc.6" + "@babel/helper-plugin-utils": "^8.0.1" }, "engines": { "node": "^22.18.0 || >=24.11.0" }, "peerDependencies": { - "@babel/core": "^8.0.0-rc.6" + "@babel/core": "^8.0.0" } }, "node_modules/@babel/template": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-8.0.0-rc.6.tgz", - "integrity": "sha512-CZFjZblLiIUEFghbB3sKs3rpYrwo65rLIklw/gNpwBm326cU6TH/xzvJZlZ+H9HpDi00eDXqNJR8CtEKW3oc/A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-8.0.0.tgz", + "integrity": "sha512-eAD0QW/AlbamBbw0FeGiwasbCVPq5ncW0HNVyLP3B9czqLyh4gvw+5JTSNt6le9+ziAU7mqDZsKTHf3jTb4chQ==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^8.0.0-rc.6", - "@babel/parser": "^8.0.0-rc.6", - "@babel/types": "^8.0.0-rc.6" + "@babel/code-frame": "^8.0.0", + "@babel/parser": "^8.0.0", + "@babel/types": "^8.0.0" }, "engines": { "node": "^22.18.0 || >=24.11.0" } }, "node_modules/@babel/traverse": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-8.0.0-rc.6.tgz", - "integrity": "sha512-/txuBViGaE9gpM8MSGShru1O2Bzp3zb3m/XKZNUsNv2SyNn++lKDDIWkiIQ/345j2FBy7CHiYTZuKhewHWyefw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-8.0.0.tgz", + "integrity": "sha512-bxTj/W2VclGE6CctlfQOpxg8MPDzXArRqkOBePw8EHfebcjF7fETWSS3BriEECo+UiU/Yblq+xUtSImFu7cTbw==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^8.0.0-rc.6", - "@babel/generator": "^8.0.0-rc.6", - "@babel/helper-globals": "^8.0.0-rc.6", - "@babel/parser": "^8.0.0-rc.6", - "@babel/template": "^8.0.0-rc.6", - "@babel/types": "^8.0.0-rc.6", + "@babel/code-frame": "^8.0.0", + "@babel/generator": "^8.0.0", + "@babel/helper-globals": "^8.0.0", + "@babel/parser": "^8.0.0", + "@babel/template": "^8.0.0", + "@babel/types": "^8.0.0", "obug": "^2.1.1" }, "engines": { @@ -265,27 +265,27 @@ } }, "node_modules/@babel/types": { - "version": "8.0.0-rc.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.0-rc.6.tgz", - "integrity": "sha512-p7/ABylAYlexb31wtRdIfH9L9A0Z2T/9H6zAqzqndkY2PLkvNNc580wGhp/gGKN4Sp9sQvSkhc6Oga8/O+wTyw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.0.tgz", + "integrity": "sha512-K8ponJDxBwDHigkeFqaqT5wLGl4bTlwMafR8k7b5CPxr6Ww+UG9ls8Yx6Tcpboxu97eeGVEEyKcHmEyOwN1vSw==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^8.0.0-rc.6", - "@babel/helper-validator-identifier": "^8.0.0-rc.6" + "@babel/helper-string-parser": "^8.0.0", + "@babel/helper-validator-identifier": "^8.0.0" }, "engines": { "node": "^22.18.0 || >=24.11.0" } }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.86.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.86.0.tgz", - "integrity": "sha512-ukZmRQ81WiTpDWO6D/cTBM7XbrNtutHKvAVnZN/8pldAwLoJArGOvkNyxPTBGsPjsoaQBJxlH+tE2TNA/92Qgw==", + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.87.0.tgz", + "integrity": "sha512-mFXZloZMzuJZXSHUmAFu/pXTk0ZJTJBluuAkrvbzidpTN8W6F2bpRFuedSH+85kbdlRLJqc+gfN+kD3JOLJK5g==", "license": "MIT", "dependencies": { - "@types/estree": "^1.0.8", - "@typescript-eslint/types": "^8.58.0", - "comment-parser": "1.4.6", + "@types/estree": "^1.0.9", + "@typescript-eslint/types": "^8.59.4", + "comment-parser": "1.4.7", "esquery": "^1.7.0", "jsdoc-type-pratt-parser": "~7.2.0" }, @@ -589,9 +589,9 @@ "license": "MIT" }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "license": "MIT" }, "node_modules/@types/gensync": { @@ -649,9 +649,9 @@ "license": "MIT" }, "node_modules/@typescript-eslint/types": { - "version": "8.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.0.tgz", - "integrity": "sha512-nLzdsT1gdOgFxxxwrlNVUBzSNBEEHJ86bblmk4QAS6stfig7rcJzWKqCyxFy3YRRHXDWEkb2NralA1nOYkkm/A==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.62.1.tgz", + "integrity": "sha512-ooCzJFaf+Hg+uG6fA3NRFGuFjlfNlDhBthbv4ZPU/0elCAFUfnyXUvf/WOpHz/jYwSmvU2GkR2LtyUfy1AxZ1Q==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -723,9 +723,9 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.10.33", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.33.tgz", - "integrity": "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==", + "version": "2.10.40", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.40.tgz", + "integrity": "sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw==", "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.cjs" @@ -747,9 +747,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "version": "4.28.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz", + "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==", "funding": [ { "type": "opencollective", @@ -766,10 +766,10 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", + "baseline-browser-mapping": "^2.10.38", + "caniuse-lite": "^1.0.30001799", + "electron-to-chromium": "^1.5.376", + "node-releases": "^2.0.48", "update-browserslist-db": "^1.2.3" }, "bin": { @@ -780,9 +780,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001793", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", - "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "version": "1.0.30001800", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001800.tgz", + "integrity": "sha512-MMHtuAz9Ys840zAY5F4k6fV5GaivZ9sPk+nz0mY+GYVzRBnYkN0mpqkSR92oWRQ19yQWo4HvBV/FnC16AJX8MA==", "funding": [ { "type": "opencollective", @@ -829,9 +829,9 @@ } }, "node_modules/comment-parser": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.6.tgz", - "integrity": "sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==", + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.7.tgz", + "integrity": "sha512-0h+uSNtQGW3D98eQt3jJ8L06Fves8hncB4V/PKdw/Qb8Hnk19VaKuTr55UNRYiSoVa7WwrFls+rh3ux9agmkeQ==", "license": "MIT", "engines": { "node": ">= 12.0.0" @@ -916,11 +916,20 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.366", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.366.tgz", - "integrity": "sha512-OlRuhb688YTCzzU3gXPLn6nGyd+F+53INE1qaKKlu6kETErE8FYsyDh0XqXEU+uBRn0MpCzz2vfNwORhkap8qg==", + "version": "1.5.383", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.383.tgz", + "integrity": "sha512-I2484/KkAvl8lm9VyjH2JnbOIV0d/UCqT7gbzs6l+o6Vmn9wgB66uVcKX+Vk6HrXtY6fbWTOEXuv8waDTuFNCw==", "license": "ISC" }, + "node_modules/empathic": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.1.tgz", + "integrity": "sha512-YGRs8knHhKHVShLkFET/rWAU8kmHbOV5LwN938RHI0pljAJ1Gf6SzXsSmRaEzcXTtOOmVqJ5+WtQPL5uigY50Q==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -943,17 +952,20 @@ } }, "node_modules/eslint": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.4.0.tgz", - "integrity": "sha512-loXy6bWOoP3EP6JA7jo6p5jMpBJmHmsNZM5SFRHLdh1MGOPurMnNBj4ZlAbaqUAaQWbCr7jHV4P7gzAyryZWkQ==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.5.0.tgz", + "integrity": "sha512-1y+7C+vi12bUK1IpZeaV3gsH9fHLBmPvYmPx42pvT/E9yG0IC8g3PUZZgp0+JLJl7ZDK0flc2gc+Aw9dpCvIsQ==", "license": "MIT", + "workspaces": [ + "packages/*" + ], "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.6.0", "@eslint/core": "^1.2.1", - "@eslint/plugin-kit": "^0.7.1", + "@eslint/plugin-kit": "^0.7.2", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -1010,23 +1022,23 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "63.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-63.0.0.tgz", - "integrity": "sha512-eDHuVGyZydr4BKgjXouU7bsn5qaqUlObXBSWRJk3vXcQgXVFnrwWIqpP7uBhRX9NQpk6NIIFyRc6F6omZNi/8g==", + "version": "63.0.9", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-63.0.9.tgz", + "integrity": "sha512-SJskF1zzPPRVfsmJyr/PqUXcpjA7o5Y0YnEoLBMDQlQWhELbYMRvK/8Fzlvh5XwEwJW8glAtKGKucaL0WGPMkw==", "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.86.0", + "@es-joy/jsdoccomment": "~0.87.0", "@es-joy/resolve.exports": "1.2.0", "are-docs-informative": "^0.0.2", - "comment-parser": "1.4.6", + "comment-parser": "1.4.7", "debug": "^4.4.3", "escape-string-regexp": "^4.0.0", "espree": "^11.2.0", "esquery": "^1.7.0", "html-entities": "^2.6.0", - "object-deep-merge": "^2.0.0", + "object-deep-merge": "^2.0.1", "parse-imports-exports": "^0.2.4", - "semver": "^7.8.0", + "semver": "^7.8.2", "spdx-expression-parse": "^4.0.0", "to-valid-identifier": "^1.0.0" }, @@ -1055,9 +1067,9 @@ } }, "node_modules/eslint-plugin-regexp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-3.1.0.tgz", - "integrity": "sha512-qGXIC3DIKZHcK1H9A9+Byz9gmndY6TTSRkSMTZpNXdyCw2ObSehRgccJv35n9AdUakEjQp5VFNLas6BMXizCZg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-3.1.1.tgz", + "integrity": "sha512-MxR5nqoQCtVWmJwia0D2+NlXX1xzdpkslsVOZLEYQ4PQWEaL65PCZXURxaBc3lPnkNFpNxzMIRmYVxdl8giXRA==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -1252,18 +1264,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-up-simple": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", - "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/flat-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", @@ -1319,9 +1319,9 @@ } }, "node_modules/globals": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", - "integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==", + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.7.0.tgz", + "integrity": "sha512-Czmyns5dUsq4seFBR/Kdydhmo8y9kC79hiSkPn0YcGtNnYWnrgt0vjrSjx9tspoDGWm2CMarffRuLjM4xUz8xg==", "license": "MIT", "engines": { "node": ">=18" @@ -1544,12 +1544,12 @@ } }, "node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "license": "ISC", + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=12" + "node": "20 || >=22" } }, "node_modules/markdown-table": { @@ -2438,29 +2438,32 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.47", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz", - "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==", + "version": "2.0.50", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz", + "integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/object-deep-merge": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/object-deep-merge/-/object-deep-merge-2.0.0.tgz", - "integrity": "sha512-3DC3UMpeffLTHiuXSy/UG4NOIYTLlY9u3V82+djSCLYClWobZiS4ivYzpIUWrRY/nfsJ8cWsKyG3QfyLePmhvg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object-deep-merge/-/object-deep-merge-2.0.1.tgz", + "integrity": "sha512-aKttDKcU3pyZqKcCkDhsMn70WmZFG2JGDQLP9EcLyTSIFQRCPWLAmBZRLJnrVUrhPG1jETEEbfdgbNtJf1LyMg==", "license": "MIT" }, "node_modules/obug": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", - "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.3.tgz", + "integrity": "sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==", "funding": [ "https://github.com/sponsors/sxzz", "https://opencollective.com/debug" ], - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } }, "node_modules/optionator": { "version": "0.9.4", @@ -2630,9 +2633,9 @@ } }, "node_modules/semver": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", - "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "license": "ISC", "bin": { "semver": "bin/semver.js" diff --git a/tools/eslint/package.json b/tools/eslint/package.json index 0002933967b711..3199c2bb7b175a 100644 --- a/tools/eslint/package.json +++ b/tools/eslint/package.json @@ -3,17 +3,17 @@ "version": "0.0.0", "private": true, "dependencies": { - "@babel/core": "^8.0.0-rc.6", - "@babel/eslint-parser": "^8.0.0-rc.6", - "@babel/plugin-syntax-import-defer": "^8.0.0-rc.6", - "@babel/plugin-syntax-import-source": "^8.0.0-rc.6", + "@babel/core": "^8.0.1", + "@babel/eslint-parser": "^8.0.1", + "@babel/plugin-syntax-import-defer": "^8.0.1", + "@babel/plugin-syntax-import-source": "^8.0.1", "@eslint/js": "^10.0.1", "@eslint/markdown": "^8.0.2", "@stylistic/eslint-plugin": "^5.10.0", - "eslint": "^10.4.0", + "eslint": "^10.5.0", "eslint-formatter-tap": "^9.0.1", - "eslint-plugin-jsdoc": "^63.0.0", - "eslint-plugin-regexp": "^3.1.0", - "globals": "^17.6.0" + "eslint-plugin-jsdoc": "^63.0.9", + "eslint-plugin-regexp": "^3.1.1", + "globals": "^17.7.0" } } diff --git a/tools/nix/benchmarkTools.nix b/tools/nix/benchmarkTools.nix index 62c744a552b7d1..7c37c423c2530a 100644 --- a/tools/nix/benchmarkTools.nix +++ b/tools/nix/benchmarkTools.nix @@ -1,9 +1,11 @@ { pkgs ? import ./pkgs.nix { }, + withHttpBenchmarkDeps ? true, }: [ pkgs.R pkgs.rPackages.ggplot2 pkgs.rPackages.plyr - pkgs.wrk ] +++ pkgs.lib.optional withHttpBenchmarkDeps pkgs.wrk +++ pkgs.lib.optional pkgs.stdenv.buildPlatform.isLinux pkgs.glibcLocales diff --git a/tools/v8_gypfiles/v8.gyp b/tools/v8_gypfiles/v8.gyp index 945aa0aa501df1..193b8aebdd28f1 100644 --- a/tools/v8_gypfiles/v8.gyp +++ b/tools/v8_gypfiles/v8.gyp @@ -149,6 +149,7 @@ '<@(torque_outputs_inc)', ], 'action': [ + '<@(emulator)', '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)torque<(EXECUTABLE_SUFFIX)', '-o', '<(SHARED_INTERMEDIATE_DIR)/torque-generated', '-v8-root', '<(V8_ROOT)', @@ -269,6 +270,7 @@ 'action': [ '<(python)', '<(V8_ROOT)/tools/run.py', + '<@(emulator)', '<@(_inputs)', '<@(_outputs)', ], @@ -470,6 +472,7 @@ }], ], 'action': [ + '<@(emulator)', '>@(_inputs)', '>@(mksnapshot_flags)', ], @@ -668,6 +671,11 @@ '; + type KeyFormatDER = 0; + type KeyFormatPEM = 1; + type KeyFormatJWK = 2; + type KeyFormatRawPublic = 3; + type KeyFormatRawPrivate = 4; + type KeyFormatRawSeed = 5; + type PublicKeyFormat = + KeyFormatDER | KeyFormatPEM | KeyFormatJWK | KeyFormatRawPublic | undefined; + type PrivateKeyFormat = + KeyFormatDER | KeyFormatPEM | KeyFormatJWK | + KeyFormatRawPrivate | KeyFormatRawSeed | undefined; + type KeyFormat = PublicKeyFormat | PrivateKeyFormat; + type KeyEncoding = string | number | null | undefined; + type KeyPassphrase = ByteSource | null | undefined; + type NamedCurve = string | null | undefined; + type PreparedAsymmetricKeyData = KeyObjectHandle | ByteSource | JwkKey; + type PreparedSecretKeyData = KeyObjectHandle | ByteSource; + type CryptoJobAsyncMode = 0; + type CryptoJobSyncMode = 1; + type CryptoJobWebCryptoMode = 2; + type CryptoJobRegularMode = CryptoJobAsyncMode | CryptoJobSyncMode; + type CryptoJobMode = CryptoJobRegularMode | CryptoJobWebCryptoMode; + type CipherJobModeEncrypt = 0; + type CipherJobModeDecrypt = 1; + type CipherJobMode = CipherJobModeEncrypt | CipherJobModeDecrypt; + type SignJobModeSign = 0; + type SignJobModeVerify = 1; + type SignJobMode = SignJobModeSign | SignJobModeVerify; + type SignJobResult = + M extends SignJobModeSign ? ArrayBuffer : boolean; + type MacJobSignatureArgs = + M extends SignJobModeVerify ? [signature: ByteSource] : [signature?: undefined]; + type SignJobSignatureArgs = + M extends SignJobModeVerify ? [signature: ByteSource] : [signature?: undefined]; + type KeyVariant = number; + type KeyPairEncodingArgs< + PublicFormat extends PublicKeyFormat = undefined, + PrivateFormat extends PrivateKeyFormat = undefined, + > = [ + publicFormat?: PublicFormat, + publicType?: KeyEncoding, + privateFormat?: PrivateFormat, + privateType?: KeyEncoding, + cipher?: string | null | undefined, + passphrase?: KeyPassphrase, + ]; + type CryptoJobResult = + [error: undefined, result: T] | + [error: Error, result: undefined]; + + interface CryptoJobAsync { + ondone?: (error: Error | undefined, result: T | undefined) => void; + run(): void; + getAsyncId?(): number; + } + + interface CryptoJobSync { + run(): CryptoJobResult; + getAsyncId?(): number; + } + + interface CryptoJobRegular { + ondone?: (error: Error | undefined, result: T | undefined) => void; + run(): CryptoJobResult; + getAsyncId?(): number; + } + + interface CryptoJobWebCrypto { + run(): Promise; + } + + type CryptoJob = CryptoJobRegular | CryptoJobWebCrypto; + type CryptoJobForMode = + [M] extends [CryptoJobWebCryptoMode] ? CryptoJobWebCrypto : + [M] extends [CryptoJobSyncMode] ? CryptoJobSync : + [M] extends [CryptoJobAsyncMode] ? CryptoJobAsync : + [M] extends [CryptoJobRegularMode] ? CryptoJobRegular : + CryptoJob; + + type GeneratedPublicKey = + Format extends undefined ? KeyObjectHandle : + Format extends KeyFormatPEM ? string : + Format extends KeyFormatJWK ? JwkKey : + Buffer; + type GeneratedPrivateKey = + Format extends undefined ? KeyObjectHandle : + Format extends KeyFormatPEM ? string : + Format extends KeyFormatJWK ? JwkKey : + Buffer; + type GeneratedKey = GeneratedPublicKey | GeneratedPrivateKey; + type GeneratedKeyPair< + PublicFormat extends PublicKeyFormat = PublicKeyFormat, + PrivateFormat extends PrivateKeyFormat = PrivateKeyFormat, + > = [ + publicKey: GeneratedPublicKey, + privateKey: GeneratedPrivateKey, + ]; + interface CryptoKey { + readonly type: 'secret' | 'public' | 'private'; + readonly extractable: boolean; + readonly algorithm: object; + readonly usages: string[]; + } + interface CryptoKeyConstructor { + readonly prototype: CryptoKey; + new(): CryptoKey; + } + interface InternalCryptoKeyConstructor { + readonly prototype: CryptoKey; + new( + handle: KeyObjectHandle, + algorithm: object | undefined, + usagesMask: number, + extractable: boolean, + ): CryptoKey; + } + interface CryptoKeyPair { + publicKey: CryptoKey; + privateKey: CryptoKey; + } + + type PreparedAsymmetricKeyArgs = [ + keyData: PreparedAsymmetricKeyData, + keyFormat: KeyFormat, + keyType: KeyEncoding, + keyPassphrase: KeyPassphrase, + keyNamedCurve: NamedCurve, + ]; + + interface Argon2JobConstructor { + new( + mode: M, + message: ByteSource, + nonce: ByteSource, + parallelism: number, + tagLength: number, + memory: number, + passes: number, + secret: ByteSource, + associatedData: ByteSource, + type: number, + ): CryptoJobForMode; + new( + mode: CryptoJobWebCryptoMode, + message: KeyObjectHandle, + nonce: ByteSource, + parallelism: number, + tagLength: number, + memory: number, + passes: number, + secret: ByteSource, + associatedData: ByteSource, + type: number, + ): CryptoJobWebCrypto; + } + + interface AESCipherJobConstructor { + new( + mode: CryptoJobWebCryptoMode, + cipherMode: CipherJobMode, + key: KeyObjectHandle, + data: ByteSource, + variant: KeyVariant, + iv?: ByteSource, + tagLengthOrCounterLength?: number, + additionalData?: OptionalByteSource, + ): CryptoJobWebCrypto; + } + + interface CShakeJobConstructor { + new( + mode: CryptoJobWebCryptoMode, + algorithm: string, + data: ByteSource, + functionName: OptionalByteSource, + customization: OptionalByteSource, + outputLength: number, + ): CryptoJobWebCrypto; + } + + interface ChaCha20Poly1305CipherJobConstructor { + new( + mode: CryptoJobWebCryptoMode, + cipherMode: CipherJobMode, + key: KeyObjectHandle, + data: ByteSource, + iv: ByteSource, + additionalData?: OptionalByteSource, + ): CryptoJobWebCrypto; + } + + interface CheckPrimeJobConstructor { + new( + mode: M, + candidate: ByteSource, + checks: number, + ): CryptoJobForMode; + } + + interface DHBitsJobConstructor { + new( + mode: M, + ...args: [ + ...publicKey: PreparedAsymmetricKeyArgs, + ...privateKey: PreparedAsymmetricKeyArgs, + ] + ): CryptoJobForMode; + } + + interface DhKeyPairGenJobConstructor { + new< + M extends CryptoJobRegularMode, + PublicFormat extends PublicKeyFormat = undefined, + PrivateFormat extends PrivateKeyFormat = undefined, + >( + mode: M, + group: string, + ...encoding: KeyPairEncodingArgs + ): CryptoJobForMode>; + new< + M extends CryptoJobRegularMode, + PublicFormat extends PublicKeyFormat = undefined, + PrivateFormat extends PrivateKeyFormat = undefined, + >( + mode: M, + primeOrPrimeLength: ByteSource | number, + generator: number, + ...encoding: KeyPairEncodingArgs + ): CryptoJobForMode>; + } + + interface DsaKeyPairGenJobConstructor { + new< + M extends CryptoJobRegularMode, + PublicFormat extends PublicKeyFormat = undefined, + PrivateFormat extends PrivateKeyFormat = undefined, + >( + mode: M, + modulusLength: number, + divisorLength: number, + ...encoding: KeyPairEncodingArgs + ): CryptoJobForMode>; + } + + interface EcKeyPairGenJobConstructor { + new< + M extends CryptoJobRegularMode, + PublicFormat extends PublicKeyFormat = undefined, + PrivateFormat extends PrivateKeyFormat = undefined, + >( + mode: M, + namedCurve: string, + paramEncoding: number | null | undefined, + ...encoding: KeyPairEncodingArgs + ): CryptoJobForMode>; + new( + mode: CryptoJobWebCryptoMode, + namedCurve: string, + paramEncoding: null | undefined, + algorithm: object, + publicUsagesMask: number, + privateUsagesMask: number, + extractable: boolean, + ): CryptoJobWebCrypto; + } + + interface HKDFJobConstructor { + new( + mode: M, + hash: string, + key: ByteSource, + salt: ByteSource, + info: ByteSource, + length: number, + ): CryptoJobForMode; + new( + mode: CryptoJobWebCryptoMode, + hash: string, + key: KeyObjectHandle, + salt: ByteSource, + info: ByteSource, + length: number, + ): CryptoJobWebCrypto; + } + + interface HashJobConstructor { + new( + mode: M, + algorithm: string, + data: ByteSource, + outputLength?: number, + ): CryptoJobForMode; + } + + interface HmacJobConstructor { + new( + mode: CryptoJobWebCryptoMode, + signMode: S, + hash: string, + key: KeyObjectHandle, + data: ByteSource, + ...signature: MacJobSignatureArgs + ): CryptoJobWebCrypto>; + } + + type KemEncapsulateTuple = [ + sharedKey: Buffer, + ciphertext: Buffer, + ]; + + interface EncapsulateResult { + sharedKey: ArrayBuffer; + ciphertext: ArrayBuffer; + } + + interface KEMEncapsulateJobConstructor { + new( + mode: M, + ...key: PreparedAsymmetricKeyArgs + ): CryptoJobForMode; + new( + mode: CryptoJobWebCryptoMode, + ...key: PreparedAsymmetricKeyArgs + ): CryptoJobWebCrypto; + } + + interface KEMDecapsulateJobConstructor { + new( + mode: M, + ...args: [ + ...key: PreparedAsymmetricKeyArgs, + ciphertext: ByteSource, + ] + ): CryptoJobForMode; + new( + mode: CryptoJobWebCryptoMode, + ...args: [ + ...key: PreparedAsymmetricKeyArgs, + ciphertext: ByteSource, + ] + ): CryptoJobWebCrypto; + } + + interface KangarooTwelveJobConstructor { + new( + mode: CryptoJobWebCryptoMode, + algorithm: string, + customization: OptionalByteSource, + outputLength: number, + data: ByteSource, + ): CryptoJobWebCrypto; + } + + interface KmacJobConstructor { + new( + mode: CryptoJobWebCryptoMode, + signMode: S, + key: KeyObjectHandle, + algorithm: string, + customization: OptionalByteSource, + keyLength: number, + outputLength: number, + data: ByteSource, + ...signature: MacJobSignatureArgs + ): CryptoJobWebCrypto>; + } + + interface NidKeyPairGenJobConstructor { + new< + M extends CryptoJobRegularMode, + PublicFormat extends PublicKeyFormat = undefined, + PrivateFormat extends PrivateKeyFormat = undefined, + >( + mode: M, + nid: number, + ...encoding: KeyPairEncodingArgs + ): CryptoJobForMode>; + new( + mode: CryptoJobWebCryptoMode, + nid: number, + algorithm: object, + publicUsagesMask: number, + privateUsagesMask: number, + extractable: boolean, + ): CryptoJobWebCrypto; + } + + interface PBKDF2JobConstructor { + new( + mode: M, + password: ByteSource, + salt: ByteSource, + iterations: number, + length: number, + digest: string, + ): CryptoJobForMode; + new( + mode: CryptoJobWebCryptoMode, + password: KeyObjectHandle, + salt: ByteSource, + iterations: number, + length: number, + digest: string, + ): CryptoJobWebCrypto; + } + + interface RandomBytesJobConstructor { + new( + mode: M, + buffer: ArrayBuffer | ArrayBufferView, + offset: number, + size: number, + ): CryptoJobForMode; + } + + interface RandomPrimeJobConstructor { + new( + mode: M, + size: number, + safe: boolean, + add: OptionalByteSource, + rem: OptionalByteSource, + ): CryptoJobForMode; + } + + interface RSACipherJobConstructor { + new( + mode: CryptoJobWebCryptoMode, + cipherMode: CipherJobMode, + key: KeyObjectHandle, + data: ByteSource, + variant: KeyVariant, + digest: string, + label?: OptionalByteSource, + ): CryptoJobWebCrypto; + } + + interface RsaKeyPairGenJobConstructor { + new< + M extends CryptoJobRegularMode, + PublicFormat extends PublicKeyFormat = undefined, + PrivateFormat extends PrivateKeyFormat = undefined, + >( + mode: M, + variant: KeyVariant, + modulusLength: number, + publicExponent: number, + ...encoding: KeyPairEncodingArgs + ): CryptoJobForMode>; + new< + M extends CryptoJobRegularMode, + PublicFormat extends PublicKeyFormat = undefined, + PrivateFormat extends PrivateKeyFormat = undefined, + >( + mode: M, + variant: KeyVariant, + modulusLength: number, + publicExponent: number, + hashAlgorithm: string | undefined, + mgf1HashAlgorithm: string | undefined, + saltLength: number | undefined, + ...encoding: KeyPairEncodingArgs + ): CryptoJobForMode>; + new( + mode: CryptoJobWebCryptoMode, + variant: KeyVariant, + modulusLength: number, + publicExponent: number, + algorithm: object, + publicUsagesMask: number, + privateUsagesMask: number, + extractable: boolean, + ): CryptoJobWebCrypto; + } + + interface ScryptJobConstructor { + new( + mode: M, + password: ByteSource, + salt: ByteSource, + N: number, + r: number, + p: number, + maxmem: number, + length: number, + ): CryptoJobForMode; + } + + interface SecretKeyGenJobConstructor { + new( + mode: M, + length: number, + ): CryptoJobForMode; + new( + mode: CryptoJobWebCryptoMode, + length: number, + algorithm: object, + usagesMask: number, + extractable: boolean, + ): CryptoJobWebCrypto; + } + + interface SignJobConstructor { + new( + mode: M, + signMode: S, + ...args: [ + ...key: PreparedAsymmetricKeyArgs, + data: ByteSource, + digest: string | null | undefined, + saltLength: number | undefined, + padding: number | undefined, + dsaEncoding: number | undefined, + context: OptionalByteSource, + ...signature: SignJobSignatureArgs, + ] + ): CryptoJobForMode>; + } + + interface TurboShakeJobConstructor { + new( + mode: CryptoJobWebCryptoMode, + algorithm: string, + domainSeparation: number, + outputLength: number, + data: ByteSource, + ): CryptoJobWebCrypto; + } + + interface KeyDetail { + modulusLength?: number; + publicExponent?: bigint; + hashAlgorithm?: string; + mgf1HashAlgorithm?: string; + saltLength?: number; + divisorLength?: number; + namedCurve?: string; + prime?: Buffer; + generator?: Buffer; + } + + interface KeyObjectHandle { + init( + type: number, + data: PreparedAsymmetricKeyData, + format?: number | null, + typeOrAlgorithm?: string | number | null, + cipherOrPassphrase?: string | ByteSource | null, + passphraseOrNamedCurve?: ByteSource | string | null, + ): void; + getKeyType(): number; + export( + format?: number, + type?: string | number | null, + cipher?: string | null, + passphrase?: ByteSource | null, + ): string | Buffer; + exportJwk(target: JwkKey, handleRsaPss: boolean): JwkKey; + rawPublicKey(): Buffer; + rawPrivateKey(): Buffer; + rawSeed(): Buffer; + exportECPublicRaw(format: number): Buffer; + exportECPrivateRaw(): Buffer; + keyDetail(target: KeyDetail): KeyDetail; + equals(other: KeyObjectHandle): boolean; + getAsymmetricKeyType(): string | undefined; + getSymmetricKeySize(): number; + checkEcKeyData(): boolean; + } + + interface NativeKeyObject { + new(handle: KeyObjectHandle): object; + } + interface NativeKeyObjectConstructor { + readonly prototype: object; + new(handle: KeyObjectHandle): object; + } + interface KeyObjectConstructor { + readonly prototype: object; + new(type: 'secret' | 'public' | 'private', handle: KeyObjectHandle): object; + } + interface KeyObjectSubtypeConstructor { + readonly prototype: object; + new(handle: KeyObjectHandle): object; + } + + interface NativeCryptoKey { + new( + handle: KeyObjectHandle, + algorithm: object | undefined, + usagesMask: number, + extractable: boolean, + ): CryptoKey; + } + + type KeyObjectSlots = [ + type: number, + handle: KeyObjectHandle, + ]; + + type CryptoKeySlots = [ + type: number, + extractable: boolean, + algorithm: object, + usagesMask: number, + handle: KeyObjectHandle, + ]; + + type CreateNativeKeyObjectClassCallback = + (NativeKeyObject: NativeKeyObjectConstructor) => [ + KeyObject: KeyObjectConstructor, + SecretKeyObject: KeyObjectSubtypeConstructor, + PublicKeyObject: KeyObjectSubtypeConstructor, + PrivateKeyObject: KeyObjectSubtypeConstructor, + ]; + + type CreateCryptoKeyClassCallback = + (NativeCryptoKey: NativeCryptoKey) => + [CryptoKeyConstructor, InternalCryptoKeyConstructor]; + + interface HashHandle { + update(data: ByteSource, encoding?: string): boolean; + digest(encoding?: string): string | Buffer; + } + + interface HmacHandle { + init(algorithm: string, key: PreparedSecretKeyData): void; + update(data: ByteSource, encoding?: string): boolean; + digest(encoding?: string): string | Buffer; + } + + interface CipherBaseHandle { + update(data: ByteSource, inputEncoding?: string): Buffer; + final(): Buffer; + getAuthTag(): Buffer; + setAuthTag(tag: ByteSource): boolean; + setAAD(aad: ByteSource, plaintextLength?: number): boolean; + setAutoPadding(autoPadding: boolean): boolean; + } + + interface DiffieHellmanHandle { + readonly verifyError: number; + generateKeys(format?: number): Buffer; + computeSecret(key: ByteSource): Buffer; + getPrime(): Buffer; + getGenerator(): Buffer; + getPublicKey(format?: number): Buffer; + getPrivateKey(): Buffer; + setPublicKey(key: ByteSource): void; + setPrivateKey(key: ByteSource): void; + } + + interface SignHandle { + init(algorithm: string): void; + update(data: ByteSource, encoding?: string): void; + sign( + ...args: [ + ...key: PreparedAsymmetricKeyArgs, + rsaPadding: number | undefined, + pssSaltLength: number | undefined, + dsaSigEnc: number, + ] + ): Buffer; + } + + interface VerifyHandle { + init(algorithm: string): void; + update(data: ByteSource, encoding?: string): void; + verify( + ...args: [ + ...key: PreparedAsymmetricKeyArgs, + signature: ByteSource, + rsaPadding: number | undefined, + pssSaltLength: number | undefined, + dsaSigEnc: number, + ] + ): boolean; + } + + interface SecureContextHandle { + context?: object; + init(secureProtocol: string | undefined, minVersion: number, maxVersion: number): void; + setKey(key: ByteSource, passphrase?: ByteSource): void; + setSigalgs(sigalgs: string): void; + setEngineKey?(privateKeyIdentifier: string, privateKeyEngine: string): void; + setCert(cert: ByteSource): void; + setAllowPartialTrustChain(): void; + addCACert(cert: ByteSource): void; + addCRL(crl: ByteSource): void; + addRootCerts(): void; + setCipherSuites(cipherSuites: string): void; + setCiphers(cipherList: string): void; + setECDHCurve(ecdhCurve: string): void; + setDHParam(dhparam: ByteSource | boolean): string | undefined; + setMinProto(minVersion: number): void; + setMaxProto(maxVersion: number): void; + getMinProto(): number; + getMaxProto(): number; + setOptions(options: number): void; + setSessionIdContext(sessionIdContext: string): void; + setSessionTimeout(sessionTimeout: number): void; + setCertificateCompression(algorithms: number): void; + close(): void; + loadPKCS12(pfx: ByteSource, passphrase?: ByteSource): void; + setClientCertEngine(clientCertEngine: string): void; + getTicketKeys(): Buffer; + setTicketKeys(keys: ByteSource): void; + enableTicketKeyCallback(): void; + getCertificate(): Buffer | null; + getIssuer(): Buffer | null; + } + + interface X509CertificateHandle { + subject(): string; + subjectAltName(): string | undefined; + issuer(): string; + getIssuerCert(): X509CertificateHandle | undefined; + infoAccess(): string | undefined; + validFrom(): string; + validTo(): string; + validFromDate(): Date; + validToDate(): Date; + fingerprint(): string; + fingerprint256(): string; + fingerprint512(): string; + keyUsage(): string[] | undefined; + serialNumber(): string; + signatureAlgorithm(): string | undefined; + signatureAlgorithmOid(): string | undefined; + raw(): Buffer; + publicKey(): KeyObjectHandle; + pem(): string; + checkCA(): boolean; + checkHost(host: string, flags?: number): string | undefined; + checkEmail(email: string, flags?: number): string | undefined; + checkIP(ip: string, flags?: number): string | undefined; + checkIssued(otherCert: X509CertificateHandle): boolean; + checkPrivateKey(pkey: KeyObjectHandle): boolean; + verify(pkey: KeyObjectHandle): boolean; + toLegacy(): object; + } + + interface CipherInfo { + name: string; + nid: number; + blockSize: number; + ivLength: number; + keyLength: number; + mode: string; + } + + type PublicKeyCipher = ( + ...args: [ + ...key: PreparedAsymmetricKeyArgs, + buffer: ByteSource, + padding: number, + oaepHash: string | undefined, + oaepLabel: OptionalByteSource, + ] + ) => Buffer; +} + +export interface CryptoBinding { + AESCipherJob: InternalCryptoBinding.AESCipherJobConstructor; + Argon2Job: InternalCryptoBinding.Argon2JobConstructor; + CShakeJob?: InternalCryptoBinding.CShakeJobConstructor; + ChaCha20Poly1305CipherJob: InternalCryptoBinding.ChaCha20Poly1305CipherJobConstructor; + CheckPrimeJob: InternalCryptoBinding.CheckPrimeJobConstructor; + DHBitsJob: InternalCryptoBinding.DHBitsJobConstructor; + DhKeyPairGenJob: InternalCryptoBinding.DhKeyPairGenJobConstructor; + DsaKeyPairGenJob: InternalCryptoBinding.DsaKeyPairGenJobConstructor; + EcKeyPairGenJob: InternalCryptoBinding.EcKeyPairGenJobConstructor; + HKDFJob: InternalCryptoBinding.HKDFJobConstructor; + HashJob: InternalCryptoBinding.HashJobConstructor; + HmacJob: InternalCryptoBinding.HmacJobConstructor; + KEMDecapsulateJob?: InternalCryptoBinding.KEMDecapsulateJobConstructor; + KEMEncapsulateJob?: InternalCryptoBinding.KEMEncapsulateJobConstructor; + KangarooTwelveJob: InternalCryptoBinding.KangarooTwelveJobConstructor; + KmacJob: InternalCryptoBinding.KmacJobConstructor; + NidKeyPairGenJob: InternalCryptoBinding.NidKeyPairGenJobConstructor; + PBKDF2Job: InternalCryptoBinding.PBKDF2JobConstructor; + RandomBytesJob: InternalCryptoBinding.RandomBytesJobConstructor; + RandomPrimeJob: InternalCryptoBinding.RandomPrimeJobConstructor; + RSACipherJob: InternalCryptoBinding.RSACipherJobConstructor; + RsaKeyPairGenJob: InternalCryptoBinding.RsaKeyPairGenJobConstructor; + ScryptJob?: InternalCryptoBinding.ScryptJobConstructor; + SecretKeyGenJob: InternalCryptoBinding.SecretKeyGenJobConstructor; + SignJob: InternalCryptoBinding.SignJobConstructor; + TurboShakeJob: InternalCryptoBinding.TurboShakeJobConstructor; + + CipherBase: new ( + isEncrypt: boolean, + cipher: string, + credential: InternalCryptoBinding.PreparedSecretKeyData, + iv: InternalCryptoBinding.ByteSource | null, + authTagLength?: number, + ) => InternalCryptoBinding.CipherBaseHandle; + DiffieHellman: new ( + sizeOrKey: number | InternalCryptoBinding.ByteSource, + generator?: number | InternalCryptoBinding.ByteSource, + ) => InternalCryptoBinding.DiffieHellmanHandle; + DiffieHellmanGroup: new (name: string) => InternalCryptoBinding.DiffieHellmanHandle; + ECDH: new (curve: string) => InternalCryptoBinding.DiffieHellmanHandle; + Hash: new ( + algorithm: string | InternalCryptoBinding.HashHandle, + xofLen?: number, + algorithmId?: number, + algorithmCache?: Record, + ) => InternalCryptoBinding.HashHandle; + Hmac: new () => InternalCryptoBinding.HmacHandle; + KeyObjectHandle: new () => InternalCryptoBinding.KeyObjectHandle; + SecureContext: new () => InternalCryptoBinding.SecureContextHandle; + Sign: new () => InternalCryptoBinding.SignHandle; + Verify: new () => InternalCryptoBinding.VerifyHandle; + + EVP_PKEY_ED25519: number; + EVP_PKEY_ED448: number; + EVP_PKEY_ML_DSA_44: number; + EVP_PKEY_ML_DSA_65: number; + EVP_PKEY_ML_DSA_87: number; + EVP_PKEY_ML_KEM_512: number; + EVP_PKEY_ML_KEM_768: number; + EVP_PKEY_ML_KEM_1024: number; + EVP_PKEY_SLH_DSA_SHA2_128F: number; + EVP_PKEY_SLH_DSA_SHA2_128S: number; + EVP_PKEY_SLH_DSA_SHA2_192F: number; + EVP_PKEY_SLH_DSA_SHA2_192S: number; + EVP_PKEY_SLH_DSA_SHA2_256F: number; + EVP_PKEY_SLH_DSA_SHA2_256S: number; + EVP_PKEY_SLH_DSA_SHAKE_128F: number; + EVP_PKEY_SLH_DSA_SHAKE_128S: number; + EVP_PKEY_SLH_DSA_SHAKE_192F: number; + EVP_PKEY_SLH_DSA_SHAKE_192S: number; + EVP_PKEY_SLH_DSA_SHAKE_256F: number; + EVP_PKEY_SLH_DSA_SHAKE_256S: number; + EVP_PKEY_X25519: number; + EVP_PKEY_X448: number; + OPENSSL_EC_EXPLICIT_CURVE: number; + OPENSSL_EC_NAMED_CURVE: number; + RSA_PKCS1_PSS_PADDING: number; + X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT: number; + X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS: number; + X509_CHECK_FLAG_NEVER_CHECK_SUBJECT: number; + X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS: number; + X509_CHECK_FLAG_NO_WILDCARDS: number; + X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS: number; + kCryptoJobAsync: InternalCryptoBinding.CryptoJobAsyncMode; + kCryptoJobSync: InternalCryptoBinding.CryptoJobSyncMode; + kCryptoJobWebCrypto: InternalCryptoBinding.CryptoJobWebCryptoMode; + kKeyEncodingPKCS1: number; + kKeyEncodingPKCS8: number; + kKeyEncodingSEC1: number; + kKeyEncodingSPKI: number; + kKeyFormatDER: InternalCryptoBinding.KeyFormatDER; + kKeyFormatJWK: InternalCryptoBinding.KeyFormatJWK; + kKeyFormatPEM: InternalCryptoBinding.KeyFormatPEM; + kKeyFormatRawPrivate: InternalCryptoBinding.KeyFormatRawPrivate; + kKeyFormatRawPublic: InternalCryptoBinding.KeyFormatRawPublic; + kKeyFormatRawSeed: InternalCryptoBinding.KeyFormatRawSeed; + kKeyTypePrivate: number; + kKeyTypePublic: number; + kKeyTypeSecret: number; + kKeyVariantAES_CBC_128: number; + kKeyVariantAES_CBC_192: number; + kKeyVariantAES_CBC_256: number; + kKeyVariantAES_CTR_128: number; + kKeyVariantAES_CTR_192: number; + kKeyVariantAES_CTR_256: number; + kKeyVariantAES_GCM_128: number; + kKeyVariantAES_GCM_192: number; + kKeyVariantAES_GCM_256: number; + kKeyVariantAES_KW_128: number; + kKeyVariantAES_KW_192: number; + kKeyVariantAES_KW_256: number; + kKeyVariantAES_OCB_128: number; + kKeyVariantAES_OCB_192: number; + kKeyVariantAES_OCB_256: number; + kKeyVariantRSA_OAEP: number; + kKeyVariantRSA_PSS: number; + kKeyVariantRSA_SSA_PKCS1_v1_5: number; + kSigEncDER: number; + kSigEncP1363: number; + kSignJobModeSign: InternalCryptoBinding.SignJobModeSign; + kSignJobModeVerify: InternalCryptoBinding.SignJobModeVerify; + kTypeArgon2d: number; + kTypeArgon2i: number; + kTypeArgon2id: number; + kWebCryptoCipherDecrypt: InternalCryptoBinding.CipherJobModeDecrypt; + kWebCryptoCipherEncrypt: InternalCryptoBinding.CipherJobModeEncrypt; + kWebCryptoKeyFormatPKCS8: number; + kWebCryptoKeyFormatRaw: number; + kWebCryptoKeyFormatSPKI: number; + + ECDHConvertKey( + key: InternalCryptoBinding.ByteSource, + curve: string, + format: number, + ): InternalCryptoBinding.Buffer | ''; + certExportChallenge(spkac: InternalCryptoBinding.ByteSource): InternalCryptoBinding.Buffer | ''; + certExportPublicKey(spkac: InternalCryptoBinding.ByteSource): InternalCryptoBinding.Buffer | ''; + certVerifySpkac(spkac: InternalCryptoBinding.ByteSource): boolean | ''; + createCryptoKeyClass( + callback: InternalCryptoBinding.CreateCryptoKeyClassCallback, + ): [ + CryptoKey: InternalCryptoBinding.CryptoKeyConstructor, + InternalCryptoKey: InternalCryptoBinding.InternalCryptoKeyConstructor, + ]; + createNativeKeyObjectClass( + callback: InternalCryptoBinding.CreateNativeKeyObjectClassCallback, + ): [ + KeyObject: InternalCryptoBinding.KeyObjectConstructor, + SecretKeyObject: InternalCryptoBinding.KeyObjectSubtypeConstructor, + PublicKeyObject: InternalCryptoBinding.KeyObjectSubtypeConstructor, + PrivateKeyObject: InternalCryptoBinding.KeyObjectSubtypeConstructor, + ]; + getBundledRootCertificates(): string[]; + getCachedAliases(): Record; + getCertificateCompressionAlgorithms(): string[]; + getCipherInfo( + nameOrNid: string | number, + keyLength?: number, + ivLength?: number, + ): InternalCryptoBinding.CipherInfo | undefined; + getCiphers(): string[]; + getCryptoKeySlots(key: object): InternalCryptoBinding.CryptoKeySlots; + getCurves(): string[]; + getExtraCACertificates(): string[]; + getFipsCrypto(): 0 | 1; + getHashes(): string[]; + getKeyObjectSlots(key: object): InternalCryptoBinding.KeyObjectSlots; + getOpenSSLSecLevelCrypto(): number | undefined; + getSSLCiphers(): string[]; + getSystemCACertificates(): string[]; + getUserRootCertificates(): string[]; + oneShotDigest( + algorithm: string, + algorithmId: number, + algorithmCache: Record, + input: InternalCryptoBinding.ByteSource, + outputEncoding: string, + outputEncodingId?: number, + outputLength?: number, + ): string | InternalCryptoBinding.Buffer; + parseX509(data: InternalCryptoBinding.ByteSource): InternalCryptoBinding.X509CertificateHandle; + privateDecrypt: InternalCryptoBinding.PublicKeyCipher; + privateEncrypt: InternalCryptoBinding.PublicKeyCipher; + publicDecrypt: InternalCryptoBinding.PublicKeyCipher; + publicEncrypt: InternalCryptoBinding.PublicKeyCipher; + resetRootCertStore(): void; + secureBuffer(length: number): Uint8Array | undefined; + secureHeapUsed(): bigint | undefined; + setEngine?(engine: string, flags: number): void; + setFipsCrypto(fips: boolean | number): void; + startLoadingCertificatesOffThread(): void; + testFipsCrypto(): 0 | 1; + timingSafeEqual( + a: ArrayBufferView | ArrayBuffer, + b: ArrayBufferView | ArrayBuffer, + ): boolean; +}