Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/string_cache/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/string_cache/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.lock":"b48cc34d0fa6616630f3e62c88929f230cee804755ee54f19e8d4dfab2f82aa7","Cargo.toml":"c7a9d4ccbdab45b0e18d85a7218000329e04d2bddb502dcedcf8ff0f8c382907","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"d13530e5e0d72b9106c735c276f88fd11aeaaccb404dda75a74d2cfafbf59268","examples/simple.rs":"227cbe14cdb0cb710a259707144b259684e9576615247628b8d57c895dd8c538","src/atom.rs":"d91ea4f98f171a6b7ab13e9dbb91bf280ada81dda746d16ade349ba9aa81b909","src/dynamic_set.rs":"e1308168a077578be1eb0e2a5d804c368b91a5f06d47deacd03ea0867bbb0334","src/lib.rs":"844ad2b53bde6f0d65650b9b034b91bdcece1ac285c0f2a97fea04382b6917e2","src/static_sets.rs":"0d91d476b5277cf3cbbcd0c9f18cc5286086fecf59654115efab5090862ec8e8","src/trivial_impls.rs":"ba12375f21c5f033a52bdf10dd6ab366702e1d68954aa012fc90cc7efc2a5ed3","tests/small-stack.rs":"f3c8dd5f38eba6e41aa44fe7a4af3a2a2e5bfc0a1fb938e76319d9780956177c"},"package":"f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"}
|
||||
198
third-party/vendor/string_cache/Cargo.lock
generated
vendored
Normal file
198
third-party/vendor/string_cache/Cargo.lock
generated
vendored
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "new_debug_unreachable"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "precomputed-hash"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
|
||||
|
||||
[[package]]
|
||||
name = "string_cache"
|
||||
version = "0.8.7"
|
||||
dependencies = [
|
||||
"new_debug_unreachable",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"phf_shared",
|
||||
"precomputed-hash",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||
51
third-party/vendor/string_cache/Cargo.toml
vendored
Normal file
51
third-party/vendor/string_cache/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "string_cache"
|
||||
version = "0.8.7"
|
||||
authors = ["The Servo Project Developers"]
|
||||
description = "A string interning library for Rust, developed as part of the Servo project."
|
||||
documentation = "https://docs.rs/string_cache/"
|
||||
readme = "README.md"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/servo/string-cache"
|
||||
|
||||
[lib]
|
||||
name = "string_cache"
|
||||
|
||||
[[test]]
|
||||
name = "small-stack"
|
||||
harness = false
|
||||
|
||||
[dependencies.new_debug_unreachable]
|
||||
version = "1.0.2"
|
||||
|
||||
[dependencies.once_cell]
|
||||
version = "1.10.0"
|
||||
|
||||
[dependencies.parking_lot]
|
||||
version = "0.12"
|
||||
|
||||
[dependencies.phf_shared]
|
||||
version = "0.10"
|
||||
|
||||
[dependencies.precomputed-hash]
|
||||
version = "0.1"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1"
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
default = ["serde_support"]
|
||||
serde_support = ["serde"]
|
||||
201
third-party/vendor/string_cache/LICENSE-APACHE
vendored
Normal file
201
third-party/vendor/string_cache/LICENSE-APACHE
vendored
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
25
third-party/vendor/string_cache/LICENSE-MIT
vendored
Normal file
25
third-party/vendor/string_cache/LICENSE-MIT
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2012-2013 Mozilla Foundation
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
78
third-party/vendor/string_cache/README.md
vendored
Normal file
78
third-party/vendor/string_cache/README.md
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# string-cache
|
||||
|
||||
[](https://github.com/servo/string-cache/actions)
|
||||
|
||||
[Documentation](https://docs.rs/string_cache/)
|
||||
|
||||
A string interning library for Rust, developed as part of the [Servo](https://github.com/servo/servo) project.
|
||||
|
||||
## Simple usage
|
||||
|
||||
In `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
string_cache = "0.8"
|
||||
```
|
||||
|
||||
In `lib.rs`:
|
||||
|
||||
```rust
|
||||
extern crate string_cache;
|
||||
use string_cache::DefaultAtom as Atom;
|
||||
```
|
||||
|
||||
## With static atoms
|
||||
|
||||
In `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[package]
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
string_cache = "0.8"
|
||||
|
||||
[build-dependencies]
|
||||
string_cache_codegen = "0.5"
|
||||
```
|
||||
|
||||
In `build.rs`:
|
||||
|
||||
```rust
|
||||
extern crate string_cache_codegen;
|
||||
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
|
||||
fn main() {
|
||||
string_cache_codegen::AtomType::new("foo::FooAtom", "foo_atom!")
|
||||
.atoms(&["foo", "bar"])
|
||||
.write_to_file(&Path::new(&env::var("OUT_DIR").unwrap()).join("foo_atom.rs"))
|
||||
.unwrap()
|
||||
}
|
||||
```
|
||||
|
||||
In `lib.rs`:
|
||||
|
||||
```rust
|
||||
extern crate string_cache;
|
||||
|
||||
mod foo {
|
||||
include!(concat!(env!("OUT_DIR"), "/foo_atom.rs"));
|
||||
}
|
||||
```
|
||||
|
||||
The generated code will define a `FooAtom` type and a `foo_atom!` macro.
|
||||
The macro can be used in expression or patterns, with strings listed in `build.rs`.
|
||||
For example:
|
||||
|
||||
```rust
|
||||
fn compute_something(input: &foo::FooAtom) -> u32 {
|
||||
match *input {
|
||||
foo_atom!("foo") => 1,
|
||||
foo_atom!("bar") => 2,
|
||||
_ => 3,
|
||||
}
|
||||
}
|
||||
```
|
||||
26
third-party/vendor/string_cache/examples/simple.rs
vendored
Normal file
26
third-party/vendor/string_cache/examples/simple.rs
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
|
||||
use string_cache::DefaultAtom;
|
||||
|
||||
fn main() {
|
||||
let mut interned_stuff = Vec::new();
|
||||
let text = "here is a sentence of text that will be tokenised and interned and some repeated \
|
||||
tokens is of text and";
|
||||
for word in text.split_whitespace() {
|
||||
let seen_before = interned_stuff
|
||||
.iter()
|
||||
// We can use impl PartialEq<T> where T is anything string-like to compare to
|
||||
// interned strings to either other interned strings, or actual strings Comparing two
|
||||
// interned strings is very fast (normally a single cpu operation).
|
||||
.filter(|interned_word| interned_word == &word)
|
||||
.count();
|
||||
if seen_before > 0 {
|
||||
println!(r#"Seen the word "{}" {} times"#, word, seen_before);
|
||||
} else {
|
||||
println!(r#"Not seen the word "{}" before"#, word);
|
||||
}
|
||||
// We use the impl From<(Cow<'a, str>, or &'a str, or String) for Atom<Static> to intern a
|
||||
// new string
|
||||
interned_stuff.push(DefaultAtom::from(word));
|
||||
}
|
||||
}
|
||||
388
third-party/vendor/string_cache/src/atom.rs
vendored
Normal file
388
third-party/vendor/string_cache/src/atom.rs
vendored
Normal file
|
|
@ -0,0 +1,388 @@
|
|||
// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use crate::dynamic_set::{Entry, DYNAMIC_SET};
|
||||
use crate::static_sets::StaticAtomSet;
|
||||
use debug_unreachable::debug_unreachable;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::Ordering::{self, Equal};
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::num::NonZeroU64;
|
||||
use std::ops;
|
||||
use std::slice;
|
||||
use std::str;
|
||||
use std::sync::atomic::Ordering::SeqCst;
|
||||
|
||||
const DYNAMIC_TAG: u8 = 0b_00;
|
||||
const INLINE_TAG: u8 = 0b_01; // len in upper nybble
|
||||
const STATIC_TAG: u8 = 0b_10;
|
||||
const TAG_MASK: u64 = 0b_11;
|
||||
const LEN_OFFSET: u64 = 4;
|
||||
const LEN_MASK: u64 = 0xF0;
|
||||
|
||||
const MAX_INLINE_LEN: usize = 7;
|
||||
const STATIC_SHIFT_BITS: usize = 32;
|
||||
|
||||
/// Represents a string that has been interned.
|
||||
///
|
||||
/// While the type definition for `Atom` indicates that it generic on a particular
|
||||
/// implementation of an atom set, you don't need to worry about this. Atoms can be static
|
||||
/// and come from a `StaticAtomSet` generated by the `string_cache_codegen` crate, or they
|
||||
/// can be dynamic and created by you on an `EmptyStaticAtomSet`.
|
||||
///
|
||||
/// `Atom` implements `Clone` but not `Copy`, since internally atoms are reference-counted;
|
||||
/// this means that you may need to `.clone()` an atom to keep copies to it in different
|
||||
/// places, or when passing it to a function that takes an `Atom` rather than an `&Atom`.
|
||||
///
|
||||
/// ## Creating an atom at runtime
|
||||
///
|
||||
/// If you use `string_cache_codegen` to generate a precomputed list of atoms, your code
|
||||
/// may then do something like read data from somewhere and extract tokens that need to be
|
||||
/// compared to the atoms. In this case, you can use `Atom::from(&str)` or
|
||||
/// `Atom::from(String)`. These create a reference-counted atom which will be
|
||||
/// automatically freed when all references to it are dropped.
|
||||
///
|
||||
/// This means that your application can safely have a loop which tokenizes data, creates
|
||||
/// atoms from the tokens, and compares the atoms to a predefined set of keywords, without
|
||||
/// running the risk of arbitrary memory consumption from creating large numbers of atoms —
|
||||
/// as long as your application does not store clones of the atoms it creates along the
|
||||
/// way.
|
||||
///
|
||||
/// For example, the following is safe and will not consume arbitrary amounts of memory:
|
||||
///
|
||||
/// ```ignore
|
||||
/// let untrusted_data = "large amounts of text ...";
|
||||
///
|
||||
/// for token in untrusted_data.split_whitespace() {
|
||||
/// let atom = Atom::from(token); // interns the string
|
||||
///
|
||||
/// if atom == Atom::from("keyword") {
|
||||
/// // handle that keyword
|
||||
/// } else if atom == Atom::from("another_keyword") {
|
||||
/// // handle that keyword
|
||||
/// } else {
|
||||
/// println!("unknown keyword");
|
||||
/// }
|
||||
/// } // atom is dropped here, so it is not kept around in memory
|
||||
/// ```
|
||||
#[derive(PartialEq, Eq)]
|
||||
// NOTE: Deriving PartialEq requires that a given string must always be interned the same way.
|
||||
pub struct Atom<Static> {
|
||||
unsafe_data: NonZeroU64,
|
||||
phantom: PhantomData<Static>,
|
||||
}
|
||||
|
||||
// FIXME: bound removed from the struct definition before of this error for pack_static:
|
||||
// "error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable"
|
||||
// https://github.com/rust-lang/rust/issues/57563
|
||||
impl<Static> Atom<Static> {
|
||||
/// For the atom!() macros
|
||||
#[inline(always)]
|
||||
#[doc(hidden)]
|
||||
pub const fn pack_static(n: u32) -> Self {
|
||||
Self {
|
||||
unsafe_data: unsafe {
|
||||
// STATIC_TAG ensures this is non-zero
|
||||
NonZeroU64::new_unchecked((STATIC_TAG as u64) | ((n as u64) << STATIC_SHIFT_BITS))
|
||||
},
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn tag(&self) -> u8 {
|
||||
(self.unsafe_data.get() & TAG_MASK) as u8
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static: StaticAtomSet> Atom<Static> {
|
||||
/// Return the internal representation. For testing.
|
||||
#[doc(hidden)]
|
||||
pub fn unsafe_data(&self) -> u64 {
|
||||
self.unsafe_data.get()
|
||||
}
|
||||
|
||||
/// Return true if this is a static Atom. For testing.
|
||||
#[doc(hidden)]
|
||||
pub fn is_static(&self) -> bool {
|
||||
self.tag() == STATIC_TAG
|
||||
}
|
||||
|
||||
/// Return true if this is a dynamic Atom. For testing.
|
||||
#[doc(hidden)]
|
||||
pub fn is_dynamic(&self) -> bool {
|
||||
self.tag() == DYNAMIC_TAG
|
||||
}
|
||||
|
||||
/// Return true if this is an inline Atom. For testing.
|
||||
#[doc(hidden)]
|
||||
pub fn is_inline(&self) -> bool {
|
||||
self.tag() == INLINE_TAG
|
||||
}
|
||||
|
||||
fn static_index(&self) -> u64 {
|
||||
self.unsafe_data.get() >> STATIC_SHIFT_BITS
|
||||
}
|
||||
|
||||
/// Get the hash of the string as it is stored in the set.
|
||||
pub fn get_hash(&self) -> u32 {
|
||||
match self.tag() {
|
||||
DYNAMIC_TAG => {
|
||||
let entry = self.unsafe_data.get() as *const Entry;
|
||||
unsafe { (*entry).hash }
|
||||
}
|
||||
STATIC_TAG => Static::get().hashes[self.static_index() as usize],
|
||||
INLINE_TAG => {
|
||||
let data = self.unsafe_data.get();
|
||||
// This may or may not be great...
|
||||
((data >> 32) ^ data) as u32
|
||||
}
|
||||
_ => unsafe { debug_unreachable!() },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_static(string_to_add: &str) -> Option<Self> {
|
||||
Self::try_static_internal(string_to_add).ok()
|
||||
}
|
||||
|
||||
fn try_static_internal(string_to_add: &str) -> Result<Self, phf_shared::Hashes> {
|
||||
let static_set = Static::get();
|
||||
let hash = phf_shared::hash(&*string_to_add, &static_set.key);
|
||||
let index = phf_shared::get_index(&hash, static_set.disps, static_set.atoms.len());
|
||||
|
||||
if static_set.atoms[index as usize] == string_to_add {
|
||||
Ok(Self::pack_static(index))
|
||||
} else {
|
||||
Err(hash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static: StaticAtomSet> Default for Atom<Static> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Atom::pack_static(Static::empty_string_index())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static: StaticAtomSet> Hash for Atom<Static> {
|
||||
#[inline]
|
||||
fn hash<H>(&self, state: &mut H)
|
||||
where
|
||||
H: Hasher,
|
||||
{
|
||||
state.write_u32(self.get_hash())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Static: StaticAtomSet> From<Cow<'a, str>> for Atom<Static> {
|
||||
fn from(string_to_add: Cow<'a, str>) -> Self {
|
||||
Self::try_static_internal(&*string_to_add).unwrap_or_else(|hash| {
|
||||
let len = string_to_add.len();
|
||||
if len <= MAX_INLINE_LEN {
|
||||
let mut data: u64 = (INLINE_TAG as u64) | ((len as u64) << LEN_OFFSET);
|
||||
{
|
||||
let dest = inline_atom_slice_mut(&mut data);
|
||||
dest[..len].copy_from_slice(string_to_add.as_bytes())
|
||||
}
|
||||
Atom {
|
||||
// INLINE_TAG ensures this is never zero
|
||||
unsafe_data: unsafe { NonZeroU64::new_unchecked(data) },
|
||||
phantom: PhantomData,
|
||||
}
|
||||
} else {
|
||||
let ptr: std::ptr::NonNull<Entry> = DYNAMIC_SET.insert(string_to_add, hash.g);
|
||||
let data = ptr.as_ptr() as u64;
|
||||
debug_assert!(0 == data & TAG_MASK);
|
||||
Atom {
|
||||
// The address of a ptr::NonNull is non-zero
|
||||
unsafe_data: unsafe { NonZeroU64::new_unchecked(data) },
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static: StaticAtomSet> Clone for Atom<Static> {
|
||||
#[inline(always)]
|
||||
fn clone(&self) -> Self {
|
||||
if self.tag() == DYNAMIC_TAG {
|
||||
let entry = self.unsafe_data.get() as *const Entry;
|
||||
unsafe { &*entry }.ref_count.fetch_add(1, SeqCst);
|
||||
}
|
||||
Atom { ..*self }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static> Drop for Atom<Static> {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
if self.tag() == DYNAMIC_TAG {
|
||||
let entry = self.unsafe_data.get() as *const Entry;
|
||||
if unsafe { &*entry }.ref_count.fetch_sub(1, SeqCst) == 1 {
|
||||
drop_slow(self)
|
||||
}
|
||||
}
|
||||
|
||||
// Out of line to guide inlining.
|
||||
fn drop_slow<Static>(this: &mut Atom<Static>) {
|
||||
DYNAMIC_SET.remove(this.unsafe_data.get() as *mut Entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static: StaticAtomSet> ops::Deref for Atom<Static> {
|
||||
type Target = str;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &str {
|
||||
unsafe {
|
||||
match self.tag() {
|
||||
DYNAMIC_TAG => {
|
||||
let entry = self.unsafe_data.get() as *const Entry;
|
||||
&(*entry).string
|
||||
}
|
||||
INLINE_TAG => {
|
||||
let len = (self.unsafe_data() & LEN_MASK) >> LEN_OFFSET;
|
||||
let src = inline_atom_slice(&self.unsafe_data);
|
||||
str::from_utf8_unchecked(&src[..(len as usize)])
|
||||
}
|
||||
STATIC_TAG => Static::get().atoms[self.static_index() as usize],
|
||||
_ => debug_unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static: StaticAtomSet> fmt::Debug for Atom<Static> {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let ty_str = unsafe {
|
||||
match self.tag() {
|
||||
DYNAMIC_TAG => "dynamic",
|
||||
INLINE_TAG => "inline",
|
||||
STATIC_TAG => "static",
|
||||
_ => debug_unreachable!(),
|
||||
}
|
||||
};
|
||||
|
||||
write!(f, "Atom('{}' type={})", &*self, ty_str)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static: StaticAtomSet> PartialOrd for Atom<Static> {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
if self.unsafe_data == other.unsafe_data {
|
||||
return Some(Equal);
|
||||
}
|
||||
self.as_ref().partial_cmp(other.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static: StaticAtomSet> Ord for Atom<Static> {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
if self.unsafe_data == other.unsafe_data {
|
||||
return Equal;
|
||||
}
|
||||
self.as_ref().cmp(other.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
// AsciiExt requires mutating methods, so we just implement the non-mutating ones.
|
||||
// We don't need to implement is_ascii because there's no performance improvement
|
||||
// over the one from &str.
|
||||
impl<Static: StaticAtomSet> Atom<Static> {
|
||||
fn from_mutated_str<F: FnOnce(&mut str)>(s: &str, f: F) -> Self {
|
||||
let mut buffer = mem::MaybeUninit::<[u8; 64]>::uninit();
|
||||
let buffer = unsafe { &mut *buffer.as_mut_ptr() };
|
||||
|
||||
if let Some(buffer_prefix) = buffer.get_mut(..s.len()) {
|
||||
buffer_prefix.copy_from_slice(s.as_bytes());
|
||||
let as_str = unsafe { ::std::str::from_utf8_unchecked_mut(buffer_prefix) };
|
||||
f(as_str);
|
||||
Atom::from(&*as_str)
|
||||
} else {
|
||||
let mut string = s.to_owned();
|
||||
f(&mut string);
|
||||
Atom::from(string)
|
||||
}
|
||||
}
|
||||
|
||||
/// Like [`to_ascii_uppercase`].
|
||||
///
|
||||
/// [`to_ascii_uppercase`]: https://doc.rust-lang.org/std/ascii/trait.AsciiExt.html#tymethod.to_ascii_uppercase
|
||||
pub fn to_ascii_uppercase(&self) -> Self {
|
||||
for (i, b) in self.bytes().enumerate() {
|
||||
if let b'a'..=b'z' = b {
|
||||
return Atom::from_mutated_str(self, |s| s[i..].make_ascii_uppercase());
|
||||
}
|
||||
}
|
||||
self.clone()
|
||||
}
|
||||
|
||||
/// Like [`to_ascii_lowercase`].
|
||||
///
|
||||
/// [`to_ascii_lowercase`]: https://doc.rust-lang.org/std/ascii/trait.AsciiExt.html#tymethod.to_ascii_lowercase
|
||||
pub fn to_ascii_lowercase(&self) -> Self {
|
||||
for (i, b) in self.bytes().enumerate() {
|
||||
if let b'A'..=b'Z' = b {
|
||||
return Atom::from_mutated_str(self, |s| s[i..].make_ascii_lowercase());
|
||||
}
|
||||
}
|
||||
self.clone()
|
||||
}
|
||||
|
||||
/// Like [`eq_ignore_ascii_case`].
|
||||
///
|
||||
/// [`eq_ignore_ascii_case`]: https://doc.rust-lang.org/std/ascii/trait.AsciiExt.html#tymethod.eq_ignore_ascii_case
|
||||
pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
|
||||
(self == other) || self.eq_str_ignore_ascii_case(&**other)
|
||||
}
|
||||
|
||||
/// Like [`eq_ignore_ascii_case`], but takes an unhashed string as `other`.
|
||||
///
|
||||
/// [`eq_ignore_ascii_case`]: https://doc.rust-lang.org/std/ascii/trait.AsciiExt.html#tymethod.eq_ignore_ascii_case
|
||||
pub fn eq_str_ignore_ascii_case(&self, other: &str) -> bool {
|
||||
(&**self).eq_ignore_ascii_case(other)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn inline_atom_slice(x: &NonZeroU64) -> &[u8] {
|
||||
unsafe {
|
||||
let x: *const NonZeroU64 = x;
|
||||
let mut data = x as *const u8;
|
||||
// All except the lowest byte, which is first in little-endian, last in big-endian.
|
||||
if cfg!(target_endian = "little") {
|
||||
data = data.offset(1);
|
||||
}
|
||||
let len = 7;
|
||||
slice::from_raw_parts(data, len)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn inline_atom_slice_mut(x: &mut u64) -> &mut [u8] {
|
||||
unsafe {
|
||||
let x: *mut u64 = x;
|
||||
let mut data = x as *mut u8;
|
||||
// All except the lowest byte, which is first in little-endian, last in big-endian.
|
||||
if cfg!(target_endian = "little") {
|
||||
data = data.offset(1);
|
||||
}
|
||||
let len = 7;
|
||||
slice::from_raw_parts_mut(data, len)
|
||||
}
|
||||
}
|
||||
108
third-party/vendor/string_cache/src/dynamic_set.rs
vendored
Normal file
108
third-party/vendor/string_cache/src/dynamic_set.rs
vendored
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use parking_lot::Mutex;
|
||||
use std::borrow::Cow;
|
||||
use std::mem;
|
||||
use std::ptr::NonNull;
|
||||
use std::sync::atomic::AtomicIsize;
|
||||
use std::sync::atomic::Ordering::SeqCst;
|
||||
|
||||
const NB_BUCKETS: usize = 1 << 12; // 4096
|
||||
const BUCKET_MASK: u32 = (1 << 12) - 1;
|
||||
|
||||
pub(crate) struct Set {
|
||||
buckets: Box<[Mutex<Option<Box<Entry>>>]>,
|
||||
}
|
||||
|
||||
pub(crate) struct Entry {
|
||||
pub(crate) string: Box<str>,
|
||||
pub(crate) hash: u32,
|
||||
pub(crate) ref_count: AtomicIsize,
|
||||
next_in_bucket: Option<Box<Entry>>,
|
||||
}
|
||||
|
||||
// Addresses are a multiples of this,
|
||||
// and therefore have have TAG_MASK bits unset, available for tagging.
|
||||
pub(crate) const ENTRY_ALIGNMENT: usize = 4;
|
||||
|
||||
#[test]
|
||||
fn entry_alignment_is_sufficient() {
|
||||
assert!(mem::align_of::<Entry>() >= ENTRY_ALIGNMENT);
|
||||
}
|
||||
|
||||
pub(crate) static DYNAMIC_SET: Lazy<Set> = Lazy::new(|| {
|
||||
// NOTE: Using const initialization for buckets breaks the small-stack test.
|
||||
// ```
|
||||
// // buckets: [Mutex<Option<Box<Entry>>>; NB_BUCKETS],
|
||||
// const MUTEX: Mutex<Option<Box<Entry>>> = Mutex::new(None);
|
||||
// let buckets = Box::new([MUTEX; NB_BUCKETS]);
|
||||
// ```
|
||||
let buckets = (0..NB_BUCKETS).map(|_| Mutex::new(None)).collect();
|
||||
Set { buckets }
|
||||
});
|
||||
|
||||
impl Set {
|
||||
pub(crate) fn insert(&self, string: Cow<str>, hash: u32) -> NonNull<Entry> {
|
||||
let bucket_index = (hash & BUCKET_MASK) as usize;
|
||||
let mut linked_list = self.buckets[bucket_index].lock();
|
||||
|
||||
{
|
||||
let mut ptr: Option<&mut Box<Entry>> = linked_list.as_mut();
|
||||
|
||||
while let Some(entry) = ptr.take() {
|
||||
if entry.hash == hash && *entry.string == *string {
|
||||
if entry.ref_count.fetch_add(1, SeqCst) > 0 {
|
||||
return NonNull::from(&mut **entry);
|
||||
}
|
||||
// Uh-oh. The pointer's reference count was zero, which means someone may try
|
||||
// to free it. (Naive attempts to defend against this, for example having the
|
||||
// destructor check to see whether the reference count is indeed zero, don't
|
||||
// work due to ABA.) Thus we need to temporarily add a duplicate string to the
|
||||
// list.
|
||||
entry.ref_count.fetch_sub(1, SeqCst);
|
||||
break;
|
||||
}
|
||||
ptr = entry.next_in_bucket.as_mut();
|
||||
}
|
||||
}
|
||||
debug_assert!(mem::align_of::<Entry>() >= ENTRY_ALIGNMENT);
|
||||
let string = string.into_owned();
|
||||
let mut entry = Box::new(Entry {
|
||||
next_in_bucket: linked_list.take(),
|
||||
hash,
|
||||
ref_count: AtomicIsize::new(1),
|
||||
string: string.into_boxed_str(),
|
||||
});
|
||||
let ptr = NonNull::from(&mut *entry);
|
||||
*linked_list = Some(entry);
|
||||
ptr
|
||||
}
|
||||
|
||||
pub(crate) fn remove(&self, ptr: *mut Entry) {
|
||||
let value: &Entry = unsafe { &*ptr };
|
||||
let bucket_index = (value.hash & BUCKET_MASK) as usize;
|
||||
|
||||
let mut linked_list = self.buckets[bucket_index].lock();
|
||||
debug_assert!(value.ref_count.load(SeqCst) == 0);
|
||||
let mut current: &mut Option<Box<Entry>> = &mut linked_list;
|
||||
|
||||
while let Some(entry_ptr) = current.as_mut() {
|
||||
let entry_ptr: *mut Entry = &mut **entry_ptr;
|
||||
if entry_ptr == ptr {
|
||||
mem::drop(mem::replace(current, unsafe {
|
||||
(*entry_ptr).next_in_bucket.take()
|
||||
}));
|
||||
break;
|
||||
}
|
||||
current = unsafe { &mut (*entry_ptr).next_in_bucket };
|
||||
}
|
||||
}
|
||||
}
|
||||
139
third-party/vendor/string_cache/src/lib.rs
vendored
Normal file
139
third-party/vendor/string_cache/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//!
|
||||
//! A library for interning things that are `AsRef<str>`.
|
||||
//!
|
||||
//! Some strings may be interned at compile time using the `string-cache-codegen` crate, or the
|
||||
//! `EmptyStaticAtomSet` may be used that has no compile-time interned strings. An `Atom` is an
|
||||
//! interned string for a given set (either `EmptyStaticAtomSet` or a generated `StaticAtomSet`).
|
||||
//!
|
||||
//! Generated `Atom`s will have assocated macros to intern static strings at compile-time.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Here are two examples, one with compile-time `Atom`s, and one without.
|
||||
//!
|
||||
//! ## With compile-time atoms
|
||||
//!
|
||||
//! In `Cargo.toml`:
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! string_cache = "0.8"
|
||||
//!
|
||||
//! [dev-dependencies]
|
||||
//! string_cache_codegen = "0.5"
|
||||
//! ```
|
||||
//!
|
||||
//! In `build.rs`:
|
||||
//!
|
||||
//! ```ignore
|
||||
//! extern crate string_cache_codegen;
|
||||
//!
|
||||
//! use std::env;
|
||||
//! use std::path::Path;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! string_cache_codegen::AtomType::new("foo::FooAtom", "foo_atom!")
|
||||
//! .atoms(&["foo", "bar"])
|
||||
//! .write_to_file(&Path::new(&env::var("OUT_DIR").unwrap()).join("foo_atom.rs"))
|
||||
//! .unwrap()
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! In `lib.rs`:
|
||||
//!
|
||||
//! ```ignore
|
||||
//! extern crate string_cache;
|
||||
//!
|
||||
//! mod foo {
|
||||
//! include!(concat!(env!("OUT_DIR"), "/foo_atom.rs"));
|
||||
//! }
|
||||
//!
|
||||
//! fn use_the_atom(t: &str) {
|
||||
//! match *t {
|
||||
//! foo_atom!("foo") => println!("Found foo!"),
|
||||
//! foo_atom!("bar") => println!("Found bar!"),
|
||||
//! // foo_atom!("baz") => println!("Found baz!"), - would be a compile time error
|
||||
//! _ => {
|
||||
//! println!("String not interned");
|
||||
//! // We can intern strings at runtime as well
|
||||
//! foo::FooAtom::from(t)
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! ## No compile-time atoms
|
||||
//!
|
||||
//! ```
|
||||
//! # extern crate string_cache;
|
||||
//! use string_cache::DefaultAtom;
|
||||
//!
|
||||
//! # fn main() {
|
||||
//! let mut interned_stuff = Vec::new();
|
||||
//! let text = "here is a sentence of text that will be tokenised and
|
||||
//! interned and some repeated tokens is of text and";
|
||||
//! for word in text.split_whitespace() {
|
||||
//! let seen_before = interned_stuff.iter()
|
||||
//! // We can use impl PartialEq<T> where T is anything string-like
|
||||
//! // to compare to interned strings to either other interned strings,
|
||||
//! // or actual strings Comparing two interned strings is very fast
|
||||
//! // (normally a single cpu operation).
|
||||
//! .filter(|interned_word| interned_word == &word)
|
||||
//! .count();
|
||||
//! if seen_before > 0 {
|
||||
//! println!(r#"Seen the word "{}" {} times"#, word, seen_before);
|
||||
//! } else {
|
||||
//! println!(r#"Not seen the word "{}" before"#, word);
|
||||
//! }
|
||||
//! // We use the impl From<(Cow<'a, str>, or &'a str, or String)> for
|
||||
//! // Atom<Static> to intern a new string.
|
||||
//! interned_stuff.push(DefaultAtom::from(word));
|
||||
//! }
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
|
||||
#![cfg_attr(test, deny(warnings))]
|
||||
|
||||
// Types, such as Atom, that impl Hash must follow the hash invariant: if two objects match
|
||||
// with PartialEq, they must also have the same Hash. Clippy warns on types that derive one while
|
||||
// manually impl-ing the other, because it seems easy for the two to drift apart, causing the
|
||||
// invariant to be violated.
|
||||
//
|
||||
// But Atom is a newtype over NonZeroU64, and probably always will be, since cheap comparisons and
|
||||
// copying are this library's purpose. So we know what the PartialEq comparison is going to do.
|
||||
//
|
||||
// The `get_hash` function, seen in `atom.rs`, consults that number, plus the global string interner
|
||||
// tables. The only way for the resulting hash for two Atoms with the same inner 64-bit number to
|
||||
// differ would be if the table entry changed between invocations, and that would be really bad.
|
||||
#![allow(clippy::derive_hash_xor_eq)]
|
||||
|
||||
mod atom;
|
||||
mod dynamic_set;
|
||||
mod static_sets;
|
||||
mod trivial_impls;
|
||||
|
||||
pub use atom::Atom;
|
||||
pub use static_sets::{EmptyStaticAtomSet, PhfStrSet, StaticAtomSet};
|
||||
|
||||
/// Use this if you don’t care about static atoms.
|
||||
pub type DefaultAtom = Atom<EmptyStaticAtomSet>;
|
||||
|
||||
// Some minor tests of internal layout here.
|
||||
// See ../integration-tests for much more.
|
||||
|
||||
/// Guard against accidental changes to the sizes of things.
|
||||
#[test]
|
||||
fn assert_sizes() {
|
||||
use std::mem::size_of;
|
||||
assert_eq!(size_of::<DefaultAtom>(), 8);
|
||||
assert_eq!(size_of::<Option<DefaultAtom>>(), size_of::<DefaultAtom>(),);
|
||||
}
|
||||
64
third-party/vendor/string_cache/src/static_sets.rs
vendored
Normal file
64
third-party/vendor/string_cache/src/static_sets.rs
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/// A static `PhfStrSet`
|
||||
///
|
||||
/// This trait is implemented by static sets of interned strings generated using
|
||||
/// `string_cache_codegen`, and `EmptyStaticAtomSet` for when strings will be added dynamically.
|
||||
///
|
||||
/// It is used by the methods of [`Atom`] to check if a string is present in the static set.
|
||||
///
|
||||
/// [`Atom`]: struct.Atom.html
|
||||
pub trait StaticAtomSet: Ord {
|
||||
/// Get the location of the static string set in the binary.
|
||||
fn get() -> &'static PhfStrSet;
|
||||
/// Get the index of the empty string, which is in every set and is used for `Atom::default`.
|
||||
fn empty_string_index() -> u32;
|
||||
}
|
||||
|
||||
/// A string set created using a [perfect hash function], specifically
|
||||
/// [Hash, Displace and Compress].
|
||||
///
|
||||
/// See the CHD document for the meaning of the struct fields.
|
||||
///
|
||||
/// [perfect hash function]: https://en.wikipedia.org/wiki/Perfect_hash_function
|
||||
/// [Hash, Displace and Compress]: http://cmph.sourceforge.net/papers/esa09.pdf
|
||||
pub struct PhfStrSet {
|
||||
#[doc(hidden)]
|
||||
pub key: u64,
|
||||
#[doc(hidden)]
|
||||
pub disps: &'static [(u32, u32)],
|
||||
#[doc(hidden)]
|
||||
pub atoms: &'static [&'static str],
|
||||
#[doc(hidden)]
|
||||
pub hashes: &'static [u32],
|
||||
}
|
||||
|
||||
/// An empty static atom set for when only dynamic strings will be added
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct EmptyStaticAtomSet;
|
||||
|
||||
impl StaticAtomSet for EmptyStaticAtomSet {
|
||||
fn get() -> &'static PhfStrSet {
|
||||
// The name is a lie: this set is not empty (it contains the empty string)
|
||||
// but that’s only to avoid divisions by zero in rust-phf.
|
||||
static SET: PhfStrSet = PhfStrSet {
|
||||
key: 0,
|
||||
disps: &[(0, 0)],
|
||||
atoms: &[""],
|
||||
// "" SipHash'd, and xored with u64_hash_to_u32.
|
||||
hashes: &[0x3ddddef3],
|
||||
};
|
||||
&SET
|
||||
}
|
||||
|
||||
fn empty_string_index() -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
119
third-party/vendor/string_cache/src/trivial_impls.rs
vendored
Normal file
119
third-party/vendor/string_cache/src/trivial_impls.rs
vendored
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use crate::{Atom, StaticAtomSet};
|
||||
#[cfg(feature = "serde_support")]
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
|
||||
impl<Static: StaticAtomSet> ::precomputed_hash::PrecomputedHash for Atom<Static> {
|
||||
fn precomputed_hash(&self) -> u32 {
|
||||
self.get_hash()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Static: StaticAtomSet> From<&'a Atom<Static>> for Atom<Static> {
|
||||
fn from(atom: &'a Self) -> Self {
|
||||
atom.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static: StaticAtomSet> PartialEq<str> for Atom<Static> {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
&self[..] == other
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static: StaticAtomSet> PartialEq<Atom<Static>> for str {
|
||||
fn eq(&self, other: &Atom<Static>) -> bool {
|
||||
self == &other[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static: StaticAtomSet> PartialEq<String> for Atom<Static> {
|
||||
fn eq(&self, other: &String) -> bool {
|
||||
self[..] == other[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Static: StaticAtomSet> From<&'a str> for Atom<Static> {
|
||||
#[inline]
|
||||
fn from(string_to_add: &str) -> Self {
|
||||
Atom::from(Cow::Borrowed(string_to_add))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static: StaticAtomSet> From<String> for Atom<Static> {
|
||||
#[inline]
|
||||
fn from(string_to_add: String) -> Self {
|
||||
Atom::from(Cow::Owned(string_to_add))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static: StaticAtomSet> fmt::Display for Atom<Static> {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
<str as fmt::Display>::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Static: StaticAtomSet> AsRef<str> for Atom<Static> {
|
||||
fn as_ref(&self) -> &str {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde_support")]
|
||||
impl<Static: StaticAtomSet> Serialize for Atom<Static> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let string: &str = self.as_ref();
|
||||
string.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde_support")]
|
||||
impl<'a, Static: StaticAtomSet> Deserialize<'a> for Atom<Static> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'a>,
|
||||
{
|
||||
use serde::de;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct AtomVisitor<Static: StaticAtomSet>(PhantomData<Static>);
|
||||
|
||||
impl<'de, Static: StaticAtomSet> de::Visitor<'de> for AtomVisitor<Static> {
|
||||
type Value = Atom<Static>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "an Atom")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(Atom::from(v))
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(Atom::from(v))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(AtomVisitor(PhantomData))
|
||||
}
|
||||
}
|
||||
17
third-party/vendor/string_cache/tests/small-stack.rs
vendored
Normal file
17
third-party/vendor/string_cache/tests/small-stack.rs
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Regression test for https://github.com/servo/html5ever/issues/393
|
||||
//
|
||||
// Create a dynamic atom − causing initialization of the global hash map −
|
||||
// in a thread that has a small stack.
|
||||
//
|
||||
// This is a separate test program rather than a `#[test] fn` among others
|
||||
// to make sure that nothing else has already initialized the map in this process.
|
||||
fn main() {
|
||||
std::thread::Builder::new()
|
||||
.stack_size(50_000)
|
||||
.spawn(|| {
|
||||
let _atom = string_cache::DefaultAtom::from("12345678");
|
||||
})
|
||||
.unwrap()
|
||||
.join()
|
||||
.unwrap()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue