Bug 1800407 - Update intl_pluralrules, unic-langid-impl and unic-langid-macros to use newer ICU4X's tinystr. r=supply-chain-reviewers,platform-i18n-reviewers,nordzilla

We have a plan to integrate ICU4X into Gecko. When importing ICU4X, tinystr
crate has 2 versions. So I should update these crates to newer version to
fix it.

Differential Revision: https://phabricator.services.mozilla.com/D162081
This commit is contained in:
Makoto Kato 2022-12-14 04:33:47 +00:00
Родитель f3ee106f12
Коммит 4df748b3ba
86 изменённых файлов: 4958 добавлений и 3005 удалений

31
Cargo.lock сгенерированный
Просмотреть файл

@ -1407,6 +1407,17 @@ dependencies = [
"winapi",
]
[[package]]
name = "displaydoc"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "dns-parser"
version = "0.8.0"
@ -2718,11 +2729,10 @@ dependencies = [
[[package]]
name = "intl_pluralrules"
version = "7.0.1"
version = "7.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b18f988384267d7066cc2be425e6faf352900652c046b6971d2e228d3b1c5ecf"
checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972"
dependencies = [
"tinystr",
"unic-langid",
]
@ -5384,9 +5394,12 @@ checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
[[package]]
name = "tinystr"
version = "0.3.4"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29738eedb4388d9ea620eeab9384884fc3f06f586a2eddb56bedc5885126c7c1"
checksum = "f8aeafdfd935e4a7fe16a91ab711fa52d54df84f9c8f7ca5837a9d1d902ef4c2"
dependencies = [
"displaydoc",
]
[[package]]
name = "tinyvec"
@ -5695,18 +5708,18 @@ dependencies = [
[[package]]
name = "unic-langid-impl"
version = "0.9.0"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a4a8eeaf0494862c1404c95ec2f4c33a2acff5076f64314b465e3ddae1b934d"
checksum = "e35bfd2f2b8796545b55d7d3fd3e89a0613f68a0d1c8bc28cb7ff96b411a35ff"
dependencies = [
"tinystr",
]
[[package]]
name = "unic-langid-macros"
version = "0.9.0"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18f980d6d87e8805f2836d64b4138cc95aa7986fa63b1f51f67d5fbff64dd6e5"
checksum = "055e618bf694161ffff0466d95cef3e1a5edc59f6ba1888e97801f2b4ebdc4fe"
dependencies = [
"proc-macro-hack",
"tinystr",

Просмотреть файл

@ -355,6 +355,16 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "0.3.4 -> 0.3.5"
[[audits.displaydoc]]
who = "Makoto Kato <m_kato@ga2.so-net.ne.jp>"
criteria = "safe-to-deploy"
version = "0.2.3"
notes = """
This crate is convenient macros to implement core::fmt::Display trait.
Although `unsafe` is used for test code to call `libc::abort()`, it has no `unsafe` code in this crate. And there is no file access.
It meets the criteria for safe-to-deploy.
"""
[[audits.dogear]]
who = "Sammy Khamis <skhamis@mozilla.com>"
criteria = "safe-to-deploy"
@ -767,6 +777,11 @@ who = "Zibi Braniecki <zibi@unicode.org>"
criteria = "safe-to-deploy"
version = "7.0.1"
[[audits.intl_pluralrules]]
who = "Makoto Kato <m_kato@ga2.so-net.ne.jp>"
criteria = "safe-to-deploy"
delta = "7.0.1 -> 7.0.2"
[[audits.itoa]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
@ -1391,6 +1406,12 @@ who = "Zibi Braniecki <zibi@unicode.org>"
criteria = "safe-to-deploy"
version = "0.6.0"
[[audits.tinystr]]
who = "Makoto Kato <m_kato@ga2.so-net.ne.jp>"
criteria = "safe-to-deploy"
version = "0.7.0"
notes = "One of original auther was Zibi Braniecki who worked at Mozilla and maintained by ICU4X developers (Google and Mozilla). I've vetted the one instance of unsafe code."
[[audits.topological-sort]]
who = "Bobby Holley <bobbyholley@gmail.com>"
criteria = "safe-to-deploy"
@ -1446,11 +1467,21 @@ who = "Zibi Braniecki <zibi@unicode.org>"
criteria = "safe-to-deploy"
version = "0.9.0"
[[audits.unic-langid-impl]]
who = "Makoto Kato <m_kato@ga2.so-net.ne.jp>"
criteria = "safe-to-deploy"
delta = "0.9.0 -> 0.9.1"
[[audits.unic-langid-macros]]
who = "Zibi Braniecki <zibi@unicode.org>"
criteria = "safe-to-deploy"
version = "0.9.0"
[[audits.unic-langid-macros]]
who = "Makoto Kato <m_kato@ga2.so-net.ne.jp>"
criteria = "safe-to-deploy"
delta = "0.9.0 -> 0.9.1"
[[audits.unic-langid-macros-impl]]
who = "Zibi Braniecki <zibi@unicode.org>"
criteria = "safe-to-deploy"

1
third_party/rust/displaydoc/.cargo-checksum.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
{"files":{"CHANGELOG.md":"1c4dbc1c48e7b5701be1d62f4628ecc1f933f70e43b5e8040203e8d98f53271d","Cargo.lock":"5a48a896619a85847e026ad6dde382c16385ca046f44eead947dbe8a787824be","Cargo.toml":"fcdfd7e2b923eb8cbf3bdf47da18cc26c17c5d530fe3704c5f7753d5541a9c2e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"a83258f76a3af3aa3ca42731473d9a2789858b25e4e153fe3dbbd6614328bdcd","README.tpl":"974701ae7f6d238bd325dd32104a5265841e79a9b79a595f7fdd964711c0cd19","examples/simple.rs":"bca524b36621ac56044cbe3eebf8892f7a3b398fd8f257fc67b17b26ae34bfbf","src/attr.rs":"a41e416d4d2a854677052f18517549a20d05cccffa04a24398107237aff3c415","src/expand.rs":"52bbf8fca0b3cb70e3a5e4ec763d294230c0afdf47612b32e46ca5fbee64154d","src/fmt.rs":"9c13cbcd337066614bc26ecfd36ea9730c9b8099083a9a7ffd79f8dc17e414f1","src/lib.rs":"168a0b9ee9dda0b26b7c68ed13c92b9e8aaf0587110b9751ede12bbfbb58be76","tests/compile_tests.rs":"935609d68eaa52e0ce9f29b3dae649787cd1f540f9b4bbadcbefcb8a0febcfc8","tests/happy.rs":"1b4c119184ca3914684c1cafaa25a8fbb9e60ef45eb257ad7ac86b8b2d7a3856","tests/no_std/enum_prefix.rs":"12401753bb44e408e1940223e8c295e63f9ddaaa114b634aac1e057a771d7eee","tests/no_std/enum_prefix_missing.rs":"8531d335c3bb7036c2adecf9af6507c46017ef1d78e222a7528396bd78316002","tests/no_std/enum_prefix_missing.stderr":"8b9f12979bdd0f88d57c5f1217accb7268eb26ee434493fe454cf89be93394b1","tests/no_std/multi_line.rs":"a87214677020029f526cdc7024d38c738f4cbba335d215dbab5cbf394118700a","tests/no_std/multi_line.stderr":"a93b9dba31f879df465fffb0cbc8b962a07181e4e94a4ef3cf34fc5422eee4a8","tests/no_std/multi_line_allow.rs":"737ea03df1c75a1adcd375a84abcc654feb39781faf9964cdfef4b3253ce1376","tests/no_std/with.rs":"c13a2d4701606a5bacfa31593c16d6417f829259dd28dfa129b729a6f8fafac2","tests/no_std/without.rs":"992344f252e856ce4979e50cb19fdb6f4dc92fb8594e2cf26f47c4ff8124f2cd","tests/no_std/without.stderr":"811331272d445ebbc00019ff62d13cd0614bd8a83153a96136911f1a30221b20","tests/num_in_field.rs":"d0bc3ba7f9aea17d3abee4ac05afe6d4a0112d3527698791e1eeaa3464e2b1d4","tests/std/enum_prefix.rs":"12401753bb44e408e1940223e8c295e63f9ddaaa114b634aac1e057a771d7eee","tests/std/enum_prefix_missing.rs":"8531d335c3bb7036c2adecf9af6507c46017ef1d78e222a7528396bd78316002","tests/std/enum_prefix_missing.stderr":"6c5eff42d8ae6c06aceff7214b570ee179329d427f6a2117097a381eed2f2f17","tests/std/multi_line.rs":"a87214677020029f526cdc7024d38c738f4cbba335d215dbab5cbf394118700a","tests/std/multi_line.stderr":"af08a172042d4c7bce308f49044c5648896ea0707fbdfa9b971bcaf951584c77","tests/std/multi_line_allow.rs":"737ea03df1c75a1adcd375a84abcc654feb39781faf9964cdfef4b3253ce1376","tests/std/multiple.rs":"f59ea8ad70b9f6cc72e66d40832c8f8ee0402b170af0fb1443615ef6af9380dd","tests/std/without.rs":"992344f252e856ce4979e50cb19fdb6f4dc92fb8594e2cf26f47c4ff8124f2cd","tests/std/without.stderr":"43bd84eca8a361b1fcfc258014115dd12080357e15b640dd7ac6f42f59eee6ca"},"package":"3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"}

39
third_party/rust/displaydoc/CHANGELOG.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,39 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
<!-- next-header -->
## [Unreleased] - ReleaseDate
# [0.2.3] - 2021-07-16
## Added
- Added `#[displaydoc("..")]` attribute for overriding a doc comment
# [0.2.2] - 2021-07-01
## Added
- Added prefix feature to use the doc comment from an enum and prepend it
before the error message from each variant.
# [0.2.1] - 2021-03-26
## Added
- Added opt in support for ignoring extra doc attributes
# [0.2.0] - 2021-03-16
## Changed
- (BREAKING) disallow multiple `doc` attributes in display impl
[https://github.com/yaahc/displaydoc/pull/22]. Allowing and ignoring extra
doc attributes made it too easy to accidentally create a broken display
implementation with missing context without realizing it, this change turns
that into a hard error and directs users towards block comments if multiple
lines are needed.
<!-- next-url -->
[Unreleased]: https://github.com/yaahc/displaydoc/compare/v0.2.3...HEAD
[0.2.3]: https://github.com/yaahc/displaydoc/compare/v0.2.2...v0.2.3
[0.2.2]: https://github.com/yaahc/displaydoc/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/yaahc/displaydoc/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/yaahc/displaydoc/releases/tag/v0.2.0

255
third_party/rust/displaydoc/Cargo.lock сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,255 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi",
]
[[package]]
name = "ctor"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "difference"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
[[package]]
name = "displaydoc"
version = "0.2.3"
dependencies = [
"libc",
"pretty_assertions",
"proc-macro2",
"quote",
"rustversion",
"static_assertions",
"syn",
"thiserror",
"trybuild",
]
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "itoa"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
[[package]]
name = "output_vt100"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
dependencies = [
"winapi",
]
[[package]]
name = "pretty_assertions"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
dependencies = [
"ansi_term",
"ctor",
"difference",
"output_vt100",
]
[[package]]
name = "proc-macro2"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustversion"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd"
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "serde"
version = "1.0.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "static_assertions"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3"
[[package]]
name = "syn"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "toml"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
dependencies = [
"serde",
]
[[package]]
name = "trybuild"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99471a206425fba51842a9186315f32d91c56eadc21ea4c21f847b59cf778f8b"
dependencies = [
"glob",
"lazy_static",
"serde",
"serde_json",
"termcolor",
"toml",
]
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

98
third_party/rust/displaydoc/Cargo.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,98 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
[package]
edition = "2018"
name = "displaydoc"
version = "0.2.3"
authors = ["Jane Lusby <jlusby@yaah.dev>"]
description = "A derive macro for implementing the display Trait via a doc comment and string interpolation\n"
homepage = "https://github.com/yaahc/displaydoc"
documentation = "https://docs.rs/displaydoc"
readme = "README.md"
keywords = ["display", "derive"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/yaahc/displaydoc"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.release]
no-dev-version = true
[[package.metadata.release.pre-release-replacements]]
file = "CHANGELOG.md"
replace = "{{version}}"
search = "Unreleased"
[[package.metadata.release.pre-release-replacements]]
exactly = 1
file = "src/lib.rs"
replace = "#![doc(html_root_url = \"https://docs.rs/{{crate_name}}/{{version}}\")]"
search = "#!\\[doc\\(html_root_url.*"
[[package.metadata.release.pre-release-replacements]]
file = "CHANGELOG.md"
replace = "{{date}}"
search = "ReleaseDate"
[[package.metadata.release.pre-release-replacements]]
exactly = 1
file = "CHANGELOG.md"
replace = "<!-- next-header -->\n\n## [Unreleased] - ReleaseDate"
search = "<!-- next-header -->"
[[package.metadata.release.pre-release-replacements]]
exactly = 1
file = "CHANGELOG.md"
replace = "...{{tag_name}}"
search = "\\.\\.\\.HEAD"
[[package.metadata.release.pre-release-replacements]]
exactly = 1
file = "CHANGELOG.md"
replace = "<!-- next-url -->\n[Unreleased]: https://github.com/yaahc/{{crate_name}}/compare/{{tag_name}}...HEAD"
search = "<!-- next-url -->"
[lib]
path = "src/lib.rs"
proc-macro = true
[dependencies.proc-macro2]
version = "1.0"
[dependencies.quote]
version = "1.0"
[dependencies.syn]
version = "1.0"
[dev-dependencies.libc]
version = "0.2"
default-features = false
[dev-dependencies.pretty_assertions]
version = "0.6.1"
[dev-dependencies.rustversion]
version = "1.0.0"
[dev-dependencies.static_assertions]
version = "0.3.4"
[dev-dependencies.thiserror]
version = "1.0.24"
[dev-dependencies.trybuild]
version = "1.0"
[features]
default = ["std"]
std = []

Просмотреть файл

Просмотреть файл

99
third_party/rust/displaydoc/README.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,99 @@
derive(Display) /// `From<docs>`
===============
[![Latest Version](https://img.shields.io/crates/v/displaydoc.svg)](https://crates.io/crates/displaydoc)
[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/displaydoc)
This library provides a convenient derive macro for the standard library's
[`core::fmt::Display`] trait.
[`core::fmt::Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
```toml
[dependencies]
displaydoc = "0.2"
```
*Compiler support: requires rustc 1.31+*
<br>
### Example
```rust
use std::io;
use displaydoc::Display;
use thiserror::Error;
#[derive(Display, Error, Debug)]
pub enum DataStoreError {
/// data store disconnected
Disconnect(#[source] io::Error),
/// the data for key `{0}` is not available
Redaction(String),
/// invalid header (expected {expected:?}, found {found:?})
InvalidHeader {
expected: String,
found: String,
},
/// unknown data store error
Unknown,
}
```
<br>
### Details
- A `Display` impl is generated for your type if you provide doc comment
messages on the struct or each variant of your enum, as shown above in the
example.
The messages support a shorthand for interpolating fields from the error.
- `/// {var}``write!("{}", self.var)`
- `/// {0}``write!("{}", self.0)`
- `/// {var:?}``write!("{:?}", self.var)`
- `/// {0:?}``write!("{:?}", self.0)`
- Two optional attributes can be added to your types next to the derive:
- `#[ignore_extra_doc_attributes]` makes the macro ignore any doc
comment attributes (or `///` lines) after the first. Multi-line
comments using `///` are otherwise treated as an error, so use this
attribute or consider switching to block doc comments (`/** */`).
- `#[prefix_enum_doc_attributes]` combines the doc comment message on
your enum itself with the messages for each variant, in the format
“enum: variant”. When added to an enum, the doc comment on the enum
becomes mandatory. When added to any other type, it has no effect.
- In case you want to have an independent doc comment, the
`#[displaydoc("...")` atrribute may be used on the variant or struct to
override it.
<br>
### FAQ
1. **Is this crate `no_std` compatible?**
* Yes! This crate implements the `core::fmt::Display` trait not the `std::fmt::Display` trait so it should work in `std` and `no_std` environments. Just add `default-features = false`.
2. **Does this crate work with `Path` and `PathBuf` via the `Display` trait?**
* Yuuup. This crate uses @dtolnay's [autoref specialization technique](https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md) to add a special trait for types to get the display impl, it then specializes for `Path` and `PathBuf` and when either of these types are found it calls `self.display()` to get a `std::path::Display<'_>` type which can be used with the Display format specifier!
#### License
<sup>
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
</sup>
<br>
<sub>
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.
</sub>

23
third_party/rust/displaydoc/README.tpl поставляемый Normal file
Просмотреть файл

@ -0,0 +1,23 @@
derive(Display) /// `From<docs>`
===============
[![Latest Version](https://img.shields.io/crates/v/displaydoc.svg)](https://crates.io/crates/displaydoc)
[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/displaydoc)
{{readme}}
#### License
<sup>
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
</sup>
<br>
<sub>
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.
</sub>

36
third_party/rust/displaydoc/examples/simple.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,36 @@
use displaydoc::Display;
#[derive(Debug, Display)]
pub enum DataStoreError {
/// data store disconnected
Disconnect,
/// the data for key `{0}` is not available
Redaction(String),
/// invalid header (expected {expected:?}, found {found:?})
InvalidHeader { expected: String, found: String },
/// unknown data store error
Unknown,
}
fn main() {
let disconnect = DataStoreError::Disconnect;
println!(
"Enum value `Disconnect` should be printed as:\n\t{}",
disconnect
);
let redaction = DataStoreError::Redaction(String::from("Dummy"));
println!(
"Enum value `Redaction` should be printed as:\n\t{}",
redaction
);
let invalid_header = DataStoreError::InvalidHeader {
expected: String::from("https"),
found: String::from("http"),
};
println!(
"Enum value `InvalidHeader` should be printed as:\n\t{}",
invalid_header
);
}

134
third_party/rust/displaydoc/src/attr.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,134 @@
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{Attribute, LitStr, Meta, Result};
#[derive(Clone)]
pub(crate) struct Display {
pub(crate) fmt: LitStr,
pub(crate) args: TokenStream,
}
pub(crate) struct VariantDisplay {
pub(crate) r#enum: Option<Display>,
pub(crate) variant: Display,
}
impl ToTokens for Display {
fn to_tokens(&self, tokens: &mut TokenStream) {
let fmt = &self.fmt;
let args = &self.args;
tokens.extend(quote! {
write!(formatter, #fmt #args)
});
}
}
impl ToTokens for VariantDisplay {
fn to_tokens(&self, tokens: &mut TokenStream) {
if let Some(ref r#enum) = self.r#enum {
r#enum.to_tokens(tokens);
tokens.extend(quote! { ?; write!(formatter, ": ")?; });
}
self.variant.to_tokens(tokens);
}
}
pub(crate) struct AttrsHelper {
ignore_extra_doc_attributes: bool,
prefix_enum_doc_attributes: bool,
}
impl AttrsHelper {
pub(crate) fn new(attrs: &[Attribute]) -> Self {
let ignore_extra_doc_attributes = attrs
.iter()
.any(|attr| attr.path.is_ident("ignore_extra_doc_attributes"));
let prefix_enum_doc_attributes = attrs
.iter()
.any(|attr| attr.path.is_ident("prefix_enum_doc_attributes"));
Self {
ignore_extra_doc_attributes,
prefix_enum_doc_attributes,
}
}
pub(crate) fn display(&self, attrs: &[Attribute]) -> Result<Option<Display>> {
let displaydoc_attr = attrs.iter().find(|attr| attr.path.is_ident("displaydoc"));
if let Some(displaydoc_attr) = displaydoc_attr {
let lit = displaydoc_attr
.parse_args()
.expect("#[displaydoc(\"foo\")] must contain string arguments");
let mut display = Display {
fmt: lit,
args: TokenStream::new(),
};
display.expand_shorthand();
return Ok(Some(display));
}
let num_doc_attrs = attrs
.iter()
.filter(|attr| attr.path.is_ident("doc"))
.count();
if !self.ignore_extra_doc_attributes && num_doc_attrs > 1 {
panic!("Multi-line comments are disabled by default by displaydoc. Please consider using block doc comments (/** */) or adding the #[ignore_extra_doc_attributes] attribute to your type next to the derive.");
}
for attr in attrs {
if attr.path.is_ident("doc") {
let meta = attr.parse_meta()?;
let lit = match meta {
Meta::NameValue(syn::MetaNameValue {
lit: syn::Lit::Str(lit),
..
}) => lit,
_ => unimplemented!(),
};
// Make an attempt and cleaning up multiline doc comments
let doc_str = lit
.value()
.lines()
.map(|line| line.trim().trim_start_matches('*').trim())
.collect::<Vec<&str>>()
.join("\n");
let lit = LitStr::new(doc_str.trim(), lit.span());
let mut display = Display {
fmt: lit,
args: TokenStream::new(),
};
display.expand_shorthand();
return Ok(Some(display));
}
}
Ok(None)
}
pub(crate) fn display_with_input(
&self,
r#enum: &[Attribute],
variant: &[Attribute],
) -> Result<Option<VariantDisplay>> {
let r#enum = if self.prefix_enum_doc_attributes {
let result = self
.display(r#enum)?
.expect("Missing doc comment on enum with #[prefix_enum_doc_attributes]. Please remove the attribute or add a doc comment to the enum itself.");
Some(result)
} else {
None
};
Ok(self
.display(variant)?
.map(|variant| VariantDisplay { r#enum, variant }))
}
}

145
third_party/rust/displaydoc/src/expand.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,145 @@
use super::attr::AttrsHelper;
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use syn::{Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Result};
pub(crate) fn derive(input: &DeriveInput) -> Result<TokenStream> {
let impls = match &input.data {
Data::Struct(data) => impl_struct(input, data),
Data::Enum(data) => impl_enum(input, data),
Data::Union(_) => Err(Error::new_spanned(input, "Unions are not supported")),
}?;
let helpers = specialization();
let dummy_const = format_ident!("_DERIVE_Display_FOR_{}", input.ident);
Ok(quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
#helpers
#impls
};
})
}
#[cfg(feature = "std")]
fn specialization() -> TokenStream {
quote! {
trait DisplayToDisplayDoc {
fn __displaydoc_display(&self) -> Self;
}
impl<T: core::fmt::Display> DisplayToDisplayDoc for &T {
fn __displaydoc_display(&self) -> Self {
self
}
}
// If the `std` feature gets enabled we want to ensure that any crate
// using displaydoc can still reference the std crate, which is already
// being compiled in by whoever enabled the `std` feature in
// `displaydoc`, even if the crates using displaydoc are no_std.
extern crate std;
trait PathToDisplayDoc {
fn __displaydoc_display(&self) -> std::path::Display<'_>;
}
impl PathToDisplayDoc for std::path::Path {
fn __displaydoc_display(&self) -> std::path::Display<'_> {
self.display()
}
}
impl PathToDisplayDoc for std::path::PathBuf {
fn __displaydoc_display(&self) -> std::path::Display<'_> {
self.display()
}
}
}
}
#[cfg(not(feature = "std"))]
fn specialization() -> TokenStream {
quote! {}
}
fn impl_struct(input: &DeriveInput, data: &DataStruct) -> Result<TokenStream> {
let ty = &input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let helper = AttrsHelper::new(&input.attrs);
let display = helper.display(&input.attrs)?.map(|display| {
let pat = match &data.fields {
Fields::Named(fields) => {
let var = fields.named.iter().map(|field| &field.ident);
quote!(Self { #(#var),* })
}
Fields::Unnamed(fields) => {
let var = (0..fields.unnamed.len()).map(|i| format_ident!("_{}", i));
quote!(Self(#(#var),*))
}
Fields::Unit => quote!(_),
};
quote! {
impl #impl_generics core::fmt::Display for #ty #ty_generics #where_clause {
fn fmt(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
#[allow(unused_variables)]
let #pat = self;
#display
}
}
}
});
Ok(quote! { #display })
}
fn impl_enum(input: &DeriveInput, data: &DataEnum) -> Result<TokenStream> {
let ty = &input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let helper = AttrsHelper::new(&input.attrs);
let displays = data
.variants
.iter()
.map(|variant| helper.display_with_input(&input.attrs, &variant.attrs))
.collect::<Result<Vec<_>>>()?;
if displays.iter().any(Option::is_some) {
let arms = data
.variants
.iter()
.zip(displays)
.map(|(variant, display)| {
let display =
display.ok_or_else(|| Error::new_spanned(variant, "missing doc comment"))?;
let ident = &variant.ident;
Ok(match &variant.fields {
Fields::Named(fields) => {
let var = fields.named.iter().map(|field| &field.ident);
quote!(#ty::#ident { #(#var),* } => { #display })
}
Fields::Unnamed(fields) => {
let var = (0..fields.unnamed.len()).map(|i| format_ident!("_{}", i));
quote!(#ty::#ident(#(#var),*) => { #display })
}
Fields::Unit => quote!(#ty::#ident => { #display }),
})
})
.collect::<Result<Vec<_>>>()?;
Ok(quote! {
impl #impl_generics core::fmt::Display for #ty #ty_generics #where_clause {
fn fmt(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
#[allow(unused_variables)]
match self {
#(#arms,)*
}
}
}
})
} else {
Err(Error::new_spanned(input, "Missing doc comments"))
}
}

159
third_party/rust/displaydoc/src/fmt.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,159 @@
use crate::attr::Display;
use proc_macro2::TokenStream;
use quote::quote_spanned;
use syn::{Ident, LitStr};
macro_rules! peek_next {
($read:ident) => {
match $read.chars().next() {
Some(next) => next,
None => return,
}
};
}
impl Display {
// Transform `"error {var}"` to `"error {}", var`.
pub(crate) fn expand_shorthand(&mut self) {
let span = self.fmt.span();
let fmt = self.fmt.value();
let mut read = fmt.as_str();
let mut out = String::new();
let mut args = TokenStream::new();
while let Some(brace) = read.find('{') {
out += &read[..=brace];
read = &read[brace + 1..];
// skip cases where we find a {{
if read.starts_with('{') {
out.push('{');
read = &read[1..];
continue;
}
let next = peek_next!(read);
let var = match next {
'0'..='9' => take_int(&mut read),
'a'..='z' | 'A'..='Z' | '_' => take_ident(&mut read),
_ => return,
};
let ident = Ident::new(&var, span);
let next = peek_next!(read);
let arg = if cfg!(feature = "std") && next == '}' {
quote_spanned!(span=> , #ident.__displaydoc_display())
} else {
quote_spanned!(span=> , #ident)
};
args.extend(arg);
}
out += read;
self.fmt = LitStr::new(&out, self.fmt.span());
self.args = args;
}
}
fn take_int(read: &mut &str) -> String {
let mut int = String::new();
int.push('_');
for (i, ch) in read.char_indices() {
match ch {
'0'..='9' => int.push(ch),
_ => {
*read = &read[i..];
break;
}
}
}
int
}
fn take_ident(read: &mut &str) -> String {
let mut ident = String::new();
for (i, ch) in read.char_indices() {
match ch {
'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => ident.push(ch),
_ => {
*read = &read[i..];
break;
}
}
}
ident
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
use proc_macro2::Span;
fn assert(input: &str, fmt: &str, args: &str) {
let mut display = Display {
fmt: LitStr::new(input, Span::call_site()),
args: TokenStream::new(),
};
display.expand_shorthand();
assert_eq!(fmt, display.fmt.value());
assert_eq!(args, display.args.to_string());
}
#[test]
fn test_expand() {
assert("fn main() {{ }}", "fn main() {{ }}", "");
}
#[test]
#[cfg_attr(not(feature = "std"), ignore)]
fn test_std_expand() {
assert(
"{v} {v:?} {0} {0:?}",
"{} {:?} {} {:?}",
", v . __displaydoc_display () , v , _0 . __displaydoc_display () , _0",
);
assert("error {var}", "error {}", ", var . __displaydoc_display ()");
assert(
"error {var1}",
"error {}",
", var1 . __displaydoc_display ()",
);
assert(
"error {var1var}",
"error {}",
", var1var . __displaydoc_display ()",
);
assert(
"The path {0}",
"The path {}",
", _0 . __displaydoc_display ()",
);
assert("The path {0:?}", "The path {:?}", ", _0");
}
#[test]
#[cfg_attr(feature = "std", ignore)]
fn test_nostd_expand() {
assert(
"{v} {v:?} {0} {0:?}",
"{} {:?} {} {:?}",
", v , v , _0 , _0",
);
assert("error {var}", "error {}", ", var");
assert("The path {0}", "The path {}", ", _0");
assert("The path {0:?}", "The path {:?}", ", _0");
assert("error {var1}", "error {}", ", var1");
assert("error {var1var}", "error {}", ", var1var");
}
}

122
third_party/rust/displaydoc/src/lib.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,122 @@
//! This library provides a convenient derive macro for the standard library's
//! [`core::fmt::Display`] trait.
//!
//! [`core::fmt::Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
//!
//! ```toml
//! [dependencies]
//! displaydoc = "0.2"
//! ```
//!
//! *Compiler support: requires rustc 1.31+*
//!
//! <br>
//!
//! ## Example
//!
//! ```rust
//! use std::io;
//! use displaydoc::Display;
//! use thiserror::Error;
//!
//! #[derive(Display, Error, Debug)]
//! pub enum DataStoreError {
//! /// data store disconnected
//! Disconnect(#[source] io::Error),
//! /// the data for key `{0}` is not available
//! Redaction(String),
//! /// invalid header (expected {expected:?}, found {found:?})
//! InvalidHeader {
//! expected: String,
//! found: String,
//! },
//! /// unknown data store error
//! Unknown,
//! }
//! ```
//!
//! <br>
//!
//! ## Details
//!
//! - A `Display` impl is generated for your type if you provide doc comment
//! messages on the struct or each variant of your enum, as shown above in the
//! example.
//!
//! The messages support a shorthand for interpolating fields from the error.
//!
//! - `/// {var}` ⟶ `write!("{}", self.var)`
//! - `/// {0}` ⟶ `write!("{}", self.0)`
//! - `/// {var:?}` ⟶ `write!("{:?}", self.var)`
//! - `/// {0:?}` ⟶ `write!("{:?}", self.0)`
//!
//! - Two optional attributes can be added to your types next to the derive:
//!
//! - `#[ignore_extra_doc_attributes]` makes the macro ignore any doc
//! comment attributes (or `///` lines) after the first. Multi-line
//! comments using `///` are otherwise treated as an error, so use this
//! attribute or consider switching to block doc comments (`/** */`).
//!
//! - `#[prefix_enum_doc_attributes]` combines the doc comment message on
//! your enum itself with the messages for each variant, in the format
//! “enum: variant”. When added to an enum, the doc comment on the enum
//! becomes mandatory. When added to any other type, it has no effect.
//!
//! - In case you want to have an independent doc comment, the
//! `#[displaydoc("...")` atrribute may be used on the variant or struct to
//! override it.
//!
//! <br>
//!
//! ## FAQ
//!
//! 1. **Is this crate `no_std` compatible?**
//! * Yes! This crate implements the `core::fmt::Display` trait not the `std::fmt::Display` trait so it should work in `std` and `no_std` environments. Just add `default-features = false`.
//!
//! 2. **Does this crate work with `Path` and `PathBuf` via the `Display` trait?**
//! * Yuuup. This crate uses @dtolnay's [autoref specialization technique](https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md) to add a special trait for types to get the display impl, it then specializes for `Path` and `PathBuf` and when either of these types are found it calls `self.display()` to get a `std::path::Display<'_>` type which can be used with the Display format specifier!
#![doc(html_root_url = "https://docs.rs/displaydoc/0.2.3")]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![warn(
rust_2018_idioms,
unreachable_pub,
bad_style,
const_err,
dead_code,
improper_ctypes,
non_shorthand_field_patterns,
no_mangle_generic_items,
overflowing_literals,
path_statements,
patterns_in_fns_without_body,
private_in_public,
unconditional_recursion,
unused,
unused_allocation,
unused_comparisons,
unused_parens,
while_true
)]
#![allow(clippy::try_err)]
#[allow(unused_extern_crates)]
extern crate proc_macro;
mod attr;
mod expand;
mod fmt;
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};
/// Derive macro for implementing `Display` via doc comment attributes
#[proc_macro_derive(
Display,
attributes(ignore_extra_doc_attributes, prefix_enum_doc_attributes, displaydoc)
)]
pub fn derive_error(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
expand::derive(&input)
.unwrap_or_else(|err| err.to_compile_error())
.into()
}

29
third_party/rust/displaydoc/tests/compile_tests.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,29 @@
#[allow(unused_attributes)]
#[rustversion::attr(not(nightly), ignore)]
#[test]
fn no_std() {
let t = trybuild::TestCases::new();
#[cfg(not(feature = "std"))]
t.compile_fail("tests/no_std/without.rs");
#[cfg(not(feature = "std"))]
t.compile_fail("tests/no_std/multi_line.rs");
#[cfg(not(feature = "std"))]
t.pass("tests/no_std/multi_line_allow.rs");
#[cfg(not(feature = "std"))]
t.compile_fail("tests/no_std/enum_prefix_missing.rs");
#[cfg(not(feature = "std"))]
t.pass("tests/no_std/enum_prefix.rs");
#[cfg(feature = "std")]
t.compile_fail("tests/std/without.rs");
#[cfg(feature = "std")]
t.compile_fail("tests/std/multi_line.rs");
#[cfg(feature = "std")]
t.pass("tests/std/multi_line_allow.rs");
#[cfg(feature = "std")]
t.compile_fail("tests/std/enum_prefix_missing.rs");
#[cfg(feature = "std")]
t.pass("tests/std/enum_prefix.rs");
#[cfg(feature = "std")]
t.pass("tests/std/multiple.rs");
t.pass("tests/no_std/with.rs");
}

152
third_party/rust/displaydoc/tests/happy.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,152 @@
use displaydoc::Display;
#[cfg(feature = "std")]
use std::path::PathBuf;
#[derive(Display)]
/// Just a basic struct {thing}
struct HappyStruct {
thing: &'static str,
}
#[derive(Display)]
#[ignore_extra_doc_attributes]
/// Just a basic struct {thing}
/// and this line should get ignored
struct HappyStruct2 {
thing: &'static str,
}
#[derive(Display)]
enum Happy {
/// I really like Variant1
Variant1,
/// Variant2 is pretty swell 2
Variant2,
/// Variant3 is okay {sometimes}
Variant3 { sometimes: &'static str },
/**
* Variant4 wants to have a lot of lines
*
* Lets see how this works out for it
*/
Variant4,
/// Variant5 has a parameter {0} and some regular comments
// A regular comment that won't get picked
Variant5(u32),
/// The path {0}
#[cfg(feature = "std")]
Variant6(PathBuf),
/// These docs are ignored
#[displaydoc("Variant7 has a parameter {0} and uses #[displaydoc]")]
/// These docs are also ignored
Variant7(u32),
}
// Used for testing indented doc comments
mod inner_mod {
use super::Display;
#[derive(Display)]
pub enum InnerHappy {
/// I really like Variant1
Variant1,
/// Variant2 is pretty swell 2
Variant2,
/// Variant3 is okay {sometimes}
Variant3 { sometimes: &'static str },
/**
* Variant4 wants to have a lot of lines
*
* Lets see how this works out for it
*/
Variant4,
/// Variant5 has a parameter {0} and some regular comments
// A regular comment that won't get picked
Variant5(u32),
/** what happens if we
* put text on the first line?
*/
Variant6,
/**
what happens if we don't use *?
*/
Variant7,
/**
*
* what about extra new lines?
*/
Variant8,
}
}
fn assert_display<T: std::fmt::Display>(input: T, expected: &'static str) {
let out = format!("{}", input);
assert_eq!(expected, out);
}
#[test]
fn does_it_print() {
assert_display(Happy::Variant1, "I really like Variant1");
assert_display(Happy::Variant2, "Variant2 is pretty swell 2");
assert_display(Happy::Variant3 { sometimes: "hi" }, "Variant3 is okay hi");
assert_display(
Happy::Variant4,
"Variant4 wants to have a lot of lines\n\nLets see how this works out for it",
);
assert_display(
Happy::Variant5(2),
"Variant5 has a parameter 2 and some regular comments",
);
assert_display(
Happy::Variant7(2),
"Variant7 has a parameter 2 and uses #[displaydoc]",
);
assert_display(HappyStruct { thing: "hi" }, "Just a basic struct hi");
assert_display(HappyStruct2 { thing: "hi2" }, "Just a basic struct hi2");
assert_display(inner_mod::InnerHappy::Variant1, "I really like Variant1");
assert_display(
inner_mod::InnerHappy::Variant2,
"Variant2 is pretty swell 2",
);
assert_display(
inner_mod::InnerHappy::Variant3 { sometimes: "hi" },
"Variant3 is okay hi",
);
assert_display(
inner_mod::InnerHappy::Variant4,
"Variant4 wants to have a lot of lines\n\nLets see how this works out for it",
);
assert_display(
inner_mod::InnerHappy::Variant5(2),
"Variant5 has a parameter 2 and some regular comments",
);
assert_display(
inner_mod::InnerHappy::Variant6,
"what happens if we\nput text on the first line?",
);
assert_display(
inner_mod::InnerHappy::Variant7,
"what happens if we don\'t use *?",
);
assert_display(
inner_mod::InnerHappy::Variant8,
"what about extra new lines?",
);
}
#[test]
#[cfg(feature = "std")]
fn does_it_print_path() {
assert_display(
Happy::Variant6(PathBuf::from("/var/log/happy")),
"The path /var/log/happy",
);
}

36
third_party/rust/displaydoc/tests/no_std/enum_prefix.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,36 @@
#![cfg_attr(not(feature = "std"), feature(lang_items, start))]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg_attr(not(feature = "std"), start)]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"]
#[no_mangle]
#[cfg(not(feature = "std"))]
pub extern "C" fn rust_eh_personality() {}
#[panic_handler]
#[cfg(not(feature = "std"))]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
libc::abort();
}
}
use displaydoc::Display;
/// this type is pretty swell
#[derive(Display)]
#[prefix_enum_doc_attributes]
enum TestType {
/// this variant is too
Variant1,
/// this variant is two
Variant2,
}
static_assertions::assert_impl_all!(label; TestType, core::fmt::Display);
#[cfg(feature = "std")]
fn main() {}

35
third_party/rust/displaydoc/tests/no_std/enum_prefix_missing.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,35 @@
#![cfg_attr(not(feature = "std"), feature(lang_items, start))]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg_attr(not(feature = "std"), start)]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"]
#[no_mangle]
#[cfg(not(feature = "std"))]
pub extern "C" fn rust_eh_personality() {}
#[panic_handler]
#[cfg(not(feature = "std"))]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
libc::abort();
}
}
use displaydoc::Display;
#[derive(Display)]
#[prefix_enum_doc_attributes]
enum TestType {
/// this variant is too
Variant1,
/// this variant is two
Variant2,
}
static_assertions::assert_impl_all!(label; TestType, core::fmt::Display);
#[cfg(feature = "std")]
fn main() {}

Просмотреть файл

@ -0,0 +1,19 @@
error: proc-macro derive panicked
--> $DIR/enum_prefix_missing.rs:22:10
|
22 | #[derive(Display)]
| ^^^^^^^
|
= help: message: Missing doc comment on enum with #[prefix_enum_doc_attributes]. Please remove the attribute or add a doc comment to the enum itself.
error[E0277]: `TestType` doesn't implement `Display`
--> $DIR/enum_prefix_missing.rs:32:44
|
32 | static_assertions::assert_impl_all!(label; TestType, core::fmt::Display);
| -------------------------------------------^^^^^^^^----------------------
| | |
| | `TestType` cannot be formatted with the default formatter
| required by this bound in `assert_impl_all`
|
= help: the trait `Display` is not implemented for `TestType`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead

37
third_party/rust/displaydoc/tests/no_std/multi_line.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,37 @@
#![cfg_attr(not(feature = "std"), feature(lang_items, start))]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg_attr(not(feature = "std"), start)]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"]
#[no_mangle]
#[cfg(not(feature = "std"))]
pub extern "C" fn rust_eh_personality() {}
#[panic_handler]
#[cfg(not(feature = "std"))]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
libc::abort();
}
}
use displaydoc::Display;
/// this type is pretty swell
#[derive(Display)]
enum TestType {
/// This one is okay
Variant1,
/// Multi
/// line
/// doc.
Variant2,
}
static_assertions::assert_impl_all!(label; TestType, core::fmt::Display);
#[cfg(feature = "std")]
fn main() {}

19
third_party/rust/displaydoc/tests/no_std/multi_line.stderr поставляемый Normal file
Просмотреть файл

@ -0,0 +1,19 @@
error: proc-macro derive panicked
--> $DIR/multi_line.rs:23:10
|
23 | #[derive(Display)]
| ^^^^^^^
|
= help: message: Multi-line comments are disabled by default by displaydoc. Please consider using block doc comments (/** */) or adding the #[ignore_extra_doc_attributes] attribute to your type next to the derive.
error[E0277]: `TestType` doesn't implement `Display`
--> $DIR/multi_line.rs:34:44
|
34 | static_assertions::assert_impl_all!(label; TestType, core::fmt::Display);
| -------------------------------------------^^^^^^^^----------------------
| | |
| | `TestType` cannot be formatted with the default formatter
| required by this bound in `assert_impl_all`
|
= help: the trait `Display` is not implemented for `TestType`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead

38
third_party/rust/displaydoc/tests/no_std/multi_line_allow.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,38 @@
#![cfg_attr(not(feature = "std"), feature(lang_items, start))]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg_attr(not(feature = "std"), start)]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"]
#[no_mangle]
#[cfg(not(feature = "std"))]
pub extern "C" fn rust_eh_personality() {}
#[panic_handler]
#[cfg(not(feature = "std"))]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
libc::abort();
}
}
use displaydoc::Display;
/// this type is pretty swell
#[derive(Display)]
#[ignore_extra_doc_attributes]
enum TestType {
/// This one is okay
Variant1,
/// Multi
/// line
/// doc.
Variant2,
}
static_assertions::assert_impl_all!(label; TestType, core::fmt::Display);
#[cfg(feature = "std")]
fn main() {}

32
third_party/rust/displaydoc/tests/no_std/with.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,32 @@
#![feature(lang_items, start)]
#![no_std]
#[start]
#[cfg(not(feature = "std"))]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"]
#[no_mangle]
#[cfg(not(feature = "std"))]
pub extern "C" fn rust_eh_personality() {}
#[panic_handler]
#[cfg(not(feature = "std"))]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
libc::abort();
}
}
#[cfg(feature = "std")]
fn main() {}
use displaydoc::Display;
/// this type is pretty swell
#[derive(Display)]
struct FakeType;
static_assertions::assert_impl_all!(label; FakeType, core::fmt::Display);

28
third_party/rust/displaydoc/tests/no_std/without.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,28 @@
#![cfg_attr(not(feature = "std"), feature(lang_items, start))]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg_attr(not(feature = "std"), start)]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"]
#[no_mangle]
#[cfg(not(feature = "std"))]
pub extern "C" fn rust_eh_personality() {}
#[panic_handler]
#[cfg(not(feature = "std"))]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
libc::abort();
}
}
use displaydoc::Display;
/// this type is pretty swell
struct FakeType;
static_assertions::assert_impl_all!(label; FakeType, core::fmt::Display);
#[cfg(feature = "std")]
fn main() {}

19
third_party/rust/displaydoc/tests/no_std/without.stderr поставляемый Normal file
Просмотреть файл

@ -0,0 +1,19 @@
warning: unused import: `displaydoc::Display`
--> $DIR/without.rs:20:5
|
20 | use displaydoc::Display;
| ^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error[E0277]: `FakeType` doesn't implement `Display`
--> $DIR/without.rs:25:44
|
25 | static_assertions::assert_impl_all!(label; FakeType, core::fmt::Display);
| -------------------------------------------^^^^^^^^----------------------
| | |
| | `FakeType` cannot be formatted with the default formatter
| required by this bound in `assert_impl_all`
|
= help: the trait `Display` is not implemented for `FakeType`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead

22
third_party/rust/displaydoc/tests/num_in_field.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,22 @@
/// {foo1} {foo2}
#[derive(displaydoc::Display)]
pub struct Test {
foo1: String,
foo2: String,
}
fn assert_display<T: std::fmt::Display>(input: T, expected: &'static str) {
let out = format!("{}", input);
assert_eq!(expected, out);
}
#[test]
fn does_it_print() {
assert_display(
Test {
foo1: "hi".into(),
foo2: "hello".into(),
},
"hi hello",
);
}

36
third_party/rust/displaydoc/tests/std/enum_prefix.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,36 @@
#![cfg_attr(not(feature = "std"), feature(lang_items, start))]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg_attr(not(feature = "std"), start)]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"]
#[no_mangle]
#[cfg(not(feature = "std"))]
pub extern "C" fn rust_eh_personality() {}
#[panic_handler]
#[cfg(not(feature = "std"))]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
libc::abort();
}
}
use displaydoc::Display;
/// this type is pretty swell
#[derive(Display)]
#[prefix_enum_doc_attributes]
enum TestType {
/// this variant is too
Variant1,
/// this variant is two
Variant2,
}
static_assertions::assert_impl_all!(label; TestType, core::fmt::Display);
#[cfg(feature = "std")]
fn main() {}

35
third_party/rust/displaydoc/tests/std/enum_prefix_missing.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,35 @@
#![cfg_attr(not(feature = "std"), feature(lang_items, start))]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg_attr(not(feature = "std"), start)]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"]
#[no_mangle]
#[cfg(not(feature = "std"))]
pub extern "C" fn rust_eh_personality() {}
#[panic_handler]
#[cfg(not(feature = "std"))]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
libc::abort();
}
}
use displaydoc::Display;
#[derive(Display)]
#[prefix_enum_doc_attributes]
enum TestType {
/// this variant is too
Variant1,
/// this variant is two
Variant2,
}
static_assertions::assert_impl_all!(label; TestType, core::fmt::Display);
#[cfg(feature = "std")]
fn main() {}

Просмотреть файл

@ -0,0 +1,19 @@
error: proc-macro derive panicked
--> $DIR/enum_prefix_missing.rs:22:10
|
22 | #[derive(Display)]
| ^^^^^^^
|
= help: message: Missing doc comment on enum with #[prefix_enum_doc_attributes]. Please remove the attribute or add a doc comment to the enum itself.
error[E0277]: `TestType` doesn't implement `std::fmt::Display`
--> $DIR/enum_prefix_missing.rs:32:44
|
32 | static_assertions::assert_impl_all!(label; TestType, core::fmt::Display);
| -------------------------------------------^^^^^^^^----------------------
| | |
| | `TestType` cannot be formatted with the default formatter
| required by this bound in `assert_impl_all`
|
= help: the trait `std::fmt::Display` is not implemented for `TestType`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead

37
third_party/rust/displaydoc/tests/std/multi_line.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,37 @@
#![cfg_attr(not(feature = "std"), feature(lang_items, start))]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg_attr(not(feature = "std"), start)]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"]
#[no_mangle]
#[cfg(not(feature = "std"))]
pub extern "C" fn rust_eh_personality() {}
#[panic_handler]
#[cfg(not(feature = "std"))]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
libc::abort();
}
}
use displaydoc::Display;
/// this type is pretty swell
#[derive(Display)]
enum TestType {
/// This one is okay
Variant1,
/// Multi
/// line
/// doc.
Variant2,
}
static_assertions::assert_impl_all!(label; TestType, core::fmt::Display);
#[cfg(feature = "std")]
fn main() {}

19
third_party/rust/displaydoc/tests/std/multi_line.stderr поставляемый Normal file
Просмотреть файл

@ -0,0 +1,19 @@
error: proc-macro derive panicked
--> $DIR/multi_line.rs:23:10
|
23 | #[derive(Display)]
| ^^^^^^^
|
= help: message: Multi-line comments are disabled by default by displaydoc. Please consider using block doc comments (/** */) or adding the #[ignore_extra_doc_attributes] attribute to your type next to the derive.
error[E0277]: `TestType` doesn't implement `std::fmt::Display`
--> $DIR/multi_line.rs:34:44
|
34 | static_assertions::assert_impl_all!(label; TestType, core::fmt::Display);
| -------------------------------------------^^^^^^^^----------------------
| | |
| | `TestType` cannot be formatted with the default formatter
| required by this bound in `assert_impl_all`
|
= help: the trait `std::fmt::Display` is not implemented for `TestType`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead

38
third_party/rust/displaydoc/tests/std/multi_line_allow.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,38 @@
#![cfg_attr(not(feature = "std"), feature(lang_items, start))]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg_attr(not(feature = "std"), start)]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"]
#[no_mangle]
#[cfg(not(feature = "std"))]
pub extern "C" fn rust_eh_personality() {}
#[panic_handler]
#[cfg(not(feature = "std"))]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
libc::abort();
}
}
use displaydoc::Display;
/// this type is pretty swell
#[derive(Display)]
#[ignore_extra_doc_attributes]
enum TestType {
/// This one is okay
Variant1,
/// Multi
/// line
/// doc.
Variant2,
}
static_assertions::assert_impl_all!(label; TestType, core::fmt::Display);
#[cfg(feature = "std")]
fn main() {}

38
third_party/rust/displaydoc/tests/std/multiple.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,38 @@
#![feature(lang_items, start)]
#![no_std]
#[start]
#[cfg(not(feature = "std"))]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"]
#[no_mangle]
#[cfg(not(feature = "std"))]
pub extern "C" fn rust_eh_personality() {}
#[panic_handler]
#[cfg(not(feature = "std"))]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
libc::abort();
}
}
#[cfg(feature = "std")]
fn main() {}
use displaydoc::Display;
/// this type is pretty swell
#[derive(Display)]
struct FakeType;
static_assertions::assert_impl_all!(label; FakeType, core::fmt::Display);
/// this type is pretty swell2
#[derive(Display)]
struct FakeType2;
static_assertions::assert_impl_all!(label2; FakeType2, core::fmt::Display);

28
third_party/rust/displaydoc/tests/std/without.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,28 @@
#![cfg_attr(not(feature = "std"), feature(lang_items, start))]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg_attr(not(feature = "std"), start)]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"]
#[no_mangle]
#[cfg(not(feature = "std"))]
pub extern "C" fn rust_eh_personality() {}
#[panic_handler]
#[cfg(not(feature = "std"))]
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe {
libc::abort();
}
}
use displaydoc::Display;
/// this type is pretty swell
struct FakeType;
static_assertions::assert_impl_all!(label; FakeType, core::fmt::Display);
#[cfg(feature = "std")]
fn main() {}

19
third_party/rust/displaydoc/tests/std/without.stderr поставляемый Normal file
Просмотреть файл

@ -0,0 +1,19 @@
warning: unused import: `displaydoc::Display`
--> $DIR/without.rs:20:5
|
20 | use displaydoc::Display;
| ^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error[E0277]: `FakeType` doesn't implement `std::fmt::Display`
--> $DIR/without.rs:25:44
|
25 | static_assertions::assert_impl_all!(label; FakeType, core::fmt::Display);
| -------------------------------------------^^^^^^^^----------------------
| | |
| | `FakeType` cannot be formatted with the default formatter
| required by this bound in `assert_impl_all`
|
= help: the trait `std::fmt::Display` is not implemented for `FakeType`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"3b7451d96ed662827dd4163d64d96840fee1c4241c2480b8cdd91ef156ad7896","README.md":"4dad9bc033a67101bc318662c055318457f0b91e12fdc0a566495b455ceeb4b8","benches/pluralrules.rs":"9c80009fa94a8dbf31bdba489f320d92a40f482c37149030fbba53cd62b5435f","src/lib.rs":"a642fa4b7147731449acf39650fc92e764716de8303d9637c3263ae3ae03b899","src/operands.rs":"b58c9f8f0f7ce4622ccc685f08b15ede09591b628deffa3b14abde873d26c44a","src/rules.rs":"7b3f0c12e0722401efbdb54873e8545f943bf4a34cba9f894ead9dc955112aaf"},"package":"b18f988384267d7066cc2be425e6faf352900652c046b6971d2e228d3b1c5ecf"}
{"files":{"Cargo.toml":"595634ece6249e274c389db766170aa88f78df41e8887d333a7cac8dad6b0bed","README.md":"7516007e35aa847bf81b8b94f45181f532bdc0aad3e389efd14691fa3aace3f0","benches/pluralrules.rs":"9c80009fa94a8dbf31bdba489f320d92a40f482c37149030fbba53cd62b5435f","src/lib.rs":"054fd83f1e8b42ef7866ec681c59617952cad48f578ca338e945d2a99178ea7d","src/operands.rs":"68d920f66ed67f361b3b0387844dbb8db57fad660f84cfcb361d8f4f5157832a","src/rules.rs":"7b3f0c12e0722401efbdb54873e8545f943bf4a34cba9f894ead9dc955112aaf"},"package":"078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972"}

40
third_party/rust/intl_pluralrules/Cargo.toml поставляемый
Просмотреть файл

@ -3,40 +3,56 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "intl_pluralrules"
version = "7.0.1"
authors = ["Kekoa Riggin <kekoariggin@gmail.com>", "Zibi Braniecki <zbraniecki@mozilla.com>"]
include = ["src/**/*", "benches/*.rs", "Cargo.toml", "README.md"]
version = "7.0.2"
authors = [
"Kekoa Riggin <kekoariggin@gmail.com>",
"Zibi Braniecki <zbraniecki@mozilla.com>",
]
include = [
"src/**/*",
"benches/*.rs",
"Cargo.toml",
"README.md",
]
description = "Unicode Plural Rules categorizer for numeric input."
readme = "README.md"
keywords = ["localization", "l10n", "i18n", "intl", "internationalization"]
categories = ["localization", "internationalization"]
keywords = [
"localization",
"l10n",
"i18n",
"intl",
"internationalization",
]
categories = [
"localization",
"internationalization",
]
license = "Apache-2.0/MIT"
repository = "https://github.com/zbraniecki/pluralrules"
[[bench]]
name = "pluralrules"
harness = false
[dependencies.tinystr]
version = "0.3.2"
[dependencies.unic-langid]
version = "0.9"
[dev-dependencies.criterion]
version = "0.3"
[dev-dependencies.unic-langid]
version = "0.9"
features = ["macros"]
[badges.coveralls]
branch = "master"
repository = "zbraniecki/pluralrules"

10
third_party/rust/intl_pluralrules/README.md поставляемый
Просмотреть файл

@ -1,9 +1,9 @@
# INTL Plural Rules
`intl_pluralrules` categorizes numbers by plural operands. See [Unicode Plural Rules](http://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules)
`intl_pluralrules` categorizes numbers by plural operands. See [Unicode Plural Rules](https://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules)
[![crates.io](http://meritbadge.herokuapp.com/intl_pluralrules)](https://crates.io/crates/intl_pluralrules)
[![crates.io](https://img.shields.io/crates/v/intl_pluralrules.svg)](https://crates.io/crates/intl_pluralrules)
[![Build Status](https://travis-ci.org/zbraniecki/pluralrules.svg?branch=master)](https://travis-ci.org/zbraniecki/pluralrules)
[![Coverage Status](https://coveralls.io/repos/github/zbraniecki/pluralrules/badge.svg?branch=master)](https://coveralls.io/github/zbraniecki/pluralrules?branch=master)
@ -37,6 +37,6 @@ Contributors
Thank you to all contributors!
[CLDR]: http://cldr.unicode.org/
[PluralRules]: http://cldr.unicode.org/index/cldr-spec/plural-rules
[LDML Language Plural Rules Syntax]: http://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules
[CLDR]: https://cldr.unicode.org/
[PluralRules]: https://cldr.unicode.org/index/cldr-spec/plural-rules
[LDML Language Plural Rules Syntax]: https://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules

Просмотреть файл

@ -1,6 +1,6 @@
//! A crate for generating plural rule operands from numberical input.
//!
//! This crate generates plural operands according to the specifications outlined at [Unicode's website](http://unicode.org/reports/tr35/tr35-numbers.html#Operands).
//! This crate generates plural operands according to the specifications outlined at [Unicode's website](https://unicode.org/reports/tr35/tr35-numbers.html#Operands).
//!
//! Input is supported for int, float, and &str.
//!

Просмотреть файл

@ -1,6 +1,6 @@
//! Plural operands in compliance with [CLDR Plural Rules](http://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules).
//! Plural operands in compliance with [CLDR Plural Rules](https://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules).
//!
//! See [full operands description](http://unicode.org/reports/tr35/tr35-numbers.html#Operands).
//! See [full operands description](https://unicode.org/reports/tr35/tr35-numbers.html#Operands).
//!
//! # Examples
//!
@ -53,7 +53,7 @@ use std::convert::TryFrom;
use std::isize;
use std::str::FromStr;
/// A full plural operands representation of a number. See [CLDR Plural Rules](http://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules) for complete operands description.
/// A full plural operands representation of a number. See [CLDR Plural Rules](https://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules) for complete operands description.
#[derive(Debug, PartialEq)]
pub struct PluralOperands {
/// Absolute value of input

Просмотреть файл

@ -1 +1 @@
{"files":{"CHANGELOG.md":"cb378d2a5c7efd2259cdb7513e1a6bc8bc05b2c5f89b69b69f1f16037495760b","Cargo.lock":"c772766a0c3008c0e528d1ef08c5d8b0e8752a308cb5a782855f691c4b3c223f","Cargo.toml":"af00927b1bd3451ef45685cb34c466566df816aa41f31555c9492c74af597c2c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"7eaffe990ac4432ab388dcda2703f5594e9b1c7a6f753882906b0b8df9876bb4","benches/construct.rs":"9c8652afb0770f60238952b06abb4b90c6cec41d50fd19b760e573eb8dff8e4f","benches/tinystr.rs":"dc61b52ca7be3312a8c504786ad60e5e2c4c729e111c2033716c9996c5e87bc8","examples/main.rs":"463f7c0db47a3843097b012315fc8b0d68baa4afca0a0fe06210ed3c8c471453","src/helpers.rs":"d7768b34dacbb586ade41249147bce1c90d1c08dbfd7c7de6792c88ea45200e1","src/lib.rs":"17740bacc4b05e433f58ddd06d86287097f83024849166e95e8ddb16e491873f","src/tinystr16.rs":"b40595634190ee298bbdcb60b3699b11a25ef2861bccdb567821815ff21fbac3","src/tinystr4.rs":"1787c52e9ec9711b0a115f4c32bee952fb410ce569db4a89fef4c5282bb4f04f","src/tinystr8.rs":"2baf0330c3a20e2e01ff791aa932450d2727d53eb8ed80d76a685bdd824700b6","src/tinystrauto.rs":"55b9333cd8a69e8ea79db72801c4f2b946c5b61108e1ddfb2bf2e06384c41f4a","tests/main.rs":"83b1892f2c5437f99be3ce6d5e98a8df42a5c293447437cc567dcc133a2768d7"},"package":"29738eedb4388d9ea620eeab9384884fc3f06f586a2eddb56bedc5885126c7c1"}
{"files":{"Cargo.toml":"279fef44ae26d0bda43cc629cbe22795d696b36635fcb7ca484e74b9d72b9eb4","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"ce7d4b009ab4878b4b647fa5c01037b4d3e8bf72e44942dbf6cf1ef217d10b4d","benches/common/mod.rs":"7a31f89cb68cec2574287636ac22fe3fc86a66688b8b1e99700a5da692bd485e","benches/construct.rs":"0e0e7c1459dd3efea0c734a999318078b53e18c3389c74a1ff5a226cd3d05cca","benches/overview.rs":"296d19b32a2d52e449140771d89f9c099d19177eb84e1395c942469d51c4c3f8","benches/read.rs":"cbf349393a50eb90e7ba53906f98a689d585242292f867a37acf6842263af4d9","benches/serde.rs":"5c88866d08c07088b82dbd5472e6276c632d11e064417f5d8f2025a5ade867f0","src/ascii.rs":"ca84603237893d515cf4d3cc5bf61470a81c499956b8bdf51239433c0d49785e","src/asciibyte.rs":"fa29de7403c0424c52c2f30bb47002b9abf4bd08b302c411ffe679d3decfb8de","src/databake.rs":"9f29e30e6deec989822cbdf01f5165e098fa544cf7e49ccea3f5de827648fc1e","src/error.rs":"859d03faa3e98d979e0d6b5d232810d42b58f9c6ef69403d442545327053265e","src/int_ops.rs":"c2be314d19dd41cf18fb3589901d7e58ee32fe3f764fb6a66b08a1e005336406","src/lib.rs":"41db27f31650945dbf41b72a21d42fa4de0722b6f0717a45a3569c3dd4f1e148","src/macros.rs":"3fe76e258b0db2896284bcf4f50a4ac35b7efc542649b4c9f13c6e71c5957ae4","src/serde.rs":"0bd6bbe2ee8195aea68dd235d59b94faa3419aaeb8939e3220dd64bd888873f5","src/ule.rs":"139543634949a95405bc49862840b0794db089abed6efe66533858376cae180f","tests/serde.rs":"cf8cee82f731928375888d1b5e7e5e50368d3e16ce372fced230c9b1ee2a7451"},"package":"f8aeafdfd935e4a7fe16a91ab711fa52d54df84f9c8f7ca5837a9d1d902ef4c2"}

35
third_party/rust/tinystr/CHANGELOG.md поставляемый
Просмотреть файл

@ -1,35 +0,0 @@
# Changelog
## Unreleased
- …
## tinystr 0.3.4 (August 21, 2020)
- Add `macros` feature which exposes `tinystr::macros`.
## tinystr 0.3.3 (July 26, 2020)
- Add `TinyStrAuto`.
- Add `no_std` feature.
## tinystr 0.3.2 (October 28, 2019)
- Add `from_bytes` method.
## tinystr 0.3.1 (October 1, 2019)
- Documentation.
## tinystr 0.3.1 (October 1, 2019)
- Documentation.
## tinystr 0.3.0 (August 23, 2019)
- Separate out `is_ascii_numeric`, `is_ascii_alphanumeric` and `is_ascii_alphabetic`.
## tinystr 0.2.0 (August 16, 2019)
- Add TinyStr16
- Add to_ascii_titlecase specialization for all TinyStr*

625
third_party/rust/tinystr/Cargo.lock сгенерированный поставляемый
Просмотреть файл

@ -1,625 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bstr"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931"
dependencies = [
"lazy_static",
"memchr",
"regex-automata",
"serde",
]
[[package]]
name = "bumpalo"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
[[package]]
name = "byteorder"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
[[package]]
name = "cast"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0"
dependencies = [
"rustc_version",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "clap"
version = "2.33.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
dependencies = [
"bitflags",
"textwrap",
"unicode-width",
]
[[package]]
name = "criterion"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70daa7ceec6cf143990669a04c7df13391d55fb27bd4079d252fca774ba244d8"
dependencies = [
"atty",
"cast",
"clap",
"criterion-plot",
"csv",
"itertools",
"lazy_static",
"num-traits",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_cbor",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d"
dependencies = [
"cast",
"itertools",
]
[[package]]
name = "crossbeam-deque"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
"maybe-uninit",
]
[[package]]
name = "crossbeam-epoch"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"lazy_static",
"maybe-uninit",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-queue"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570"
dependencies = [
"cfg-if",
"crossbeam-utils",
"maybe-uninit",
]
[[package]]
name = "crossbeam-utils"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
dependencies = [
"autocfg",
"cfg-if",
"lazy_static",
]
[[package]]
name = "csv"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279"
dependencies = [
"bstr",
"csv-core",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "csv-core"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
dependencies = [
"memchr",
]
[[package]]
name = "either"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
[[package]]
name = "half"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177"
[[package]]
name = "hermit-abi"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
dependencies = [
"libc",
]
[[package]]
name = "itertools"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
[[package]]
name = "js-sys"
version = "0.3.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4b9172132a62451e56142bff9afc91c8e4a4500aa5b847da36815b63bfda916"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
[[package]]
name = "log"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
dependencies = [
"cfg-if",
]
[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]]
name = "memchr"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
[[package]]
name = "memoffset"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c198b026e1bbf08a937e94c6c60f9ec4a2267f5b0d2eec9c1b21b061ce2be55f"
dependencies = [
"autocfg",
]
[[package]]
name = "num-traits"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "oorandom"
version = "11.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a170cebd8021a008ea92e4db85a72f80b35df514ec664b296fdcbb654eac0b2c"
[[package]]
name = "plotters"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d1685fbe7beba33de0330629da9d955ac75bd54f33d7b79f9a895590124f6bb"
dependencies = [
"js-sys",
"num-traits",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "proc-macro2"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f02856753d04e03e26929f820d0a0a337ebe71f849801eea335d464b349080"
dependencies = [
"autocfg",
"crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e92e15d89083484e11353891f1af602cc661426deb9564c298b270c726973280"
dependencies = [
"crossbeam-deque",
"crossbeam-queue",
"crossbeam-utils",
"lazy_static",
"num_cpus",
]
[[package]]
name = "regex"
version = "1.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
dependencies = [
"byteorder",
]
[[package]]
name = "regex-syntax"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[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 = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3"
[[package]]
name = "serde_cbor"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622"
dependencies = [
"half",
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3433e879a558dde8b5e8feb2a04899cf34fdde1fafb894687e52105fc1162ac3"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "syn"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8d5d96e8cbb005d6959f119f773bfaebb5684296108fb32600c00cde305b2cd"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "tinystr"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707151f004e8db265b83b1c7509d6c3b4c2c2bc8696113cbe0a8e595c2fdbd3b"
[[package]]
name = "tinystr"
version = "0.3.4"
dependencies = [
"criterion",
"tinystr-macros",
]
[[package]]
name = "tinystr-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c97a45afd04e6bf6d5945895d6982afd9a428e0ebf66585d5e09961d8319ac30"
dependencies = [
"tinystr 0.3.3",
]
[[package]]
name = "tinytemplate"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d3dc76004a03cec1c5932bca4cdc2e39aaa798e3f82363dd94f9adf6098c12f"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "walkdir"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
dependencies = [
"same-file",
"winapi",
"winapi-util",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a634620115e4a229108b71bde263bb4220c483b3f07f5ba514ee8d15064c4c2"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e53963b583d18a5aa3aaae4b4c1cb535218246131ba22a71f05b518098571df"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fcfd5ef6eec85623b4c6e844293d4516470d8f19cd72d0d12246017eb9060b8"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9adff9ee0e94b926ca81b57f57f86d5545cdcb1d259e21ec9bdd95b901754c75"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f7b90ea6c632dd06fd765d44542e234d5e63d9bb917ecd64d79778a13bd79ae"
[[package]]
name = "web-sys"
version = "0.3.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "863539788676619aac1a23e2df3655e96b32b0e05eb72ca34ba045ad573c625d"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

108
third_party/rust/tinystr/Cargo.toml поставляемый
Просмотреть файл

@ -3,40 +3,112 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
edition = "2021"
name = "tinystr"
version = "0.3.4"
authors = ["Raph Levien <raph.levien@gmail.com>", "Zibi Braniecki <zibi@braniecki.net>"]
description = "A small ASCII-only bounded length string representation.\n"
readme = "README.md"
keywords = ["string", "str", "small", "tiny", "no_std"]
version = "0.7.0"
authors = ["The ICU4X Project Developers"]
include = [
"src/**/*",
"examples/**/*",
"benches/**/*",
"tests/**/*",
"Cargo.toml",
"LICENSE",
"README.md",
]
description = "A small ASCII-only bounded length string representation."
keywords = [
"string",
"str",
"small",
"tiny",
"no_std",
]
categories = ["data-structures"]
license = "Apache-2.0/MIT"
repository = "https://github.com/zbraniecki/tinystr"
license = "Unicode-DFS-2016"
repository = "https://github.com/unicode-org/icu4x"
resolver = "2"
[package.metadata.docs.rs]
all-features = true
[[test]]
name = "serde"
required-features = ["serde"]
[[bench]]
name = "overview"
harness = false
[[bench]]
name = "construct"
harness = false
required-features = ["bench"]
[[bench]]
name = "tinystr"
name = "read"
harness = false
[dependencies.tinystr-macros]
required-features = ["bench"]
[[bench]]
name = "serde"
harness = false
required-features = [
"bench",
"serde",
]
[dependencies.databake]
version = "0.1"
optional = true
[dependencies.displaydoc]
version = "0.2.3"
default-features = false
[dependencies.serde]
version = "1.0.123"
features = ["alloc"]
optional = true
default-features = false
[dependencies.zerovec]
version = "0.9"
optional = true
[dev-dependencies.bincode]
version = "1.3"
[dev-dependencies.criterion]
version = "0.3"
[dev-dependencies.postcard]
version = "1.0.0"
features = ["use-std"]
[dev-dependencies.rand]
version = "0.8.5"
features = ["small_rng"]
[dev-dependencies.serde_json]
version = "1.0"
features = ["alloc"]
default-features = false
[dev-dependencies.tinystr_old]
version = "0.4"
features = ["serde"]
package = "tinystr"
[features]
alloc = []
default = ["std"]
macros = ["tinystr-macros"]
std = []
bench = []
default = ["alloc"]
zerovec = ["dep:zerovec"]

51
third_party/rust/tinystr/LICENSE поставляемый Normal file
Просмотреть файл

@ -0,0 +1,51 @@
UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
See Terms of Use <https://www.unicode.org/copyright.html>
for definitions of Unicode Inc.s Data Files and Software.
NOTICE TO USER: Carefully read the following legal agreement.
BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S
DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"),
YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
TERMS AND CONDITIONS OF THIS AGREEMENT.
IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE
THE DATA FILES OR SOFTWARE.
COPYRIGHT AND PERMISSION NOTICE
Copyright © 1991-2022 Unicode, Inc. All rights reserved.
Distributed under the Terms of Use in https://www.unicode.org/copyright.html.
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Unicode data files and any associated documentation
(the "Data Files") or Unicode software and any associated documentation
(the "Software") to deal in the Data Files or Software
without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, and/or sell copies of
the Data Files or Software, and to permit persons to whom the Data Files
or Software are furnished to do so, provided that either
(a) this copyright and permission notice appear with all copies
of the Data Files or Software, or
(b) this copyright and permission notice appear in associated
Documentation.
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THE DATA FILES OR SOFTWARE.
Except as contained in this notice, the name of a copyright holder
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in these Data Files or Software without prior
written authorization of the copyright holder.
Portions of ICU4X may have been adapted from ICU4C and/or ICU4J.
ICU 1.8.1 to ICU 57.1 © 1995-2016 International Business Machines Corporation and others.

118
third_party/rust/tinystr/README.md поставляемый
Просмотреть файл

@ -1,95 +1,53 @@
# tinystr [![crates.io](http://meritbadge.herokuapp.com/tinystr)](https://crates.io/crates/tinystr) [![Build Status](https://travis-ci.org/zbraniecki/tinystr.svg?branch=master)](https://travis-ci.org/zbraniecki/tinystr) [![Coverage Status](https://coveralls.io/repos/github/zbraniecki/tinystr/badge.svg?branch=master)](https://coveralls.io/github/zbraniecki/tinystr?branch=master)
# tinystr [![crates.io](https://img.shields.io/crates/v/tinystr)](https://crates.io/crates/tinystr)
`tinystr` is a small ASCII-only bounded length string representation.
`tinystr` is a utility crate of the [`ICU4X`] project.
Usage
-----
It includes [`TinyAsciiStr`], a core API for representing small ASCII-only bounded length strings.
It is optimized for operations on strings of size 8 or smaller. When use cases involve comparison
and conversion of strings for lowercase/uppercase/titlecase, or checking
numeric/alphabetic/alphanumeric, `TinyAsciiStr` is the edge performance library.
## Examples
```rust
use tinystr::{TinyStr4, TinyStr8, TinyStr16, TinyStrAuto};
use tinystr::TinyAsciiStr;
fn main() {
let s1: TinyStr4 = "tEsT".parse()
.expect("Failed to parse.");
let s1: TinyAsciiStr<4> = "tEsT".parse().expect("Failed to parse.");
assert_eq!(s1, "tEsT");
assert_eq!(s1.to_ascii_uppercase(), "TEST");
assert_eq!(s1.to_ascii_lowercase(), "test");
assert_eq!(s1.to_ascii_titlecase(), "Test");
assert_eq!(s1.is_ascii_alphanumeric(), true);
assert_eq!(s1, "tEsT");
assert_eq!(s1.to_ascii_uppercase(), "TEST");
assert_eq!(s1.to_ascii_lowercase(), "test");
assert_eq!(s1.to_ascii_titlecase(), "Test");
assert_eq!(s1.is_ascii_alphanumeric(), true);
assert_eq!(s1.is_ascii_numeric(), false);
let s2: TinyStr8 = "New York".parse()
.expect("Failed to parse.");
let s2 = TinyAsciiStr::<8>::try_from_raw(*b"New York")
.expect("Failed to parse.");
assert_eq!(s2, "New York");
assert_eq!(s2.to_ascii_uppercase(), "NEW YORK");
assert_eq!(s2.to_ascii_lowercase(), "new york");
assert_eq!(s2.to_ascii_titlecase(), "New york");
assert_eq!(s2.is_ascii_alphanumeric(), false);
let s3: TinyStr16 = "metaMoRphosis123".parse()
.expect("Failed to parse.");
assert_eq!(s3, "metaMoRphosis123");
assert_eq!(s3.to_ascii_uppercase(), "METAMORPHOSIS123");
assert_eq!(s3.to_ascii_lowercase(), "metamorphosis123");
assert_eq!(s3.to_ascii_titlecase(), "Metamorphosis123");
assert_eq!(s3.is_ascii_alphanumeric(), true);
let s4: TinyStrAuto = "shortNoAlloc".parse().unwrap();
assert!(matches!(s4, TinyStrAuto::Tiny { .. }));
assert_eq!(s4, "shortNoAlloc");
let s5: TinyStrAuto = "longFallbackToHeap".parse().unwrap();
assert!(matches!(s4, TinyStrAuto::Heap { .. }));
assert_eq!(s4, "shortNoAlloc");
}
assert_eq!(s2, "New York");
assert_eq!(s2.to_ascii_uppercase(), "NEW YORK");
assert_eq!(s2.to_ascii_lowercase(), "new york");
assert_eq!(s2.to_ascii_titlecase(), "New york");
assert_eq!(s2.is_ascii_alphanumeric(), false);
```
Details
-------
## Details
The crate provides three structs and an enum:
* `TinyStr4` an ASCII-only string limited to 4 characters.
* `TinyStr8` an ASCII-only string limited to 8 characters.
* `TinyStr16` an ASCII-only string limited to 16 characters.
* `TinyStrAuto` (enum):
* `Tiny` when the string is 16 characters or less.
* `Heap` when the string is 17 or more characters.
When strings are of size 8 or smaller, the struct transforms the strings as `u32`/`u64` and uses
bitmasking to provide basic string manipulation operations:
* `is_ascii_numeric`
* `is_ascii_alphabetic`
* `is_ascii_alphanumeric`
* `to_ascii_lowercase`
* `to_ascii_uppercase`
* `to_ascii_titlecase`
* `PartialEq`
The structs stores the characters as `u32`/`u64`/`u128` and uses bitmasking to provide basic string manipulation operations:
* is_ascii_numeric
* is_ascii_alphabetic
* is_ascii_alphanumeric
* to_ascii_lowercase
* to_ascii_uppercase
* to_ascii_titlecase
* PartialEq
`TinyAsciiStr` will fall back to `u8` character manipulation for strings of length greater than 8.
`TinyStrAuto` stores the string as a TinyStr16 when it is short enough, or else falls back to a standard `String`. You should use TinyStrAuto when you expect most strings to be 16 characters or smaller, but occasionally you receive one that exceeds that length. Unlike the structs, `TinyStrAuto` does not implement `Copy`.
[`ICU4X`]: ../icu/index.html
This set is sufficient for certain classes of uses such as `unic-langid` libraries.
## More Information
no_std
------
Disable the `std` feature of this crate to make it `#[no_std]`. Doing so disables `TinyStrAuto`. You
can re-enable `TinyStrAuto` in `#[no_std]` mode by enabling the `alloc` feature.
Performance
-----------
For those uses, TinyStr provides [performance characteristics](https://github.com/zbraniecki/tinystr/wiki/Performance) much better than the regular `String`.
Status
------
The crate is fully functional and ready to be used in production.
The capabilities can be extended.
#### License
<sup>
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
</sup
For more information on development, authorship, contributing etc. please visit [`ICU4X home page`](https://github.com/unicode-org/icu4x).

79
third_party/rust/tinystr/benches/common/mod.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,79 @@
// 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 file was adapted from parts of https://github.com/zbraniecki/tinystr
pub static STRINGS_4: &[&str] = &[
"US", "GB", "AR", "Hans", "CN", "AT", "PL", "FR", "AT", "Cyrl", "SR", "NO", "FR", "MK", "UK",
];
pub static STRINGS_8: &[&str] = &[
"Latn", "windows", "AR", "Hans", "macos", "AT", "pl", "FR", "en", "Cyrl", "SR", "NO", "419",
"und", "UK",
];
pub static STRINGS_16: &[&str] = &[
"Latn",
"windows",
"AR",
"Hans",
"macos",
"AT",
"infiniband",
"FR",
"en",
"Cyrl",
"FromIntegral",
"NO",
"419",
"MacintoshOSX2019",
"UK",
];
#[macro_export]
macro_rules! bench_block {
($c:expr, $name:expr, $action:ident) => {
let mut group4 = $c.benchmark_group(&format!("{}/4", $name));
group4.bench_function("String", $action!(String, STRINGS_4));
group4.bench_function("TinyAsciiStr<4>", $action!(TinyAsciiStr<4>, STRINGS_4));
group4.bench_function(
"tinystr_old::TinyStr4",
$action!(tinystr_old::TinyStr4, STRINGS_4),
);
group4.bench_function("TinyAsciiStr<8>", $action!(TinyAsciiStr<8>, STRINGS_4));
group4.bench_function(
"tinystr_old::TinyStr8",
$action!(tinystr_old::TinyStr8, STRINGS_4),
);
group4.bench_function("TinyAsciiStr<16>", $action!(TinyAsciiStr<16>, STRINGS_4));
group4.bench_function(
"tinystr_old::TinyStr16",
$action!(tinystr_old::TinyStr16, STRINGS_4),
);
group4.finish();
let mut group8 = $c.benchmark_group(&format!("{}/8", $name));
group8.bench_function("String", $action!(String, STRINGS_8));
group8.bench_function("TinyAsciiStr<8>", $action!(TinyAsciiStr<8>, STRINGS_8));
group8.bench_function("TinyAsciiStr<16>", $action!(TinyAsciiStr<16>, STRINGS_8));
group8.bench_function(
"tinystr_old::TinyStr8",
$action!(tinystr_old::TinyStr8, STRINGS_8),
);
group8.bench_function(
"tinystr_old::TinyStr16",
$action!(tinystr_old::TinyStr16, STRINGS_8),
);
group8.finish();
let mut group16 = $c.benchmark_group(&format!("{}/16", $name));
group16.bench_function("String", $action!(String, STRINGS_16));
group16.bench_function("TinyAsciiStr<16>", $action!(TinyAsciiStr<16>, STRINGS_16));
group16.bench_function(
"tinystr_old::TinyStr16",
$action!(tinystr_old::TinyStr16, STRINGS_16),
);
group16.finish();
};
}

175
third_party/rust/tinystr/benches/construct.rs поставляемый
Просмотреть файл

@ -1,91 +1,41 @@
// 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 file was adapted from https://github.com/zbraniecki/tinystr
mod common;
use common::*;
use criterion::black_box;
use criterion::criterion_group;
use criterion::criterion_main;
use criterion::Bencher;
use criterion::Criterion;
use criterion::Fun;
use tinystr::{TinyStr16, TinyStr4, TinyStr8, TinyStrAuto};
static STRINGS_4: &[&str] = &[
"US", "GB", "AR", "Hans", "CN", "AT", "PL", "FR", "AT", "Cyrl", "SR", "NO", "FR", "MK", "UK",
];
static STRINGS_8: &[&str] = &[
"Latn", "windows", "AR", "Hans", "macos", "AT", "pl", "FR", "en", "Cyrl", "SR", "NO", "419",
"und", "UK",
];
static STRINGS_16: &[&str] = &[
"Latn",
"windows",
"AR",
"Hans",
"macos",
"AT",
"infiniband",
"FR",
"en",
"Cyrl",
"FromIntegral",
"NO",
"419",
"MacintoshOSX2019",
"UK",
];
macro_rules! bench_block {
($c:expr, $name:expr, $action:ident) => {
let funcs = vec![
Fun::new("String", $action!(String)),
Fun::new("TinyStr4", $action!(TinyStr4)),
Fun::new("TinyStr8", $action!(TinyStr8)),
Fun::new("TinyStr16", $action!(TinyStr16)),
Fun::new("TinyStrAuto", $action!(TinyStrAuto)),
];
$c.bench_functions(&format!("{}/4", $name), funcs, STRINGS_4);
let funcs = vec![
Fun::new("String", $action!(String)),
Fun::new("TinyStr8", $action!(TinyStr8)),
Fun::new("TinyStr16", $action!(TinyStr16)),
Fun::new("TinyStrAuto", $action!(TinyStrAuto)),
];
$c.bench_functions(&format!("{}/8", $name), funcs, STRINGS_8);
let funcs = vec![
Fun::new("String", $action!(String)),
Fun::new("TinyStr16", $action!(TinyStr16)),
Fun::new("TinyStrAuto", $action!(TinyStrAuto)),
];
$c.bench_functions(&format!("{}/16", $name), funcs, STRINGS_16);
};
}
use tinystr::TinyAsciiStr;
fn construct_from_str(c: &mut Criterion) {
macro_rules! cfs {
($r:ty) => {
|b: &mut Bencher, strings: &&[&str]| {
($r:ty, $inputs:expr) => {
|b: &mut Bencher| {
b.iter(|| {
for s in *strings {
for s in $inputs {
let _: $r = black_box(s.parse().unwrap());
}
})
}
};
};
}
bench_block!(c, "construct_from_str", cfs);
}
fn construct_from_bytes(c: &mut Criterion) {
macro_rules! cfu {
($r:ty) => {
|b, inputs: &&[&str]| {
let raw: Vec<&[u8]> = inputs.iter().map(|s| s.as_bytes()).collect();
($r:ty, $inputs:expr) => {
|b| {
let raw: Vec<&[u8]> = $inputs.iter().map(|s| s.as_bytes()).collect();
b.iter(move || {
for u in &raw {
let _ = black_box(<$r>::from_bytes(*u).unwrap());
@ -93,62 +43,47 @@ fn construct_from_bytes(c: &mut Criterion) {
})
}
};
};
}
let funcs = vec![
Fun::new("TinyStr4", cfu!(TinyStr4)),
Fun::new("TinyStr8", cfu!(TinyStr8)),
Fun::new("TinyStr16", cfu!(TinyStr16)),
];
let mut group4 = c.benchmark_group("construct_from_bytes/4");
group4.bench_function("TinyAsciiStr<4>", cfu!(TinyAsciiStr<4>, STRINGS_4));
group4.bench_function(
"tinystr_old::TinyStr4",
cfu!(tinystr_old::TinyStr4, STRINGS_4),
);
group4.bench_function("TinyAsciiStr<8>", cfu!(TinyAsciiStr<8>, STRINGS_4));
group4.bench_function(
"tinystr_old::TinyStr8",
cfu!(tinystr_old::TinyStr8, STRINGS_4),
);
group4.bench_function("TinyAsciiStr<16>", cfu!(TinyAsciiStr<16>, STRINGS_4));
group4.bench_function(
"tinystr_old::TinyStr16",
cfu!(tinystr_old::TinyStr16, STRINGS_4),
);
group4.finish();
c.bench_functions("construct_from_bytes/4", funcs, STRINGS_4);
let mut group8 = c.benchmark_group("construct_from_bytes/8");
group8.bench_function("TinyAsciiStr<8>", cfu!(TinyAsciiStr<8>, STRINGS_8));
group8.bench_function(
"tinystr_old::TinyStr8",
cfu!(tinystr_old::TinyStr8, STRINGS_8),
);
group8.bench_function("TinyAsciiStr<16>", cfu!(TinyAsciiStr<16>, STRINGS_8));
group8.bench_function(
"tinystr_old::TinyStr16",
cfu!(tinystr_old::TinyStr16, STRINGS_8),
);
group8.finish();
let funcs = vec![
Fun::new("TinyStr8", cfu!(TinyStr8)),
Fun::new("TinyStr16", cfu!(TinyStr16)),
];
c.bench_functions("construct_from_bytes/8", funcs, STRINGS_8);
let funcs = vec![Fun::new("TinyStr16", cfu!(TinyStr16))];
c.bench_functions("construct_from_bytes/16", funcs, STRINGS_16);
let mut group16 = c.benchmark_group("construct_from_bytes/16");
group16.bench_function("TinyAsciiStr<16>", cfu!(TinyAsciiStr<16>, STRINGS_16));
group16.bench_function(
"tinystr_old::TinyStr16",
cfu!(tinystr_old::TinyStr16, STRINGS_16),
);
group16.finish();
}
fn construct_unchecked(c: &mut Criterion) {
macro_rules! cu {
($tty:ty, $rty:ty) => {
|b, inputs: &&[&str]| {
let raw: Vec<$rty> = inputs
.iter()
.map(|s| s.parse::<$tty>().unwrap().into())
.collect();
b.iter(move || {
for num in &raw {
let _ = unsafe { <$tty>::new_unchecked(black_box(*num)) };
}
})
}
};
};
let funcs = vec![Fun::new("TinyStr4", cu!(TinyStr4, u32))];
c.bench_functions("construct_unchecked/4", funcs, STRINGS_4);
let funcs = vec![Fun::new("TinyStr8", cu!(TinyStr8, u64))];
c.bench_functions("construct_unchecked/8", funcs, STRINGS_8);
let funcs = vec![Fun::new("TinyStr16", cu!(TinyStr16, u128))];
c.bench_functions("construct_unchecked/16", funcs, STRINGS_16);
}
criterion_group!(
benches,
construct_from_str,
construct_from_bytes,
construct_unchecked,
);
criterion_group!(benches, construct_from_str, construct_from_bytes,);
criterion_main!(benches);

165
third_party/rust/tinystr/benches/overview.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,165 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
mod common;
use common::*;
use criterion::black_box;
use criterion::criterion_group;
use criterion::criterion_main;
use criterion::Criterion;
use tinystr::TinyAsciiStr;
use tinystr_old::TinyStr16;
use tinystr_old::TinyStr4;
use tinystr_old::TinyStr8;
fn overview(c: &mut Criterion) {
let mut g = c.benchmark_group("overview");
g.bench_function("construct/TinyAsciiStr", |b| {
b.iter(|| {
for s in STRINGS_4 {
let _: TinyAsciiStr<4> = black_box(s).parse().unwrap();
let _: TinyAsciiStr<8> = black_box(s).parse().unwrap();
let _: TinyAsciiStr<16> = black_box(s).parse().unwrap();
}
for s in STRINGS_8 {
let _: TinyAsciiStr<8> = black_box(s).parse().unwrap();
let _: TinyAsciiStr<16> = black_box(s).parse().unwrap();
}
for s in STRINGS_16 {
let _: TinyAsciiStr<16> = black_box(s).parse().unwrap();
}
});
});
g.bench_function("construct/TinyStr", |b| {
b.iter(|| {
for s in STRINGS_4 {
let _: TinyStr4 = black_box(s).parse().unwrap();
let _: TinyStr8 = black_box(s).parse().unwrap();
let _: TinyStr16 = black_box(s).parse().unwrap();
}
for s in STRINGS_8 {
let _: TinyStr8 = black_box(s).parse().unwrap();
let _: TinyStr16 = black_box(s).parse().unwrap();
}
for s in STRINGS_16 {
let _: TinyStr16 = black_box(s).parse().unwrap();
}
});
});
let parsed_ascii_4: Vec<TinyAsciiStr<4>> = STRINGS_4
.iter()
.map(|s| s.parse::<TinyAsciiStr<4>>().unwrap())
.collect();
let parsed_ascii_8: Vec<TinyAsciiStr<8>> = STRINGS_4
.iter()
.chain(STRINGS_8)
.map(|s| s.parse::<TinyAsciiStr<8>>().unwrap())
.collect();
let parsed_ascii_16: Vec<TinyAsciiStr<16>> = STRINGS_4
.iter()
.chain(STRINGS_8)
.chain(STRINGS_16)
.map(|s| s.parse::<TinyAsciiStr<16>>().unwrap())
.collect();
let parsed_tiny_4: Vec<TinyStr4> = STRINGS_4
.iter()
.map(|s| s.parse::<TinyStr4>().unwrap())
.collect();
let parsed_tiny_8: Vec<TinyStr8> = STRINGS_4
.iter()
.chain(STRINGS_8)
.map(|s| s.parse::<TinyStr8>().unwrap())
.collect();
let parsed_tiny_16: Vec<TinyStr16> = STRINGS_4
.iter()
.chain(STRINGS_8)
.chain(STRINGS_16)
.map(|s| s.parse::<TinyStr16>().unwrap())
.collect();
g.bench_function("read/TinyAsciiStr", |b| {
b.iter(|| {
let mut collector: usize = 0;
for t in black_box(&parsed_ascii_4) {
let s: &str = t;
collector += s.bytes().map(usize::from).sum::<usize>();
}
for t in black_box(&parsed_ascii_8) {
let s: &str = t;
collector += s.bytes().map(usize::from).sum::<usize>();
}
for t in black_box(&parsed_ascii_16) {
let s: &str = t;
collector += s.bytes().map(usize::from).sum::<usize>();
}
collector
});
});
g.bench_function("read/TinyStr", |b| {
b.iter(|| {
let mut collector: usize = 0;
for t in black_box(&parsed_tiny_4) {
let s: &str = t;
collector += s.bytes().map(usize::from).sum::<usize>();
}
for t in black_box(&parsed_tiny_8) {
let s: &str = t;
collector += s.bytes().map(usize::from).sum::<usize>();
}
for t in black_box(&parsed_tiny_16) {
let s: &str = t;
collector += s.bytes().map(usize::from).sum::<usize>();
}
collector
});
});
g.bench_function("compare/TinyAsciiStr", |b| {
b.iter(|| {
let mut collector: usize = 0;
for ts in black_box(&parsed_ascii_4).windows(2) {
let o = ts[0].cmp(&ts[1]);
collector ^= o as usize;
}
for ts in black_box(&parsed_ascii_8).windows(2) {
let o = ts[0].cmp(&ts[1]);
collector ^= o as usize;
}
for ts in black_box(&parsed_ascii_16).windows(2) {
let o = ts[0].cmp(&ts[1]);
collector ^= o as usize;
}
collector
});
});
g.bench_function("compare/TinyStr", |b| {
b.iter(|| {
let mut collector: usize = 0;
for ts in black_box(&parsed_tiny_4).windows(2) {
let o = ts[0].cmp(&ts[1]);
collector ^= o as usize;
}
for ts in black_box(&parsed_tiny_8).windows(2) {
let o = ts[0].cmp(&ts[1]);
collector ^= o as usize;
}
for ts in black_box(&parsed_tiny_16).windows(2) {
let o = ts[0].cmp(&ts[1]);
collector ^= o as usize;
}
collector
});
});
}
criterion_group!(benches, overview,);
criterion_main!(benches);

34
third_party/rust/tinystr/benches/read.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,34 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
mod common;
use common::*;
use criterion::black_box;
use criterion::criterion_group;
use criterion::criterion_main;
use criterion::Bencher;
use criterion::Criterion;
use tinystr::TinyAsciiStr;
fn read(c: &mut Criterion) {
macro_rules! cfs {
($r:ty, $inputs:expr) => {
|b: &mut Bencher| {
let parsed: Vec<$r> = $inputs.iter().map(|s| s.parse().unwrap()).collect();
b.iter(|| {
for s in &parsed {
let _: &str = black_box(&**s);
}
})
}
};
}
bench_block!(c, "read", cfs);
}
criterion_group!(benches, read,);
criterion_main!(benches);

37
third_party/rust/tinystr/benches/serde.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,37 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
mod common;
use common::*;
use criterion::black_box;
use criterion::criterion_group;
use criterion::criterion_main;
use criterion::Bencher;
use criterion::Criterion;
use tinystr::TinyAsciiStr;
fn deserialize(c: &mut Criterion) {
macro_rules! cfs {
($r:ty, $inputs:expr) => {
|b: &mut Bencher| {
let serialized: Vec<Vec<u8>> = $inputs
.iter()
.map(|s| postcard::to_stdvec(&s.parse::<$r>().unwrap()).unwrap())
.collect();
b.iter(|| {
for bytes in &serialized {
let _: Result<$r, _> = black_box(postcard::from_bytes(bytes));
}
})
}
};
}
bench_block!(c, "deserialize", cfs);
}
criterion_group!(benches, deserialize,);
criterion_main!(benches);

176
third_party/rust/tinystr/benches/tinystr.rs поставляемый
Просмотреть файл

@ -1,176 +0,0 @@
use criterion::black_box;
use criterion::criterion_group;
use criterion::criterion_main;
use criterion::Bencher;
use criterion::Criterion;
use criterion::Fun;
use tinystr::{TinyStr16, TinyStr4, TinyStr8};
static STRINGS_4: &[&str] = &[
"US", "GB", "AR", "Hans", "CN", "AT", "PL", "FR", "AT", "Cyrl", "SR", "NO", "FR", "MK", "UK",
];
static STRINGS_8: &[&str] = &[
"Latn", "windows", "AR", "Hans", "macos", "AT", "pl", "FR", "en", "Cyrl", "SR", "NO", "419",
"und", "UK",
];
static STRINGS_16: &[&str] = &[
"Latn",
"windows",
"AR",
"Hans",
"macos",
"AT",
"infiniband",
"FR",
"en",
"Cyrl",
"FromIntegral",
"NO",
"419",
"MacintoshOSX2019",
"UK",
];
macro_rules! bench_block {
($c:expr, $name:expr, $action:ident) => {
let funcs = vec![
Fun::new("String", $action!(String)),
Fun::new("TinyStr4", $action!(TinyStr4)),
Fun::new("TinyStr8", $action!(TinyStr8)),
Fun::new("TinyStr16", $action!(TinyStr16)),
];
$c.bench_functions(&format!("{}/4", $name), funcs, STRINGS_4);
let funcs = vec![
Fun::new("String", $action!(String)),
Fun::new("TinyStr8", $action!(TinyStr8)),
Fun::new("TinyStr16", $action!(TinyStr16)),
];
$c.bench_functions(&format!("{}/8", $name), funcs, STRINGS_8);
let funcs = vec![
Fun::new("String", $action!(String)),
Fun::new("TinyStr16", $action!(TinyStr16)),
];
$c.bench_functions(&format!("{}/16", $name), funcs, STRINGS_16);
};
}
macro_rules! convert_to_ascii {
($ty:ty, $action:ident) => {
|b: &mut Bencher, inputs: &&[&str]| {
let raw: Vec<$ty> = inputs.iter().map(|s| s.parse::<$ty>().unwrap()).collect();
b.iter(move || {
for s in &raw {
let _ = black_box(s.$action());
}
})
}
};
}
fn convert_to_ascii_lowercase(c: &mut Criterion) {
macro_rules! ctal {
($ty:ty) => {
convert_to_ascii!($ty, to_ascii_lowercase)
};
}
bench_block!(c, "convert_to_ascii_lowercase", ctal);
}
fn convert_to_ascii_uppercase(c: &mut Criterion) {
macro_rules! ctau {
($ty:ty) => {
convert_to_ascii!($ty, to_ascii_uppercase)
};
}
bench_block!(c, "convert_to_ascii_uppercase", ctau);
}
trait ExtToAsciiTitlecase {
#[inline(always)]
fn to_ascii_titlecase(&self) -> String;
}
impl ExtToAsciiTitlecase for str {
fn to_ascii_titlecase(&self) -> String {
let mut result = self.to_ascii_lowercase();
result[0..1].make_ascii_uppercase();
result
}
}
fn convert_to_ascii_titlecase(c: &mut Criterion) {
macro_rules! ctat {
($ty:ty) => {
convert_to_ascii!($ty, to_ascii_titlecase)
};
}
bench_block!(c, "convert_to_ascii_titlecase", ctat);
}
trait ExtIsAsciiAlphanumeric {
#[inline(always)]
fn is_ascii_alphanumeric(&self) -> bool;
}
impl ExtIsAsciiAlphanumeric for str {
fn is_ascii_alphanumeric(&self) -> bool {
self.chars().all(|c| c.is_ascii_alphanumeric())
}
}
fn test_is_ascii_alphanumeric(c: &mut Criterion) {
macro_rules! tiaa {
($ty:ty) => {
|b: &mut Bencher, inputs: &&[&str]| {
let raw: Vec<$ty> = inputs.iter().map(|s| s.parse::<$ty>().unwrap()).collect();
b.iter(move || {
for s in &raw {
let _ = black_box(s.is_ascii_alphanumeric());
}
})
}
};
}
bench_block!(c, "test_is_ascii_alphanumeric", tiaa);
}
fn test_eq(c: &mut Criterion) {
macro_rules! te {
($ty:ty) => {
|b: &mut Bencher, inputs: &&[&str]| {
let raw: Vec<$ty> = inputs.iter().map(|s| s.parse::<$ty>().unwrap()).collect();
b.iter(move || {
for s in &raw {
for l in &raw {
let _ = black_box(s == l);
}
}
})
}
};
}
bench_block!(c, "test_eq", te);
}
criterion_group!(
benches,
convert_to_ascii_lowercase,
convert_to_ascii_uppercase,
convert_to_ascii_titlecase,
test_is_ascii_alphanumeric,
test_eq,
);
criterion_main!(benches);

18
third_party/rust/tinystr/examples/main.rs поставляемый
Просмотреть файл

@ -1,18 +0,0 @@
use tinystr::{TinyStr4, TinyStr8};
fn main() {
let s1: TinyStr4 = "tEsT".parse().expect("Failed to parse.");
assert_eq!(s1, "tEsT");
assert_eq!(s1.to_ascii_uppercase(), "TEST");
assert_eq!(s1.to_ascii_lowercase(), "test");
assert_eq!(s1.to_ascii_titlecase(), "Test");
assert_eq!(s1.is_ascii_alphanumeric(), true);
let s2: TinyStr8 = "New York".parse().expect("Failed to parse.");
assert_eq!(s2, "New York");
assert_eq!(s2.to_ascii_uppercase(), "NEW YORK");
assert_eq!(s2.to_ascii_lowercase(), "new york");
assert_eq!(s2.is_ascii_alphanumeric(), false);
}

987
third_party/rust/tinystr/src/ascii.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,987 @@
// 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::asciibyte::AsciiByte;
use crate::int_ops::{Aligned4, Aligned8};
use crate::TinyStrError;
use core::fmt;
use core::ops::Deref;
use core::str::{self, FromStr};
#[repr(transparent)]
#[derive(PartialEq, Eq, Ord, PartialOrd, Copy, Clone, Hash)]
pub struct TinyAsciiStr<const N: usize> {
bytes: [AsciiByte; N],
}
impl<const N: usize> TinyAsciiStr<N> {
/// Creates a `TinyAsciiStr<N>` from the given byte slice.
/// `bytes` may contain at most `N` non-null ASCII bytes.
pub const fn from_bytes(bytes: &[u8]) -> Result<Self, TinyStrError> {
Self::from_bytes_inner(bytes, 0, bytes.len(), false)
}
/// Attempts to parse a fixed-length byte array to a `TinyAsciiStr`.
///
/// The byte array may contain trailing NUL bytes.
///
/// # Example
///
/// ```
/// use tinystr::tinystr;
/// use tinystr::TinyAsciiStr;
///
/// assert_eq!(
/// TinyAsciiStr::<3>::try_from_raw(*b"GB\0"),
/// Ok(tinystr!(3, "GB"))
/// );
/// assert_eq!(
/// TinyAsciiStr::<3>::try_from_raw(*b"USD"),
/// Ok(tinystr!(3, "USD"))
/// );
/// assert!(matches!(TinyAsciiStr::<3>::try_from_raw(*b"\0A\0"), Err(_)));
/// ```
pub const fn try_from_raw(raw: [u8; N]) -> Result<Self, TinyStrError> {
Self::from_bytes_inner(&raw, 0, N, true)
}
/// Equivalent to [`from_bytes(bytes[start..end])`](Self::from_bytes),
/// but callable in a `const` context (which range indexing is not).
pub const fn from_bytes_manual_slice(
bytes: &[u8],
start: usize,
end: usize,
) -> Result<Self, TinyStrError> {
Self::from_bytes_inner(bytes, start, end, false)
}
#[inline]
pub(crate) const fn from_bytes_inner(
bytes: &[u8],
start: usize,
end: usize,
allow_trailing_null: bool,
) -> Result<Self, TinyStrError> {
let len = end - start;
if len > N {
return Err(TinyStrError::TooLarge { max: N, len });
}
let mut out = [0; N];
let mut i = 0;
let mut found_null = false;
// Indexing is protected by TinyStrError::TooLarge
#[allow(clippy::indexing_slicing)]
while i < len {
let b = bytes[start + i];
if b == 0 {
found_null = true;
} else if b >= 0x80 {
return Err(TinyStrError::NonAscii);
} else if found_null {
// Error if there are contentful bytes after null
return Err(TinyStrError::ContainsNull);
}
out[i] = b;
i += 1;
}
if !allow_trailing_null && found_null {
// We found some trailing nulls, error
return Err(TinyStrError::ContainsNull);
}
Ok(Self {
// SAFETY: `out` only contains ASCII bytes and has same size as `self.bytes`
bytes: unsafe { AsciiByte::to_ascii_byte_array(&out) },
})
}
// TODO: This function shadows the FromStr trait. Rename?
#[inline]
pub const fn from_str(s: &str) -> Result<Self, TinyStrError> {
Self::from_bytes_inner(s.as_bytes(), 0, s.len(), false)
}
#[inline]
pub const fn as_str(&self) -> &str {
// as_bytes is valid utf8
unsafe { str::from_utf8_unchecked(self.as_bytes()) }
}
#[inline]
#[must_use]
pub const fn len(&self) -> usize {
if N <= 4 {
Aligned4::from_ascii_bytes(&self.bytes).len()
} else if N <= 8 {
Aligned8::from_ascii_bytes(&self.bytes).len()
} else {
let mut i = 0;
#[allow(clippy::indexing_slicing)] // < N is safe
while i < N && self.bytes[i] as u8 != AsciiByte::B0 as u8 {
i += 1
}
i
}
}
#[inline]
#[must_use]
pub const fn is_empty(&self) -> bool {
self.bytes[0] as u8 == AsciiByte::B0 as u8
}
#[inline]
#[must_use]
pub const fn as_bytes(&self) -> &[u8] {
/// core::slice::from_raw_parts(a, b) = core::mem::transmute((a, b)) hack
/// ```compile_fail
/// const unsafe fn canary() { core::slice::from_raw_parts(0 as *const u8, 0); }
/// ```
const _: () = ();
// Safe because `self.bytes.as_slice()` pointer-casts to `&[u8]`,
// and changing the length of that slice to self.len() < N is safe.
unsafe { core::mem::transmute((self.bytes.as_slice().as_ptr(), self.len())) }
}
#[inline]
#[must_use]
pub const fn all_bytes(&self) -> &[u8; N] {
// SAFETY: `self.bytes` has same size as [u8; N]
unsafe { core::mem::transmute(&self.bytes) }
}
#[inline]
#[must_use]
/// Resizes a TinyAsciiStr<N> to a TinyAsciiStr<M>.
///
/// If M < len() the string gets truncated, otherwise only the
/// memory representation changes.
pub const fn resize<const M: usize>(self) -> TinyAsciiStr<M> {
let mut bytes = [0; M];
let mut i = 0;
// Indexing is protected by the loop guard
#[allow(clippy::indexing_slicing)]
while i < M && i < N {
bytes[i] = self.bytes[i] as u8;
i += 1;
}
// `self.bytes` only contains ASCII bytes, with no null bytes between
// ASCII characters, so this also holds for `bytes`.
unsafe { TinyAsciiStr::from_bytes_unchecked(bytes) }
}
/// # Safety
/// Must be called with a bytes array made of valid ASCII bytes, with no null bytes
/// between ASCII characters
#[must_use]
pub const unsafe fn from_bytes_unchecked(bytes: [u8; N]) -> Self {
Self {
bytes: AsciiByte::to_ascii_byte_array(&bytes),
}
}
}
macro_rules! check_is {
($self:ident, $check_int:ident, $check_u8:ident) => {
if N <= 4 {
Aligned4::from_ascii_bytes(&$self.bytes).$check_int()
} else if N <= 8 {
Aligned8::from_ascii_bytes(&$self.bytes).$check_int()
} else {
let mut i = 0;
// Won't panic because self.bytes has length N
#[allow(clippy::indexing_slicing)]
while i < N && $self.bytes[i] as u8 != AsciiByte::B0 as u8 {
if !($self.bytes[i] as u8).$check_u8() {
return false;
}
i += 1;
}
true
}
};
($self:ident, $check_int:ident, !$check_u8_0_inv:ident, !$check_u8_1_inv:ident) => {
if N <= 4 {
Aligned4::from_ascii_bytes(&$self.bytes).$check_int()
} else if N <= 8 {
Aligned8::from_ascii_bytes(&$self.bytes).$check_int()
} else {
// Won't panic because N is > 8
if ($self.bytes[0] as u8).$check_u8_0_inv() {
return false;
}
let mut i = 1;
// Won't panic because self.bytes has length N
#[allow(clippy::indexing_slicing)]
while i < N && $self.bytes[i] as u8 != AsciiByte::B0 as u8 {
if ($self.bytes[i] as u8).$check_u8_1_inv() {
return false;
}
i += 1;
}
true
}
};
($self:ident, $check_int:ident, $check_u8_0_inv:ident, $check_u8_1_inv:ident) => {
if N <= 4 {
Aligned4::from_ascii_bytes(&$self.bytes).$check_int()
} else if N <= 8 {
Aligned8::from_ascii_bytes(&$self.bytes).$check_int()
} else {
// Won't panic because N is > 8
if !($self.bytes[0] as u8).$check_u8_0_inv() {
return false;
}
let mut i = 1;
// Won't panic because self.bytes has length N
#[allow(clippy::indexing_slicing)]
while i < N && $self.bytes[i] as u8 != AsciiByte::B0 as u8 {
if !($self.bytes[i] as u8).$check_u8_1_inv() {
return false;
}
i += 1;
}
true
}
};
}
impl<const N: usize> TinyAsciiStr<N> {
/// Checks if the value is composed of ASCII alphabetic characters:
///
/// * U+0041 'A' ..= U+005A 'Z', or
/// * U+0061 'a' ..= U+007A 'z'.
///
/// # Examples
///
/// ```
/// use tinystr::TinyAsciiStr;
///
/// let s1: TinyAsciiStr<4> = "Test".parse().expect("Failed to parse.");
/// let s2: TinyAsciiStr<4> = "Te3t".parse().expect("Failed to parse.");
///
/// assert!(s1.is_ascii_alphabetic());
/// assert!(!s2.is_ascii_alphabetic());
/// ```
#[inline]
#[must_use]
pub const fn is_ascii_alphabetic(&self) -> bool {
check_is!(self, is_ascii_alphabetic, is_ascii_alphabetic)
}
/// Checks if the value is composed of ASCII alphanumeric characters:
///
/// * U+0041 'A' ..= U+005A 'Z', or
/// * U+0061 'a' ..= U+007A 'z', or
/// * U+0030 '0' ..= U+0039 '9'.
///
/// # Examples
///
/// ```
/// use tinystr::TinyAsciiStr;
///
/// let s1: TinyAsciiStr<4> = "A15b".parse().expect("Failed to parse.");
/// let s2: TinyAsciiStr<4> = "[3@w".parse().expect("Failed to parse.");
///
/// assert!(s1.is_ascii_alphanumeric());
/// assert!(!s2.is_ascii_alphanumeric());
/// ```
#[inline]
#[must_use]
pub const fn is_ascii_alphanumeric(&self) -> bool {
check_is!(self, is_ascii_alphanumeric, is_ascii_alphanumeric)
}
/// Checks if the value is composed of ASCII decimal digits:
///
/// * U+0030 '0' ..= U+0039 '9'.
///
/// # Examples
///
/// ```
/// use tinystr::TinyAsciiStr;
///
/// let s1: TinyAsciiStr<4> = "312".parse().expect("Failed to parse.");
/// let s2: TinyAsciiStr<4> = "3d".parse().expect("Failed to parse.");
///
/// assert!(s1.is_ascii_numeric());
/// assert!(!s2.is_ascii_numeric());
/// ```
#[inline]
#[must_use]
pub const fn is_ascii_numeric(&self) -> bool {
check_is!(self, is_ascii_numeric, is_ascii_digit)
}
/// Checks if the value is in ASCII lower case.
///
/// All letter characters are checked for case. Non-letter characters are ignored.
///
/// # Examples
///
/// ```
/// use tinystr::TinyAsciiStr;
///
/// let s1: TinyAsciiStr<4> = "teSt".parse().expect("Failed to parse.");
/// let s2: TinyAsciiStr<4> = "test".parse().expect("Failed to parse.");
/// let s3: TinyAsciiStr<4> = "001z".parse().expect("Failed to parse.");
///
/// assert!(!s1.is_ascii_lowercase());
/// assert!(s2.is_ascii_lowercase());
/// assert!(s3.is_ascii_lowercase());
/// ```
#[inline]
#[must_use]
pub const fn is_ascii_lowercase(&self) -> bool {
check_is!(
self,
is_ascii_lowercase,
!is_ascii_uppercase,
!is_ascii_uppercase
)
}
/// Checks if the value is in ASCII title case.
///
/// This verifies that the first character is ASCII uppercase and all others ASCII lowercase.
/// Non-letter characters are ignored.
///
/// # Examples
///
/// ```
/// use tinystr::TinyAsciiStr;
///
/// let s1: TinyAsciiStr<4> = "teSt".parse().expect("Failed to parse.");
/// let s2: TinyAsciiStr<4> = "Test".parse().expect("Failed to parse.");
/// let s3: TinyAsciiStr<4> = "001z".parse().expect("Failed to parse.");
///
/// assert!(!s1.is_ascii_titlecase());
/// assert!(s2.is_ascii_titlecase());
/// assert!(s3.is_ascii_titlecase());
/// ```
#[inline]
#[must_use]
pub const fn is_ascii_titlecase(&self) -> bool {
check_is!(
self,
is_ascii_titlecase,
!is_ascii_lowercase,
!is_ascii_uppercase
)
}
/// Checks if the value is in ASCII upper case.
///
/// All letter characters are checked for case. Non-letter characters are ignored.
///
/// # Examples
///
/// ```
/// use tinystr::TinyAsciiStr;
///
/// let s1: TinyAsciiStr<4> = "teSt".parse().expect("Failed to parse.");
/// let s2: TinyAsciiStr<4> = "TEST".parse().expect("Failed to parse.");
/// let s3: TinyAsciiStr<4> = "001z".parse().expect("Failed to parse.");
///
/// assert!(!s1.is_ascii_uppercase());
/// assert!(s2.is_ascii_uppercase());
/// assert!(!s3.is_ascii_uppercase());
/// ```
#[inline]
#[must_use]
pub const fn is_ascii_uppercase(&self) -> bool {
check_is!(
self,
is_ascii_uppercase,
!is_ascii_lowercase,
!is_ascii_lowercase
)
}
/// Checks if the value is composed of ASCII alphabetic lower case characters:
///
/// * U+0061 'a' ..= U+007A 'z',
///
/// # Examples
///
/// ```
/// use tinystr::TinyAsciiStr;
///
/// let s1: TinyAsciiStr<4> = "Test".parse().expect("Failed to parse.");
/// let s2: TinyAsciiStr<4> = "Te3t".parse().expect("Failed to parse.");
/// let s3: TinyAsciiStr<4> = "teSt".parse().expect("Failed to parse.");
/// let s4: TinyAsciiStr<4> = "test".parse().expect("Failed to parse.");
/// let s5: TinyAsciiStr<4> = "001z".parse().expect("Failed to parse.");
///
/// assert!(!s1.is_ascii_alphabetic_lowercase());
/// assert!(!s2.is_ascii_alphabetic_lowercase());
/// assert!(!s3.is_ascii_alphabetic_lowercase());
/// assert!(s4.is_ascii_alphabetic_lowercase());
/// assert!(!s5.is_ascii_alphabetic_lowercase());
/// ```
#[inline]
#[must_use]
pub const fn is_ascii_alphabetic_lowercase(&self) -> bool {
check_is!(
self,
is_ascii_alphabetic_lowercase,
is_ascii_lowercase,
is_ascii_lowercase
)
}
/// Checks if the value is composed of ASCII alphabetic, with the first character being ASCII uppercase, and all others ASCII lowercase.
///
/// # Examples
///
/// ```
/// use tinystr::TinyAsciiStr;
///
/// let s1: TinyAsciiStr<4> = "Test".parse().expect("Failed to parse.");
/// let s2: TinyAsciiStr<4> = "Te3t".parse().expect("Failed to parse.");
/// let s3: TinyAsciiStr<4> = "teSt".parse().expect("Failed to parse.");
/// let s4: TinyAsciiStr<4> = "test".parse().expect("Failed to parse.");
/// let s5: TinyAsciiStr<4> = "001z".parse().expect("Failed to parse.");
///
/// assert!(s1.is_ascii_alphabetic_titlecase());
/// assert!(!s2.is_ascii_alphabetic_titlecase());
/// assert!(!s3.is_ascii_alphabetic_titlecase());
/// assert!(!s4.is_ascii_alphabetic_titlecase());
/// assert!(!s5.is_ascii_alphabetic_titlecase());
/// ```
#[inline]
#[must_use]
pub const fn is_ascii_alphabetic_titlecase(&self) -> bool {
check_is!(
self,
is_ascii_alphabetic_titlecase,
is_ascii_uppercase,
is_ascii_lowercase
)
}
/// Checks if the value is composed of ASCII alphabetic upper case characters:
///
/// * U+0041 'A' ..= U+005A 'Z',
///
/// # Examples
///
/// ```
/// use tinystr::TinyAsciiStr;
///
/// let s1: TinyAsciiStr<4> = "Test".parse().expect("Failed to parse.");
/// let s2: TinyAsciiStr<4> = "Te3t".parse().expect("Failed to parse.");
/// let s3: TinyAsciiStr<4> = "teSt".parse().expect("Failed to parse.");
/// let s4: TinyAsciiStr<4> = "TEST".parse().expect("Failed to parse.");
/// let s5: TinyAsciiStr<4> = "001z".parse().expect("Failed to parse.");
///
/// assert!(!s1.is_ascii_alphabetic_uppercase());
/// assert!(!s2.is_ascii_alphabetic_uppercase());
/// assert!(!s3.is_ascii_alphabetic_uppercase());
/// assert!(s4.is_ascii_alphabetic_uppercase());
/// assert!(!s5.is_ascii_alphabetic_uppercase());
/// ```
#[inline]
#[must_use]
pub const fn is_ascii_alphabetic_uppercase(&self) -> bool {
check_is!(
self,
is_ascii_alphabetic_uppercase,
is_ascii_uppercase,
is_ascii_uppercase
)
}
}
macro_rules! to {
($self:ident, $to:ident, $later_char_to:ident $(,$first_char_to:ident)?) => {{
let mut i = 0;
if N <= 4 {
let aligned = Aligned4::from_ascii_bytes(&$self.bytes).$to().to_ascii_bytes();
// Won't panic because self.bytes has length N and aligned has length >= N
#[allow(clippy::indexing_slicing)]
while i < N {
$self.bytes[i] = aligned[i];
i += 1;
}
} else if N <= 8 {
let aligned = Aligned8::from_ascii_bytes(&$self.bytes).$to().to_ascii_bytes();
// Won't panic because self.bytes has length N and aligned has length >= N
#[allow(clippy::indexing_slicing)]
while i < N {
$self.bytes[i] = aligned[i];
i += 1;
}
} else {
// Won't panic because self.bytes has length N
#[allow(clippy::indexing_slicing)]
while i < N && $self.bytes[i] as u8 != AsciiByte::B0 as u8 {
// SAFETY: AsciiByte is repr(u8) and has same size as u8
unsafe {
$self.bytes[i] = core::mem::transmute(
($self.bytes[i] as u8).$later_char_to()
);
}
i += 1;
}
// SAFETY: AsciiByte is repr(u8) and has same size as u8
$(
$self.bytes[0] = unsafe {
core::mem::transmute(($self.bytes[0] as u8).$first_char_to())
};
)?
}
$self
}};
}
impl<const N: usize> TinyAsciiStr<N> {
/// Converts this type to its ASCII lower case equivalent in-place.
///
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', other characters are unchanged.
///
/// # Examples
///
/// ```
/// use tinystr::TinyAsciiStr;
///
/// let s1: TinyAsciiStr<4> = "TeS3".parse().expect("Failed to parse.");
///
/// assert_eq!(&*s1.to_ascii_lowercase(), "tes3");
/// ```
#[inline]
#[must_use]
pub const fn to_ascii_lowercase(mut self) -> Self {
to!(self, to_ascii_lowercase, to_ascii_lowercase)
}
/// Converts this type to its ASCII title case equivalent in-place.
///
/// The first character is converted to ASCII uppercase; the remaining characters
/// are converted to ASCII lowercase.
///
/// # Examples
///
/// ```
/// use tinystr::TinyAsciiStr;
///
/// let s1: TinyAsciiStr<4> = "teSt".parse().expect("Failed to parse.");
///
/// assert_eq!(&*s1.to_ascii_titlecase(), "Test");
/// ```
#[inline]
#[must_use]
pub const fn to_ascii_titlecase(mut self) -> Self {
to!(
self,
to_ascii_titlecase,
to_ascii_lowercase,
to_ascii_uppercase
)
}
/// Converts this type to its ASCII upper case equivalent in-place.
///
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', other characters are unchanged.
///
/// # Examples
///
/// ```
/// use tinystr::TinyAsciiStr;
///
/// let s1: TinyAsciiStr<4> = "Tes3".parse().expect("Failed to parse.");
///
/// assert_eq!(&*s1.to_ascii_uppercase(), "TES3");
/// ```
#[inline]
#[must_use]
pub const fn to_ascii_uppercase(mut self) -> Self {
to!(self, to_ascii_uppercase, to_ascii_uppercase)
}
}
impl<const N: usize> fmt::Debug for TinyAsciiStr<N> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self.as_str(), f)
}
}
impl<const N: usize> fmt::Display for TinyAsciiStr<N> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self.as_str(), f)
}
}
impl<const N: usize> Deref for TinyAsciiStr<N> {
type Target = str;
#[inline]
fn deref(&self) -> &str {
self.as_str()
}
}
impl<const N: usize> FromStr for TinyAsciiStr<N> {
type Err = TinyStrError;
#[inline]
fn from_str(s: &str) -> Result<Self, TinyStrError> {
Self::from_str(s)
}
}
impl<const N: usize> PartialEq<str> for TinyAsciiStr<N> {
fn eq(&self, other: &str) -> bool {
self.deref() == other
}
}
impl<const N: usize> PartialEq<&str> for TinyAsciiStr<N> {
fn eq(&self, other: &&str) -> bool {
self.deref() == *other
}
}
#[cfg(feature = "alloc")]
impl<const N: usize> PartialEq<alloc::string::String> for TinyAsciiStr<N> {
fn eq(&self, other: &alloc::string::String) -> bool {
self.deref() == other.deref()
}
}
#[cfg(feature = "alloc")]
impl<const N: usize> PartialEq<TinyAsciiStr<N>> for alloc::string::String {
fn eq(&self, other: &TinyAsciiStr<N>) -> bool {
self.deref() == other.deref()
}
}
#[cfg(test)]
mod test {
use super::*;
use rand::distributions::Distribution;
use rand::distributions::Standard;
use rand::rngs::SmallRng;
use rand::seq::SliceRandom;
use rand::SeedableRng;
const STRINGS: &[&str] = &[
"Latn",
"laTn",
"windows",
"AR",
"Hans",
"macos",
"AT",
"infiniband",
"FR",
"en",
"Cyrl",
"FromIntegral",
"NO",
"419",
"MacintoshOSX2019",
"a3z",
"A3z",
"A3Z",
"a3Z",
"3A",
"3Z",
"3a",
"3z",
"@@[`{",
"UK",
"E12",
];
fn gen_strings(num_strings: usize, allowed_lengths: &[usize]) -> Vec<String> {
let mut rng = SmallRng::seed_from_u64(2022);
// Need to do this in 2 steps since the RNG is needed twice
let string_lengths = core::iter::repeat_with(|| *allowed_lengths.choose(&mut rng).unwrap())
.take(num_strings)
.collect::<Vec<usize>>();
string_lengths
.iter()
.map(|len| {
Standard
.sample_iter(&mut rng)
.filter(|b: &u8| *b > 0 && *b < 0x80)
.take(*len)
.collect::<Vec<u8>>()
})
.map(|byte_vec| String::from_utf8(byte_vec).expect("All ASCII"))
.collect()
}
fn check_operation<T, F1, F2, const N: usize>(reference_f: F1, tinystr_f: F2)
where
F1: Fn(&str) -> T,
F2: Fn(TinyAsciiStr<N>) -> T,
T: core::fmt::Debug + core::cmp::PartialEq,
{
for s in STRINGS
.iter()
.map(|s| s.to_string())
.chain(gen_strings(100, &[3, 4, 5, 8, 12]))
{
let t = match TinyAsciiStr::<N>::from_str(&s) {
Ok(t) => t,
Err(TinyStrError::TooLarge { .. }) => continue,
Err(e) => panic!("{}", e),
};
let expected = reference_f(&s);
let actual = tinystr_f(t);
assert_eq!(expected, actual, "TinyAsciiStr<{}>: {:?}", N, s);
}
}
#[test]
fn test_is_ascii_alphabetic() {
fn check<const N: usize>() {
check_operation(
|s| s.chars().all(|c| c.is_ascii_alphabetic()),
|t: TinyAsciiStr<N>| TinyAsciiStr::is_ascii_alphabetic(&t),
)
}
check::<2>();
check::<3>();
check::<4>();
check::<5>();
check::<8>();
check::<16>();
}
#[test]
fn test_is_ascii_alphanumeric() {
fn check<const N: usize>() {
check_operation(
|s| s.chars().all(|c| c.is_ascii_alphanumeric()),
|t: TinyAsciiStr<N>| TinyAsciiStr::is_ascii_alphanumeric(&t),
)
}
check::<2>();
check::<3>();
check::<4>();
check::<5>();
check::<8>();
check::<16>();
}
#[test]
fn test_is_ascii_numeric() {
fn check<const N: usize>() {
check_operation(
|s| s.chars().all(|c| c.is_ascii_digit()),
|t: TinyAsciiStr<N>| TinyAsciiStr::is_ascii_numeric(&t),
)
}
check::<2>();
check::<3>();
check::<4>();
check::<5>();
check::<8>();
check::<16>();
}
#[test]
fn test_is_ascii_lowercase() {
fn check<const N: usize>() {
check_operation(
|s| {
s == TinyAsciiStr::<16>::from_str(s)
.unwrap()
.to_ascii_lowercase()
.as_str()
},
|t: TinyAsciiStr<N>| TinyAsciiStr::is_ascii_lowercase(&t),
)
}
check::<2>();
check::<3>();
check::<4>();
check::<5>();
check::<8>();
check::<16>();
}
#[test]
fn test_is_ascii_titlecase() {
fn check<const N: usize>() {
check_operation(
|s| {
s == TinyAsciiStr::<16>::from_str(s)
.unwrap()
.to_ascii_titlecase()
.as_str()
},
|t: TinyAsciiStr<N>| TinyAsciiStr::is_ascii_titlecase(&t),
)
}
check::<2>();
check::<3>();
check::<4>();
check::<5>();
check::<8>();
check::<16>();
}
#[test]
fn test_is_ascii_uppercase() {
fn check<const N: usize>() {
check_operation(
|s| {
s == TinyAsciiStr::<16>::from_str(s)
.unwrap()
.to_ascii_uppercase()
.as_str()
},
|t: TinyAsciiStr<N>| TinyAsciiStr::is_ascii_uppercase(&t),
)
}
check::<2>();
check::<3>();
check::<4>();
check::<5>();
check::<8>();
check::<16>();
}
#[test]
fn test_is_ascii_alphabetic_lowercase() {
fn check<const N: usize>() {
check_operation(
|s| {
// Check alphabetic
s.chars().all(|c| c.is_ascii_alphabetic()) &&
// Check lowercase
s == TinyAsciiStr::<16>::from_str(s)
.unwrap()
.to_ascii_lowercase()
.as_str()
},
|t: TinyAsciiStr<N>| TinyAsciiStr::is_ascii_alphabetic_lowercase(&t),
)
}
check::<2>();
check::<3>();
check::<4>();
check::<5>();
check::<8>();
check::<16>();
}
#[test]
fn test_is_ascii_alphabetic_titlecase() {
fn check<const N: usize>() {
check_operation(
|s| {
// Check alphabetic
s.chars().all(|c| c.is_ascii_alphabetic()) &&
// Check titlecase
s == TinyAsciiStr::<16>::from_str(s)
.unwrap()
.to_ascii_titlecase()
.as_str()
},
|t: TinyAsciiStr<N>| TinyAsciiStr::is_ascii_alphabetic_titlecase(&t),
)
}
check::<2>();
check::<3>();
check::<4>();
check::<5>();
check::<8>();
check::<16>();
}
#[test]
fn test_is_ascii_alphabetic_uppercase() {
fn check<const N: usize>() {
check_operation(
|s| {
// Check alphabetic
s.chars().all(|c| c.is_ascii_alphabetic()) &&
// Check uppercase
s == TinyAsciiStr::<16>::from_str(s)
.unwrap()
.to_ascii_uppercase()
.as_str()
},
|t: TinyAsciiStr<N>| TinyAsciiStr::is_ascii_alphabetic_uppercase(&t),
)
}
check::<2>();
check::<3>();
check::<4>();
check::<5>();
check::<8>();
check::<16>();
}
#[test]
fn test_to_ascii_lowercase() {
fn check<const N: usize>() {
check_operation(
|s| {
s.chars()
.map(|c| c.to_ascii_lowercase())
.collect::<String>()
},
|t: TinyAsciiStr<N>| TinyAsciiStr::to_ascii_lowercase(t).to_string(),
)
}
check::<2>();
check::<3>();
check::<4>();
check::<5>();
check::<8>();
check::<16>();
}
#[test]
fn test_to_ascii_titlecase() {
fn check<const N: usize>() {
check_operation(
|s| {
let mut r = s
.chars()
.map(|c| c.to_ascii_lowercase())
.collect::<String>();
// Safe because the string is nonempty and an ASCII string
unsafe { r.as_bytes_mut()[0].make_ascii_uppercase() };
r
},
|t: TinyAsciiStr<N>| TinyAsciiStr::to_ascii_titlecase(t).to_string(),
)
}
check::<2>();
check::<3>();
check::<4>();
check::<5>();
check::<8>();
check::<16>();
}
#[test]
fn test_to_ascii_uppercase() {
fn check<const N: usize>() {
check_operation(
|s| {
s.chars()
.map(|c| c.to_ascii_uppercase())
.collect::<String>()
},
|t: TinyAsciiStr<N>| TinyAsciiStr::to_ascii_uppercase(t).to_string(),
)
}
check::<2>();
check::<3>();
check::<4>();
check::<5>();
check::<8>();
check::<16>();
}
}

145
third_party/rust/tinystr/src/asciibyte.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,145 @@
// 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 ).
#[repr(u8)]
#[allow(dead_code)]
#[derive(PartialEq, Eq, Ord, PartialOrd, Copy, Clone, Hash)]
pub enum AsciiByte {
B0 = 0,
B1 = 1,
B2 = 2,
B3 = 3,
B4 = 4,
B5 = 5,
B6 = 6,
B7 = 7,
B8 = 8,
B9 = 9,
B10 = 10,
B11 = 11,
B12 = 12,
B13 = 13,
B14 = 14,
B15 = 15,
B16 = 16,
B17 = 17,
B18 = 18,
B19 = 19,
B20 = 20,
B21 = 21,
B22 = 22,
B23 = 23,
B24 = 24,
B25 = 25,
B26 = 26,
B27 = 27,
B28 = 28,
B29 = 29,
B30 = 30,
B31 = 31,
B32 = 32,
B33 = 33,
B34 = 34,
B35 = 35,
B36 = 36,
B37 = 37,
B38 = 38,
B39 = 39,
B40 = 40,
B41 = 41,
B42 = 42,
B43 = 43,
B44 = 44,
B45 = 45,
B46 = 46,
B47 = 47,
B48 = 48,
B49 = 49,
B50 = 50,
B51 = 51,
B52 = 52,
B53 = 53,
B54 = 54,
B55 = 55,
B56 = 56,
B57 = 57,
B58 = 58,
B59 = 59,
B60 = 60,
B61 = 61,
B62 = 62,
B63 = 63,
B64 = 64,
B65 = 65,
B66 = 66,
B67 = 67,
B68 = 68,
B69 = 69,
B70 = 70,
B71 = 71,
B72 = 72,
B73 = 73,
B74 = 74,
B75 = 75,
B76 = 76,
B77 = 77,
B78 = 78,
B79 = 79,
B80 = 80,
B81 = 81,
B82 = 82,
B83 = 83,
B84 = 84,
B85 = 85,
B86 = 86,
B87 = 87,
B88 = 88,
B89 = 89,
B90 = 90,
B91 = 91,
B92 = 92,
B93 = 93,
B94 = 94,
B95 = 95,
B96 = 96,
B97 = 97,
B98 = 98,
B99 = 99,
B100 = 100,
B101 = 101,
B102 = 102,
B103 = 103,
B104 = 104,
B105 = 105,
B106 = 106,
B107 = 107,
B108 = 108,
B109 = 109,
B110 = 110,
B111 = 111,
B112 = 112,
B113 = 113,
B114 = 114,
B115 = 115,
B116 = 116,
B117 = 117,
B118 = 118,
B119 = 119,
B120 = 120,
B121 = 121,
B122 = 122,
B123 = 123,
B124 = 124,
B125 = 125,
B126 = 126,
B127 = 127,
}
impl AsciiByte {
// Convert [u8; N] to [AsciiByte; N]
#[inline]
pub const unsafe fn to_ascii_byte_array<const N: usize>(bytes: &[u8; N]) -> [AsciiByte; N] {
*(bytes as *const [u8; N] as *const [AsciiByte; N])
}
}

21
third_party/rust/tinystr/src/databake.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,21 @@
// 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::TinyAsciiStr;
use databake::*;
impl<const N: usize> Bake for TinyAsciiStr<N> {
fn bake(&self, env: &CrateEnv) -> TokenStream {
env.insert("tinystr");
let string = self.as_str();
quote! {
::tinystr::tinystr!(#N, #string)
}
}
}
#[test]
fn test() {
test_bake!(TinyAsciiStr<10>, const: crate::tinystr!(10usize, "foo"), tinystr);
}

16
third_party/rust/tinystr/src/error.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,16 @@
// 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 displaydoc::Display;
#[derive(Display, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum TinyStrError {
#[displaydoc("found string of larger length {len} when constructing string of length {max}")]
TooLarge { max: usize, len: usize },
#[displaydoc("tinystr types do not support strings with null bytes")]
ContainsNull,
#[displaydoc("attempted to construct TinyStrAuto from a non-ascii string")]
NonAscii,
}

32
third_party/rust/tinystr/src/helpers.rs поставляемый
Просмотреть файл

@ -1,32 +0,0 @@
use std::num::NonZeroU32;
use std::ptr::copy_nonoverlapping;
use super::Error;
#[cfg(any(feature = "std", test))]
pub use std::string::String;
#[cfg(all(not(feature = "std"), not(test)))]
extern crate alloc;
#[cfg(all(not(feature = "std"), not(test)))]
pub use alloc::string::String;
#[inline(always)]
pub(crate) unsafe fn make_4byte_bytes(
bytes: &[u8],
len: usize,
mask: u32,
) -> Result<NonZeroU32, Error> {
// Mask is always supplied as little-endian.
let mask = u32::from_le(mask);
let mut word: u32 = 0;
copy_nonoverlapping(bytes.as_ptr(), &mut word as *mut u32 as *mut u8, len);
if (word & mask) != 0 {
return Err(Error::NonAscii);
}
if ((mask - word) & mask) != 0 {
return Err(Error::InvalidNull);
}
Ok(NonZeroU32::new_unchecked(word))
}

315
third_party/rust/tinystr/src/int_ops.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,315 @@
// 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::asciibyte::AsciiByte;
/// Internal helper struct that performs operations on aligned integers.
/// Supports strings up to 4 bytes long.
#[repr(transparent)]
pub struct Aligned4(u32);
impl Aligned4 {
/// # Panics
/// Panics if N is greater than 4
#[inline]
pub const fn from_bytes<const N: usize>(src: &[u8; N]) -> Self {
let mut bytes = [0; 4];
let mut i = 0;
// The function documentation defines when panics may occur
#[allow(clippy::indexing_slicing)]
while i < N {
bytes[i] = src[i];
i += 1;
}
Self(u32::from_ne_bytes(bytes))
}
#[inline]
pub const fn from_ascii_bytes<const N: usize>(src: &[AsciiByte; N]) -> Self {
Self::from_bytes::<N>(unsafe { core::mem::transmute(src) })
}
#[inline]
pub const fn to_bytes(&self) -> [u8; 4] {
self.0.to_ne_bytes()
}
#[inline]
pub const fn to_ascii_bytes(&self) -> [AsciiByte; 4] {
unsafe { core::mem::transmute(self.to_bytes()) }
}
pub const fn len(&self) -> usize {
let word = self.0;
#[cfg(target_endian = "little")]
let len = (4 - word.leading_zeros() / 8) as usize;
#[cfg(target_endian = "big")]
let len = (4 - word.trailing_zeros() / 8) as usize;
len
}
pub const fn is_ascii_alphabetic(&self) -> bool {
let word = self.0;
// Each of the following bitmasks set *the high bit* (0x8) to 0 for valid and 1 for invalid.
// `mask` sets all NUL bytes to 0.
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
// `lower` converts the string to lowercase. It may also change the value of non-alpha
// characters, but this does not matter for the alphabetic test that follows.
let lower = word | 0x2020_2020;
// `alpha` sets all alphabetic bytes to 0. We only need check for lowercase characters.
let alpha = !(lower + 0x1f1f_1f1f) | (lower + 0x0505_0505);
// The overall string is valid if every character passes at least one test.
// We performed two tests here: non-NUL (`mask`) and alphabetic (`alpha`).
(alpha & mask) == 0
}
pub const fn is_ascii_alphanumeric(&self) -> bool {
let word = self.0;
// See explanatory comments in is_ascii_alphabetic
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
let numeric = !(word + 0x5050_5050) | (word + 0x4646_4646);
let lower = word | 0x2020_2020;
let alpha = !(lower + 0x1f1f_1f1f) | (lower + 0x0505_0505);
(alpha & numeric & mask) == 0
}
pub const fn is_ascii_numeric(&self) -> bool {
let word = self.0;
// See explanatory comments in is_ascii_alphabetic
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
let numeric = !(word + 0x5050_5050) | (word + 0x4646_4646);
(numeric & mask) == 0
}
pub const fn is_ascii_lowercase(&self) -> bool {
let word = self.0;
// For efficiency, this function tests for an invalid string rather than a valid string.
// A string is ASCII lowercase iff it contains no uppercase ASCII characters.
// `invalid_case` sets all uppercase ASCII characters to 0 and all others to 1.
let invalid_case = !(word + 0x3f3f_3f3f) | (word + 0x2525_2525);
// The string is valid if it contains no invalid characters (if all high bits are 1).
(invalid_case & 0x8080_8080) == 0x8080_8080
}
pub const fn is_ascii_titlecase(&self) -> bool {
let word = self.0;
// See explanatory comments in is_ascii_lowercase
let invalid_case = if cfg!(target_endian = "little") {
!(word + 0x3f3f_3f1f) | (word + 0x2525_2505)
} else {
!(word + 0x1f3f_3f3f) | (word + 0x0525_2525)
};
(invalid_case & 0x8080_8080) == 0x8080_8080
}
pub const fn is_ascii_uppercase(&self) -> bool {
let word = self.0;
// See explanatory comments in is_ascii_lowercase
let invalid_case = !(word + 0x1f1f_1f1f) | (word + 0x0505_0505);
(invalid_case & 0x8080_8080) == 0x8080_8080
}
pub const fn is_ascii_alphabetic_lowercase(&self) -> bool {
let word = self.0;
// `mask` sets all NUL bytes to 0.
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
// `lower_alpha` sets all lowercase ASCII characters to 0 and all others to 1.
let lower_alpha = !(word + 0x1f1f_1f1f) | (word + 0x0505_0505);
// The overall string is valid if every character passes at least one test.
// We performed two tests here: non-NUL (`mask`) and lowercase ASCII character (`alpha`).
(lower_alpha & mask) == 0
}
pub const fn is_ascii_alphabetic_titlecase(&self) -> bool {
let word = self.0;
// See explanatory comments in is_ascii_alphabetic_lowercase
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
let title_case = if cfg!(target_endian = "little") {
!(word + 0x1f1f_1f3f) | (word + 0x0505_0525)
} else {
!(word + 0x3f1f_1f1f) | (word + 0x2505_0505)
};
(title_case & mask) == 0
}
pub const fn is_ascii_alphabetic_uppercase(&self) -> bool {
let word = self.0;
// See explanatory comments in is_ascii_alphabetic_lowercase
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
let upper_alpha = !(word + 0x3f3f_3f3f) | (word + 0x2525_2525);
(upper_alpha & mask) == 0
}
pub const fn to_ascii_lowercase(&self) -> Self {
let word = self.0;
let result = word | (((word + 0x3f3f_3f3f) & !(word + 0x2525_2525) & 0x8080_8080) >> 2);
Self(result)
}
pub const fn to_ascii_titlecase(&self) -> Self {
let word = self.0.to_le();
let mask = ((word + 0x3f3f_3f1f) & !(word + 0x2525_2505) & 0x8080_8080) >> 2;
let result = (word | mask) & !(0x20 & mask);
Self(u32::from_le(result))
}
pub const fn to_ascii_uppercase(&self) -> Self {
let word = self.0;
let result = word & !(((word + 0x1f1f_1f1f) & !(word + 0x0505_0505) & 0x8080_8080) >> 2);
Self(result)
}
}
/// Internal helper struct that performs operations on aligned integers.
/// Supports strings up to 8 bytes long.
#[repr(transparent)]
pub struct Aligned8(u64);
impl Aligned8 {
/// # Panics
/// Panics if N is greater than 8
#[inline]
pub const fn from_bytes<const N: usize>(src: &[u8; N]) -> Self {
let mut bytes = [0; 8];
let mut i = 0;
// The function documentation defines when panics may occur
#[allow(clippy::indexing_slicing)]
while i < N {
bytes[i] = src[i];
i += 1;
}
Self(u64::from_ne_bytes(bytes))
}
#[inline]
pub const fn from_ascii_bytes<const N: usize>(src: &[AsciiByte; N]) -> Self {
Self::from_bytes::<N>(unsafe { core::mem::transmute(src) })
}
#[inline]
pub const fn to_bytes(&self) -> [u8; 8] {
self.0.to_ne_bytes()
}
#[inline]
pub const fn to_ascii_bytes(&self) -> [AsciiByte; 8] {
unsafe { core::mem::transmute(self.to_bytes()) }
}
pub const fn len(&self) -> usize {
let word = self.0;
#[cfg(target_endian = "little")]
let len = (8 - word.leading_zeros() / 8) as usize;
#[cfg(target_endian = "big")]
let len = (8 - word.trailing_zeros() / 8) as usize;
len
}
pub const fn is_ascii_alphabetic(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f_7f7f_7f7f) & 0x8080_8080_8080_8080;
let lower = word | 0x2020_2020_2020_2020;
let alpha = !(lower + 0x1f1f_1f1f_1f1f_1f1f) | (lower + 0x0505_0505_0505_0505);
(alpha & mask) == 0
}
pub const fn is_ascii_alphanumeric(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f_7f7f_7f7f) & 0x8080_8080_8080_8080;
let numeric = !(word + 0x5050_5050_5050_5050) | (word + 0x4646_4646_4646_4646);
let lower = word | 0x2020_2020_2020_2020;
let alpha = !(lower + 0x1f1f_1f1f_1f1f_1f1f) | (lower + 0x0505_0505_0505_0505);
(alpha & numeric & mask) == 0
}
pub const fn is_ascii_numeric(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f_7f7f_7f7f) & 0x8080_8080_8080_8080;
let numeric = !(word + 0x5050_5050_5050_5050) | (word + 0x4646_4646_4646_4646);
(numeric & mask) == 0
}
pub const fn is_ascii_lowercase(&self) -> bool {
let word = self.0;
let invalid_case = !(word + 0x3f3f_3f3f_3f3f_3f3f) | (word + 0x2525_2525_2525_2525);
(invalid_case & 0x8080_8080_8080_8080) == 0x8080_8080_8080_8080
}
pub const fn is_ascii_titlecase(&self) -> bool {
let word = self.0;
let invalid_case = if cfg!(target_endian = "little") {
!(word + 0x3f3f_3f3f_3f3f_3f1f) | (word + 0x2525_2525_2525_2505)
} else {
!(word + 0x1f3f_3f3f_3f3f_3f3f) | (word + 0x0525_2525_2525_2525)
};
(invalid_case & 0x8080_8080_8080_8080) == 0x8080_8080_8080_8080
}
pub const fn is_ascii_uppercase(&self) -> bool {
let word = self.0;
let invalid_case = !(word + 0x1f1f_1f1f_1f1f_1f1f) | (word + 0x0505_0505_0505_0505);
(invalid_case & 0x8080_8080_8080_8080) == 0x8080_8080_8080_8080
}
pub const fn is_ascii_alphabetic_lowercase(&self) -> bool {
let word = self.0;
// `mask` sets all NUL bytes to 0.
let mask = (word + 0x7f7f_7f7f_7f7f_7f7f) & 0x8080_8080_8080_8080;
// `lower_alpha` sets all lowercase ASCII characters to 0 and all others to 1.
let lower_alpha = !(word + 0x1f1f_1f1f_1f1f_1f1f) | (word + 0x0505_0505_0505_0505);
// The overall string is valid if every character passes at least one test.
// We performed two tests here: non-NUL (`mask`) and lowercase ASCII character (`alpha`).
(lower_alpha & mask) == 0
}
pub const fn is_ascii_alphabetic_titlecase(&self) -> bool {
let word = self.0;
// See explanatory comments in is_ascii_alphabetic_lowercase
let mask = (word + 0x7f7f_7f7f_7f7f_7f7f) & 0x8080_8080_8080_8080;
let title_case = if cfg!(target_endian = "little") {
!(word + 0x1f1f_1f1f_1f1f_1f3f) | (word + 0x0505_0505_0505_0525)
} else {
!(word + 0x3f1f_1f1f_1f1f_1f1f) | (word + 0x2505_0505_0505_0505)
};
(title_case & mask) == 0
}
pub const fn is_ascii_alphabetic_uppercase(&self) -> bool {
let word = self.0;
// See explanatory comments in is_ascii_alphabetic_lowercase
let mask = (word + 0x7f7f_7f7f_7f7f_7f7f) & 0x8080_8080_8080_8080;
let upper_alpha = !(word + 0x3f3f_3f3f_3f3f_3f3f) | (word + 0x2525_2525_2525_2525);
(upper_alpha & mask) == 0
}
pub const fn to_ascii_lowercase(&self) -> Self {
let word = self.0;
let result = word
| (((word + 0x3f3f_3f3f_3f3f_3f3f)
& !(word + 0x2525_2525_2525_2525)
& 0x8080_8080_8080_8080)
>> 2);
Self(result)
}
pub const fn to_ascii_titlecase(&self) -> Self {
let word = self.0.to_le();
let mask = ((word + 0x3f3f_3f3f_3f3f_3f1f)
& !(word + 0x2525_2525_2525_2505)
& 0x8080_8080_8080_8080)
>> 2;
let result = (word | mask) & !(0x20 & mask);
Self(u64::from_le(result))
}
pub const fn to_ascii_uppercase(&self) -> Self {
let word = self.0;
let result = word
& !(((word + 0x1f1f_1f1f_1f1f_1f1f)
& !(word + 0x0505_0505_0505_0505)
& 0x8080_8080_8080_8080)
>> 2);
Self(result)
}
}

163
third_party/rust/tinystr/src/lib.rs поставляемый
Просмотреть файл

@ -1,105 +1,116 @@
//! `tinystr` is a small ASCII-only bounded length string representation.
// 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 ).
//! `tinystr` is a utility crate of the [`ICU4X`] project.
//!
//! The crate is meant to be used for scenarios where one needs a fast
//! and memory efficient way to store and manipulate short ASCII-only strings.
//! It includes [`TinyAsciiStr`], a core API for representing small ASCII-only bounded length strings.
//!
//! `tinystr` converts each string into an unsigned integer, and uses bitmasking
//! to compare, convert cases and test for common characteristics of strings.
//!
//! # Details
//! It is optimized for operations on strings of size 8 or smaller. When use cases involve comparison
//! and conversion of strings for lowercase/uppercase/titlecase, or checking
//! numeric/alphabetic/alphanumeric, `TinyAsciiStr` is the edge performance library.
//!
//! The crate provides three structs and an enum:
//! * `TinyStr4` an ASCII-only string limited to 4 characters.
//! * `TinyStr8` an ASCII-only string limited to 8 characters.
//! * `TinyStr16` an ASCII-only string limited to 16 characters.
//! * `TinyStrAuto` (enum):
//! * `Tiny` when the string is 16 characters or less.
//! * `Heap` when the string is 17 or more characters.
//! # Examples
//!
//! `TinyStrAuto` stores the string as a TinyStr16 when it is short enough, or else falls back to a
//! standard `String`. You should use TinyStrAuto when you expect most strings to be 16 characters
//! or smaller, but occasionally you receive one that exceeds that length. Unlike the structs,
//! `TinyStrAuto` does not implement `Copy`.
//! ```rust
//! use tinystr::TinyAsciiStr;
//!
//! # no_std
//!
//! Disable the `std` feature of this crate to make it `#[no_std]`. Doing so disables `TinyStrAuto`.
//! You can re-enable `TinyStrAuto` in `#[no_std]` mode by enabling the `alloc` feature.
//!
//! # Example
//!
//! ```
//! use tinystr::{TinyStr4, TinyStr8, TinyStr16, TinyStrAuto};
//!
//! let s1: TinyStr4 = "tEsT".parse()
//! .expect("Failed to parse.");
//! let s1: TinyAsciiStr<4> = "tEsT".parse().expect("Failed to parse.");
//!
//! assert_eq!(s1, "tEsT");
//! assert_eq!(s1.to_ascii_uppercase(), "TEST");
//! assert_eq!(s1.to_ascii_lowercase(), "test");
//! assert_eq!(s1.to_ascii_titlecase(), "Test");
//! assert_eq!(s1.is_ascii_alphanumeric(), true);
//! assert_eq!(s1.is_ascii_numeric(), false);
//!
//! let s2: TinyStr8 = "New York".parse()
//! .expect("Failed to parse.");
//! let s2 = TinyAsciiStr::<8>::try_from_raw(*b"New York")
//! .expect("Failed to parse.");
//!
//! assert_eq!(s2, "New York");
//! assert_eq!(s2.to_ascii_uppercase(), "NEW YORK");
//! assert_eq!(s2.to_ascii_lowercase(), "new york");
//! assert_eq!(s2.to_ascii_titlecase(), "New york");
//! assert_eq!(s2.is_ascii_alphanumeric(), false);
//!
//! let s3: TinyStr16 = "metaMoRphosis123".parse()
//! .expect("Failed to parse.");
//!
//! assert_eq!(s3, "metaMoRphosis123");
//! assert_eq!(s3.to_ascii_uppercase(), "METAMORPHOSIS123");
//! assert_eq!(s3.to_ascii_lowercase(), "metamorphosis123");
//! assert_eq!(s3.to_ascii_titlecase(), "Metamorphosis123");
//! assert_eq!(s3.is_ascii_alphanumeric(), true);
//!
//! let s4: TinyStrAuto = "shortNoAlloc".parse().unwrap();
//! assert!(matches!(s4, TinyStrAuto::Tiny { .. }));
//! assert_eq!(s4, "shortNoAlloc");
//!
//! let s5: TinyStrAuto = "longFallbackToHeap".parse().unwrap();
//! assert!(matches!(s5, TinyStrAuto::Heap { .. }));
//! assert_eq!(s5, "longFallbackToHeap");
//! ```
//!
//! # Details
//!
//! When strings are of size 8 or smaller, the struct transforms the strings as `u32`/`u64` and uses
//! bitmasking to provide basic string manipulation operations:
//! * `is_ascii_numeric`
//! * `is_ascii_alphabetic`
//! * `is_ascii_alphanumeric`
//! * `to_ascii_lowercase`
//! * `to_ascii_uppercase`
//! * `to_ascii_titlecase`
//! * `PartialEq`
//!
//! `TinyAsciiStr` will fall back to `u8` character manipulation for strings of length greater than 8.
#![no_std]
//!
//! [`ICU4X`]: ../icu/index.html
#[cfg(any(feature = "std", test))]
extern crate std;
// https://github.com/unicode-org/icu4x/blob/main/docs/process/boilerplate.md#library-annotations
#![cfg_attr(not(test), no_std)]
#![cfg_attr(
not(test),
deny(
clippy::indexing_slicing,
clippy::unwrap_used,
clippy::expect_used,
clippy::panic,
clippy::exhaustive_structs,
clippy::exhaustive_enums,
missing_debug_implementations,
)
)]
#[cfg(all(not(feature = "std"), not(test)))]
extern crate core as std;
mod macros;
mod helpers;
mod tinystr16;
mod tinystr4;
mod tinystr8;
mod ascii;
mod asciibyte;
mod error;
mod int_ops;
#[cfg(any(feature = "std", feature = "alloc"))]
mod tinystrauto;
#[cfg(feature = "serde")]
mod serde;
pub use tinystr16::TinyStr16;
pub use tinystr4::TinyStr4;
pub use tinystr8::TinyStr8;
#[cfg(feature = "databake")]
mod databake;
#[cfg(any(feature = "std", feature = "alloc"))]
pub use tinystrauto::TinyStrAuto;
#[cfg(feature = "zerovec")]
mod ule;
#[cfg(feature = "macros")]
pub use tinystr_macros as macros;
#[cfg(any(feature = "serde", feature = "alloc"))]
extern crate alloc;
/// Enum to store the various types of errors that can cause parsing a TinyStr to fail.
#[derive(PartialEq, Eq, Debug)]
pub enum Error {
/// String is too large or too small to store as TinyStr.
InvalidSize,
/// String is empty.
InvalidNull,
/// String contains non-ASCII character(s).
NonAscii,
pub use ascii::TinyAsciiStr;
pub use error::TinyStrError;
/// These are temporary compatability reexports that will be removed
/// in a future version.
pub type TinyStr4 = TinyAsciiStr<4>;
/// These are temporary compatability reexports that will be removed
/// in a future version.
pub type TinyStr8 = TinyAsciiStr<8>;
/// These are temporary compatability reexports that will be removed
/// in a future version.
pub type TinyStr16 = TinyAsciiStr<16>;
#[test]
fn test_size() {
assert_eq!(
core::mem::size_of::<TinyStr4>(),
core::mem::size_of::<Option<TinyStr4>>()
);
assert_eq!(
core::mem::size_of::<TinyStr8>(),
core::mem::size_of::<Option<TinyStr8>>()
);
}
// /// Allows unit tests to use the macro
// #[cfg(test)]
// mod tinystr {
// pub use super::{TinyAsciiStr, TinyStrError};
// }

32
third_party/rust/tinystr/src/macros.rs поставляемый Normal file
Просмотреть файл

@ -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 ).
#[macro_export]
macro_rules! tinystr {
($n:literal, $s:literal) => {{
// Force it into a const context; otherwise it may get evaluated at runtime instead.
const TINYSTR_MACRO_CONST: $crate::TinyAsciiStr<$n> = {
match $crate::TinyAsciiStr::from_bytes($s.as_bytes()) {
Ok(s) => s,
// We are okay with panicking here because this is in a const context
#[allow(clippy::panic)]
// Cannot format the error since formatting isn't const yet
Err(_) => panic!(concat!("Failed to construct tinystr from ", $s)),
}
};
TINYSTR_MACRO_CONST
}};
}
#[cfg(test)]
mod tests {
#[test]
fn test_macro_construction() {
let s1 = tinystr!(8, "foobar");
assert_eq!(&*s1, "foobar");
let s1 = tinystr!(12, "foobarbaz");
assert_eq!(&*s1, "foobarbaz");
}
}

91
third_party/rust/tinystr/src/serde.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,91 @@
// 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::TinyAsciiStr;
use alloc::borrow::Cow;
use alloc::string::ToString;
use core::fmt;
use core::marker::PhantomData;
use core::ops::Deref;
use serde::de::{Error, SeqAccess, Visitor};
use serde::ser::SerializeTuple;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
impl<const N: usize> Serialize for TinyAsciiStr<N> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if serializer.is_human_readable() {
self.deref().serialize(serializer)
} else {
let mut seq = serializer.serialize_tuple(N)?;
for byte in self.all_bytes() {
seq.serialize_element(byte)?;
}
seq.end()
}
}
}
struct TinyAsciiStrVisitor<const N: usize> {
marker: PhantomData<TinyAsciiStr<N>>,
}
impl<const N: usize> TinyAsciiStrVisitor<N> {
fn new() -> Self {
TinyAsciiStrVisitor {
marker: PhantomData,
}
}
}
impl<'de, const N: usize> Visitor<'de> for TinyAsciiStrVisitor<N> {
type Value = TinyAsciiStr<N>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a TinyAsciiStr<{}>", N)
}
#[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut bytes = [0u8; N];
let mut zeroes = false;
for out in &mut bytes.iter_mut().take(N) {
let byte = seq
.next_element()?
.ok_or_else(|| Error::invalid_length(N, &self))?;
if byte == 0 {
zeroes = true;
} else if zeroes {
return Err(Error::custom("TinyAsciiStr cannot contain null bytes"));
}
if byte >= 0x80 {
return Err(Error::custom("TinyAsciiStr cannot contain non-ascii bytes"));
}
*out = byte;
}
Ok(unsafe { TinyAsciiStr::from_bytes_unchecked(bytes) })
}
}
impl<'de, const N: usize> Deserialize<'de> for TinyAsciiStr<N> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
if deserializer.is_human_readable() {
let x: Cow<'de, str> = Deserialize::deserialize(deserializer)?;
TinyAsciiStr::from_str(&x).map_err(|e| Error::custom(e.to_string()))
} else {
deserializer.deserialize_tuple(N, TinyAsciiStrVisitor::<N>::new())
}
}
}

327
third_party/rust/tinystr/src/tinystr16.rs поставляемый
Просмотреть файл

@ -1,327 +0,0 @@
use std::cmp::Ordering;
use std::convert::Into;
use std::fmt;
use std::num::NonZeroU128;
use std::ops::Deref;
use std::ptr::copy_nonoverlapping;
use std::str::FromStr;
use crate::Error;
/// A tiny string that is from 1 to 16 non-NUL ASCII characters.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr16;
///
/// let s1: TinyStr16 = "Metamorphosis".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1, "Metamorphosis");
/// assert!(s1.is_ascii_alphabetic());
/// ```
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct TinyStr16(NonZeroU128);
impl TinyStr16 {
/// Creates a TinyStr16 from a byte slice.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr16;
///
/// let s1 = TinyStr16::from_bytes("Testing".as_bytes())
/// .expect("Failed to parse.");
///
/// assert_eq!(s1, "Testing");
/// ```
#[inline(always)]
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
let len = bytes.len();
if len < 1 || len > 16 {
return Err(Error::InvalidSize);
}
unsafe {
let mut word: u128 = 0;
copy_nonoverlapping(bytes.as_ptr(), &mut word as *mut u128 as *mut u8, len);
let mask = 0x80808080_80808080_80808080_80808080u128 >> (8 * (16 - len));
// TODO: could do this with #cfg(target_endian), but this is clearer and
// more confidence-inspiring.
let mask = u128::from_le(mask);
if (word & mask) != 0 {
return Err(Error::NonAscii);
}
if ((mask - word) & mask) != 0 {
return Err(Error::InvalidNull);
}
Ok(Self(NonZeroU128::new_unchecked(word)))
}
}
/// An unsafe constructor intended for cases where the consumer
/// guarantees that the input is a little endian integer which
/// is a correct representation of a `TinyStr16` string.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr16;
///
/// let s1: TinyStr16 = "Metamorphosis".parse()
/// .expect("Failed to parse.");
///
/// let num: u128 = s1.into();
///
/// let s2 = unsafe { TinyStr16::new_unchecked(num) };
///
/// assert_eq!(s1, s2);
/// assert_eq!(s2.as_str(), "Metamorphosis");
/// ```
///
/// # Safety
///
/// The method does not validate the `u128` to be properly encoded
/// value for `TinyStr16`.
/// The value can be retrieved via `Into<u128> for TinyStr16`.
#[inline(always)]
pub const unsafe fn new_unchecked(text: u128) -> Self {
Self(NonZeroU128::new_unchecked(u128::from_le(text)))
}
/// Extracts a string slice containing the entire `TinyStr16`.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr16;
///
/// let s1: TinyStr16 = "Metamorphosis".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1.as_str(), "Metamorphosis");
/// ```
#[inline(always)]
pub fn as_str(&self) -> &str {
self.deref()
}
/// Checks if the value is composed of ASCII alphabetic characters:
///
/// * U+0041 'A' ..= U+005A 'Z', or
/// * U+0061 'a' ..= U+007A 'z'.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr16;
///
/// let s1: TinyStr16 = "Metamorphosis".parse()
/// .expect("Failed to parse.");
/// let s2: TinyStr16 = "Met3mo4pho!is".parse()
/// .expect("Failed to parse.");
///
/// assert!(s1.is_ascii_alphabetic());
/// assert!(!s2.is_ascii_alphabetic());
/// ```
pub fn is_ascii_alphabetic(self) -> bool {
let word = self.0.get();
let mask =
(word + 0x7f7f7f7f_7f7f7f7f_7f7f7f7f_7f7f7f7f) & 0x80808080_80808080_80808080_80808080;
let lower = word | 0x20202020_20202020_20202020_20202020;
let alpha = !(lower + 0x1f1f1f1f_1f1f1f1f_1f1f1f1f_1f1f1f1f)
| (lower + 0x05050505_05050505_05050505_05050505);
(alpha & mask) == 0
}
/// Checks if the value is composed of ASCII alphanumeric characters:
///
/// * U+0041 'A' ..= U+005A 'Z', or
/// * U+0061 'a' ..= U+007A 'z', or
/// * U+0030 '0' ..= U+0039 '9'.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr16;
///
/// let s1: TinyStr16 = "A15bingA1".parse()
/// .expect("Failed to parse.");
/// let s2: TinyStr16 = "[3@w00Fs1".parse()
/// .expect("Failed to parse.");
///
/// assert!(s1.is_ascii_alphanumeric());
/// assert!(!s2.is_ascii_alphanumeric());
/// ```
pub fn is_ascii_alphanumeric(self) -> bool {
let word = self.0.get();
let mask =
(word + 0x7f7f7f7f_7f7f7f7f_7f7f7f7f_7f7f7f7f) & 0x80808080_80808080_80808080_80808080;
let numeric = !(word + 0x50505050_50505050_50505050_50505050)
| (word + 0x46464646_46464646_46464646_46464646);
let lower = word | 0x20202020_20202020_20202020_20202020;
let alpha = !(lower + 0x1f1f1f1f_1f1f1f1f_1f1f1f1f_1f1f1f1f)
| (lower + 0x05050505_05050505_05050505_05050505);
(alpha & numeric & mask) == 0
}
/// Checks if the value is composed of ASCII decimal digits:
///
/// * U+0030 '0' ..= U+0039 '9'.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr16;
///
/// let s1: TinyStr16 = "31212314141".parse()
/// .expect("Failed to parse.");
/// let s2: TinyStr16 = "3d3d3d3d".parse()
/// .expect("Failed to parse.");
///
/// assert!(s1.is_ascii_numeric());
/// assert!(!s2.is_ascii_numeric());
/// ```
pub fn is_ascii_numeric(self) -> bool {
let word = self.0.get();
let mask =
(word + 0x7f7f7f7f_7f7f7f7f_7f7f7f7f_7f7f7f7f) & 0x80808080_80808080_80808080_80808080;
let numeric = !(word + 0x50505050_50505050_50505050_50505050)
| (word + 0x46464646_46464646_46464646_46464646);
(numeric & mask) == 0
}
/// Converts this type to its ASCII lower case equivalent in-place.
///
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', other characters are unchanged.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr16;
///
/// let s1: TinyStr16 = "MeTAmOrpHo3sis".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1.to_ascii_lowercase(), "metamorpho3sis");
/// ```
pub fn to_ascii_lowercase(self) -> Self {
let word = self.0.get();
let result = word
| (((word + 0x3f3f3f3f_3f3f3f3f_3f3f3f3f_3f3f3f3f)
& !(word + 0x25252525_25252525_25252525_25252525)
& 0x80808080_80808080_80808080_80808080)
>> 2);
unsafe { Self(NonZeroU128::new_unchecked(result)) }
}
/// Converts this type to its ASCII title case equivalent in-place.
///
/// First character, if is an ASCII letter 'a' to 'z' is mapped to 'A' to 'Z',
/// other characters are unchanged.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr16;
///
/// let s1: TinyStr16 = "metamorphosis".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1.to_ascii_titlecase(), "Metamorphosis");
/// ```
pub fn to_ascii_titlecase(self) -> Self {
let word = self.0.get().to_le();
let mask = ((word + 0x3f3f3f3f_3f3f3f3f_3f3f3f3f_3f3f3f1f)
& !(word + 0x25252525_25252525_25252525_25252505)
& 0x80808080_80808080_80808080_80808080)
>> 2;
let result = (word | mask) & !(0x20 & mask);
unsafe { Self(NonZeroU128::new_unchecked(u128::from_le(result))) }
}
/// Converts this type to its ASCII upper case equivalent in-place.
///
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', other characters are unchanged.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr16;
///
/// let s1: TinyStr16 = "Met3amorphosis".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1.to_ascii_uppercase(), "MET3AMORPHOSIS");
/// ```
pub fn to_ascii_uppercase(self) -> Self {
let word = self.0.get();
let result = word
& !(((word + 0x1f1f1f1f_1f1f1f1f_1f1f1f1f_1f1f1f1f)
& !(word + 0x05050505_05050505_05050505_05050505)
& 0x80808080_80808080_80808080_80808080)
>> 2);
unsafe { Self(NonZeroU128::new_unchecked(result)) }
}
}
impl fmt::Display for TinyStr16 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.deref())
}
}
impl fmt::Debug for TinyStr16 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.deref())
}
}
impl Deref for TinyStr16 {
type Target = str;
#[inline(always)]
fn deref(&self) -> &str {
// Again, could use #cfg to hand-roll a big-endian implementation.
let word = self.0.get().to_le();
let len = (16 - word.leading_zeros() / 8) as usize;
unsafe {
let slice = core::slice::from_raw_parts(&self.0 as *const _ as *const u8, len);
std::str::from_utf8_unchecked(slice)
}
}
}
impl PartialEq<&str> for TinyStr16 {
fn eq(&self, other: &&str) -> bool {
self.deref() == *other
}
}
impl PartialOrd for TinyStr16 {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for TinyStr16 {
fn cmp(&self, other: &Self) -> Ordering {
self.0.get().to_be().cmp(&other.0.get().to_be())
}
}
impl FromStr for TinyStr16 {
type Err = Error;
#[inline(always)]
fn from_str(text: &str) -> Result<Self, Self::Err> {
Self::from_bytes(text.as_bytes())
}
}
impl Into<u128> for TinyStr16 {
fn into(self) -> u128 {
self.0.get().to_le()
}
}

299
third_party/rust/tinystr/src/tinystr4.rs поставляемый
Просмотреть файл

@ -1,299 +0,0 @@
use std::cmp::Ordering;
use std::convert::Into;
use std::fmt;
use std::num::NonZeroU32;
use std::ops::Deref;
use std::str::FromStr;
use crate::helpers::make_4byte_bytes;
use crate::Error;
/// A tiny string that is from 1 to 4 non-NUL ASCII characters.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr4;
///
/// let s1: TinyStr4 = "Test".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1, "Test");
/// assert!(s1.is_ascii_alphabetic());
/// ```
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct TinyStr4(NonZeroU32);
impl TinyStr4 {
/// Creates a TinyStr4 from a byte slice.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr4;
///
/// let s1 = TinyStr4::from_bytes("Test".as_bytes())
/// .expect("Failed to parse.");
///
/// assert_eq!(s1, "Test");
/// ```
#[inline(always)]
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
unsafe {
match bytes.len() {
1 => make_4byte_bytes(bytes, 1, 0x80).map(Self),
2 => make_4byte_bytes(bytes, 2, 0x8080).map(Self),
3 => make_4byte_bytes(bytes, 3, 0x0080_8080).map(Self),
4 => make_4byte_bytes(bytes, 4, 0x8080_8080).map(Self),
_ => Err(Error::InvalidSize),
}
}
}
/// An unsafe constructor intended for cases where the consumer
/// guarantees that the input is a little endian integer which
/// is a correct representation of a `TinyStr4` string.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr4;
///
/// let s1: TinyStr4 = "Test".parse()
/// .expect("Failed to parse.");
///
/// let num: u32 = s1.into();
///
/// let s2 = unsafe { TinyStr4::new_unchecked(num) };
///
/// assert_eq!(s1, s2);
/// assert_eq!(s2.as_str(), "Test");
/// ```
///
/// # Safety
///
/// The method does not validate the `u32` to be properly encoded
/// value for `TinyStr4`.
/// The value can be retrieved via `Into<u32> for TinyStr4`.
#[inline(always)]
pub const unsafe fn new_unchecked(text: u32) -> Self {
Self(NonZeroU32::new_unchecked(u32::from_le(text)))
}
/// Extracts a string slice containing the entire `TinyStr4`.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr4;
///
/// let s1: TinyStr4 = "Test".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1.as_str(), "Test");
/// ```
#[inline(always)]
pub fn as_str(&self) -> &str {
self.deref()
}
/// Checks if the value is composed of ASCII alphabetic characters:
///
/// * U+0041 'A' ..= U+005A 'Z', or
/// * U+0061 'a' ..= U+007A 'z'.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr4;
///
/// let s1: TinyStr4 = "Test".parse()
/// .expect("Failed to parse.");
/// let s2: TinyStr4 = "Te3t".parse()
/// .expect("Failed to parse.");
///
/// assert!(s1.is_ascii_alphabetic());
/// assert!(!s2.is_ascii_alphabetic());
/// ```
pub fn is_ascii_alphabetic(self) -> bool {
let word = self.0.get();
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
let lower = word | 0x2020_2020;
let alpha = !(lower + 0x1f1f_1f1f) | (lower + 0x0505_0505);
(alpha & mask) == 0
}
/// Checks if the value is composed of ASCII alphanumeric characters:
///
/// * U+0041 'A' ..= U+005A 'Z', or
/// * U+0061 'a' ..= U+007A 'z', or
/// * U+0030 '0' ..= U+0039 '9'.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr4;
///
/// let s1: TinyStr4 = "A15b".parse()
/// .expect("Failed to parse.");
/// let s2: TinyStr4 = "[3@w".parse()
/// .expect("Failed to parse.");
///
/// assert!(s1.is_ascii_alphanumeric());
/// assert!(!s2.is_ascii_alphanumeric());
/// ```
pub fn is_ascii_alphanumeric(self) -> bool {
let word = self.0.get();
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
let numeric = !(word + 0x5050_5050) | (word + 0x4646_4646);
let lower = word | 0x2020_2020;
let alpha = !(lower + 0x1f1f_1f1f) | (lower + 0x0505_0505);
(alpha & numeric & mask) == 0
}
/// Checks if the value is composed of ASCII decimal digits:
///
/// * U+0030 '0' ..= U+0039 '9'.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr4;
///
/// let s1: TinyStr4 = "312".parse()
/// .expect("Failed to parse.");
/// let s2: TinyStr4 = "3d".parse()
/// .expect("Failed to parse.");
///
/// assert!(s1.is_ascii_numeric());
/// assert!(!s2.is_ascii_numeric());
/// ```
pub fn is_ascii_numeric(self) -> bool {
let word = self.0.get();
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
let numeric = !(word + 0x5050_5050) | (word + 0x4646_4646);
(numeric & mask) == 0
}
/// Converts this type to its ASCII lower case equivalent in-place.
///
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', other characters are unchanged.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr4;
///
/// let s1: TinyStr4 = "TeS3".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1.to_ascii_lowercase(), "tes3");
/// ```
pub fn to_ascii_lowercase(self) -> Self {
let word = self.0.get();
let result = word | (((word + 0x3f3f_3f3f) & !(word + 0x2525_2525) & 0x8080_8080) >> 2);
unsafe { Self(NonZeroU32::new_unchecked(result)) }
}
/// Converts this type to its ASCII title case equivalent in-place.
///
/// First character, if is an ASCII letter 'a' to 'z' is mapped to 'A' to 'Z',
/// other characters are unchanged.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr4;
///
/// let s1: TinyStr4 = "test".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1.to_ascii_titlecase(), "Test");
/// ```
pub fn to_ascii_titlecase(self) -> Self {
let word = self.0.get().to_le();
let mask = ((word + 0x3f3f_3f1f) & !(word + 0x2525_2505) & 0x8080_8080) >> 2;
let result = (word | mask) & !(0x20 & mask);
unsafe { Self(NonZeroU32::new_unchecked(u32::from_le(result))) }
}
/// Converts this type to its ASCII upper case equivalent in-place.
///
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', other characters are unchanged.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr4;
///
/// let s1: TinyStr4 = "Tes3".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1.to_ascii_uppercase(), "TES3");
/// ```
pub fn to_ascii_uppercase(self) -> Self {
let word = self.0.get();
let result = word & !(((word + 0x1f1f_1f1f) & !(word + 0x0505_0505) & 0x8080_8080) >> 2);
unsafe { Self(NonZeroU32::new_unchecked(result)) }
}
}
impl fmt::Display for TinyStr4 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.deref())
}
}
impl fmt::Debug for TinyStr4 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.deref())
}
}
impl Deref for TinyStr4 {
type Target = str;
#[inline(always)]
fn deref(&self) -> &str {
// Again, could use #cfg to hand-roll a big-endian implementation.
let word = self.0.get().to_le();
let len = (4 - word.leading_zeros() / 8) as usize;
unsafe {
let slice = core::slice::from_raw_parts(&self.0 as *const _ as *const u8, len);
std::str::from_utf8_unchecked(slice)
}
}
}
impl PartialEq<&str> for TinyStr4 {
fn eq(&self, other: &&str) -> bool {
self.deref() == *other
}
}
impl PartialOrd for TinyStr4 {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for TinyStr4 {
fn cmp(&self, other: &Self) -> Ordering {
self.0.get().to_be().cmp(&other.0.get().to_be())
}
}
impl FromStr for TinyStr4 {
type Err = Error;
#[inline(always)]
fn from_str(text: &str) -> Result<Self, Self::Err> {
Self::from_bytes(text.as_bytes())
}
}
impl Into<u32> for TinyStr4 {
fn into(self) -> u32 {
self.0.get().to_le()
}
}

319
third_party/rust/tinystr/src/tinystr8.rs поставляемый
Просмотреть файл

@ -1,319 +0,0 @@
use std::cmp::Ordering;
use std::convert::Into;
use std::fmt;
use std::num::NonZeroU64;
use std::ops::Deref;
use std::ptr::copy_nonoverlapping;
use std::str::FromStr;
use crate::Error;
/// A tiny string that is from 1 to 8 non-NUL ASCII characters.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr8;
///
/// let s1: TinyStr8 = "Testing".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1, "Testing");
/// assert!(s1.is_ascii_alphabetic());
/// ```
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct TinyStr8(NonZeroU64);
impl TinyStr8 {
/// Creates a TinyStr8 from a byte slice.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr8;
///
/// let s1 = TinyStr8::from_bytes("Testing".as_bytes())
/// .expect("Failed to parse.");
///
/// assert_eq!(s1, "Testing");
/// ```
#[inline(always)]
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
let len = bytes.len();
if len < 1 || len > 8 {
return Err(Error::InvalidSize);
}
unsafe {
let mut word: u64 = 0;
copy_nonoverlapping(bytes.as_ptr(), &mut word as *mut u64 as *mut u8, len);
let mask = 0x80808080_80808080u64 >> (8 * (8 - len));
// TODO: could do this with #cfg(target_endian), but this is clearer and
// more confidence-inspiring.
let mask = u64::from_le(mask);
if (word & mask) != 0 {
return Err(Error::NonAscii);
}
if ((mask - word) & mask) != 0 {
return Err(Error::InvalidNull);
}
Ok(Self(NonZeroU64::new_unchecked(word)))
}
}
/// An unsafe constructor intended for cases where the consumer
/// guarantees that the input is a little endian integer which
/// is a correct representation of a `TinyStr8` string.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr8;
///
/// let s1: TinyStr8 = "Testing".parse()
/// .expect("Failed to parse.");
///
/// let num: u64 = s1.into();
///
/// let s2 = unsafe { TinyStr8::new_unchecked(num) };
///
/// assert_eq!(s1, s2);
/// assert_eq!(s2.as_str(), "Testing");
/// ```
///
/// # Safety
///
/// The method does not validate the `u64` to be properly encoded
/// value for `TinyStr8`.
/// The value can be retrieved via `Into<u64> for TinyStr8`.
#[inline(always)]
pub const unsafe fn new_unchecked(text: u64) -> Self {
Self(NonZeroU64::new_unchecked(u64::from_le(text)))
}
/// Extracts a string slice containing the entire `TinyStr8`.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr8;
///
/// let s1: TinyStr8 = "Testing".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1.as_str(), "Testing");
/// ```
#[inline(always)]
pub fn as_str(&self) -> &str {
self.deref()
}
/// Checks if the value is composed of ASCII alphabetic characters:
///
/// * U+0041 'A' ..= U+005A 'Z', or
/// * U+0061 'a' ..= U+007A 'z'.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr8;
///
/// let s1: TinyStr8 = "Testing".parse()
/// .expect("Failed to parse.");
/// let s2: TinyStr8 = "Te3ting".parse()
/// .expect("Failed to parse.");
///
/// assert!(s1.is_ascii_alphabetic());
/// assert!(!s2.is_ascii_alphabetic());
/// ```
pub fn is_ascii_alphabetic(self) -> bool {
let word = self.0.get();
let mask = (word + 0x7f7f7f7f_7f7f7f7f) & 0x80808080_80808080;
let lower = word | 0x20202020_20202020;
let alpha = !(lower + 0x1f1f1f1f_1f1f1f1f) | (lower + 0x05050505_05050505);
(alpha & mask) == 0
}
/// Checks if the value is composed of ASCII alphanumeric characters:
///
/// * U+0041 'A' ..= U+005A 'Z', or
/// * U+0061 'a' ..= U+007A 'z', or
/// * U+0030 '0' ..= U+0039 '9'.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr8;
///
/// let s1: TinyStr8 = "A15bing".parse()
/// .expect("Failed to parse.");
/// let s2: TinyStr8 = "[3@wing".parse()
/// .expect("Failed to parse.");
///
/// assert!(s1.is_ascii_alphanumeric());
/// assert!(!s2.is_ascii_alphanumeric());
/// ```
pub fn is_ascii_alphanumeric(self) -> bool {
let word = self.0.get();
let mask = (word + 0x7f7f7f7f_7f7f7f7f) & 0x80808080_80808080;
let numeric = !(word + 0x50505050_50505050) | (word + 0x46464646_46464646);
let lower = word | 0x20202020_20202020;
let alpha = !(lower + 0x1f1f1f1f_1f1f1f1f) | (lower + 0x05050505_05050505);
(alpha & numeric & mask) == 0
}
/// Checks if the value is composed of ASCII decimal digits:
///
/// * U+0030 '0' ..= U+0039 '9'.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr8;
///
/// let s1: TinyStr8 = "3121029".parse()
/// .expect("Failed to parse.");
/// let s2: TinyStr8 = "3d212d".parse()
/// .expect("Failed to parse.");
///
/// assert!(s1.is_ascii_numeric());
/// assert!(!s2.is_ascii_numeric());
/// ```
pub fn is_ascii_numeric(self) -> bool {
let word = self.0.get();
let mask = (word + 0x7f7f7f7f_7f7f7f7f) & 0x80808080_80808080;
let numeric = !(word + 0x50505050_50505050) | (word + 0x46464646_46464646);
(numeric & mask) == 0
}
/// Converts this type to its ASCII lower case equivalent in-place.
///
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', other characters are unchanged.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr8;
///
/// let s1: TinyStr8 = "TeS3ing".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1.to_ascii_lowercase(), "tes3ing");
/// ```
pub fn to_ascii_lowercase(self) -> Self {
let word = self.0.get();
let result = word
| (((word + 0x3f3f3f3f_3f3f3f3f)
& !(word + 0x25252525_25252525)
& 0x80808080_80808080)
>> 2);
unsafe { Self(NonZeroU64::new_unchecked(result)) }
}
/// Converts this type to its ASCII title case equivalent in-place.
///
/// First character, if is an ASCII letter 'a' to 'z' is mapped to 'A' to 'Z',
/// other characters are unchanged.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr8;
///
/// let s1: TinyStr8 = "testing".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1.to_ascii_titlecase(), "Testing");
/// ```
pub fn to_ascii_titlecase(self) -> Self {
let word = self.0.get().to_le();
let mask =
((word + 0x3f3f3f3f_3f3f3f1f) & !(word + 0x25252525_25252505) & 0x80808080_80808080)
>> 2;
let result = (word | mask) & !(0x20 & mask);
unsafe { Self(NonZeroU64::new_unchecked(u64::from_le(result))) }
}
/// Converts this type to its ASCII upper case equivalent in-place.
///
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', other characters are unchanged.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStr8;
///
/// let s1: TinyStr8 = "Tes3ing".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1.to_ascii_uppercase(), "TES3ING");
/// ```
pub fn to_ascii_uppercase(self) -> Self {
let word = self.0.get();
let result = word
& !(((word + 0x1f1f1f1f_1f1f1f1f)
& !(word + 0x05050505_05050505)
& 0x80808080_80808080)
>> 2);
unsafe { Self(NonZeroU64::new_unchecked(result)) }
}
}
impl fmt::Display for TinyStr8 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.deref())
}
}
impl fmt::Debug for TinyStr8 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.deref())
}
}
impl Deref for TinyStr8 {
type Target = str;
#[inline(always)]
fn deref(&self) -> &str {
// Again, could use #cfg to hand-roll a big-endian implementation.
let word = self.0.get().to_le();
let len = (8 - word.leading_zeros() / 8) as usize;
unsafe {
let slice = core::slice::from_raw_parts(&self.0 as *const _ as *const u8, len);
std::str::from_utf8_unchecked(slice)
}
}
}
impl PartialEq<&str> for TinyStr8 {
fn eq(&self, other: &&str) -> bool {
self.deref() == *other
}
}
impl PartialOrd for TinyStr8 {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for TinyStr8 {
fn cmp(&self, other: &Self) -> Ordering {
self.0.get().to_be().cmp(&other.0.get().to_be())
}
}
impl FromStr for TinyStr8 {
type Err = Error;
#[inline(always)]
fn from_str(text: &str) -> Result<Self, Self::Err> {
TinyStr8::from_bytes(text.as_bytes())
}
}
impl Into<u64> for TinyStr8 {
fn into(self) -> u64 {
self.0.get().to_le()
}
}

72
third_party/rust/tinystr/src/tinystrauto.rs поставляемый
Просмотреть файл

@ -1,72 +0,0 @@
use std::fmt;
use std::ops::Deref;
use std::str::FromStr;
use crate::helpers::String;
use crate::Error;
use crate::TinyStr16;
/// An ASCII string that is tiny when <= 16 chars and a String otherwise.
///
/// # Examples
///
/// ```
/// use tinystr::TinyStrAuto;
///
/// let s1: TinyStrAuto = "Testing".parse()
/// .expect("Failed to parse.");
///
/// assert_eq!(s1, "Testing");
/// ```
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub enum TinyStrAuto {
/// Up to 16 characters stored on the stack.
Tiny(TinyStr16),
/// 17 or more characters stored on the heap.
Heap(String),
}
impl fmt::Display for TinyStrAuto {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.deref().fmt(f)
}
}
impl Deref for TinyStrAuto {
type Target = str;
fn deref(&self) -> &str {
use TinyStrAuto::*;
match self {
Tiny(value) => value.deref(),
Heap(value) => value.deref(),
}
}
}
impl PartialEq<&str> for TinyStrAuto {
fn eq(&self, other: &&str) -> bool {
self.deref() == *other
}
}
impl FromStr for TinyStrAuto {
type Err = Error;
fn from_str(text: &str) -> Result<Self, Self::Err> {
if text.len() <= 16 {
match TinyStr16::from_str(text) {
Ok(result) => Ok(TinyStrAuto::Tiny(result)),
Err(err) => Err(err),
}
} else {
if !text.is_ascii() {
return Err(Error::NonAscii);
}
match String::from_str(text) {
Ok(result) => Ok(TinyStrAuto::Heap(result)),
Err(_) => unreachable!(),
}
}
}
}

76
third_party/rust/tinystr/src/ule.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,76 @@
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
use crate::TinyAsciiStr;
use zerovec::maps::ZeroMapKV;
use zerovec::ule::*;
use zerovec::{ZeroSlice, ZeroVec};
// Safety (based on the safety checklist on the ULE trait):
// 1. CharULE does not include any uninitialized or padding bytes.
// (achieved by `#[repr(transparent)]` on a type that satisfies this invariant)
// 2. CharULE is aligned to 1 byte.
// (achieved by `#[repr(transparent)]` on a type that satisfies this invariant)
// 3. The impl of validate_byte_slice() returns an error if any byte is not valid.
// 4. The impl of validate_byte_slice() returns an error if there are extra bytes.
// 5. The other ULE methods use the default impl.
// 6. CharULE byte equality is semantic equality
unsafe impl<const N: usize> ULE for TinyAsciiStr<N> {
#[inline]
fn validate_byte_slice(bytes: &[u8]) -> Result<(), ZeroVecError> {
if bytes.len() % N != 0 {
return Err(ZeroVecError::length::<Self>(bytes.len()));
}
// Validate the bytes
for chunk in bytes.chunks_exact(N) {
let _ = TinyAsciiStr::<N>::from_bytes_inner(chunk, 0, N, true)
.map_err(|_| ZeroVecError::parse::<Self>())?;
}
Ok(())
}
}
impl<const N: usize> AsULE for TinyAsciiStr<N> {
type ULE = Self;
#[inline]
fn to_unaligned(self) -> Self::ULE {
self
}
#[inline]
fn from_unaligned(unaligned: Self::ULE) -> Self {
unaligned
}
}
impl<'a, const N: usize> ZeroMapKV<'a> for TinyAsciiStr<N> {
type Container = ZeroVec<'a, TinyAsciiStr<N>>;
type Slice = ZeroSlice<TinyAsciiStr<N>>;
type GetType = TinyAsciiStr<N>;
type OwnedType = TinyAsciiStr<N>;
}
#[cfg(test)]
mod test {
use crate::*;
use zerovec::*;
#[test]
fn test_zerovec() {
let mut vec = ZeroVec::<TinyAsciiStr<7>>::new();
vec.with_mut(|v| v.push("foobar".parse().unwrap()));
vec.with_mut(|v| v.push("baz".parse().unwrap()));
vec.with_mut(|v| v.push("quux".parse().unwrap()));
let bytes = vec.as_bytes();
let vec: ZeroVec<TinyAsciiStr<7>> = ZeroVec::parse_byte_slice(bytes).unwrap();
assert_eq!(&*vec.get(0).unwrap(), "foobar");
assert_eq!(&*vec.get(1).unwrap(), "baz");
assert_eq!(&*vec.get(2).unwrap(), "quux");
}
}

