summaryrefslogtreecommitdiffstats
path: root/vendor/memchr-2.3.4
diff options
context:
space:
mode:
authorEllie Huxtable <e@elm.sh>2021-05-17 19:51:09 +0100
committerEllie Huxtable <e@elm.sh>2021-05-17 19:51:09 +0100
commitd0215a937a7889a97e11778ee4b0f9a12de01278 (patch)
tree5a8fd5ad62e6b5a4c218746ff2d4bd97373a48de /vendor/memchr-2.3.4
parent802a2258cbd839c5b82d24f74d7aebe4a27d8dc5 (diff)
Vendor dependenciesvendor
Just testing how CI works with this. I tend to prefer vendoring, as it means that if you have a copy of the code *you can always build it*. Even if you're 20 years in the future This is the output of ``` cargo vendor --versioned-dirs ```
Diffstat (limited to 'vendor/memchr-2.3.4')
-rw-r--r--vendor/memchr-2.3.4/.cargo-checksum.json1
-rw-r--r--vendor/memchr-2.3.4/COPYING3
-rw-r--r--vendor/memchr-2.3.4/Cargo.toml42
-rw-r--r--vendor/memchr-2.3.4/LICENSE-MIT21
-rw-r--r--vendor/memchr-2.3.4/README.md79
-rw-r--r--vendor/memchr-2.3.4/UNLICENSE24
-rw-r--r--vendor/memchr-2.3.4/build.rs74
-rw-r--r--vendor/memchr-2.3.4/rustfmt.toml2
-rw-r--r--vendor/memchr-2.3.4/src/c.rs44
-rw-r--r--vendor/memchr-2.3.4/src/fallback.rs330
-rw-r--r--vendor/memchr-2.3.4/src/iter.rs173
-rw-r--r--vendor/memchr-2.3.4/src/lib.rs451
-rw-r--r--vendor/memchr-2.3.4/src/naive.rs25
-rw-r--r--vendor/memchr-2.3.4/src/tests/iter.rs229
-rw-r--r--vendor/memchr-2.3.4/src/tests/memchr.rs131
-rw-r--r--vendor/memchr-2.3.4/src/tests/miri.rs19
-rw-r--r--vendor/memchr-2.3.4/src/tests/mod.rs362
-rw-r--r--vendor/memchr-2.3.4/src/tests/x86_64-soft_float.json15
-rw-r--r--vendor/memchr-2.3.4/src/x86/avx.rs703
-rw-r--r--vendor/memchr-2.3.4/src/x86/mod.rs119
-rw-r--r--vendor/memchr-2.3.4/src/x86/sse2.rs793
-rw-r--r--vendor/memchr-2.3.4/src/x86/sse42.rs75
22 files changed, 3715 insertions, 0 deletions
diff --git a/vendor/memchr-2.3.4/.cargo-checksum.json b/vendor/memchr-2.3.4/.cargo-checksum.json
new file mode 100644
index 00000000..cffbb8dc
--- /dev/null
+++ b/vendor/memchr-2.3.4/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"97791f3b1dcca115ef7340a312aad0320a79ff91b93cc8fc50b7dcd652721aa3","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"d2ab7c9c77235b68d1cc856ab5ef7b5115312098469edcac9d5611c5b74d3cd1","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","build.rs":"740225b5280e53e8d73971c6ccc55152d6af32e94132bc6980fdc0eb1fb3ab48","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/c.rs":"86fe35cbb46c8bece9927fbde20f1ca3af526defdde05ac969ad2f4bc9bb25e9","src/fallback.rs":"79519255d480a9c2667c06f9287931cfc2b85f6af6fcf92d453a11ee161dcb74","src/iter.rs":"23b1066d6b40159fe944388db7743c89422b1110ddb44667fde6d722f178ed4e","src/lib.rs":"8278d5f65db8081fa5ad3a0d17dac54d30de3d7a01b0dc4479927156e40b225c","src/naive.rs":"c7453bc99cc4e58eb37cf5a50c88688833e50a270ee1849baefddb8acc0ccd94","src/tests/iter.rs":"8d5999a2a5b8a3228c76cd82cd3ee86dfa6f7b4022405b1f06eedf7d74e4c704","src/tests/memchr.rs":"f30074eeab99a16ce5ca8a30f1890f86c43c0422523a7195cbb3ca5f3e465b67","src/tests/miri.rs":"27859a7ac1d0a9305b2d114e6dd8876f3d5e47fc46a81be96239c793ac6edb1f","src/tests/mod.rs":"2ad0c82d33b32562087254522641ea7bfa2a283130152be5e927a33f1978ebc7","src/tests/x86_64-soft_float.json":"c0e416487fe9b4809534edb7db2a9eff3453dc40d9f1e23362c37f45a77ec717","src/x86/avx.rs":"b19987410e49a079f33162424c42494626c91303c41824961e478be3b537c9c9","src/x86/mod.rs":"0b13becaabc150a0099f7528226c82e288136cc7ebcdb8e96cf5ee9aae0f05b6","src/x86/sse2.rs":"7c1b8248a8cd48396cb70a862d77f9a972f1e16324d65c260f39d13af73bf638","src/x86/sse42.rs":"f671ae9dd2b518a823e499a09ce32d4957bc5ae043db90d61c027e32f688f2b2"},"package":"0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"} \ No newline at end of file
diff --git a/vendor/memchr-2.3.4/COPYING b/vendor/memchr-2.3.4/COPYING
new file mode 100644
index 00000000..bb9c20a0
--- /dev/null
+++ b/vendor/memchr-2.3.4/COPYING
@@ -0,0 +1,3 @@
+This project is dual-licensed under the Unlicense and MIT licenses.
+
+You may use this code under the terms of either license.
diff --git a/vendor/memchr-2.3.4/Cargo.toml b/vendor/memchr-2.3.4/Cargo.toml
new file mode 100644
index 00000000..1fc0b64f
--- /dev/null
+++ b/vendor/memchr-2.3.4/Cargo.toml
@@ -0,0 +1,42 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "memchr"
+version = "2.3.4"
+authors = ["Andrew Gallant <jamslam@gmail.com>", "bluss"]
+exclude = ["/ci/*", "/.travis.yml", "/Makefile", "/appveyor.yml"]
+description = "Safe interface to memchr."
+homepage = "https://github.com/BurntSushi/rust-memchr"
+documentation = "https://docs.rs/memchr/"
+readme = "README.md"
+keywords = ["memchr", "char", "scan", "strchr", "string"]
+license = "Unlicense/MIT"
+repository = "https://github.com/BurntSushi/rust-memchr"
+[profile.test]
+opt-level = 3
+
+[lib]
+name = "memchr"
+bench = false
+[dependencies.libc]
+version = "0.2.18"
+optional = true
+default-features = false
+[dev-dependencies.quickcheck]
+version = "0.9"
+default-features = false
+
+[features]
+default = ["std"]
+std = []
+use_std = ["std"]
diff --git a/vendor/memchr-2.3.4/LICENSE-MIT b/vendor/memchr-2.3.4/LICENSE-MIT
new file mode 100644
index 00000000..3b0a5dc0
--- /dev/null
+++ b/vendor/memchr-2.3.4/LICENSE-MIT
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Andrew Gallant
+
+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/memchr-2.3.4/README.md b/vendor/memchr-2.3.4/README.md
new file mode 100644
index 00000000..f78a5a53
--- /dev/null
+++ b/vendor/memchr-2.3.4/README.md
@@ -0,0 +1,79 @@
+memchr
+======
+The `memchr` crate provides heavily optimized routines for searching bytes.
+
+[![Build status](https://github.com/BurntSushi/rust-memchr/workflows/ci/badge.svg)](https://github.com/BurntSushi/rust-memchr/actions)
+[![](http://meritbadge.herokuapp.com/memchr)](https://crates.io/crates/memchr)
+
+Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
+
+
+### Documentation
+
+[https://docs.rs/memchr](https://docs.rs/memchr)
+
+
+### Overview
+
+The `memchr` function is traditionally provided by libc, but its
+performance can vary significantly depending on the specific
+implementation of libc that is used. They can range from manually tuned
+Assembly implementations (like that found in GNU's libc) all the way to
+non-vectorized C implementations (like that found in MUSL).
+
+To smooth out the differences between implementations of libc, at least
+on `x86_64` for Rust 1.27+, this crate provides its own implementation of
+`memchr` that should perform competitively with the one found in GNU's libc.
+The implementation is in pure Rust and has no dependency on a C compiler or an
+Assembler.
+
+Additionally, GNU libc also provides an extension, `memrchr`. This crate
+provides its own implementation of `memrchr` as well, on top of `memchr2`,
+`memchr3`, `memrchr2` and `memrchr3`. The difference between `memchr` and
+`memchr2` is that `memchr2` permits finding all occurrences of two bytes
+instead of one. Similarly for `memchr3`.
+
+### Compiling without the standard library
+
+memchr links to the standard library by default, but you can disable the
+`std` feature if you want to use it in a `#![no_std]` crate:
+
+```toml
+[dependencies]
+memchr = { version = "2", default-features = false }
+```
+
+On x86 platforms, when the `std` feature is disabled, the SSE2
+implementation of memchr will be used in compilers that support it. When
+`std` is enabled, the AVX implementation of memchr will be used if the CPU
+is determined to support it at runtime.
+
+### Using libc
+
+`memchr` is a routine that is part of libc, although this crate does not use
+libc by default. Instead, it uses its own routines, which are either vectorized
+or generic fallback routines. In general, these should be competitive with
+what's in libc, although this has not been tested for all architectures. If
+using `memchr` from libc is desirable and a vectorized routine is not otherwise
+available in this crate, then enabling the `libc` feature will use libc's
+version of `memchr`.
+
+The rest of the functions in this crate, e.g., `memchr2` or `memrchr3`, are not
+a standard part of libc, so they will always use the implementations in this
+crate. One exception to this is `memrchr`, which is an extension commonly found
+on Linux. On Linux, `memrchr` is used in precisely the same scenario as
+`memchr`, as described above.
+
+
+### Minimum Rust version policy
+
+This crate's minimum supported `rustc` version is `1.28.0`.
+
+The current policy is that the minimum Rust version required to use this crate
+can be increased in minor version updates. For example, if `crate 1.0` requires
+Rust 1.20.0, then `crate 1.0.z` for all values of `z` will also require Rust
+1.20.0 or newer. However, `crate 1.y` for `y > 0` may require a newer minimum
+version of Rust.
+
+In general, this crate will be conservative with respect to the minimum
+supported version of Rust.
diff --git a/vendor/memchr-2.3.4/UNLICENSE b/vendor/memchr-2.3.4/UNLICENSE
new file mode 100644
index 00000000..68a49daa
--- /dev/null
+++ b/vendor/memchr-2.3.4/UNLICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+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 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.
+
+For more information, please refer to <http://unlicense.org/>
diff --git a/vendor/memchr-2.3.4/build.rs b/vendor/memchr-2.3.4/build.rs
new file mode 100644
index 00000000..e07ad6f1
--- /dev/null
+++ b/vendor/memchr-2.3.4/build.rs
@@ -0,0 +1,74 @@
+use std::env;
+
+fn main() {
+ enable_simd_optimizations();
+ enable_libc();
+}
+
+// This adds various simd cfgs if this compiler and target support it.
+//
+// This can be disabled with RUSTFLAGS="--cfg memchr_disable_auto_simd", but
+// this is generally only intended for testing.
+//
+// On targets which don't feature SSE2, this is disabled, as LLVM wouln't know
+// how to work with SSE2 operands. Enabling SSE4.2 and AVX on SSE2-only targets
+// is not a problem. In that case, the fastest option will be chosen at
+// runtime.
+fn enable_simd_optimizations() {
+ if is_env_set("CARGO_CFG_MEMCHR_DISABLE_AUTO_SIMD")
+ || !target_has_feature("sse2")
+ {
+ return;
+ }
+ println!("cargo:rustc-cfg=memchr_runtime_simd");
+ println!("cargo:rustc-cfg=memchr_runtime_sse2");
+ println!("cargo:rustc-cfg=memchr_runtime_sse42");
+ println!("cargo:rustc-cfg=memchr_runtime_avx");
+}
+
+// This adds a `memchr_libc` cfg if and only if libc can be used, if no other
+// better option is available.
+//
+// This could be performed in the source code, but it's simpler to do it once
+// here and consolidate it into one cfg knob.
+//
+// Basically, we use libc only if its enabled and if we aren't targeting a
+// known bad platform. For example, wasm32 doesn't have a libc and the
+// performance of memchr on Windows is seemingly worse than the fallback
+// implementation.
+fn enable_libc() {
+ const NO_ARCH: &'static [&'static str] = &["wasm32", "windows"];
+ const NO_ENV: &'static [&'static str] = &["sgx"];
+
+ if !is_feature_set("LIBC") {
+ return;
+ }
+
+ let arch = match env::var("CARGO_CFG_TARGET_ARCH") {
+ Err(_) => return,
+ Ok(arch) => arch,
+ };
+ let env = match env::var("CARGO_CFG_TARGET_ENV") {
+ Err(_) => return,
+ Ok(env) => env,
+ };
+ if NO_ARCH.contains(&&*arch) || NO_ENV.contains(&&*env) {
+ return;
+ }
+
+ println!("cargo:rustc-cfg=memchr_libc");
+}
+
+fn is_feature_set(name: &str) -> bool {
+ is_env_set(&format!("CARGO_FEATURE_{}", name))
+}
+
+fn is_env_set(name: &str) -> bool {
+ env::var_os(name).is_some()
+}
+
+fn target_has_feature(feature: &str) -> bool {
+ env::var("CARGO_CFG_TARGET_FEATURE")
+ .map(|features| features.contains(feature))
+ .unwrap_or(false)
+}
diff --git a/vendor/memchr-2.3.4/rustfmt.toml b/vendor/memchr-2.3.4/rustfmt.toml
new file mode 100644
index 00000000..aa37a218
--- /dev/null
+++ b/vendor/memchr-2.3.4/rustfmt.toml
@@ -0,0 +1,2 @@
+max_width = 79
+use_small_heuristics = "max"
diff --git a/vendor/memchr-2.3.4/src/c.rs b/vendor/memchr-2.3.4/src/c.rs
new file mode 100644
index 00000000..63feca97
--- /dev/null
+++ b/vendor/memchr-2.3.4/src/c.rs
@@ -0,0 +1,44 @@
+// This module defines safe wrappers around memchr (POSIX) and memrchr (GNU
+// extension).
+
+#![allow(dead_code)]
+
+extern crate libc;
+
+use self::libc::{c_int, c_void, size_t};
+
+pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
+ let p = unsafe {
+ libc::memchr(
+ haystack.as_ptr() as *const c_void,
+ needle as c_int,
+ haystack.len() as size_t,
+ )
+ };
+ if p.is_null() {
+ None
+ } else {
+ Some(p as usize - (haystack.as_ptr() as usize))
+ }
+}
+
+// memrchr is a GNU extension. We know it's available on Linux, so start there.
+#[cfg(target_os = "linux")]
+pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
+ // GNU's memrchr() will - unlike memchr() - error if haystack is empty.
+ if haystack.is_empty() {
+ return None;
+ }
+ let p = unsafe {
+ libc::memrchr(
+ haystack.as_ptr() as *const c_void,
+ needle as c_int,
+ haystack.len() as size_t,
+ )
+ };
+ if p.is_null() {
+ None
+ } else {
+ Some(p as usize - (haystack.as_ptr() as usize))
+ }
+}
diff --git a/vendor/memchr-2.3.4/src/fallback.rs b/vendor/memchr-2.3.4/src/fallback.rs
new file mode 100644
index 00000000..8bc32b27
--- /dev/null
+++ b/vendor/memchr-2.3.4/src/fallback.rs
@@ -0,0 +1,330 @@
+// This module defines pure Rust platform independent implementations of all
+// the memchr routines. We do our best to make them fast. Some of them may even
+// get auto-vectorized.
+
+use core::cmp;
+use core::usize;
+
+#[cfg(target_pointer_width = "16")]
+const USIZE_BYTES: usize = 2;
+
+#[cfg(target_pointer_width = "32")]
+const USIZE_BYTES: usize = 4;
+
+#[cfg(target_pointer_width = "64")]
+const USIZE_BYTES: usize = 8;
+
+// The number of bytes to loop at in one iteration of memchr/memrchr.
+const LOOP_SIZE: usize = 2 * USIZE_BYTES;
+
+/// Return `true` if `x` contains any zero byte.
+///
+/// From *Matters Computational*, J. Arndt
+///
+/// "The idea is to subtract one from each of the bytes and then look for
+/// bytes where the borrow propagated all the way to the most significant
+/// bit."
+#[inline(always)]
+fn contains_zero_byte(x: usize) -> bool {
+ const LO_U64: u64 = 0x0101010101010101;
+ const HI_U64: u64 = 0x8080808080808080;
+
+ const LO_USIZE: usize = LO_U64 as usize;
+ const HI_USIZE: usize = HI_U64 as usize;
+
+ x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0
+}
+
+/// Repeat the given byte into a word size number. That is, every 8 bits
+/// is equivalent to the given byte. For example, if `b` is `\x4E` or
+/// `01001110` in binary, then the returned value on a 32-bit system would be:
+/// `01001110_01001110_01001110_01001110`.
+#[inline(always)]
+fn repeat_byte(b: u8) -> usize {
+ (b as usize) * (usize::MAX / 255)
+}
+
+pub fn memchr(n1: u8, haystack: &[u8]) -> Option<usize> {
+ let vn1 = repeat_byte(n1);
+ let confirm = |byte| byte == n1;
+ let loop_size = cmp::min(LOOP_SIZE, haystack.len());
+ let align = USIZE_BYTES - 1;
+ let start_ptr = haystack.as_ptr();
+ let end_ptr = haystack[haystack.len()..].as_ptr();
+ let mut ptr = start_ptr;
+
+ unsafe {
+ if haystack.len() < USIZE_BYTES {
+ return forward_search(start_ptr, end_ptr, ptr, confirm);
+ }
+
+ let chunk = (ptr as *const usize).read_unaligned();
+ if contains_zero_byte(chunk ^ vn1) {
+ return forward_search(start_ptr, end_ptr, ptr, confirm);
+ }
+
+ ptr = ptr.add(USIZE_BYTES - (start_ptr as usize & align));
+ debug_assert!(ptr > start_ptr);
+ debug_assert!(end_ptr.sub(USIZE_BYTES) >= start_ptr);
+ while loop_size == LOOP_SIZE && ptr <= end_ptr.sub(loop_size) {
+ debug_assert_eq!(0, (ptr as usize) % USIZE_BYTES);
+
+ let a = *(ptr as *const usize);
+ let b = *(ptr.add(USIZE_BYTES) as *const usize);
+ let eqa = contains_zero_byte(a ^ vn1);
+ let eqb = contains_zero_byte(b ^ vn1);
+ if eqa || eqb {
+ break;
+ }
+ ptr = ptr.add(LOOP_SIZE);
+ }
+ forward_search(start_ptr, end_ptr, ptr, confirm)
+ }
+}
+
+/// Like `memchr`, but searches for two bytes instead of one.
+pub fn memchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> {
+ let vn1 = repeat_byte(n1);
+ let vn2 = repeat_byte(n2);
+ let confirm = |byte| byte == n1 || byte == n2;
+ let align = USIZE_BYTES - 1;
+ let start_ptr = haystack.as_ptr();
+ let end_ptr = haystack[haystack.len()..].as_ptr();
+ let mut ptr = start_ptr;
+
+ unsafe {
+ if haystack.len() < USIZE_BYTES {
+ return forward_search(start_ptr, end_ptr, ptr, confirm);
+ }
+
+ let chunk = (ptr as *const usize).read_unaligned();
+ let eq1 = contains_zero_byte(chunk ^ vn1);
+ let eq2 = contains_zero_byte(chunk ^ vn2);
+ if eq1 || eq2 {
+ return forward_search(start_ptr, end_ptr, ptr, confirm);
+ }
+
+ ptr = ptr.add(USIZE_BYTES - (start_ptr as usize & align));
+ debug_assert!(ptr > start_ptr);
+ debug_assert!(end_ptr.sub(USIZE_BYTES) >= start_ptr);
+ while ptr <= end_ptr.sub(USIZE_BYTES) {
+ debug_assert_eq!(0, (ptr as usize) % USIZE_BYTES);
+
+ let chunk = *(ptr as *const usize);
+ let eq1 = contains_zero_byte(chunk ^ vn1);
+ let eq2 = contains_zero_byte(chunk ^ vn2);
+ if eq1 || eq2 {
+ break;
+ }
+ ptr = ptr.add(USIZE_BYTES);
+ }
+ forward_search(start_ptr, end_ptr, ptr, confirm)
+ }
+}
+
+/// Like `memchr`, but searches for three bytes instead of one.
+pub fn memchr3(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option<usize> {
+ let vn1 = repeat_byte(n1);
+ let vn2 = repeat_byte(n2);
+ let vn3 = repeat_byte(n3);
+ let confirm = |byte| byte == n1 || byte == n2 || byte == n3;
+ let align = USIZE_BYTES - 1;
+ let start_ptr = haystack.as_ptr();
+ let end_ptr = haystack[haystack.len()..].as_ptr();
+ let mut ptr = start_ptr;
+
+ unsafe {
+ if haystack.len() < USIZE_BYTES {
+ return forward_search(start_ptr, end_ptr, ptr, confirm);
+ }
+
+ let chunk = (ptr as *const usize).read_unaligned();
+ let eq1 = contains_zero_byte(chunk ^ vn1);
+ let eq2 = contains_zero_byte(chunk ^ vn2);
+ let eq3 = contains_zero_byte(chunk ^ vn3);
+ if eq1 || eq2 || eq3 {
+ return forward_search(start_ptr, end_ptr, ptr, confirm);
+ }
+
+ ptr = ptr.add(USIZE_BYTES - (start_ptr as usize & align));
+ debug_assert!(ptr > start_ptr);
+ debug_assert!(end_ptr.sub(USIZE_BYTES) >= start_ptr);
+ while ptr <= end_ptr.sub(USIZE_BYTES) {
+ debug_assert_eq!(0, (ptr as usize) % USIZE_BYTES);
+
+ let chunk = *(ptr as *const usize);
+ let eq1 = contains_zero_byte(chunk ^ vn1);
+ let eq2 = contains_zero_byte(chunk ^ vn2);
+ let eq3 = contains_zero_byte(chunk ^ vn3);
+ if eq1 || eq2 || eq3 {
+ break;
+ }
+ ptr = ptr.add(USIZE_BYTES);
+ }
+ forward_search(start_ptr, end_ptr, ptr, confirm)
+ }
+}
+
+/// Return the last index matching the byte `x` in `text`.
+pub fn memrchr(n1: u8, haystack: &[u8]) -> Option<usize> {
+ let vn1 = repeat_byte(n1);
+ let confirm = |byte| byte == n1;
+ let loop_size = cmp::min(LOOP_SIZE, haystack.len());
+ let align = USIZE_BYTES - 1;
+ let start_ptr = haystack.as_ptr();
+ let end_ptr = haystack[haystack.len()..].as_ptr();
+ let mut ptr = end_ptr;
+
+ unsafe {
+ if haystack.len() < USIZE_BYTES {
+ return reverse_search(start_ptr, end_ptr, ptr, confirm);
+ }
+
+ let chunk = (ptr.sub(USIZE_BYTES) as *const usize).read_unaligned();
+ if contains_zero_byte(chunk ^ vn1) {
+ return reverse_search(start_ptr, end_ptr, ptr, confirm);
+ }
+
+ ptr = (end_ptr as usize & !align) as *const u8;
+ debug_assert!(start_ptr <= ptr && ptr <= end_ptr);
+ while loop_size == LOOP_SIZE && ptr >= start_ptr.add(loop_size) {
+ debug_assert_eq!(0, (ptr as usize) % USIZE_BYTES);
+
+ let a = *(ptr.sub(2 * USIZE_BYTES) as *const usize);
+ let b = *(ptr.sub(1 * USIZE_BYTES) as *const usize);
+ let eqa = contains_zero_byte(a ^ vn1);
+ let eqb = contains_zero_byte(b ^ vn1);
+ if eqa || eqb {
+ break;
+ }
+ ptr = ptr.sub(loop_size);
+ }
+ reverse_search(start_ptr, end_ptr, ptr, confirm)
+ }
+}
+
+/// Like `memrchr`, but searches for two bytes instead of one.
+pub fn memrchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> {
+ let vn1 = repeat_byte(n1);
+ let vn2 = repeat_byte(n2);
+ let confirm = |byte| byte == n1 || byte == n2;
+ let align = USIZE_BYTES - 1;
+ let start_ptr = haystack.as_ptr();
+ let end_ptr = haystack[haystack.len()..].as_ptr();
+ let mut ptr = end_ptr;
+
+ unsafe {
+ if haystack.len() < USIZE_BYTES {
+ return reverse_search(start_ptr, end_ptr, ptr, confirm);
+ }
+
+ let chunk = (ptr.sub(USIZE_BYTES) as *const usize).read_unaligned();
+ let eq1 = contains_zero_byte(chunk ^ vn1);
+ let eq2 = contains_zero_byte(chunk ^ vn2);
+ if eq1 || eq2 {
+ return reverse_search(start_ptr, end_ptr, ptr, confirm);
+ }
+
+ ptr = (end_ptr as usize & !align) as *const u8;
+ debug_assert!(start_ptr <= ptr && ptr <= end_ptr);
+ while ptr >= start_ptr.add(USIZE_BYTES) {
+ debug_assert_eq!(0, (ptr as usize) % USIZE_BYTES);
+
+ let chunk = *(ptr.sub(USIZE_BYTES) as *const usize);
+ let eq1 = contains_zero_byte(chunk ^ vn1);
+ let eq2 = contains_zero_byte(chunk ^ vn2);
+ if eq1 || eq2 {
+ break;
+ }
+ ptr = ptr.sub(USIZE_BYTES);
+ }
+ reverse_search(start_ptr, end_ptr, ptr, confirm)
+ }
+}
+
+/// Like `memrchr`, but searches for three bytes instead of one.
+pub fn memrchr3(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option<usize> {
+ let vn1 = repeat_byte(n1);
+ let vn2 = repeat_byte(n2);
+ let vn3 = repeat_byte(n3);
+ let confirm = |byte| byte == n1 || byte == n2 || byte == n3;
+ let align = USIZE_BYTES - 1;
+ let start_ptr = haystack.as_ptr();
+ let end_ptr = haystack[haystack.len()..].as_ptr();
+ let mut ptr = end_ptr;
+
+ unsafe {
+ if haystack.len() < USIZE_BYTES {
+ return reverse_search(start_ptr, end_ptr, ptr, confirm);
+ }
+
+ let chunk = (ptr.sub(USIZE_BYTES) as *const usize).read_unaligned();
+ let eq1 = contains_zero_byte(chunk ^ vn1);
+ let eq2 = contains_zero_byte(chunk ^ vn2);
+ let eq3 = contains_zero_byte(chunk ^ vn3);
+ if eq1 || eq2 || eq3 {
+ return reverse_search(start_ptr, end_ptr, ptr, confirm);
+ }
+
+ ptr = (end_ptr as usize & !align) as *const u8;
+ debug_assert!(start_ptr <= ptr && ptr <= end_ptr);
+ while ptr >= start_ptr.add(USIZE_BYTES) {
+ debug_assert_eq!(0, (ptr as usize) % USIZE_BYTES);
+
+ let chunk = *(ptr.sub(USIZE_BYTES) as *const usize);
+ let eq1 = contains_zero_byte(chunk ^ vn1);
+ let eq2 = contains_zero_byte(chunk ^ vn2);
+ let eq3 = contains_zero_byte(chunk ^ vn3);
+ if eq1 || eq2 || eq3 {
+ break;
+ }
+ ptr = ptr.sub(USIZE_BYTES);
+ }
+ reverse_search(start_ptr, end_ptr, ptr, confirm)
+ }
+}
+
+#[inline(always)]
+unsafe fn forward_search<F: Fn(u8) -> bool>(
+ start_ptr: *const u8,
+ end_ptr: *const u8,
+ mut ptr: *const u8,
+ confirm: F,
+) -> Option<usize> {
+ debug_assert!(start_ptr <= ptr);
+ debug_assert!(ptr <= end_ptr);
+
+ while ptr < end_ptr {
+ if confirm(*ptr) {
+ return Some(sub(ptr, start_ptr));
+ }
+ ptr = ptr.offset(1);
+ }
+ None
+}
+
+#[inline(always)]
+unsafe fn reverse_search<F: Fn(u8) -> bool>(
+ start_ptr: *const u8,
+ end_ptr: *const u8,
+ mut ptr: *const u8,
+ confirm: F,
+) -> Option<usize> {
+ debug_assert!(start_ptr <= ptr);
+ debug_assert!(ptr <= end_ptr);
+
+ while ptr > start_ptr {
+ ptr = ptr.offset(-1);
+ if confirm(*ptr) {
+ return Some(sub(ptr, start_ptr));
+ }
+ }
+ None
+}
+
+/// Subtract `b` from `a` and return the difference. `a` should be greater than
+/// or equal to `b`.
+fn sub(a: *const u8, b: *const u8) -> usize {
+ debug_assert!(a >= b);
+ (a as usize) - (b as usize)
+}
diff --git a/vendor/memchr-2.3.4/src/iter.rs b/vendor/memchr-2.3.4/src/iter.rs
new file mode 100644
index 00000000..6217ae4a
--- /dev/null
+++ b/vendor/memchr-2.3.4/src/iter.rs
@@ -0,0 +1,173 @@
+use {memchr, memchr2, memchr3, memrchr, memrchr2, memrchr3};
+
+macro_rules! iter_next {
+ // Common code for the memchr iterators:
+ // update haystack and position and produce the index
+ //
+ // self: &mut Self where Self is the iterator
+ // search_result: Option<usize> which is the result of the corresponding
+ // memchr function.
+ //
+ // Returns Option<usize> (the next iterator element)
+ ($self_:expr, $search_result:expr) => {
+ $search_result.map(move |index| {
+ // split and take the remaining back half
+ $self_.haystack = $self_.haystack.split_at(index + 1).1;
+ let found_position = $self_.position + index;
+ $self_.position = found_position + 1;
+ found_position
+ })
+ };
+}
+
+macro_rules! iter_next_back {
+ ($self_:expr, $search_result:expr) => {
+ $search_result.map(move |index| {
+ // split and take the remaining front half
+ $self_.haystack = $self_.haystack.split_at(index).0;
+ $self_.position + index
+ })
+ };
+}
+
+/// An iterator for `memchr`.
+pub struct Memchr<'a> {
+ needle: u8,
+ // The haystack to iterate over
+ haystack: &'a [u8],
+ // The index
+ position: usize,
+}
+
+impl<'a> Memchr<'a> {
+ /// Creates a new iterator that yields all positions of needle in haystack.
+ #[inline]
+ pub fn new(needle: u8, haystack: &[u8]) -> Memchr {
+ Memchr { needle: needle, haystack: haystack, position: 0 }
+ }
+}
+
+impl<'a> Iterator for Memchr<'a> {
+ type Item = usize;
+
+ #[inline]
+ fn next(&mut self) -> Option<usize> {
+ iter_next!(self, memchr(self.needle, self.haystack))
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (0, Some(self.haystack.len()))
+ }
+}
+
+impl<'a> DoubleEndedIterator for Memchr<'a> {
+ #[inline]
+ fn next_back(&mut self) -> Option<Self::Item> {
+ iter_next_back!(self, memrchr(self.needle, self.haystack))
+ }
+}
+
+/// An iterator for `memchr2`.
+pub struct Memchr2<'a> {
+ needle1: u8,
+ needle2: u8,
+ // The haystack to iterate over
+ haystack: &'a [u8],
+ // The index
+ position: usize,
+}
+
+impl<'a> Memchr2<'a> {
+ /// Creates a new iterator that yields all positions of needle in haystack.
+ #[inline]
+ pub fn new(needle1: u8, needle2: u8, haystack: &[u8]) -> Memchr2 {
+ Memchr2 {
+ needle1: needle1,
+ needle2: needle2,
+ haystack: haystack,
+ position: 0,
+ }
+ }
+}
+
+impl<'a> Iterator for Memchr2<'a> {