summaryrefslogtreecommitdiffstats
path: root/vendor/string_cache
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/string_cache')
-rw-r--r--vendor/string_cache/.cargo-checksum.json1
-rw-r--r--vendor/string_cache/Cargo.lock158
-rw-r--r--vendor/string_cache/Cargo.toml50
-rw-r--r--vendor/string_cache/LICENSE-APACHE201
-rw-r--r--vendor/string_cache/LICENSE-MIT25
-rw-r--r--vendor/string_cache/README.md78
-rw-r--r--vendor/string_cache/examples/simple.rs26
-rw-r--r--vendor/string_cache/src/atom.rs391
-rw-r--r--vendor/string_cache/src/dynamic_set.rs108
-rw-r--r--vendor/string_cache/src/lib.rs139
-rw-r--r--vendor/string_cache/src/static_sets.rs64
-rw-r--r--vendor/string_cache/src/trivial_impls.rs119
-rw-r--r--vendor/string_cache/tests/small-stack.rs17
13 files changed, 1377 insertions, 0 deletions
diff --git a/vendor/string_cache/.cargo-checksum.json b/vendor/string_cache/.cargo-checksum.json
new file mode 100644
index 000000000..39023d295
--- /dev/null
+++ b/vendor/string_cache/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"ca63167cb0772820bf3ea4ab32bc915e4f9732dab7521bd9c6da068ff83ed4dc","Cargo.toml":"913fff4dae8e06b0384fd26b7d3b1305a74ebed08364ad3548a03a9298f67cb0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"d13530e5e0d72b9106c735c276f88fd11aeaaccb404dda75a74d2cfafbf59268","examples/simple.rs":"227cbe14cdb0cb710a259707144b259684e9576615247628b8d57c895dd8c538","src/atom.rs":"f8c1a75cac54254633497fed370396efa62c2b82a3c9c629ec6ae598c44ea321","src/dynamic_set.rs":"c10c776a76b97facb9de03de9ad6c923bb6e64757f37941d7bd3458b32f53470","src/lib.rs":"844ad2b53bde6f0d65650b9b034b91bdcece1ac285c0f2a97fea04382b6917e2","src/static_sets.rs":"0d91d476b5277cf3cbbcd0c9f18cc5286086fecf59654115efab5090862ec8e8","src/trivial_impls.rs":"ba12375f21c5f033a52bdf10dd6ab366702e1d68954aa012fc90cc7efc2a5ed3","tests/small-stack.rs":"f3c8dd5f38eba6e41aa44fe7a4af3a2a2e5bfc0a1fb938e76319d9780956177c"},"package":"33994d0838dc2d152d17a62adf608a869b5e846b65b389af7f3dbc1de45c5b26"} \ No newline at end of file
diff --git a/vendor/string_cache/Cargo.lock b/vendor/string_cache/Cargo.lock
new file mode 100644
index 000000000..b7e316bc8
--- /dev/null
+++ b/vendor/string_cache/Cargo.lock
@@ -0,0 +1,158 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
+
+[[package]]
+name = "libc"
+version = "0.2.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c"
+
+[[package]]
+name = "lock_api"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "new_debug_unreachable"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30"
+
+[[package]]
+name = "parking_lot"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
+dependencies = [
+ "cfg-if",
+ "instant",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi",
+]
+
+[[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.98"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fe5626ac617da2f2d9c48af5515a21d5a480dbd151e01bb1c355e26a3e68113"
+
+[[package]]
+name = "siphasher"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83da420ee8d1a89e640d0948c646c1c088758d3a3c538f943bfa97bdac17929d"
+
+[[package]]
+name = "smallvec"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
+
+[[package]]
+name = "string_cache"
+version = "0.8.3"
+dependencies = [
+ "lazy_static",
+ "new_debug_unreachable",
+ "parking_lot",
+ "phf_shared",
+ "precomputed-hash",
+ "serde",
+]
+
+[[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-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/vendor/string_cache/Cargo.toml b/vendor/string_cache/Cargo.toml
new file mode 100644
index 000000000..f5f17fa9f
--- /dev/null
+++ b/vendor/string_cache/Cargo.toml
@@ -0,0 +1,50 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "string_cache"
+version = "0.8.3"
+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/"
+license = "MIT / Apache-2.0"
+repository = "https://github.com/servo/string-cache"
+
+[lib]
+name = "string_cache"
+
+[[test]]
+name = "small-stack"
+harness = false
+
+[dependencies.lazy_static]
+version = "1.1.0"
+
+[dependencies.new_debug_unreachable]
+version = "1.0.2"
+
+[dependencies.parking_lot]
+version = "0.11"
+
+[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"]
diff --git a/vendor/string_cache/LICENSE-APACHE b/vendor/string_cache/LICENSE-APACHE
new file mode 100644
index 000000000..16fe87b06
--- /dev/null
+++ b/vendor/string_cache/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/vendor/string_cache/LICENSE-MIT b/vendor/string_cache/LICENSE-MIT
new file mode 100644
index 000000000..807526f57
--- /dev/null
+++ b/vendor/string_cache/LICENSE-MIT
@@ -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.
diff --git a/vendor/string_cache/README.md b/vendor/string_cache/README.md
new file mode 100644
index 000000000..fdf4c0a35
--- /dev/null
+++ b/vendor/string_cache/README.md
@@ -0,0 +1,78 @@
+# string-cache
+
+[![Build Status](https://github.com/servo/string-cache/actions/workflows/ci.yml/badge.svg)](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,
+ }
+}
+```
diff --git a/vendor/string_cache/examples/simple.rs b/vendor/string_cache/examples/simple.rs
new file mode 100644
index 000000000..f063b06bc
--- /dev/null
+++ b/vendor/string_cache/examples/simple.rs
@@ -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));
+ }
+}
diff --git a/vendor/string_cache/src/atom.rs b/vendor/string_cache/src/atom.rs
new file mode 100644
index 000000000..c02651b31
--- /dev/null
+++ b/vendor/string_cache/src/atom.rs
@@ -0,0 +1,391 @@
+// 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 repersentation. 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.lock().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
+ .lock()
+ .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)
+ }
+}
diff --git a/vendor/string_cache/src/dynamic_set.rs b/vendor/string_cache/src/dynamic_set.rs
new file mode 100644
index 000000000..602b700c8
--- /dev/null
+++ b/vendor/string_cache/src/dynamic_set.rs
@@ -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 lazy_static::lazy_static;
+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<[Option<Box<Entry>>; NB_BUCKETS]>,
+}
+
+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);
+}
+
+lazy_static! {
+ pub(crate) static ref DYNAMIC_SET: Mutex<Set> = Mutex::new({
+ type T = Option<Box<Entry>>;
+ let _static_assert_size_eq = std::mem::transmute::<T, usize>;
+ let vec = std::mem::ManuallyDrop::new(vec![0_usize; NB_BUCKETS]);
+ Set {
+ buckets: unsafe { Box::from_raw(vec.as_ptr() as *mut [T; NB_BUCKETS]) },
+ }
+ });
+}
+
+impl Set {
+ pub(crate) fn insert(&mut self, string: Cow<str>, hash: u32) -> NonNull<Entry> {
+ let bucket_index = (hash & BUCKET_MASK) as usize;
+ {
+ let mut ptr: Option<&mut Box<Entry>> = self.buckets[bucket_index].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: self.buckets[bucket_index].take(),
+ hash,
+ ref_count: AtomicIsize::new(1),
+ string: string.into_boxed_str(),
+ });
+ let ptr = NonNull::from(&mut *entry);
+ self.buckets[bucket_index] = Some(entry);
+
+ ptr
+ }
+
+ pub(crate) fn remove(&mut self, ptr: *mut Entry) {
+ let bucket_index = {
+ let value: &Entry = unsafe { &*ptr };
+ debug_assert!(value.ref_count.load(SeqCst) == 0);
+ (value.hash & BUCKET_MASK) as usize
+ };
+
+ let mut current: &mut Option<Box<Entry>> = &mut self.buckets[bucket_index];
+
+ 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 };
+ }
+ }
+}
diff --git a/vendor/string_cache/src/lib.rs b/vendor/string_cache/src/lib.rs
new file mode 100644
index 000000000..441cb4ef0
--- /dev/null
+++ b/vendor/string_cache/src/lib.rs
@@ -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>(),);
+}
diff --git a/vendor/string_cache/src/static_sets.rs b/vendor/string_cache/src/static_sets.rs
new file mode 100644
index 000000000..f7f1799fc
--- /dev/null
+++ b/vendor/string_cache/src/static_sets.rs
@@ -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
+ }
+}
diff --git a/vendor/string_cache/src/trivial_impls.rs b/vendor/string_cache/src/trivial_impls.rs
new file mode 100644
index 000000000..960dde0d4
--- /dev/null
+++ b/vendor/string_cache/src/trivial_impls.rs
@@ -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))
+ }
+}
diff --git a/vendor/string_cache/tests/small-stack.rs b/vendor/string_cache/tests/small-stack.rs
new file mode 100644
index 000000000..bb607af6a
--- /dev/null
+++ b/vendor/string_cache/tests/small-stack.rs
@@ -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()
+}