538
third_party/rust/tinystr/tests/main.rs поставляемый
Просмотреть файл

@ -1,538 +0,0 @@
use std::fmt::Write;
use std::mem::size_of;
use std::ops::Deref;
use tinystr::{Error, TinyStr16, TinyStr4, TinyStr8};
#[cfg(any(feature = "std", feature = "alloc"))]
use tinystr::TinyStrAuto;
#[test]
fn tiny_sizes() {
assert_eq!(4, size_of::<TinyStr4>());
assert_eq!(8, size_of::<TinyStr8>());
assert_eq!(16, size_of::<TinyStr16>());
assert_eq!(24, size_of::<String>());
// Note: TinyStrAuto is size 32 even when a smaller TinyStr type is used
#[cfg(any(feature = "std", feature = "alloc"))]
assert_eq!(32, size_of::<TinyStrAuto>());
}
#[test]
fn tiny4_basic() {
let s: TinyStr4 = "abc".parse().unwrap();
assert_eq!(s.deref(), "abc");
}
#[test]
fn tiny4_from_bytes() {
let s = TinyStr4::from_bytes("abc".as_bytes()).unwrap();
assert_eq!(s.deref(), "abc");
assert_eq!(
TinyStr4::from_bytes(&[0, 159, 146, 150]),
Err(Error::NonAscii)
);
assert_eq!(TinyStr4::from_bytes(&[]), Err(Error::InvalidSize));
assert_eq!(TinyStr4::from_bytes(&[0]), Err(Error::InvalidNull));
}
#[test]
fn tiny4_size() {
assert_eq!("".parse::<TinyStr4>(), Err(Error::InvalidSize));
assert!("1".parse::<TinyStr4>().is_ok());
assert!("12".parse::<TinyStr4>().is_ok());
assert!("123".parse::<TinyStr4>().is_ok());
assert!("1234".parse::<TinyStr4>().is_ok());
assert_eq!("12345".parse::<TinyStr4>(), Err(Error::InvalidSize));
assert_eq!("123456789".parse::<TinyStr4>(), Err(Error::InvalidSize));
}
#[test]
fn tiny4_null() {
assert_eq!("a\u{0}b".parse::<TinyStr4>(), Err(Error::InvalidNull));
}
#[test]
fn tiny4_new_unchecked() {
let reference: TinyStr4 = "en".parse().unwrap();
let uval: u32 = reference.into();
let s = unsafe { TinyStr4::new_unchecked(uval) };
assert_eq!(s, reference);
assert_eq!(s, "en");
}
#[test]
fn tiny4_nonascii() {
assert_eq!("\u{4000}".parse::<TinyStr4>(), Err(Error::NonAscii));
}
#[test]
fn tiny4_alpha() {
let s: TinyStr4 = "@aZ[".parse().unwrap();
assert!(!s.is_ascii_alphabetic());
assert!(!s.is_ascii_alphanumeric());
assert_eq!(s.to_ascii_uppercase().as_str(), "@AZ[");
assert_eq!(s.to_ascii_lowercase().as_str(), "@az[");
assert!("abYZ".parse::<TinyStr4>().unwrap().is_ascii_alphabetic());
assert!("abYZ".parse::<TinyStr4>().unwrap().is_ascii_alphanumeric());
assert!("a123".parse::<TinyStr4>().unwrap().is_ascii_alphanumeric());
assert!(!"a123".parse::<TinyStr4>().unwrap().is_ascii_alphabetic());
}
#[test]
fn tiny4_numeric() {
let s: TinyStr4 = "@aZ[".parse().unwrap();
assert!(!s.is_ascii_numeric());
assert!("0123".parse::<TinyStr4>().unwrap().is_ascii_numeric());
}
#[test]
fn tiny4_titlecase() {
assert_eq!(
"abcd"
.parse::<TinyStr4>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"Abcd"
);
assert_eq!(
"ABCD"
.parse::<TinyStr4>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"Abcd"
);
assert_eq!(
"aBCD"
.parse::<TinyStr4>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"Abcd"
);
assert_eq!(
"A123"
.parse::<TinyStr4>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"A123"
);
assert_eq!(
"123a"
.parse::<TinyStr4>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"123a"
);
}
#[test]
fn tiny4_ord() {
let mut v: Vec<TinyStr4> = vec!["zh".parse().unwrap(), "fr".parse().unwrap()];
v.sort();
assert_eq!(v.get(0).unwrap().as_str(), "fr");
assert_eq!(v.get(1).unwrap().as_str(), "zh");
}
#[test]
fn tiny4_eq() {
let s1: TinyStr4 = "en".parse().unwrap();
let s2: TinyStr4 = "fr".parse().unwrap();
let s3: TinyStr4 = "en".parse().unwrap();
assert_eq!(s1, s3);
assert_ne!(s1, s2);
}
#[test]
fn tiny4_display() {
let s: TinyStr4 = "abcd".parse().unwrap();
let mut result = String::new();
write!(result, "{}", s).unwrap();
assert_eq!(result, "abcd");
assert_eq!(format!("{}", s), "abcd");
}
#[test]
fn tiny4_debug() {
let s: TinyStr4 = "abcd".parse().unwrap();
assert_eq!(format!("{:#?}", s), "\"abcd\"");
}
#[test]
fn tiny8_basic() {
let s: TinyStr8 = "abcde".parse().unwrap();
assert_eq!(s.deref(), "abcde");
}
#[test]
fn tiny8_from_bytes() {
let s = TinyStr8::from_bytes("abcde".as_bytes()).unwrap();
assert_eq!(s.deref(), "abcde");
assert_eq!(
TinyStr8::from_bytes(&[0, 159, 146, 150]),
Err(Error::NonAscii)
);
assert_eq!(TinyStr8::from_bytes(&[]), Err(Error::InvalidSize));
assert_eq!(TinyStr8::from_bytes(&[0]), Err(Error::InvalidNull));
}
#[test]
fn tiny8_size() {
assert_eq!("".parse::<TinyStr8>(), Err(Error::InvalidSize));
assert!("1".parse::<TinyStr8>().is_ok());
assert!("12".parse::<TinyStr8>().is_ok());
assert!("123".parse::<TinyStr8>().is_ok());
assert!("1234".parse::<TinyStr8>().is_ok());
assert!("12345".parse::<TinyStr8>().is_ok());
assert!("123456".parse::<TinyStr8>().is_ok());
assert!("1234567".parse::<TinyStr8>().is_ok());
assert!("12345678".parse::<TinyStr8>().is_ok());
assert_eq!("123456789".parse::<TinyStr8>(), Err(Error::InvalidSize));
}
#[test]
fn tiny8_null() {
assert_eq!("a\u{0}b".parse::<TinyStr8>(), Err(Error::InvalidNull));
}
#[test]
fn tiny8_new_unchecked() {
let reference: TinyStr8 = "Windows".parse().unwrap();
let uval: u64 = reference.into();
let s = unsafe { TinyStr8::new_unchecked(uval) };
assert_eq!(s, reference);
assert_eq!(s, "Windows");
}
#[test]
fn tiny8_nonascii() {
assert_eq!("\u{4000}".parse::<TinyStr8>(), Err(Error::NonAscii));
}
#[test]
fn tiny8_alpha() {
let s: TinyStr8 = "@abcXYZ[".parse().unwrap();
assert!(!s.is_ascii_alphabetic());
assert!(!s.is_ascii_alphanumeric());
assert_eq!(s.to_ascii_uppercase().as_str(), "@ABCXYZ[");
assert_eq!(s.to_ascii_lowercase().as_str(), "@abcxyz[");
assert!("abcXYZ".parse::<TinyStr8>().unwrap().is_ascii_alphabetic());
assert!("abcXYZ"
.parse::<TinyStr8>()
.unwrap()
.is_ascii_alphanumeric());
assert!(!"abc123".parse::<TinyStr8>().unwrap().is_ascii_alphabetic());
assert!("abc123"
.parse::<TinyStr8>()
.unwrap()
.is_ascii_alphanumeric());
}
#[test]
fn tiny8_numeric() {
let s: TinyStr8 = "@abcXYZ[".parse().unwrap();
assert!(!s.is_ascii_numeric());
assert!("01234567".parse::<TinyStr8>().unwrap().is_ascii_numeric());
}
#[test]
fn tiny8_titlecase() {
assert_eq!(
"abcdabcd"
.parse::<TinyStr8>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"Abcdabcd"
);
assert_eq!(
"ABCDABCD"
.parse::<TinyStr8>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"Abcdabcd"
);
assert_eq!(
"aBCDaBCD"
.parse::<TinyStr8>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"Abcdabcd"
);
assert_eq!(
"A123a123"
.parse::<TinyStr8>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"A123a123"
);
assert_eq!(
"123a123A"
.parse::<TinyStr8>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"123a123a"
);
}
#[test]
fn tiny8_ord() {
let mut v: Vec<TinyStr8> = vec!["nedis".parse().unwrap(), "macos".parse().unwrap()];
v.sort();
assert_eq!(v.get(0).unwrap().as_str(), "macos");
assert_eq!(v.get(1).unwrap().as_str(), "nedis");
}
#[test]
fn tiny8_eq() {
let s1: TinyStr8 = "windows".parse().unwrap();
let s2: TinyStr8 = "mac".parse().unwrap();
let s3: TinyStr8 = "windows".parse().unwrap();
assert_eq!(s1, s3);
assert_ne!(s1, s2);
}
#[test]
fn tiny8_display() {
let s: TinyStr8 = "abcdef".parse().unwrap();
let mut result = String::new();
write!(result, "{}", s).unwrap();
assert_eq!(result, "abcdef");
assert_eq!(format!("{}", s), "abcdef");
}
#[test]
fn tiny8_debug() {
let s: TinyStr8 = "abcdef".parse().unwrap();
assert_eq!(format!("{:#?}", s), "\"abcdef\"");
}
#[test]
fn tiny16_from_bytes() {
let s = TinyStr16::from_bytes("abcdefghijk".as_bytes()).unwrap();
assert_eq!(s.deref(), "abcdefghijk");
assert_eq!(
TinyStr16::from_bytes(&[0, 159, 146, 150]),
Err(Error::NonAscii)
);
assert_eq!(TinyStr16::from_bytes(&[]), Err(Error::InvalidSize));
assert_eq!(TinyStr16::from_bytes(&[0]), Err(Error::InvalidNull));
}
#[test]
fn tiny16_size() {
assert_eq!("".parse::<TinyStr16>(), Err(Error::InvalidSize));
assert!("1".parse::<TinyStr16>().is_ok());
assert!("12".parse::<TinyStr16>().is_ok());
assert!("123".parse::<TinyStr16>().is_ok());
assert!("1234".parse::<TinyStr16>().is_ok());
assert!("12345".parse::<TinyStr16>().is_ok());
assert!("123456".parse::<TinyStr16>().is_ok());
assert!("1234567".parse::<TinyStr16>().is_ok());
assert!("12345678".parse::<TinyStr16>().is_ok());
assert!("123456781".parse::<TinyStr16>().is_ok());
assert!("1234567812".parse::<TinyStr16>().is_ok());
assert!("12345678123".parse::<TinyStr16>().is_ok());
assert!("123456781234".parse::<TinyStr16>().is_ok());
assert!("1234567812345".parse::<TinyStr16>().is_ok());
assert!("12345678123456".parse::<TinyStr16>().is_ok());
assert!("123456781234567".parse::<TinyStr16>().is_ok());
assert!("1234567812345678".parse::<TinyStr16>().is_ok());
assert_eq!(
"12345678123456789".parse::<TinyStr16>(),
Err(Error::InvalidSize)
);
}
#[test]
fn tiny16_null() {
assert_eq!("a\u{0}b".parse::<TinyStr16>(), Err(Error::InvalidNull));
}
#[test]
fn tiny16_new_unchecked() {
let reference: TinyStr16 = "WindowsCE/ME/NT".parse().unwrap();
let uval: u128 = reference.into();
let s = unsafe { TinyStr16::new_unchecked(uval) };
assert_eq!(s, reference);
assert_eq!(s, "WindowsCE/ME/NT");
}
#[test]
fn tiny16_nonascii() {
assert_eq!("\u{4000}".parse::<TinyStr16>(), Err(Error::NonAscii));
}
#[test]
fn tiny16_alpha() {
let s: TinyStr16 = "@abcdefgTUVWXYZ[".parse().unwrap();
assert!(!s.is_ascii_alphabetic());
assert!(!s.is_ascii_alphanumeric());
assert_eq!(s.to_ascii_uppercase().as_str(), "@ABCDEFGTUVWXYZ[");
assert_eq!(s.to_ascii_lowercase().as_str(), "@abcdefgtuvwxyz[");
assert!("abcdefgTUVWXYZ"
.parse::<TinyStr16>()
.unwrap()
.is_ascii_alphabetic());
assert!("abcdefgTUVWXYZ"
.parse::<TinyStr16>()
.unwrap()
.is_ascii_alphanumeric());
assert!(!"abcdefg0123456"
.parse::<TinyStr16>()
.unwrap()
.is_ascii_alphabetic());
assert!("abcdefgTUVWXYZ"
.parse::<TinyStr16>()
.unwrap()
.is_ascii_alphanumeric());
}
#[test]
fn tiny16_numeric() {
let s: TinyStr16 = "@abcdefgTUVWXYZ[".parse().unwrap();
assert!(!s.is_ascii_numeric());
assert!("0123456789"
.parse::<TinyStr16>()
.unwrap()
.is_ascii_numeric());
}
#[test]
fn tiny16_titlecase() {
assert_eq!(
"abcdabcdabcdabcd"
.parse::<TinyStr16>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"Abcdabcdabcdabcd"
);
assert_eq!(
"ABCDABCDABCDABCD"
.parse::<TinyStr16>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"Abcdabcdabcdabcd"
);
assert_eq!(
"aBCDaBCDaBCDaBCD"
.parse::<TinyStr16>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"Abcdabcdabcdabcd"
);
assert_eq!(
"A123a123A123a123"
.parse::<TinyStr16>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"A123a123a123a123"
);
assert_eq!(
"123a123A123a123A"
.parse::<TinyStr16>()
.unwrap()
.to_ascii_titlecase()
.as_str(),
"123a123a123a123a"
);
}
#[test]
fn tiny16_ord() {
let mut v: Vec<TinyStr16> = vec!["nedis_xxxx".parse().unwrap(), "macos_xxxx".parse().unwrap()];
v.sort();
assert_eq!(v.get(0).unwrap().as_str(), "macos_xxxx");
assert_eq!(v.get(1).unwrap().as_str(), "nedis_xxxx");
}
#[test]
fn tiny16_eq() {
let s1: TinyStr16 = "windows98SE".parse().unwrap();
let s2: TinyStr16 = "mac".parse().unwrap();
let s3: TinyStr16 = "windows98SE".parse().unwrap();
assert_eq!(s1, s3);
assert_ne!(s1, s2);
}
#[test]
fn tiny16_display() {
let s: TinyStr16 = "abcdefghijkl".parse().unwrap();
let mut result = String::new();
write!(result, "{}", s).unwrap();
assert_eq!(result, "abcdefghijkl");
assert_eq!(format!("{}", s), "abcdefghijkl");
}
#[test]
fn tiny16_debug() {
let s: TinyStr16 = "abcdefghijkl".parse().unwrap();
assert_eq!(format!("{:#?}", s), "\"abcdefghijkl\"");
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[test]
fn tinyauto_basic() {
let s1: TinyStrAuto = "abc".parse().unwrap();
assert_eq!(s1, "abc");
let s2: TinyStrAuto = "veryveryveryveryverylong".parse().unwrap();
assert_eq!(s2, "veryveryveryveryverylong");
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[test]
fn tinyauto_nonascii() {
assert_eq!("\u{4000}".parse::<TinyStrAuto>(), Err(Error::NonAscii));
assert_eq!(
"veryveryveryveryverylong\u{4000}".parse::<TinyStrAuto>(),
Err(Error::NonAscii)
);
}
#[cfg(feature = "macros")]
const TS: TinyStr8 = tinystr::macros::tinystr8!("test");
#[cfg(feature = "macros")]
#[test]
fn tinystr_macros() {
use tinystr::macros::*;
let x: TinyStr8 = "test".parse().unwrap();
assert_eq!(TS, x);
let x: TinyStr4 = "foo".parse().unwrap();
assert_eq!(tinystr4!("foo"), x);
let x: TinyStr8 = "barbaz".parse().unwrap();
assert_eq!(tinystr8!("barbaz"), x);
let x: TinyStr16 = "metamorphosis".parse().unwrap();
assert_eq!(tinystr16!("metamorphosis"), x);
}

39
third_party/rust/tinystr/tests/serde.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,39 @@
// 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 tinystr::*;
// Tests largely adapted from `tinystr` crate
// https://github.com/zbraniecki/tinystr/blob/4e4eab55dd6bded7f29a18b41452c506c461716c/tests/serde.rs
macro_rules! test_roundtrip {
($f:ident, $n:literal, $val:expr) => {
#[test]
fn $f() {
let tiny: TinyAsciiStr<$n> = $val.parse().unwrap();
let json_string = serde_json::to_string(&tiny).unwrap();
let expected_json = concat!("\"", $val, "\"");
assert_eq!(json_string, expected_json);
let recover: TinyAsciiStr<$n> = serde_json::from_str(&json_string).unwrap();
assert_eq!(&*tiny, &*recover);
let bin = bincode::serialize(&tiny).unwrap();
assert_eq!(bin, &tiny.all_bytes()[..]);
let debin: TinyAsciiStr<$n> = bincode::deserialize(&bin).unwrap();
assert_eq!(&*tiny, &*debin);
let post = postcard::to_stdvec(&tiny).unwrap();
assert_eq!(post, &tiny.all_bytes()[..]);
let unpost: TinyAsciiStr<$n> = postcard::from_bytes(&post).unwrap();
assert_eq!(&*tiny, &*unpost);
}
};
}
test_roundtrip!(test_roundtrip4_1, 4, "en");
test_roundtrip!(test_roundtrip4_2, 4, "Latn");
test_roundtrip!(test_roundtrip8, 8, "calendar");
test_roundtrip!(test_roundtrip16, 16, "verylongstring");
test_roundtrip!(test_roundtrip10, 11, "shortstring");
test_roundtrip!(test_roundtrip30, 24, "veryveryverylongstring");

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.lock":"7a6bb71d558693114436f11f7089237447a936cc8365f8afe0305e0b68dae07b","Cargo.toml":"0495636d8071b0d804764190a2daa3f6f780336d80bd8712ef7c197963fd5ce4","README.md":"1ce686b1ba46e7fff771db934d1e8905e3d96c73d9e6712ca85011cf63cf4157","benches/canonicalize.rs":"1bc9db6454ed711c1c1d58a9236d1ed02c40645782338697812dc21b26c2295f","benches/langid.rs":"46dc68e1ee1c998fe957035c11c373cc5d2c2993dd3058aeb36014028618a46e","benches/likely_subtags.rs":"672b47687d20d4294e2de78dc6eb1d36400a4b4c672082d15415fb18faf2e508","benches/parser.rs":"f9cf158bf5d146ef413e63e952c0a866269ba2be0db44a0aa88a5e61fdf53b4a","data/cldr-misc-full/README.md":"b4bbc8e56b8c9f5d482d2dd211e53720cdca27b0e98eec274e56577d41906b92","src/bin/generate_layout.rs":"e1df742c318ba4de09a25edad082a398da1d5591ac24074f9eadf3f40d677a9a","src/bin/generate_likelysubtags.rs":"c38ef8e59044578e51681723dbaf7f9669ccb7c7487f24ef6a430aad194f160f","src/errors.rs":"091525fd3d704cc4698bab82af9fff1f2e6fc793910700790ec3ef943b3eddfe","src/layout_table.rs":"c311b5399a22efd69f14decb00aee7dfb2943a090832e2aef127e2853ad1ce0b","src/lib.rs":"75b5e8958ba0139ef60139e61441d29c80bde8552d1adead3905165c11ed97cd","src/likelysubtags/mod.rs":"66889568b883675465faa445e257b4b70e9dcba98c6c523eb34a08ebb50377c0","src/likelysubtags/tables.rs":"47ab40497145adc553f9f585d1ec79d01028495a57b1907392642afd26986e89","src/parser/errors.rs":"2dacf5bf388499c9fbecf64ef950038f123335e87b6691bcdb88d185678f38d5","src/parser/mod.rs":"30f9ff487ab7b023ec7e6cfbfe4f4ebc41ca524cef0eba96a6b77ad624c9f6b8","src/serde.rs":"2ce1fdea1217c4f72b2c8e00f333902ff496c54eef5b4534adb289375c50aef0","src/subtags/language.rs":"1f7dbc4a10b58a6d1b729dc986a20396ce75558dfb1f9be223d5723a5e241e73","src/subtags/mod.rs":"ba23712d7ce5e0fa896c97ddc91d7eacbf21a99d62c15f5cf19a6653876bf56b","src/subtags/region.rs":"8cfd794f41f48fdf9742c9149b7360ea7cbd84c93abd13fe5a5317c46b4c48fc","src/subtags/script.rs":"94760b06f50f8f32c45af4f238b66e32428e5710ce4eabab4c943b5ebda3b0fe","src/subtags/variant.rs":"a8647d82c49df0d8df7fda33033d0df7a235beecfb35f459122675ab16b2dd8e"},"package":"1a4a8eeaf0494862c1404c95ec2f4c33a2acff5076f64314b465e3ddae1b934d"}
{"files":{"Cargo.lock":"da3d5fabc92472ac1f45fa321f1e188fd3fff22b3234d3f74e78a8f79503aac9","Cargo.toml":"67560e144c925cdb1467085067b51138da8461c4babd170777e90082a1664d61","README.md":"1ce686b1ba46e7fff771db934d1e8905e3d96c73d9e6712ca85011cf63cf4157","benches/canonicalize.rs":"1bc9db6454ed711c1c1d58a9236d1ed02c40645782338697812dc21b26c2295f","benches/langid.rs":"46dc68e1ee1c998fe957035c11c373cc5d2c2993dd3058aeb36014028618a46e","benches/likely_subtags.rs":"33debb6db4eabd0166525c7c06868f86e35958c2d0d9e5e7668f28b1aff3da23","benches/parser.rs":"bc5460589125aca2ca4c4cf475fde81e7de6aa70c7bf8443996b6246b44110a3","data/cldr-misc-full/README.md":"b4bbc8e56b8c9f5d482d2dd211e53720cdca27b0e98eec274e56577d41906b92","src/bin/generate_layout.rs":"e1df742c318ba4de09a25edad082a398da1d5591ac24074f9eadf3f40d677a9a","src/bin/generate_likelysubtags.rs":"9b0df3a008d0f6090ee441e4c649f00f9b78c7d23434f389fe3de2288951cf72","src/errors.rs":"091525fd3d704cc4698bab82af9fff1f2e6fc793910700790ec3ef943b3eddfe","src/layout_table.rs":"c311b5399a22efd69f14decb00aee7dfb2943a090832e2aef127e2853ad1ce0b","src/lib.rs":"75b5e8958ba0139ef60139e61441d29c80bde8552d1adead3905165c11ed97cd","src/likelysubtags/mod.rs":"66889568b883675465faa445e257b4b70e9dcba98c6c523eb34a08ebb50377c0","src/likelysubtags/tables.rs":"47ab40497145adc553f9f585d1ec79d01028495a57b1907392642afd26986e89","src/parser/errors.rs":"2dacf5bf388499c9fbecf64ef950038f123335e87b6691bcdb88d185678f38d5","src/parser/mod.rs":"30f9ff487ab7b023ec7e6cfbfe4f4ebc41ca524cef0eba96a6b77ad624c9f6b8","src/serde.rs":"2ce1fdea1217c4f72b2c8e00f333902ff496c54eef5b4534adb289375c50aef0","src/subtags/language.rs":"ea198788c10a9b24a88d2316d516a1b6325b20c57c1d05586edc7c50acc1e27d","src/subtags/mod.rs":"ba23712d7ce5e0fa896c97ddc91d7eacbf21a99d62c15f5cf19a6653876bf56b","src/subtags/region.rs":"f3455679067ed0da9103d5433586cb4809628847e923bbcf35cc2d2b25a0d35e","src/subtags/script.rs":"c5ca9a2ab6d8b3a1dc3f52a73665223f0dd30901b8e5d722dd93e58a69710f5d","src/subtags/variant.rs":"a0feec8b44933ff04a3d3f91e9e69f7537468e7c813c3780eb87e51512f6d1dd","tests/canonicalize_test.rs":"5ca005223ae159c15f8809c28c1cc950dc4d69063d9de70b885f18ef8e6cca28","tests/fixtures.rs":"d03a280b67080dac1bc333255e89d8903164688a6dfaed5adbea68efd65ef1bc","tests/language_identifier_test.rs":"90a4d7ac4961c1e214de166036c1b5cae21f3a99f157fe00d149d8b9106cb7b9","tests/likelysubtags.rs":"f5db0c3ec9f545eef148914486c7a74f1bbc629f4dcff3077242c174c0c1c6a3"},"package":"e35bfd2f2b8796545b55d7d3fd3e89a0613f68a0d1c8bc28cb7ff96b411a35ff"}

361
third_party/rust/unic-langid-impl/Cargo.lock сгенерированный поставляемый
Просмотреть файл

@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "atty"
version = "0.2.14"
@ -13,21 +15,21 @@ dependencies = [
[[package]]
name = "autocfg"
version = "1.0.0"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.2.1"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bstr"
version = "0.2.12"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41"
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
dependencies = [
"lazy_static",
"memchr",
@ -37,36 +39,27 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.2.1"
version = "3.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187"
[[package]]
name = "byteorder"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
[[package]]
name = "cast"
version = "0.2.3"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0"
dependencies = [
"rustc_version",
]
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cfg-if"
version = "0.1.10"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "2.33.0"
version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"bitflags",
"textwrap",
@ -75,9 +68,9 @@ dependencies = [
[[package]]
name = "criterion"
version = "0.3.2"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63f696897c88b57f4ffe3c69d8e1a0613c7d0e6c4833363c8560fbde9c47b966"
checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f"
dependencies = [
"atty",
"cast",
@ -92,6 +85,7 @@ dependencies = [
"rayon",
"regex",
"serde",
"serde_cbor",
"serde_derive",
"serde_json",
"tinytemplate",
@ -100,70 +94,66 @@ dependencies = [
[[package]]
name = "criterion-plot"
version = "0.4.2"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddeaf7989f00f2e1d871a26a110f3ed713632feac17f65f03ca938c542618b60"
checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876"
dependencies = [
"cast",
"itertools",
]
[[package]]
name = "crossbeam-deque"
version = "0.7.3"
name = "crossbeam-channel"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
"maybe-uninit",
]
[[package]]
name = "crossbeam-epoch"
version = "0.8.2"
version = "0.9.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"lazy_static",
"maybe-uninit",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-queue"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.7.2"
version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac"
dependencies = [
"autocfg",
"cfg-if",
"lazy_static",
]
[[package]]
name = "csv"
version = "1.1.3"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279"
checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
dependencies = [
"bstr",
"csv-core",
"itoa",
"itoa 0.4.8",
"ryu",
"serde",
]
@ -178,40 +168,63 @@ dependencies = [
]
[[package]]
name = "either"
version = "1.5.3"
name = "displaydoc"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "either"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
name = "half"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
[[package]]
name = "hermit-abi"
version = "0.1.12"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "itertools"
version = "0.9.0"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "0.4.5"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "itoa"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
[[package]]
name = "js-sys"
version = "0.3.39"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa5a448de267e7358beaf4a5d849518fe9a0c13fce7afd44b06e68550e5562a7"
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
dependencies = [
"wasm-bindgen",
]
@ -224,101 +237,118 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.69"
version = "0.2.135"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
[[package]]
name = "log"
version = "0.4.8"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]]
name = "memchr"
version = "2.3.3"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
version = "0.5.4"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]]
name = "num-traits"
version = "0.2.11"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "oorandom"
version = "11.1.1"
name = "once_cell"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94af325bc33c7f60191be4e2c984d48aaa21e2854f473b85398344b60c9b6358"
checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
[[package]]
name = "oorandom"
version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "plotters"
version = "0.2.14"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9b1d9ca091d370ea3a78d5619145d1b59426ab0c9eedbad2514a4cee08bf389"
checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97"
dependencies = [
"js-sys",
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "proc-macro2"
version = "1.0.12"
name = "plotters-backend"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319"
checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142"
[[package]]
name = "plotters-svg"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f"
dependencies = [
"unicode-xid",
"plotters-backend",
]
[[package]]
name = "proc-macro2"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.4"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.3.0"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098"
checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
dependencies = [
"autocfg",
"crossbeam-deque",
"either",
"rayon-core",
@ -326,55 +356,42 @@ dependencies = [
[[package]]
name = "rayon-core"
version = "1.7.0"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9"
checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-queue",
"crossbeam-utils",
"lazy_static",
"num_cpus",
]
[[package]]
name = "regex"
version = "1.3.7"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.1.9"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
dependencies = [
"byteorder",
]
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
version = "0.6.17"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "ryu"
version = "1.0.4"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "same-file"
@ -391,35 +408,30 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.106"
version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399"
checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.106"
name = "serde_cbor"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c"
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
dependencies = [
"half",
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
dependencies = [
"proc-macro2",
"quote",
@ -428,24 +440,24 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.52"
version = "1.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7894c8ed05b7a3a279aeb79025fdec1d3158080b75b98a08faf2806bb799edd"
checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45"
dependencies = [
"itoa",
"itoa 1.0.4",
"ryu",
"serde",
]
[[package]]
name = "syn"
version = "1.0.18"
version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213"
checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
"unicode-ident",
]
[[package]]
@ -459,15 +471,18 @@ dependencies = [
[[package]]
name = "tinystr"
version = "0.3.2"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bac79c4b51eda1b090b1edebfb667821bbb51f713855164dc7cec2cb8ac2ba3"
checksum = "f8aeafdfd935e4a7fe16a91ab711fa52d54df84f9c8f7ca5837a9d1d902ef4c2"
dependencies = [
"displaydoc",
]
[[package]]
name = "tinytemplate"
version = "1.0.4"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45e4bc5ac99433e0dcb8b9f309dd271a165ae37dde129b9e0ce1bfdd8bfe4891"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
@ -475,7 +490,7 @@ dependencies = [
[[package]]
name = "unic-langid-impl"
version = "0.9.0"
version = "0.9.1"
dependencies = [
"criterion",
"serde",
@ -484,22 +499,22 @@ dependencies = [
]
[[package]]
name = "unicode-width"
version = "0.1.7"
name = "unicode-ident"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
[[package]]
name = "unicode-xid"
version = "0.2.0"
name = "unicode-width"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "walkdir"
version = "2.3.1"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
dependencies = [
"same-file",
"winapi",
@ -508,9 +523,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
version = "0.2.62"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c7d40d09cdbf0f4895ae58cf57d92e1e57a9dd8ed2e8390514b54a47cc5551"
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@ -518,13 +533,13 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.62"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3972e137ebf830900db522d6c8fd74d1900dcfc733462e9a12e942b00b4ac94"
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
@ -533,9 +548,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.62"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cd85aa2c579e8892442954685f0d801f9129de24fa2136b2c6a539c76b65776"
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -543,9 +558,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.62"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eb197bd3a47553334907ffd2f16507b4f4f01bbec3ac921a7719e0decdfe72a"
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [
"proc-macro2",
"quote",
@ -556,15 +571,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.62"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a91c2916119c17a8e316507afaaa2dd94b47646048014bbdf6bef098c1bb58ad"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
[[package]]
name = "web-sys"
version = "0.3.39"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bc359e5dd3b46cb9687a051d50a2fdd228e4ba7cf6fcf861a5365c3d671a642"
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
dependencies = [
"js-sys",
"wasm-bindgen",
@ -572,9 +587,9 @@ dependencies = [
[[package]]
name = "winapi"
version = "0.3.8"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",

28
third_party/rust/unic-langid-impl/Cargo.toml поставляемый
Просмотреть файл

@ -3,19 +3,24 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "unic-langid-impl"
version = "0.9.0"
version = "0.9.1"
authors = ["Zibi Braniecki <gandalf@mozilla.com>"]
include = ["src/**/*", "benches/*.rs", "Cargo.toml", "README.md"]
include = [
"src/**/*",
"benches/*.rs",
"tests/*.rs",
"Cargo.toml",
"README.md",
]
description = "API for managing Unicode Language Identifiers"
readme = "README.md"
categories = ["internationalization"]
@ -51,6 +56,7 @@ harness = false
name = "likely_subtags"
harness = false
required-features = ["likelysubtags"]
[dependencies.serde]
version = "1.0"
optional = true
@ -60,7 +66,8 @@ version = "1.0"
optional = true
[dependencies.tinystr]
version = "0.3.2"
version = "0.7.0"
[dev-dependencies.criterion]
version = "0.3"
@ -72,5 +79,8 @@ features = ["derive"]
version = "1.0"
[features]
binary = ["serde", "serde_json"]
binary = [
"serde",
"serde_json",
]
likelysubtags = []

Просмотреть файл

@ -1,9 +1,8 @@
use criterion::black_box;
use criterion::criterion_group;
use criterion::criterion_main;
use criterion::Criterion;
use tinystr::{TinyStr4, TinyStr8};
use unic_langid_impl::subtags;
use unic_langid_impl::LanguageIdentifier;
static STRINGS: &[&str] = &[
@ -49,51 +48,37 @@ static STRINGS: &[&str] = &[
];
fn maximize_bench(c: &mut Criterion) {
let langids: Vec<LanguageIdentifier> = STRINGS
.iter()
.map(|s| -> LanguageIdentifier { s.parse().unwrap() })
.collect();
c.bench_function("maximize", move |b| {
b.iter(|| {
let langids: Vec<LanguageIdentifier> = STRINGS
.iter()
.map(|s| -> LanguageIdentifier { s.parse().unwrap() })
.collect();
for mut s in langids {
for mut s in langids.clone().into_iter() {
s.maximize();
let _ = black_box(s.to_string());
}
})
});
}
fn extract_input(s: &str) -> (Option<TinyStr8>, Option<TinyStr4>, Option<TinyStr4>) {
let chunks: Vec<&str> = s.split("-").collect();
let mut lang: Option<TinyStr8> = chunks.get(0).map(|s| s.parse().unwrap());
let mut script: Option<TinyStr4> = chunks.get(1).map(|s| s.parse().unwrap());
let mut region: Option<TinyStr4> = chunks.get(2).map(|s| s.parse().unwrap());
if let Some(l) = lang {
if l.as_str() == "und" {
lang = None;
}
}
if let Some(s) = script {
if s.as_str().chars().count() == 2 {
region = script;
script = None;
}
}
(lang, script, region)
fn extract_input(
s: &str,
) -> (
subtags::Language,
Option<subtags::Script>,
Option<subtags::Region>,
) {
let langid: LanguageIdentifier = s.parse().unwrap();
(langid.language, langid.script, langid.region)
}
fn raw_maximize_bench(c: &mut Criterion) {
let entries: Vec<(Option<TinyStr8>, Option<TinyStr4>, Option<TinyStr4>)> =
STRINGS.iter().map(|s| extract_input(s)).collect();
let entries: Vec<_> = STRINGS.iter().map(|s| extract_input(s)).collect();
c.bench_function("raw_maximize", move |b| {
b.iter(|| {
for (lang, script, region) in &entries {
let _ = unic_langid_impl::likelysubtags::maximize(
lang.clone(),
script.clone(),
region.clone(),
);
for (lang, script, region) in entries.clone().into_iter() {
let _ = unic_langid_impl::likelysubtags::maximize(lang, script, region);
}
})
});

Просмотреть файл

@ -21,6 +21,13 @@ fn language_identifier_parser_bench(c: &mut Criterion) {
"fr-FR",
"mk",
"uk",
"en-US",
"en-GB",
"es-AR",
"th",
"de",
"zh-Cyrl-HN",
"en-Latn-US",
];
c.bench_function("language_identifier_parser", |b| {
@ -49,6 +56,13 @@ fn language_identifier_parser_casing_bench(c: &mut Criterion) {
"fr_fr",
"Mk",
"uK",
"en-us",
"en_gb",
"ES-AR",
"tH",
"DE",
"ZH_cyrl_hN",
"eN-lAtN-uS",
];
c.bench_function("language_identifier_parser_casing", |b| {
let slices: Vec<&[u8]> = strings.iter().map(|s| s.as_bytes()).collect();

Просмотреть файл

@ -1,6 +1,5 @@
use serde_json::Value;
use std::fs;
use std::str::FromStr;
use tinystr::TinyStr8;
use unic_langid_impl::{subtags, LanguageIdentifier};
@ -77,7 +76,7 @@ fn main() {
match (lang, script, region) {
(None, None, None) => lang_only.push((
TinyStr8::from_str("und").unwrap().into(),
u64::from_le_bytes(*TinyStr8::from_str("und").unwrap().all_bytes()),
(val_lang, val_script, val_region),
)),
(Some(l), None, None) => lang_only.push((

Просмотреть файл

@ -34,7 +34,7 @@ impl Language {
/// This function accepts any u64 that is exected to be a valid
/// `TinyStr8` and a valid `Language` subtag.
pub const unsafe fn from_raw_unchecked(v: u64) -> Self {
Self(Some(TinyStr8::new_unchecked(v)))
Self(Some(TinyStr8::from_bytes_unchecked(v.to_le_bytes())))
}
pub fn matches<O: Borrow<Self>>(
@ -59,13 +59,13 @@ impl Language {
impl From<Language> for Option<u64> {
fn from(input: Language) -> Self {
input.0.map(|i| i.into())
input.0.map(|i| u64::from_le_bytes(*i.all_bytes()))
}
}
impl From<&Language> for Option<u64> {
fn from(input: &Language) -> Self {
input.0.map(|i| i.into())
input.0.map(|i| u64::from_le_bytes(*i.all_bytes()))
}
}

Просмотреть файл

@ -37,13 +37,13 @@ impl Region {
/// This function accepts any u64 that is exected to be a valid
/// `TinyStr4` and a valid `Region` subtag.
pub const unsafe fn from_raw_unchecked(v: u32) -> Self {
Self(TinyStr4::new_unchecked(v))
Self(TinyStr4::from_bytes_unchecked(v.to_le_bytes()))
}
}
impl From<Region> for u32 {
fn from(input: Region) -> Self {
input.0.into()
u32::from_le_bytes(*input.0.all_bytes())
}
}

Просмотреть файл

@ -25,13 +25,13 @@ impl Script {
/// This function accepts any u64 that is exected to be a valid
/// `TinyStr4` and a valid `Script` subtag.
pub const unsafe fn from_raw_unchecked(v: u32) -> Self {
Self(TinyStr4::new_unchecked(v))
Self(TinyStr4::from_bytes_unchecked(v.to_le_bytes()))
}
}
impl From<Script> for u32 {
fn from(input: Script) -> Self {
input.0.into()
u32::from_le_bytes(*input.0.all_bytes())
}
}

Просмотреть файл

@ -35,19 +35,19 @@ impl Variant {
/// This function accepts any u64 that is exected to be a valid
/// `TinyStr8` and a valid `Variant` subtag.
pub const unsafe fn from_raw_unchecked(v: u64) -> Self {
Self(TinyStr8::new_unchecked(v))
Self(TinyStr8::from_bytes_unchecked(v.to_le_bytes()))
}
}
impl From<Variant> for u64 {
fn from(input: Variant) -> Self {
input.0.into()
u64::from_le_bytes(*input.0.all_bytes())
}
}
impl From<&Variant> for u64 {
fn from(input: &Variant) -> Self {
input.0.into()
u64::from_le_bytes(*input.0.all_bytes())
}
}

13
third_party/rust/unic-langid-impl/tests/canonicalize_test.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,13 @@
use unic_langid_impl::canonicalize;
fn assert_canonicalize(input: &str, output: &str) {
assert_eq!(&canonicalize(input).unwrap(), output);
}
#[test]
fn test_canonicalize() {
assert_canonicalize("Pl", "pl");
assert_canonicalize("eN-uS", "en-US");
assert_canonicalize("ZH_hans_hK", "zh-Hans-HK");
assert_canonicalize("en-scouse-fonipa", "en-fonipa-scouse");
}

75
third_party/rust/unic-langid-impl/tests/fixtures.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,75 @@
use std::convert::TryInto;
use std::error::Error;
use std::fs::File;
use std::path::Path;
use unic_langid_impl::LanguageIdentifier;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct LangIdTestInputData {
string: String,
}
#[derive(Serialize, Deserialize, Debug)]
struct LangIdTestOutputObject {
language: Option<String>,
script: Option<String>,
region: Option<String>,
#[serde(default)]
variants: Vec<String>,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
enum LangIdTestOutput {
String(String),
Object(LangIdTestOutputObject),
}
#[derive(Serialize, Deserialize)]
struct LangIdTestSet {
input: LangIdTestInputData,
output: LangIdTestOutput,
}
fn read_langid_testsets<P: AsRef<Path>>(path: P) -> Result<Vec<LangIdTestSet>, Box<dyn Error>> {
let file = File::open(path)?;
let sets = serde_json::from_reader(file)?;
Ok(sets)
}
fn test_langid_fixtures(path: &str) {
let tests = read_langid_testsets(path).unwrap();
for test in tests {
let s = test.input.string;
let langid: LanguageIdentifier = s.parse().expect("Parsing failed.");
match test.output {
LangIdTestOutput::Object(o) => {
let expected = LanguageIdentifier::from_parts(
o.language.try_into().unwrap(),
o.script.as_ref().map(|s| s.parse().unwrap()),
o.region.as_ref().map(|r| r.parse().unwrap()),
o.variants
.iter()
.map(|s| s.parse().unwrap())
.collect::<Vec<_>>()
.as_ref(),
);
assert_eq!(langid, expected);
}
LangIdTestOutput::String(s) => {
assert_eq!(langid.to_string(), s);
}
}
}
}
#[test]
fn parse() {
test_langid_fixtures("./tests/fixtures/parsing.json");
}

Просмотреть файл

@ -0,0 +1,192 @@
use unic_langid_impl::parser::parse_language_identifier;
use unic_langid_impl::subtags;
use unic_langid_impl::CharacterDirection;
use unic_langid_impl::LanguageIdentifier;
fn assert_language_identifier(
loc: &LanguageIdentifier,
language: Option<&str>,
script: Option<&str>,
region: Option<&str>,
variants: Option<&[&str]>,
) {
assert_eq!(
loc.language,
language.map_or(subtags::Language::default(), |l| {
subtags::Language::from_bytes(l.as_bytes()).unwrap()
})
);
assert_eq!(loc.script, script.map(|s| s.parse().unwrap()));
assert_eq!(loc.region, region.map(|r| r.parse().unwrap()));
let v = variants
.unwrap_or(&[])
.iter()
.map(|v| -> subtags::Variant { v.parse().unwrap() })
.collect::<Vec<_>>();
assert_eq!(
loc.variants().collect::<Vec<_>>(),
v.iter().collect::<Vec<_>>(),
);
}
fn assert_parsed_language_identifier(
input: &str,
language: Option<&str>,
script: Option<&str>,
region: Option<&str>,
variants: Option<&[&str]>,
) {
let langid = parse_language_identifier(input.as_bytes()).unwrap();
assert_language_identifier(&langid, language, script, region, variants);
}
#[test]
fn test_language_identifier_parser() {
assert_parsed_language_identifier("pl", Some("pl"), None, None, None);
assert_parsed_language_identifier("und", None, None, None, None);
assert_parsed_language_identifier("en-US", Some("en"), None, Some("US"), None);
assert_parsed_language_identifier("en-Latn-US", Some("en"), Some("Latn"), Some("US"), None);
assert_parsed_language_identifier("sl-nedis", Some("sl"), None, None, Some(&["nedis"]));
}
#[test]
fn test_language_casing() {
assert_parsed_language_identifier("Pl", Some("pl"), None, None, None);
assert_parsed_language_identifier("En-uS", Some("en"), None, Some("US"), None);
assert_parsed_language_identifier("eN-lAtN-uS", Some("en"), Some("Latn"), Some("US"), None);
assert_parsed_language_identifier("ZH_cyrl_hN", Some("zh"), Some("Cyrl"), Some("HN"), None);
}
#[test]
fn test_serialize_langid() {
let langid: LanguageIdentifier = "en-Latn-US".parse().unwrap();
assert_eq!(&langid.to_string(), "en-Latn-US");
}
#[test]
fn test_sorted_variants() {
let langid: LanguageIdentifier = "en-nedis-macos".parse().unwrap();
assert_eq!(&langid.to_string(), "en-macos-nedis");
let langid = LanguageIdentifier::from_parts(
"en".parse().unwrap(),
None,
None,
&["nedis".parse().unwrap(), "macos".parse().unwrap()],
);
assert_eq!(&langid.to_string(), "en-macos-nedis");
}
#[test]
fn test_from_parts_unchecked() {
let langid: LanguageIdentifier = "en-nedis-macos".parse().unwrap();
let (lang, script, region, variants) = langid.into_parts();
let langid = LanguageIdentifier::from_raw_parts_unchecked(
lang,
script,
region,
Some(variants.into_boxed_slice()),
);
assert_eq!(&langid.to_string(), "en-macos-nedis");
}
#[test]
fn test_matches() {
let langid_en: LanguageIdentifier = "en".parse().unwrap();
let langid_en_us: LanguageIdentifier = "en-US".parse().unwrap();
let langid_en_us2: LanguageIdentifier = "en-US".parse().unwrap();
let langid_pl: LanguageIdentifier = "pl".parse().unwrap();
assert_eq!(langid_en.matches(&langid_en_us, false, false), false);
assert_eq!(langid_en_us.matches(&langid_en_us2, false, false), true);
assert_eq!(langid_en.matches(&langid_pl, false, false), false);
assert_eq!(langid_en.matches(&langid_en_us, true, false), true);
}
#[test]
fn test_set_fields() {
let mut langid = LanguageIdentifier::default();
assert_eq!(&langid.to_string(), "und");
langid.language = "pl".parse().expect("Setting language failed");
assert_eq!(&langid.to_string(), "pl");
langid.language = "de".parse().expect("Setting language failed");
assert_eq!(&langid.to_string(), "de");
langid.region = Some("AT".parse().expect("Setting region failed"));
assert_eq!(&langid.to_string(), "de-AT");
langid.script = Some("Latn".parse().expect("Setting script failed"));
assert_eq!(&langid.to_string(), "de-Latn-AT");
langid.set_variants(&["macos".parse().expect("Setting variants failed")]);
assert_eq!(&langid.to_string(), "de-Latn-AT-macos");
assert_eq!(langid.has_variant("macos".parse().unwrap()), true);
assert_eq!(langid.has_variant("windows".parse().unwrap()), false);
langid.language.clear();
assert_eq!(&langid.to_string(), "und-Latn-AT-macos");
langid.region = None;
assert_eq!(&langid.to_string(), "und-Latn-macos");
langid.script = None;
assert_eq!(&langid.to_string(), "und-macos");
langid.clear_variants();
assert_eq!(&langid.to_string(), "und");
assert_eq!(langid.has_variant("macos".parse().unwrap()), false);
}
#[test]
fn test_matches_as_range() {
let langid: LanguageIdentifier = "en-US".parse().unwrap();
let langid2: LanguageIdentifier = "en-US-windows".parse().unwrap();
assert_eq!(langid.matches(&langid2, false, false), false);
assert_eq!(langid.matches(&langid2, true, false), true);
assert_eq!(langid.matches(&langid2, false, true), false);
assert_eq!(langid.matches(&langid2, true, true), true);
}
#[test]
fn test_character_direction() {
let langid: LanguageIdentifier = "en-US".parse().unwrap();
let langid2: LanguageIdentifier = "ar-AF".parse().unwrap();
assert_eq!(langid.character_direction(), CharacterDirection::LTR);
assert_eq!(langid2.character_direction(), CharacterDirection::RTL);
}
#[test]
fn test_langid_ord() {
let input = &[
"en-US-macos-zarab",
"en-US-macos-nedis",
"en-US-macos",
"en-GB",
"en",
"en-US",
"ar",
"fr",
"de",
];
let mut langids = input
.iter()
.map(|l| -> LanguageIdentifier { l.parse().unwrap() })
.collect::<Vec<_>>();
langids.sort();
let result = langids.iter().map(|l| l.to_string()).collect::<Vec<_>>();
assert_eq!(
&result,
&[
"ar",
"de",
"en",
"en-GB",
"en-US",
"en-US-macos",
"en-US-macos-nedis",
"en-US-macos-zarab",
"fr"
]
);
}

113
third_party/rust/unic-langid-impl/tests/likelysubtags.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,113 @@
use unic_langid_impl::likelysubtags::{maximize, minimize, CLDR_VERSION};
use unic_langid_impl::subtags;
static STRINGS: &[(&str, Option<&str>)] = &[
("en-US", Some("en-Latn-US")),
("en-GB", Some("en-Latn-GB")),
("es-AR", Some("es-Latn-AR")),
("it", Some("it-Latn-IT")),
("zh-Hans-CN", None),
("de-AT", Some("de-Latn-AT")),
("pl", Some("pl-Latn-PL")),
("fr-FR", Some("fr-Latn-FR")),
("de-AT", Some("de-Latn-AT")),
("sr-Cyrl-SR", None),
("nb-NO", Some("nb-Latn-NO")),
("fr-FR", Some("fr-Latn-FR")),
("mk", Some("mk-Cyrl-MK")),
("uk", Some("uk-Cyrl-UA")),
("und-PL", Some("pl-Latn-PL")),
("und-Latn-AM", Some("ku-Latn-AM")),
("ug-Cyrl", Some("ug-Cyrl-KZ")),
("sr-ME", Some("sr-Latn-ME")),
("mn-Mong", Some("mn-Mong-CN")),
("lif-Limb", Some("lif-Limb-IN")),
("gan", Some("gan-Hans-CN")),
("zh-Hant", Some("zh-Hant-TW")),
("yue-Hans", Some("yue-Hans-CN")),
("unr", Some("unr-Beng-IN")),
("unr-Deva", Some("unr-Deva-NP")),
("und-Thai-CN", Some("lcp-Thai-CN")),
("ug-Cyrl", Some("ug-Cyrl-KZ")),
("en-Latn-DE", None),
("pl-FR", Some("pl-Latn-FR")),
("de-CH", Some("de-Latn-CH")),
("tuq", Some("tuq-Latn")),
("sr-ME", Some("sr-Latn-ME")),
("ng", Some("ng-Latn-NA")),
("klx", Some("klx-Latn")),
("kk-Arab", Some("kk-Arab-CN")),
("en-Cyrl", Some("en-Cyrl-US")),
("und-Cyrl-UK", Some("ru-Cyrl-UK")),
("und-Arab", Some("ar-Arab-EG")),
("und-Arab-FO", Some("ar-Arab-FO")),
("zh-TW", Some("zh-Hant-TW")),
];
fn extract_input(
s: &str,
) -> (
subtags::Language,
Option<subtags::Script>,
Option<subtags::Region>,
) {
let chunks: Vec<&str> = s.split("-").collect();
let lang: subtags::Language = chunks[0].parse().unwrap();
let (script, region) = if let Some(s) = chunks.get(1) {
if let Ok(script) = s.parse() {
let region = chunks.get(2).map(|r| r.parse().unwrap());
(Some(script), region)
} else {
let region = s.parse().unwrap();
(None, Some(region))
}
} else {
(None, None)
};
(lang, script, region)
}
fn extract_output(
s: Option<&str>,
) -> Option<(
subtags::Language,
Option<subtags::Script>,
Option<subtags::Region>,
)> {
s.map(|s| {
let chunks: Vec<&str> = s.split("-").collect();
(
chunks[0].parse().unwrap(),
chunks.get(1).map(|s| s.parse().unwrap()),
chunks.get(2).map(|s| s.parse().unwrap()),
)
})
}
#[test]
fn maximize_test() {
for i in STRINGS {
let chunks = extract_input(i.0);
let result = maximize(chunks.0, chunks.1, chunks.2);
assert_eq!(extract_output(i.1), result);
}
}
#[test]
fn version_works() {
assert_eq!(CLDR_VERSION, "36");
}
#[test]
fn minimize_test() {
let lang = "zh".parse().unwrap();
let script = "Hant".parse().unwrap();
let result = minimize(lang, Some(script), None);
assert_eq!(result, Some(extract_input("zh-TW")));
let lang = "en".parse().unwrap();
let script = "Latn".parse().unwrap();
let region = "US".parse().unwrap();
let result = minimize(lang, Some(script), Some(region));
assert_eq!(result, Some(extract_input("en")));
}

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"37b883b01864161cffe562ddcc7226d60a6a104229da7b5f269a18738782efb7","README.md":"6bab9883bd094c16d22f7aeddb59b391c1567c167ffed2f28aee9e2a82de1a1d","src/lib.rs":"f850878a5d545496073593ef1ca340ef385f78bc6585c5d3b46fe8ffc2087bd5"},"package":"18f980d6d87e8805f2836d64b4138cc95aa7986fa63b1f51f67d5fbff64dd6e5"}
{"files":{"Cargo.toml":"debce559451d7edd257495d2f7a8c3bd081e1ec15625d42668165cec8f2a4cf7","README.md":"6bab9883bd094c16d22f7aeddb59b391c1567c167ffed2f28aee9e2a82de1a1d","src/lib.rs":"f850878a5d545496073593ef1ca340ef385f78bc6585c5d3b46fe8ffc2087bd5"},"package":"055e618bf694161ffff0466d95cef3e1a5edc59f6ba1888e97801f2b4ebdc4fe"}

Просмотреть файл

@ -3,29 +3,37 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "unic-langid-macros"
version = "0.9.0"
authors = ["Manish Goregaokar <manishsmail@gmail.com>", "Zibi Braniecki <gandalf@mozilla.com>"]
include = ["src/**/*", "benches/*.rs", "Cargo.toml", "README.md"]
version = "0.9.1"
authors = [
"Manish Goregaokar <manishsmail@gmail.com>",
"Zibi Braniecki <gandalf@mozilla.com>",
]
include = [
"src/**/*",
"benches/*.rs",
"Cargo.toml",
"README.md",
]
description = "API for managing Unicode Language Identifiers"
readme = "README.md"
categories = ["internationalization"]
license = "MIT/Apache-2.0"
repository = "https://github.com/zbraniecki/unic-locale"
[dependencies.proc-macro-hack]
version = "0.5"
[dependencies.tinystr]
version = "0.3.2"
version = "0.7.0"
[dependencies.unic-langid-impl]
version = "0.9"