RPM build fix (reverted CI changes which will need to be un-reverted or made conditional) and vendor Rust dependencies to make builds much faster in any CI system.
This commit is contained in:
1
zeroidc/vendor/httparse/.cargo-checksum.json
vendored
Normal file
1
zeroidc/vendor/httparse/.cargo-checksum.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"files":{"Cargo.toml":"96b4a31393d0f0140e9aad3481243a2404467448621e40a297ad3f5f1c71c50b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"d1e7f8223db09ae257ac95039ab91b95676c1ac7e55c7a6e996fd76e01fb3453","README.md":"eb23916ad2e4e904ee31e2af02e71ffd8f2d0c97f9e529f3e02f300a120e2c8b","benches/parse.rs":"6f3be57dae549574569b812acab6213f4136ba9c4ad60a21848043d26e6aaece","build.rs":"8ae7a55b0cca81a9997a151bd52e4658af9c6a5c176e65bbec532a20ab23360a","src/iter.rs":"14fca7e8c1a77feaaba91ff983242780c78d3e927db9fd80d79ad80bb3862886","src/lib.rs":"7a9a6c1176f9c7218ed2a241fe571732cc727585d620ee4a1bd624f553dee098","src/macros.rs":"7cab653acace88f47eadf57e0397946128b5693cba4c8b99e53903730216eb62","src/simd/avx2.rs":"82180f58bebb05bbbf3d5b1f6ff95f85114303860551fd5f274158a162989322","src/simd/fallback.rs":"0234cc11459f3225d6e3d329068a01206e39625a538bdc292e0d1beaa06a37e5","src/simd/mod.rs":"e647c7e4e0c7bcdf1de67d702568efdc4d44b4bf4384e9c549c312b7799b3017","src/simd/sse42.rs":"534898c5812ae2815abd3b997928dd7718fba2d0d15c32fef77b92ed44af5d3b","tests/uri.rs":"1e6ae7eff244c7c51d8c07c14916abf3de650325fba81434bb48ec3f270c04cc"},"package":"496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c"}
|
||||
51
zeroidc/vendor/httparse/Cargo.toml
vendored
Normal file
51
zeroidc/vendor/httparse/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]
|
||||
name = "httparse"
|
||||
version = "1.7.1"
|
||||
authors = ["Sean McArthur <sean@seanmonstar.com>"]
|
||||
build = "build.rs"
|
||||
description = "A tiny, safe, speedy, zero-copy HTTP/1.x parser."
|
||||
documentation = "https://docs.rs/httparse"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"http",
|
||||
"parser",
|
||||
"no_std",
|
||||
]
|
||||
categories = [
|
||||
"network-programming",
|
||||
"no-std",
|
||||
"parser-implementations",
|
||||
"web-programming",
|
||||
]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/seanmonstar/httparse"
|
||||
|
||||
[profile.bench]
|
||||
opt-level = 3
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
|
||||
[lib]
|
||||
bench = false
|
||||
|
||||
[[bench]]
|
||||
name = "parse"
|
||||
harness = false
|
||||
|
||||
[dev-dependencies.criterion]
|
||||
version = "0.3.5"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = []
|
||||
201
zeroidc/vendor/httparse/LICENSE-APACHE
vendored
Normal file
201
zeroidc/vendor/httparse/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.
|
||||
20
zeroidc/vendor/httparse/LICENSE-MIT
vendored
Normal file
20
zeroidc/vendor/httparse/LICENSE-MIT
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2015-2021 Sean McArthur
|
||||
|
||||
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.
|
||||
|
||||
43
zeroidc/vendor/httparse/README.md
vendored
Normal file
43
zeroidc/vendor/httparse/README.md
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
# httparse
|
||||
|
||||
[](https://crates.io/crates/httparse)
|
||||
[](https://docs.rs/httparse)
|
||||
[](./LICENSE-MIT)
|
||||
[](https://github.com/seanmonstar/httparse/actions?query=workflow%3ACI)
|
||||
[![Discord chat][discord-badge]][discord-url]
|
||||
|
||||
A push parser for the HTTP 1.x protocol. Avoids allocations. No copy. **Fast.**
|
||||
|
||||
Works with `no_std`, simply disable the `std` Cargo feature.
|
||||
|
||||
[Changelog](https://github.com/seanmonstar/httparse/releases)
|
||||
|
||||
|
||||
[discord-badge]: https://img.shields.io/discord/500028886025895936.svg?logo=discord
|
||||
[discord-url]: https://discord.gg/kkwpueZ
|
||||
|
||||
## Usage
|
||||
|
||||
```rust
|
||||
let mut headers = [httparse::EMPTY_HEADER; 64];
|
||||
let mut req = httparse::Request::new(&mut headers);
|
||||
|
||||
let buf = b"GET /index.html HTTP/1.1\r\nHost";
|
||||
assert!(req.parse(buf)?.is_partial());
|
||||
|
||||
// a partial request, so we try again once we have more data
|
||||
|
||||
let buf = b"GET /index.html HTTP/1.1\r\nHost: example.domain\r\n\r\n";
|
||||
assert!(req.parse(buf)?.is_complete());
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Licensed under either of
|
||||
|
||||
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or https://apache.org/licenses/LICENSE-2.0)
|
||||
- MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
|
||||
93
zeroidc/vendor/httparse/benches/parse.rs
vendored
Normal file
93
zeroidc/vendor/httparse/benches/parse.rs
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
extern crate criterion;
|
||||
extern crate httparse;
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
|
||||
|
||||
const REQ_SHORT: &'static [u8] = b"\
|
||||
GET / HTTP/1.0\r\n\
|
||||
Host: example.com\r\n\
|
||||
Cookie: session=60; user_id=1\r\n\r\n";
|
||||
|
||||
const REQ: &'static [u8] = b"\
|
||||
GET /wp-content/uploads/2010/03/hello-kitty-darth-vader-pink.jpg HTTP/1.1\r\n\
|
||||
Host: www.kittyhell.com\r\n\
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; ja-JP-mac; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 Pathtraq/0.9\r\n\
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n\
|
||||
Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n\
|
||||
Accept-Encoding: gzip,deflate\r\n\
|
||||
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n\
|
||||
Keep-Alive: 115\r\n\
|
||||
Connection: keep-alive\r\n\
|
||||
Cookie: wp_ozh_wsa_visits=2; wp_ozh_wsa_visit_lasttime=xxxxxxxxxx; __utma=xxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.x; __utmz=xxxxxxxxx.xxxxxxxxxx.x.x.utmccn=(referral)|utmcsr=reader.livedoor.com|utmcct=/reader/|utmcmd=referral|padding=under256\r\n\r\n";
|
||||
|
||||
fn req(c: &mut Criterion) {
|
||||
let mut headers = [httparse::Header{ name: "", value: &[] }; 16];
|
||||
let mut req = httparse::Request::new(&mut headers);
|
||||
|
||||
c.benchmark_group("req")
|
||||
.throughput(Throughput::Bytes(REQ.len() as u64))
|
||||
.bench_function("req", |b| b.iter(|| {
|
||||
assert_eq!(black_box(req.parse(REQ).unwrap()), httparse::Status::Complete(REQ.len()));
|
||||
}));
|
||||
}
|
||||
|
||||
fn req_short(c: &mut Criterion) {
|
||||
let mut headers = [httparse::Header{ name: "", value: &[] }; 16];
|
||||
let mut req = httparse::Request::new(&mut headers);
|
||||
|
||||
c.benchmark_group("req_short")
|
||||
.throughput(Throughput::Bytes(REQ_SHORT.len() as u64))
|
||||
.bench_function("req_short", |b| b.iter(|| {
|
||||
assert_eq!(black_box(req.parse(REQ_SHORT).unwrap()), httparse::Status::Complete(REQ_SHORT.len()));
|
||||
}));
|
||||
}
|
||||
|
||||
const RESP_SHORT: &'static [u8] = b"\
|
||||
HTTP/1.0 200 OK\r\n\
|
||||
Date: Wed, 21 Oct 2015 07:28:00 GMT\r\n\
|
||||
Set-Cookie: session=60; user_id=1\r\n\r\n";
|
||||
|
||||
// These particular headers don't all make semantic sense for a response, but they're syntactically valid.
|
||||
const RESP: &'static [u8] = b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Date: Wed, 21 Oct 2015 07:28:00 GMT\r\n\
|
||||
Host: www.kittyhell.com\r\n\
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; ja-JP-mac; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 Pathtraq/0.9\r\n\
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n\
|
||||
Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n\
|
||||
Accept-Encoding: gzip,deflate\r\n\
|
||||
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n\
|
||||
Keep-Alive: 115\r\n\
|
||||
Connection: keep-alive\r\n\
|
||||
Cookie: wp_ozh_wsa_visits=2; wp_ozh_wsa_visit_lasttime=xxxxxxxxxx; __utma=xxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.x; __utmz=xxxxxxxxx.xxxxxxxxxx.x.x.utmccn=(referral)|utmcsr=reader.livedoor.com|utmcct=/reader/|utmcmd=referral|padding=under256\r\n\r\n";
|
||||
|
||||
fn resp(c: &mut Criterion) {
|
||||
let mut headers = [httparse::Header{ name: "", value: &[] }; 16];
|
||||
let mut resp = httparse::Response::new(&mut headers);
|
||||
|
||||
c.benchmark_group("resp")
|
||||
.throughput(Throughput::Bytes(RESP.len() as u64))
|
||||
.bench_function("resp", |b| b.iter(|| {
|
||||
assert_eq!(black_box(resp.parse(RESP).unwrap()), httparse::Status::Complete(RESP.len()));
|
||||
}));
|
||||
}
|
||||
|
||||
fn resp_short(c: &mut Criterion) {
|
||||
let mut headers = [httparse::Header{ name: "", value: &[] }; 16];
|
||||
let mut resp = httparse::Response::new(&mut headers);
|
||||
|
||||
c.benchmark_group("resp_short")
|
||||
.throughput(Throughput::Bytes(RESP_SHORT.len() as u64))
|
||||
.bench_function("resp_short", |b| b.iter(|| {
|
||||
assert_eq!(black_box(resp.parse(RESP_SHORT).unwrap()), httparse::Status::Complete(RESP_SHORT.len()));
|
||||
}));
|
||||
}
|
||||
|
||||
criterion_group!{
|
||||
name = benches;
|
||||
config = Criterion::default().sample_size(100).measurement_time(Duration::from_secs(10));
|
||||
targets = req, req_short, resp, resp_short
|
||||
}
|
||||
criterion_main!(benches);
|
||||
165
zeroidc/vendor/httparse/build.rs
vendored
Normal file
165
zeroidc/vendor/httparse/build.rs
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
use std::env;
|
||||
//use std::ffi::OsString;
|
||||
//use std::process::Command;
|
||||
|
||||
fn main() {
|
||||
// We don't currently need to check the Version anymore...
|
||||
// But leaving this in place in case we need to in the future.
|
||||
/*
|
||||
let rustc = env::var_os("RUSTC").unwrap_or(OsString::from("rustc"));
|
||||
let output = Command::new(&rustc)
|
||||
.arg("--version")
|
||||
.output()
|
||||
.expect("failed to check 'rustc --version'")
|
||||
.stdout;
|
||||
|
||||
let version = String::from_utf8(output)
|
||||
.expect("rustc version output should be utf-8");
|
||||
*/
|
||||
|
||||
enable_new_features(/*&version*/);
|
||||
}
|
||||
|
||||
fn enable_new_features(/*raw_version: &str*/) {
|
||||
/*
|
||||
let version = match Version::parse(raw_version) {
|
||||
Ok(version) => version,
|
||||
Err(err) => {
|
||||
println!("cargo:warning=failed to parse `rustc --version`: {}", err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
enable_simd(/*version*/);
|
||||
}
|
||||
|
||||
fn enable_simd(/*version: Version*/) {
|
||||
if env::var_os("CARGO_FEATURE_STD").is_none() {
|
||||
println!("cargo:warning=building for no_std disables httparse SIMD");
|
||||
return;
|
||||
}
|
||||
if env::var_os("CARGO_CFG_MIRI").is_some() {
|
||||
println!("cargo:warning=building for Miri disables httparse SIMD");
|
||||
return;
|
||||
}
|
||||
|
||||
let env_disable = "CARGO_CFG_HTTPARSE_DISABLE_SIMD";
|
||||
if var_is(env_disable, "1") {
|
||||
println!("cargo:warning=detected {} environment variable, disabling SIMD", env_disable);
|
||||
return;
|
||||
}
|
||||
|
||||
println!("cargo:rustc-cfg=httparse_simd");
|
||||
|
||||
// cfg(target_feature) isn't stable yet, but CARGO_CFG_TARGET_FEATURE has
|
||||
// a list... We aren't doing anything unsafe, since the is_x86_feature_detected
|
||||
// macro still checks in the actual lib, BUT!
|
||||
//
|
||||
// By peeking at the list here, we can change up slightly how we do feature
|
||||
// detection in the lib. If our features aren't in the feature list, we
|
||||
// stick with a cached runtime detection strategy.
|
||||
//
|
||||
// But if the features *are* in the list, we benefit from removing our cache,
|
||||
// since the compiler will eliminate several branches with its internal
|
||||
// cfg(target_feature) usage.
|
||||
|
||||
|
||||
let env_runtime_only = "CARGO_CFG_HTTPARSE_DISABLE_SIMD_COMPILETIME";
|
||||
if var_is(env_runtime_only, "1") {
|
||||
println!("cargo:warning=detected {} environment variable, using runtime SIMD detection only", env_runtime_only);
|
||||
return;
|
||||
}
|
||||
let feature_list = match env::var_os("CARGO_CFG_TARGET_FEATURE") {
|
||||
Some(var) => match var.into_string() {
|
||||
Ok(s) => s,
|
||||
Err(_) => {
|
||||
println!("cargo:warning=CARGO_CFG_TARGET_FEATURE was not valid utf-8");
|
||||
return;
|
||||
},
|
||||
},
|
||||
None => {
|
||||
println!("cargo:warning=CARGO_CFG_TARGET_FEATURE was not set");
|
||||
return
|
||||
},
|
||||
};
|
||||
|
||||
let mut saw_sse42 = false;
|
||||
let mut saw_avx2 = false;
|
||||
|
||||
for feature in feature_list.split(',') {
|
||||
let feature = feature.trim();
|
||||
if !saw_sse42 && feature == "sse4.2" {
|
||||
saw_sse42 = true;
|
||||
println!("cargo:rustc-cfg=httparse_simd_target_feature_sse42");
|
||||
}
|
||||
|
||||
if !saw_avx2 && feature == "avx2" {
|
||||
saw_avx2 = true;
|
||||
println!("cargo:rustc-cfg=httparse_simd_target_feature_avx2");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
|
||||
struct Version {
|
||||
major: u32,
|
||||
minor: u32,
|
||||
patch: u32,
|
||||
}
|
||||
|
||||
impl Version {
|
||||
fn parse(mut s: &str) -> Result<Version, String> {
|
||||
if !s.starts_with("rustc ") {
|
||||
return Err(format!("unrecognized version string: {}", s));
|
||||
}
|
||||
s = &s["rustc ".len()..];
|
||||
|
||||
let parts: Vec<&str> = s.split(".").collect();
|
||||
if parts.len() < 3 {
|
||||
return Err(format!("not enough version parts: {:?}", parts));
|
||||
}
|
||||
|
||||
let mut num = String::new();
|
||||
for c in parts[0].chars() {
|
||||
if !c.is_digit(10) {
|
||||
break;
|
||||
}
|
||||
num.push(c);
|
||||
}
|
||||
let major = num.parse::<u32>().map_err(|e| e.to_string())?;
|
||||
|
||||
num.clear();
|
||||
for c in parts[1].chars() {
|
||||
if !c.is_digit(10) {
|
||||
break;
|
||||
}
|
||||
num.push(c);
|
||||
}
|
||||
let minor = num.parse::<u32>().map_err(|e| e.to_string())?;
|
||||
|
||||
num.clear();
|
||||
for c in parts[2].chars() {
|
||||
if !c.is_digit(10) {
|
||||
break;
|
||||
}
|
||||
num.push(c);
|
||||
}
|
||||
let patch = num.parse::<u32>().map_err(|e| e.to_string())?;
|
||||
|
||||
Ok(Version {
|
||||
major: major,
|
||||
minor: minor,
|
||||
patch: patch,
|
||||
})
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
fn var_is(key: &str, val: &str) -> bool {
|
||||
match env::var(key) {
|
||||
Ok(v) => v == val,
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
216
zeroidc/vendor/httparse/src/iter.rs
vendored
Normal file
216
zeroidc/vendor/httparse/src/iter.rs
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
use core::slice;
|
||||
|
||||
pub struct Bytes<'a> {
|
||||
slice: &'a [u8],
|
||||
pos: usize
|
||||
}
|
||||
|
||||
impl<'a> Bytes<'a> {
|
||||
#[inline]
|
||||
pub fn new(slice: &'a [u8]) -> Bytes<'a> {
|
||||
Bytes {
|
||||
slice,
|
||||
pos: 0
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pos(&self) -> usize {
|
||||
self.pos
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn peek(&self) -> Option<u8> {
|
||||
self.slice.get(self.pos).cloned()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn bump(&mut self) {
|
||||
debug_assert!(self.pos < self.slice.len(), "overflow");
|
||||
self.pos += 1;
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[inline]
|
||||
pub unsafe fn advance(&mut self, n: usize) {
|
||||
debug_assert!(self.pos + n <= self.slice.len(), "overflow");
|
||||
self.pos += n;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.slice.len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn slice(&mut self) -> &'a [u8] {
|
||||
// not moving position at all, so it's safe
|
||||
unsafe {
|
||||
self.slice_skip(0)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn slice_skip(&mut self, skip: usize) -> &'a [u8] {
|
||||
debug_assert!(self.pos >= skip);
|
||||
let head_pos = self.pos - skip;
|
||||
let ptr = self.slice.as_ptr();
|
||||
let head = slice::from_raw_parts(ptr, head_pos);
|
||||
let tail = slice::from_raw_parts(ptr.add(self.pos), self.slice.len() - self.pos);
|
||||
self.pos = 0;
|
||||
self.slice = tail;
|
||||
head
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn next_8<'b>(&'b mut self) -> Option<Bytes8<'b, 'a>> {
|
||||
if self.slice.len() >= self.pos + 8 {
|
||||
Some(Bytes8::new(self))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsRef<[u8]> for Bytes<'a> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.slice[self.pos..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Bytes<'a> {
|
||||
type Item = u8;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<u8> {
|
||||
if self.slice.len() > self.pos {
|
||||
let b = unsafe { *self.slice.get_unchecked(self.pos) };
|
||||
self.pos += 1;
|
||||
Some(b)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Bytes8<'a, 'b: 'a> {
|
||||
bytes: &'a mut Bytes<'b>,
|
||||
#[cfg(debug_assertions)]
|
||||
pos: usize
|
||||
}
|
||||
|
||||
macro_rules! bytes8_methods {
|
||||
($f:ident, $pos:expr) => {
|
||||
#[inline]
|
||||
pub fn $f(&mut self) -> u8 {
|
||||
self.assert_pos($pos);
|
||||
let b = unsafe { *self.bytes.slice.get_unchecked(self.bytes.pos) };
|
||||
self.bytes.pos += 1;
|
||||
b
|
||||
}
|
||||
};
|
||||
() => {
|
||||
bytes8_methods!(_0, 0);
|
||||
bytes8_methods!(_1, 1);
|
||||
bytes8_methods!(_2, 2);
|
||||
bytes8_methods!(_3, 3);
|
||||
bytes8_methods!(_4, 4);
|
||||
bytes8_methods!(_5, 5);
|
||||
bytes8_methods!(_6, 6);
|
||||
bytes8_methods!(_7, 7);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> Bytes8<'a, 'b> {
|
||||
bytes8_methods! {}
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[inline]
|
||||
fn new(bytes: &'a mut Bytes<'b>) -> Bytes8<'a, 'b> {
|
||||
Bytes8 {
|
||||
bytes: bytes,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
#[inline]
|
||||
fn new(bytes: &'a mut Bytes<'b>) -> Bytes8<'a, 'b> {
|
||||
Bytes8 {
|
||||
bytes,
|
||||
pos: 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[inline]
|
||||
fn assert_pos(&mut self, _pos: usize) {
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
#[inline]
|
||||
fn assert_pos(&mut self, pos: usize) {
|
||||
assert!(self.pos == pos);
|
||||
self.pos += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Bytes;
|
||||
|
||||
#[test]
|
||||
fn test_next_8_too_short() {
|
||||
// Start with 10 bytes.
|
||||
let slice = [0u8, 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8];
|
||||
let mut bytes = Bytes::new(&slice);
|
||||
// Skip 3 of them.
|
||||
unsafe { bytes.advance(3); }
|
||||
// There should be 7 left, not enough to call next_8.
|
||||
assert!(bytes.next_8().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_next_8_just_right() {
|
||||
// Start with 10 bytes.
|
||||
let slice = [0u8, 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8];
|
||||
let mut bytes = Bytes::new(&slice);
|
||||
// Skip 2 of them.
|
||||
unsafe { bytes.advance(2); }
|
||||
// There should be 8 left, just enough to call next_8.
|
||||
let ret = bytes.next_8();
|
||||
assert!(ret.is_some());
|
||||
let mut ret = ret.unwrap();
|
||||
// They should be the bytes starting with 2.
|
||||
assert_eq!(ret._0(), 2u8);
|
||||
assert_eq!(ret._1(), 3u8);
|
||||
assert_eq!(ret._2(), 4u8);
|
||||
assert_eq!(ret._3(), 5u8);
|
||||
assert_eq!(ret._4(), 6u8);
|
||||
assert_eq!(ret._5(), 7u8);
|
||||
assert_eq!(ret._6(), 8u8);
|
||||
assert_eq!(ret._7(), 9u8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_next_8_extra() {
|
||||
// Start with 10 bytes.
|
||||
let slice = [0u8, 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8];
|
||||
let mut bytes = Bytes::new(&slice);
|
||||
// Skip 1 of them.
|
||||
unsafe { bytes.advance(1); }
|
||||
// There should be 9 left, more than enough to call next_8.
|
||||
let ret = bytes.next_8();
|
||||
assert!(ret.is_some());
|
||||
let mut ret = ret.unwrap();
|
||||
// They should be the bytes starting with 1.
|
||||
assert_eq!(ret._0(), 1u8);
|
||||
assert_eq!(ret._1(), 2u8);
|
||||
assert_eq!(ret._2(), 3u8);
|
||||
assert_eq!(ret._3(), 4u8);
|
||||
assert_eq!(ret._4(), 5u8);
|
||||
assert_eq!(ret._5(), 6u8);
|
||||
assert_eq!(ret._6(), 7u8);
|
||||
assert_eq!(ret._7(), 8u8);
|
||||
}
|
||||
}
|
||||
1917
zeroidc/vendor/httparse/src/lib.rs
vendored
Normal file
1917
zeroidc/vendor/httparse/src/lib.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
59
zeroidc/vendor/httparse/src/macros.rs
vendored
Normal file
59
zeroidc/vendor/httparse/src/macros.rs
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
///! Utility macros
|
||||
|
||||
macro_rules! next {
|
||||
($bytes:ident) => ({
|
||||
match $bytes.next() {
|
||||
Some(b) => b,
|
||||
None => return Ok(Status::Partial)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! expect {
|
||||
($bytes:ident.next() == $pat:pat => $ret:expr) => {
|
||||
expect!(next!($bytes) => $pat |? $ret)
|
||||
};
|
||||
($e:expr => $pat:pat |? $ret:expr) => {
|
||||
match $e {
|
||||
v@$pat => v,
|
||||
_ => return $ret
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! complete {
|
||||
($e:expr) => {
|
||||
match $e? {
|
||||
Status::Complete(v) => v,
|
||||
Status::Partial => return Ok(Status::Partial)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! byte_map {
|
||||
($($flag:expr,)*) => ([
|
||||
$($flag != 0,)*
|
||||
])
|
||||
}
|
||||
|
||||
macro_rules! space {
|
||||
($bytes:ident or $err:expr) => ({
|
||||
expect!($bytes.next() == b' ' => Err($err));
|
||||
$bytes.slice();
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! newline {
|
||||
($bytes:ident) => ({
|
||||
match next!($bytes) {
|
||||
b'\r' => {
|
||||
expect!($bytes.next() == b'\n' => Err(Error::NewLine));
|
||||
$bytes.slice();
|
||||
},
|
||||
b'\n' => {
|
||||
$bytes.slice();
|
||||
},
|
||||
_ => return Err(Error::NewLine)
|
||||
}
|
||||
})
|
||||
}
|
||||
181
zeroidc/vendor/httparse/src/simd/avx2.rs
vendored
Normal file
181
zeroidc/vendor/httparse/src/simd/avx2.rs
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
use ::iter::Bytes;
|
||||
|
||||
pub enum Scan {
|
||||
/// Returned when an implementation finds a noteworthy token.
|
||||
Found,
|
||||
/// Returned when an implementation couldn't keep running because the input was too short.
|
||||
TooShort,
|
||||
}
|
||||
|
||||
|
||||
pub unsafe fn parse_uri_batch_32(bytes: &mut Bytes) -> Scan {
|
||||
while bytes.as_ref().len() >= 32 {
|
||||
let advance = match_url_char_32_avx(bytes.as_ref());
|
||||
bytes.advance(advance);
|
||||
|
||||
if advance != 32 {
|
||||
return Scan::Found;
|
||||
}
|
||||
}
|
||||
Scan::TooShort
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "avx2")]
|
||||
#[inline]
|
||||
#[allow(non_snake_case, overflowing_literals)]
|
||||
unsafe fn match_url_char_32_avx(buf: &[u8]) -> usize {
|
||||
debug_assert!(buf.len() >= 32);
|
||||
|
||||
/*
|
||||
#[cfg(target_arch = "x86")]
|
||||
use core::arch::x86::*;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
*/
|
||||
use core::arch::x86_64::*;
|
||||
|
||||
let ptr = buf.as_ptr();
|
||||
|
||||
let LSH: __m256i = _mm256_set1_epi8(0x0f);
|
||||
|
||||
// See comment in sse42::match_url_char_16_sse.
|
||||
|
||||
let URI: __m256i = _mm256_setr_epi8(
|
||||
0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
|
||||
0xfc, 0xfc, 0xfc, 0xfc, 0xf4, 0xfc, 0xf4, 0x7c,
|
||||
0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
|
||||
0xfc, 0xfc, 0xfc, 0xfc, 0xf4, 0xfc, 0xf4, 0x7c,
|
||||
);
|
||||
let ARF: __m256i = _mm256_setr_epi8(
|
||||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
);
|
||||
|
||||
let data = _mm256_lddqu_si256(ptr as *const _);
|
||||
let rbms = _mm256_shuffle_epi8(URI, data);
|
||||
let cols = _mm256_and_si256(LSH, _mm256_srli_epi16(data, 4));
|
||||
let bits = _mm256_and_si256(_mm256_shuffle_epi8(ARF, cols), rbms);
|
||||
|
||||
let v = _mm256_cmpeq_epi8(bits, _mm256_setzero_si256());
|
||||
let r = 0xffff_ffff_0000_0000 | _mm256_movemask_epi8(v) as u64;
|
||||
|
||||
_tzcnt_u64(r) as usize
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
unsafe fn match_url_char_32_avx(_: &[u8]) -> usize {
|
||||
unreachable!("AVX2 detection should be disabled for x86");
|
||||
}
|
||||
|
||||
pub unsafe fn match_header_value_batch_32(bytes: &mut Bytes) -> Scan {
|
||||
while bytes.as_ref().len() >= 32 {
|
||||
let advance = match_header_value_char_32_avx(bytes.as_ref());
|
||||
bytes.advance(advance);
|
||||
|
||||
if advance != 32 {
|
||||
return Scan::Found;
|
||||
}
|
||||
}
|
||||
Scan::TooShort
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "avx2")]
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
unsafe fn match_header_value_char_32_avx(buf: &[u8]) -> usize {
|
||||
debug_assert!(buf.len() >= 32);
|
||||
|
||||
/*
|
||||
#[cfg(target_arch = "x86")]
|
||||
use core::arch::x86::*;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
*/
|
||||
use core::arch::x86_64::*;
|
||||
|
||||
let ptr = buf.as_ptr();
|
||||
|
||||
// %x09 %x20-%x7e %x80-%xff
|
||||
let TAB: __m256i = _mm256_set1_epi8(0x09);
|
||||
let DEL: __m256i = _mm256_set1_epi8(0x7f);
|
||||
let LOW: __m256i = _mm256_set1_epi8(0x20);
|
||||
|
||||
let dat = _mm256_lddqu_si256(ptr as *const _);
|
||||
// unsigned comparison dat >= LOW
|
||||
let low = _mm256_cmpeq_epi8(_mm256_max_epu8(dat, LOW), dat);
|
||||
let tab = _mm256_cmpeq_epi8(dat, TAB);
|
||||
let del = _mm256_cmpeq_epi8(dat, DEL);
|
||||
let bit = _mm256_andnot_si256(del, _mm256_or_si256(low, tab));
|
||||
let rev = _mm256_cmpeq_epi8(bit, _mm256_setzero_si256());
|
||||
let res = 0xffff_ffff_0000_0000 | _mm256_movemask_epi8(rev) as u64;
|
||||
|
||||
_tzcnt_u64(res) as usize
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
unsafe fn match_header_value_char_32_avx(_: &[u8]) -> usize {
|
||||
unreachable!("AVX2 detection should be disabled for x86");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn avx2_code_matches_uri_chars_table() {
|
||||
match super::detect() {
|
||||
super::AVX_2 | super::AVX_2_AND_SSE_42 => {},
|
||||
_ => return,
|
||||
}
|
||||
|
||||
unsafe {
|
||||
assert!(byte_is_allowed(b'_', parse_uri_batch_32));
|
||||
|
||||
for (b, allowed) in ::URI_MAP.iter().cloned().enumerate() {
|
||||
assert_eq!(
|
||||
byte_is_allowed(b as u8, parse_uri_batch_32), allowed,
|
||||
"byte_is_allowed({:?}) should be {:?}", b, allowed,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn avx2_code_matches_header_value_chars_table() {
|
||||
match super::detect() {
|
||||
super::AVX_2 | super::AVX_2_AND_SSE_42 => {},
|
||||
_ => return,
|
||||
}
|
||||
|
||||
unsafe {
|
||||
assert!(byte_is_allowed(b'_', match_header_value_batch_32));
|
||||
|
||||
for (b, allowed) in ::HEADER_VALUE_MAP.iter().cloned().enumerate() {
|
||||
assert_eq!(
|
||||
byte_is_allowed(b as u8, match_header_value_batch_32), allowed,
|
||||
"byte_is_allowed({:?}) should be {:?}", b, allowed,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
unsafe fn byte_is_allowed(byte: u8, f: unsafe fn(bytes: &mut Bytes<'_>) -> Scan) -> bool {
|
||||
let slice = [
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', byte, b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
];
|
||||
let mut bytes = Bytes::new(&slice);
|
||||
|
||||
f(&mut bytes);
|
||||
|
||||
match bytes.pos() {
|
||||
32 => true,
|
||||
26 => false,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
8
zeroidc/vendor/httparse/src/simd/fallback.rs
vendored
Normal file
8
zeroidc/vendor/httparse/src/simd/fallback.rs
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
use ::iter::Bytes;
|
||||
|
||||
// Fallbacks that do nothing...
|
||||
|
||||
#[inline(always)]
|
||||
pub fn match_uri_vectored(_: &mut Bytes) {}
|
||||
#[inline(always)]
|
||||
pub fn match_header_value_vectored(_: &mut Bytes) {}
|
||||
284
zeroidc/vendor/httparse/src/simd/mod.rs
vendored
Normal file
284
zeroidc/vendor/httparse/src/simd/mod.rs
vendored
Normal file
@@ -0,0 +1,284 @@
|
||||
#[cfg(not(all(
|
||||
httparse_simd,
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
)))]
|
||||
mod fallback;
|
||||
|
||||
#[cfg(not(all(
|
||||
httparse_simd,
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
)))]
|
||||
pub use self::fallback::*;
|
||||
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
))]
|
||||
mod sse42;
|
||||
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
any(
|
||||
httparse_simd_target_feature_avx2,
|
||||
not(httparse_simd_target_feature_sse42),
|
||||
),
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
))]
|
||||
mod avx2;
|
||||
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
))]
|
||||
pub const SSE_42: usize = 1;
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
any(not(httparse_simd_target_feature_sse42), httparse_simd_target_feature_avx2),
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
))]
|
||||
pub const AVX_2: usize = 2;
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
any(
|
||||
not(httparse_simd_target_feature_sse42),
|
||||
httparse_simd_target_feature_avx2,
|
||||
test,
|
||||
),
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
))]
|
||||
pub const AVX_2_AND_SSE_42: usize = 3;
|
||||
#[cfg(httparse_simd)]
|
||||
const NONE: usize = ::core::usize::MAX;
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
not(any(
|
||||
httparse_simd_target_feature_sse42,
|
||||
httparse_simd_target_feature_avx2,
|
||||
)),
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
))]
|
||||
mod runtime {
|
||||
//! Runtime detection of simd features. Used when the build script
|
||||
//! doesn't notice any target features at build time.
|
||||
//!
|
||||
//! While `is_x86_feature_detected!` has it's own caching built-in,
|
||||
//! at least in 1.27.0, the functions don't inline, leaving using it
|
||||
//! actually *slower* than just using the scalar fallback.
|
||||
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
static FEATURE: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
const INIT: usize = 0;
|
||||
|
||||
pub fn detect() -> usize {
|
||||
let feat = FEATURE.load(Ordering::Relaxed);
|
||||
if feat == INIT {
|
||||
if cfg!(target_arch = "x86_64") && is_x86_feature_detected!("avx2") {
|
||||
if is_x86_feature_detected!("sse4.2") {
|
||||
FEATURE.store(super::AVX_2_AND_SSE_42, Ordering::Relaxed);
|
||||
return super::AVX_2_AND_SSE_42;
|
||||
} else {
|
||||
FEATURE.store(super::AVX_2, Ordering::Relaxed);
|
||||
return super::AVX_2;
|
||||
}
|
||||
} else if is_x86_feature_detected!("sse4.2") {
|
||||
FEATURE.store(super::SSE_42, Ordering::Relaxed);
|
||||
return super::SSE_42;
|
||||
} else {
|
||||
FEATURE.store(super::NONE, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
feat
|
||||
}
|
||||
|
||||
pub fn match_uri_vectored(bytes: &mut ::Bytes) {
|
||||
unsafe {
|
||||
match detect() {
|
||||
super::SSE_42 => super::sse42::parse_uri_batch_16(bytes),
|
||||
super::AVX_2 => { super::avx2::parse_uri_batch_32(bytes); },
|
||||
super::AVX_2_AND_SSE_42 => {
|
||||
if let super::avx2::Scan::Found = super::avx2::parse_uri_batch_32(bytes) {
|
||||
return;
|
||||
}
|
||||
super::sse42::parse_uri_batch_16(bytes)
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
// else do nothing
|
||||
}
|
||||
|
||||
pub fn match_header_value_vectored(bytes: &mut ::Bytes) {
|
||||
unsafe {
|
||||
match detect() {
|
||||
super::SSE_42 => super::sse42::match_header_value_batch_16(bytes),
|
||||
super::AVX_2 => { super::avx2::match_header_value_batch_32(bytes); },
|
||||
super::AVX_2_AND_SSE_42 => {
|
||||
if let super::avx2::Scan::Found = super::avx2::match_header_value_batch_32(bytes) {
|
||||
return;
|
||||
}
|
||||
super::sse42::match_header_value_batch_16(bytes)
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
// else do nothing
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
not(any(
|
||||
httparse_simd_target_feature_sse42,
|
||||
httparse_simd_target_feature_avx2,
|
||||
)),
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
))]
|
||||
pub use self::runtime::*;
|
||||
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
httparse_simd_target_feature_sse42,
|
||||
not(httparse_simd_target_feature_avx2),
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
))]
|
||||
mod sse42_compile_time {
|
||||
pub fn match_uri_vectored(bytes: &mut ::Bytes) {
|
||||
if detect() == super::SSE_42 {
|
||||
unsafe {
|
||||
super::sse42::parse_uri_batch_16(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
// else do nothing
|
||||
}
|
||||
|
||||
pub fn match_header_value_vectored(bytes: &mut ::Bytes) {
|
||||
if detect() == super::SSE_42 {
|
||||
unsafe {
|
||||
super::sse42::match_header_value_batch_16(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
// else do nothing
|
||||
}
|
||||
|
||||
pub fn detect() -> usize {
|
||||
if is_x86_feature_detected!("sse4.2") {
|
||||
super::SSE_42
|
||||
} else {
|
||||
super::NONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
httparse_simd_target_feature_sse42,
|
||||
not(httparse_simd_target_feature_avx2),
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
))]
|
||||
pub use self::sse42_compile_time::*;
|
||||
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
httparse_simd_target_feature_avx2,
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
))]
|
||||
mod avx2_compile_time {
|
||||
pub fn match_uri_vectored(bytes: &mut ::Bytes) {
|
||||
// do both, since avx2 only works when bytes.len() >= 32
|
||||
if detect() == super::AVX_2_AND_SSE_42 {
|
||||
unsafe {
|
||||
super::avx2::parse_uri_batch_32(bytes);
|
||||
}
|
||||
|
||||
}
|
||||
if detect() == super::SSE_42 {
|
||||
unsafe {
|
||||
super::sse42::parse_uri_batch_16(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
// else do nothing
|
||||
}
|
||||
|
||||
pub fn match_header_value_vectored(bytes: &mut ::Bytes) {
|
||||
// do both, since avx2 only works when bytes.len() >= 32
|
||||
if detect() == super::AVX_2_AND_SSE_42 {
|
||||
let scanned = unsafe {
|
||||
super::avx2::match_header_value_batch_32(bytes)
|
||||
};
|
||||
|
||||
if let super::avx2::Scan::Found = scanned {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if detect() == super::SSE_42 {
|
||||
unsafe {
|
||||
super::sse42::match_header_value_batch_16(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
// else do nothing
|
||||
}
|
||||
|
||||
pub fn detect() -> usize {
|
||||
if cfg!(target_arch = "x86_64") && is_x86_feature_detected!("avx2") {
|
||||
super::AVX_2_AND_SSE_42
|
||||
} else if is_x86_feature_detected!("sse4.2") {
|
||||
super::SSE_42
|
||||
} else {
|
||||
super::NONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
httparse_simd_target_feature_avx2,
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
))]
|
||||
pub use self::avx2_compile_time::*;
|
||||
157
zeroidc/vendor/httparse/src/simd/sse42.rs
vendored
Normal file
157
zeroidc/vendor/httparse/src/simd/sse42.rs
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
use ::iter::Bytes;
|
||||
|
||||
pub unsafe fn parse_uri_batch_16(bytes: &mut Bytes) {
|
||||
while bytes.as_ref().len() >= 16 {
|
||||
let advance = match_url_char_16_sse(bytes.as_ref());
|
||||
bytes.advance(advance);
|
||||
|
||||
if advance != 16 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[target_feature(enable = "sse4.2")]
|
||||
#[allow(non_snake_case, overflowing_literals)]
|
||||
unsafe fn match_url_char_16_sse(buf: &[u8]) -> usize {
|
||||
debug_assert!(buf.len() >= 16);
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
use core::arch::x86::*;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use core::arch::x86_64::*;
|
||||
|
||||
let ptr = buf.as_ptr();
|
||||
|
||||
let LSH: __m128i = _mm_set1_epi8(0x0f);
|
||||
|
||||
// The first 0xf8 corresponds to the 8 first rows of the first column
|
||||
// of URI_MAP in the crate's root, with the first row corresponding to bit 0
|
||||
// and the 8th row corresponding to bit 7.
|
||||
// The 8 first rows give 0 0 0 1 1 1 1 1, which is 0xf8 (with least
|
||||
// significant digit on the left).
|
||||
//
|
||||
// Another example just to drive the point home: in column 15, '>' is
|
||||
// rejected, so the values are 0 0 1 0 1 1 1 1, which gives us 0xf4.
|
||||
//
|
||||
// Thanks to Vlad Krasnov for explaining this stuff to us mere mortals in
|
||||
// a GitHub comment!
|
||||
//
|
||||
// https://github.com/seanmonstar/httparse/pull/89#issuecomment-807039219
|
||||
|
||||
let URI: __m128i = _mm_setr_epi8(
|
||||
0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
|
||||
0xfc, 0xfc, 0xfc, 0xfc, 0xf4, 0xfc, 0xf4, 0x7c,
|
||||
);
|
||||
let ARF: __m128i = _mm_setr_epi8(
|
||||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
);
|
||||
|
||||
let data = _mm_lddqu_si128(ptr as *const _);
|
||||
let rbms = _mm_shuffle_epi8(URI, data);
|
||||
let cols = _mm_and_si128(LSH, _mm_srli_epi16(data, 4));
|
||||
let bits = _mm_and_si128(_mm_shuffle_epi8(ARF, cols), rbms);
|
||||
|
||||
let v = _mm_cmpeq_epi8(bits, _mm_setzero_si128());
|
||||
let r = 0xffff_0000 | _mm_movemask_epi8(v) as u32;
|
||||
|
||||
_tzcnt_u32(r) as usize
|
||||
}
|
||||
|
||||
pub unsafe fn match_header_value_batch_16(bytes: &mut Bytes) {
|
||||
while bytes.as_ref().len() >= 16 {
|
||||
let advance = match_header_value_char_16_sse(bytes.as_ref());
|
||||
bytes.advance(advance);
|
||||
|
||||
if advance != 16 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[target_feature(enable = "sse4.2")]
|
||||
#[allow(non_snake_case)]
|
||||
unsafe fn match_header_value_char_16_sse(buf: &[u8]) -> usize {
|
||||
debug_assert!(buf.len() >= 16);
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
use core::arch::x86::*;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use core::arch::x86_64::*;
|
||||
|
||||
let ptr = buf.as_ptr();
|
||||
|
||||
// %x09 %x20-%x7e %x80-%xff
|
||||
let TAB: __m128i = _mm_set1_epi8(0x09);
|
||||
let DEL: __m128i = _mm_set1_epi8(0x7f);
|
||||
let LOW: __m128i = _mm_set1_epi8(0x20);
|
||||
|
||||
let dat = _mm_lddqu_si128(ptr as *const _);
|
||||
// unsigned comparison dat >= LOW
|
||||
let low = _mm_cmpeq_epi8(_mm_max_epu8(dat, LOW), dat);
|
||||
let tab = _mm_cmpeq_epi8(dat, TAB);
|
||||
let del = _mm_cmpeq_epi8(dat, DEL);
|
||||
let bit = _mm_andnot_si128(del, _mm_or_si128(low, tab));
|
||||
let rev = _mm_cmpeq_epi8(bit, _mm_setzero_si128());
|
||||
let res = 0xffff_0000 | _mm_movemask_epi8(rev) as u32;
|
||||
|
||||
_tzcnt_u32(res) as usize
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sse_code_matches_uri_chars_table() {
|
||||
match super::detect() {
|
||||
super::SSE_42 | super::AVX_2_AND_SSE_42 => {},
|
||||
_ => return,
|
||||
}
|
||||
|
||||
unsafe {
|
||||
assert!(byte_is_allowed(b'_', parse_uri_batch_16));
|
||||
|
||||
for (b, allowed) in ::URI_MAP.iter().cloned().enumerate() {
|
||||
assert_eq!(
|
||||
byte_is_allowed(b as u8, parse_uri_batch_16), allowed,
|
||||
"byte_is_allowed({:?}) should be {:?}", b, allowed,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sse_code_matches_header_value_chars_table() {
|
||||
match super::detect() {
|
||||
super::SSE_42 | super::AVX_2_AND_SSE_42 => {},
|
||||
_ => return,
|
||||
}
|
||||
|
||||
unsafe {
|
||||
assert!(byte_is_allowed(b'_', match_header_value_batch_16));
|
||||
|
||||
for (b, allowed) in ::HEADER_VALUE_MAP.iter().cloned().enumerate() {
|
||||
assert_eq!(
|
||||
byte_is_allowed(b as u8, match_header_value_batch_16), allowed,
|
||||
"byte_is_allowed({:?}) should be {:?}", b, allowed,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
unsafe fn byte_is_allowed(byte: u8, f: unsafe fn(bytes: &mut Bytes<'_>)) -> bool {
|
||||
let slice = [
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', byte, b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
];
|
||||
let mut bytes = Bytes::new(&slice);
|
||||
|
||||
f(&mut bytes);
|
||||
|
||||
match bytes.pos() {
|
||||
16 => true,
|
||||
10 => false,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
3693
zeroidc/vendor/httparse/tests/uri.rs
vendored
Normal file
3693
zeroidc/vendor/httparse/tests/uri.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user